Add buttons to allow loading of incomplete diffs (#16829)
This PR adds two buttons to the stats and the end of the diffs list to load the (some of) the remaining incomplete diff sections. Contains #16775 Signed-off-by: Andrew Thornton <art27@cantab.net> ## Screenshots ### Show more button at the end of the diff ![Screenshot from 2021-09-04 11-12-37](https://user-images.githubusercontent.com/1824502/132091009-b1f6113e-2c04-4be5-8a04-b8ecea56887b.png) ### Show more button at the end of the diff stats box ![Screenshot from 2021-09-04 11-14-54](https://user-images.githubusercontent.com/1824502/132091063-86da5a6d-6628-4b82-bea9-3655cd9f40f6.png)
This commit is contained in:
parent
bdfd751af8
commit
a889d0cc8c
12 changed files with 228 additions and 155 deletions
|
@ -46,7 +46,7 @@ func (repo *Repository) GetMergeBase(tmpRemote string, base, head string) (strin
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCompareInfo generates and returns compare information between base and head branches of repositories.
|
// GetCompareInfo generates and returns compare information between base and head branches of repositories.
|
||||||
func (repo *Repository) GetCompareInfo(basePath, baseBranch, headBranch string, directComparison bool) (_ *CompareInfo, err error) {
|
func (repo *Repository) GetCompareInfo(basePath, baseBranch, headBranch string, directComparison, fileOnly bool) (_ *CompareInfo, err error) {
|
||||||
var (
|
var (
|
||||||
remoteBranch string
|
remoteBranch string
|
||||||
tmpRemote string
|
tmpRemote string
|
||||||
|
@ -87,6 +87,7 @@ func (repo *Repository) GetCompareInfo(basePath, baseBranch, headBranch string,
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have a common base - therefore we know that ... should work
|
// We have a common base - therefore we know that ... should work
|
||||||
|
if !fileOnly {
|
||||||
logs, err := NewCommand("log", baseCommitID+separator+headBranch, prettyLogFormat).RunInDirBytes(repo.Path)
|
logs, err := NewCommand("log", baseCommitID+separator+headBranch, prettyLogFormat).RunInDirBytes(repo.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -95,6 +96,9 @@ func (repo *Repository) GetCompareInfo(basePath, baseBranch, headBranch string,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("parsePrettyFormatLogToList: %v", err)
|
return nil, fmt.Errorf("parsePrettyFormatLogToList: %v", err)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
compareInfo.Commits = []*Commit{}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
compareInfo.Commits = []*Commit{}
|
compareInfo.Commits = []*Commit{}
|
||||||
compareInfo.MergeBase, err = GetFullCommitID(repo.Path, remoteBranch)
|
compareInfo.MergeBase, err = GetFullCommitID(repo.Path, remoteBranch)
|
||||||
|
|
|
@ -2027,7 +2027,8 @@ diff.file_image_height = Height
|
||||||
diff.file_byte_size = Size
|
diff.file_byte_size = Size
|
||||||
diff.file_suppressed = File diff suppressed because it is too large
|
diff.file_suppressed = File diff suppressed because it is too large
|
||||||
diff.file_suppressed_line_too_long = File diff suppressed because one or more lines are too long
|
diff.file_suppressed_line_too_long = File diff suppressed because one or more lines are too long
|
||||||
diff.too_many_files = Some files were not shown because too many files changed in this diff
|
diff.too_many_files = Some files were not shown because too many files have changed in this diff
|
||||||
|
diff.show_more = Show More
|
||||||
diff.generated = generated
|
diff.generated = generated
|
||||||
diff.vendored = vendored
|
diff.vendored = vendored
|
||||||
diff.comment.placeholder = Leave a comment
|
diff.comment.placeholder = Leave a comment
|
||||||
|
|
|
@ -1016,7 +1016,7 @@ func parseCompareInfo(ctx *context.APIContext, form api.CreatePullRequestOption)
|
||||||
return nil, nil, nil, nil, "", ""
|
return nil, nil, nil, nil, "", ""
|
||||||
}
|
}
|
||||||
|
|
||||||
compareInfo, err := headGitRepo.GetCompareInfo(models.RepoPath(baseRepo.Owner.Name, baseRepo.Name), baseBranch, headBranch, true)
|
compareInfo, err := headGitRepo.GetCompareInfo(models.RepoPath(baseRepo.Owner.Name, baseRepo.Name), baseBranch, headBranch, true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
headGitRepo.Close()
|
headGitRepo.Close()
|
||||||
ctx.Error(http.StatusInternalServerError, "GetCompareInfo", err)
|
ctx.Error(http.StatusInternalServerError, "GetCompareInfo", err)
|
||||||
|
@ -1193,9 +1193,9 @@ func GetPullRequestCommits(ctx *context.APIContext) {
|
||||||
}
|
}
|
||||||
defer baseGitRepo.Close()
|
defer baseGitRepo.Close()
|
||||||
if pr.HasMerged {
|
if pr.HasMerged {
|
||||||
prInfo, err = baseGitRepo.GetCompareInfo(pr.BaseRepo.RepoPath(), pr.MergeBase, pr.GetGitRefName(), true)
|
prInfo, err = baseGitRepo.GetCompareInfo(pr.BaseRepo.RepoPath(), pr.MergeBase, pr.GetGitRefName(), true, false)
|
||||||
} else {
|
} else {
|
||||||
prInfo, err = baseGitRepo.GetCompareInfo(pr.BaseRepo.RepoPath(), pr.BaseBranch, pr.GetGitRefName(), true)
|
prInfo, err = baseGitRepo.GetCompareInfo(pr.BaseRepo.RepoPath(), pr.BaseBranch, pr.GetGitRefName(), true, false)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetCompareInfo", err)
|
ctx.ServerError("GetCompareInfo", err)
|
||||||
|
|
|
@ -264,6 +264,8 @@ func Diff(ctx *context.Context) {
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fileOnly := ctx.FormBool("file-only")
|
||||||
|
|
||||||
if ctx.Data["PageIsWiki"] != nil {
|
if ctx.Data["PageIsWiki"] != nil {
|
||||||
gitRepo, err = git.OpenRepository(ctx.Repo.Repository.WikiPath())
|
gitRepo, err = git.OpenRepository(ctx.Repo.Repository.WikiPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -288,16 +290,8 @@ func Diff(ctx *context.Context) {
|
||||||
commitID = commit.ID.String()
|
commitID = commit.ID.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
statuses, err := models.GetLatestCommitStatus(ctx.Repo.Repository.ID, commitID, db.ListOptions{})
|
|
||||||
if err != nil {
|
|
||||||
log.Error("GetLatestCommitStatus: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.Data["CommitStatus"] = models.CalcCommitStatus(statuses)
|
|
||||||
ctx.Data["CommitStatuses"] = statuses
|
|
||||||
|
|
||||||
diff, err := gitdiff.GetDiffCommitWithWhitespaceBehavior(gitRepo,
|
diff, err := gitdiff.GetDiffCommitWithWhitespaceBehavior(gitRepo,
|
||||||
commitID, setting.Git.MaxGitDiffLines,
|
commitID, ctx.FormString("skip-to"), setting.Git.MaxGitDiffLines,
|
||||||
setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles,
|
setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles,
|
||||||
gitdiff.GetWhitespaceFlag(ctx.Data["WhitespaceBehavior"].(string)),
|
gitdiff.GetWhitespaceFlag(ctx.Data["WhitespaceBehavior"].(string)),
|
||||||
false)
|
false)
|
||||||
|
@ -333,10 +327,23 @@ func Diff(ctx *context.Context) {
|
||||||
setCompareContext(ctx, parentCommit, commit, headTarget)
|
setCompareContext(ctx, parentCommit, commit, headTarget)
|
||||||
ctx.Data["Title"] = commit.Summary() + " · " + base.ShortSha(commitID)
|
ctx.Data["Title"] = commit.Summary() + " · " + base.ShortSha(commitID)
|
||||||
ctx.Data["Commit"] = commit
|
ctx.Data["Commit"] = commit
|
||||||
|
ctx.Data["Diff"] = diff
|
||||||
|
if fileOnly {
|
||||||
|
ctx.HTML(http.StatusOK, tplDiffBox)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
statuses, err := models.GetLatestCommitStatus(ctx.Repo.Repository.ID, commitID, db.ListOptions{})
|
||||||
|
if err != nil {
|
||||||
|
log.Error("GetLatestCommitStatus: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Data["CommitStatus"] = models.CalcCommitStatus(statuses)
|
||||||
|
ctx.Data["CommitStatuses"] = statuses
|
||||||
|
|
||||||
verification := models.ParseCommitWithSignature(commit)
|
verification := models.ParseCommitWithSignature(commit)
|
||||||
ctx.Data["Verification"] = verification
|
ctx.Data["Verification"] = verification
|
||||||
ctx.Data["Author"] = models.ValidateCommitWithEmail(commit)
|
ctx.Data["Author"] = models.ValidateCommitWithEmail(commit)
|
||||||
ctx.Data["Diff"] = diff
|
|
||||||
ctx.Data["Parents"] = parents
|
ctx.Data["Parents"] = parents
|
||||||
ctx.Data["DiffNotAvailable"] = diff.NumFiles == 0
|
ctx.Data["DiffNotAvailable"] = diff.NumFiles == 0
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ import (
|
||||||
const (
|
const (
|
||||||
tplCompare base.TplName = "repo/diff/compare"
|
tplCompare base.TplName = "repo/diff/compare"
|
||||||
tplBlobExcerpt base.TplName = "repo/diff/blob_excerpt"
|
tplBlobExcerpt base.TplName = "repo/diff/blob_excerpt"
|
||||||
|
tplDiffBox base.TplName = "repo/diff/box"
|
||||||
)
|
)
|
||||||
|
|
||||||
// setCompareContext sets context data.
|
// setCompareContext sets context data.
|
||||||
|
@ -161,6 +162,8 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
|
||||||
baseRepo := ctx.Repo.Repository
|
baseRepo := ctx.Repo.Repository
|
||||||
ci := &CompareInfo{}
|
ci := &CompareInfo{}
|
||||||
|
|
||||||
|
fileOnly := ctx.FormBool("file-only")
|
||||||
|
|
||||||
// Get compared branches information
|
// Get compared branches information
|
||||||
// A full compare url is of the form:
|
// A full compare url is of the form:
|
||||||
//
|
//
|
||||||
|
@ -411,17 +414,21 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
|
||||||
if rootRepo != nil &&
|
if rootRepo != nil &&
|
||||||
rootRepo.ID != ci.HeadRepo.ID &&
|
rootRepo.ID != ci.HeadRepo.ID &&
|
||||||
rootRepo.ID != baseRepo.ID {
|
rootRepo.ID != baseRepo.ID {
|
||||||
perm, branches, tags, err := getBranchesAndTagsForRepo(ctx.User, rootRepo)
|
canRead := rootRepo.CheckUnitUser(ctx.User, models.UnitTypeCode)
|
||||||
|
if canRead {
|
||||||
|
ctx.Data["RootRepo"] = rootRepo
|
||||||
|
if !fileOnly {
|
||||||
|
branches, tags, err := getBranchesAndTagsForRepo(ctx.User, rootRepo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetBranchesForRepo", err)
|
ctx.ServerError("GetBranchesForRepo", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if perm {
|
|
||||||
ctx.Data["RootRepo"] = rootRepo
|
|
||||||
ctx.Data["RootRepoBranches"] = branches
|
ctx.Data["RootRepoBranches"] = branches
|
||||||
ctx.Data["RootRepoTags"] = tags
|
ctx.Data["RootRepoTags"] = tags
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If we have a ownForkRepo and it's different from:
|
// If we have a ownForkRepo and it's different from:
|
||||||
// 1. The computed base
|
// 1. The computed base
|
||||||
|
@ -432,17 +439,20 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
|
||||||
ownForkRepo.ID != ci.HeadRepo.ID &&
|
ownForkRepo.ID != ci.HeadRepo.ID &&
|
||||||
ownForkRepo.ID != baseRepo.ID &&
|
ownForkRepo.ID != baseRepo.ID &&
|
||||||
(rootRepo == nil || ownForkRepo.ID != rootRepo.ID) {
|
(rootRepo == nil || ownForkRepo.ID != rootRepo.ID) {
|
||||||
perm, branches, tags, err := getBranchesAndTagsForRepo(ctx.User, ownForkRepo)
|
canRead := ownForkRepo.CheckUnitUser(ctx.User, models.UnitTypeCode)
|
||||||
|
if canRead {
|
||||||
|
ctx.Data["OwnForkRepo"] = ownForkRepo
|
||||||
|
if !fileOnly {
|
||||||
|
branches, tags, err := getBranchesAndTagsForRepo(ctx.User, ownForkRepo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetBranchesForRepo", err)
|
ctx.ServerError("GetBranchesForRepo", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if perm {
|
|
||||||
ctx.Data["OwnForkRepo"] = ownForkRepo
|
|
||||||
ctx.Data["OwnForkRepoBranches"] = branches
|
ctx.Data["OwnForkRepoBranches"] = branches
|
||||||
ctx.Data["OwnForkRepoTags"] = tags
|
ctx.Data["OwnForkRepoTags"] = tags
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if head branch is valid.
|
// Check if head branch is valid.
|
||||||
headIsCommit := ci.HeadGitRepo.IsCommitExist(ci.HeadBranch)
|
headIsCommit := ci.HeadGitRepo.IsCommitExist(ci.HeadBranch)
|
||||||
|
@ -492,7 +502,7 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo {
|
||||||
headBranchRef = git.TagPrefix + ci.HeadBranch
|
headBranchRef = git.TagPrefix + ci.HeadBranch
|
||||||
}
|
}
|
||||||
|
|
||||||
ci.CompareInfo, err = ci.HeadGitRepo.GetCompareInfo(baseRepo.RepoPath(), baseBranchRef, headBranchRef, ci.DirectComparison)
|
ci.CompareInfo, err = ci.HeadGitRepo.GetCompareInfo(baseRepo.RepoPath(), baseBranchRef, headBranchRef, ci.DirectComparison, fileOnly)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetCompareInfo", err)
|
ctx.ServerError("GetCompareInfo", err)
|
||||||
return nil
|
return nil
|
||||||
|
@ -545,7 +555,7 @@ func PrepareCompareDiff(
|
||||||
}
|
}
|
||||||
|
|
||||||
diff, err := gitdiff.GetDiffRangeWithWhitespaceBehavior(ci.HeadGitRepo,
|
diff, err := gitdiff.GetDiffRangeWithWhitespaceBehavior(ci.HeadGitRepo,
|
||||||
beforeCommitID, headCommitID, setting.Git.MaxGitDiffLines,
|
beforeCommitID, headCommitID, ctx.FormString("skip-to"), setting.Git.MaxGitDiffLines,
|
||||||
setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, whitespaceBehavior, ci.DirectComparison)
|
setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, whitespaceBehavior, ci.DirectComparison)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetDiffRangeWithWhitespaceBehavior", err)
|
ctx.ServerError("GetDiffRangeWithWhitespaceBehavior", err)
|
||||||
|
@ -606,29 +616,22 @@ func PrepareCompareDiff(
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBranchesAndTagsForRepo(user *models.User, repo *models.Repository) (bool, []string, []string, error) {
|
func getBranchesAndTagsForRepo(user *models.User, repo *models.Repository) (branches, tags []string, err error) {
|
||||||
perm, err := models.GetUserRepoPermission(repo, user)
|
|
||||||
if err != nil {
|
|
||||||
return false, nil, nil, err
|
|
||||||
}
|
|
||||||
if !perm.CanRead(models.UnitTypeCode) {
|
|
||||||
return false, nil, nil, nil
|
|
||||||
}
|
|
||||||
gitRepo, err := git.OpenRepository(repo.RepoPath())
|
gitRepo, err := git.OpenRepository(repo.RepoPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
defer gitRepo.Close()
|
defer gitRepo.Close()
|
||||||
|
|
||||||
branches, _, err := gitRepo.GetBranches(0, 0)
|
branches, _, err = gitRepo.GetBranches(0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
tags, err := gitRepo.GetTags(0, 0)
|
tags, err = gitRepo.GetTags(0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
return true, branches, tags, nil
|
return branches, tags, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompareDiff show different from one commit to another commit
|
// CompareDiff show different from one commit to another commit
|
||||||
|
@ -665,6 +668,12 @@ func CompareDiff(ctx *context.Context) {
|
||||||
}
|
}
|
||||||
ctx.Data["Tags"] = baseTags
|
ctx.Data["Tags"] = baseTags
|
||||||
|
|
||||||
|
fileOnly := ctx.FormBool("file-only")
|
||||||
|
if fileOnly {
|
||||||
|
ctx.HTML(http.StatusOK, tplDiffBox)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
headBranches, _, err := ci.HeadGitRepo.GetBranches(0, 0)
|
headBranches, _, err := ci.HeadGitRepo.GetBranches(0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetBranches", err)
|
ctx.ServerError("GetBranches", err)
|
||||||
|
|
|
@ -318,7 +318,7 @@ func PrepareMergedViewPullInfo(ctx *context.Context, issue *models.Issue) *git.C
|
||||||
ctx.Data["HasMerged"] = true
|
ctx.Data["HasMerged"] = true
|
||||||
|
|
||||||
compareInfo, err := ctx.Repo.GitRepo.GetCompareInfo(ctx.Repo.Repository.RepoPath(),
|
compareInfo, err := ctx.Repo.GitRepo.GetCompareInfo(ctx.Repo.Repository.RepoPath(),
|
||||||
pull.MergeBase, pull.GetGitRefName(), true)
|
pull.MergeBase, pull.GetGitRefName(), true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "fatal: Not a valid object name") || strings.Contains(err.Error(), "unknown revision or path not in the working tree") {
|
if strings.Contains(err.Error(), "fatal: Not a valid object name") || strings.Contains(err.Error(), "unknown revision or path not in the working tree") {
|
||||||
ctx.Data["IsPullRequestBroken"] = true
|
ctx.Data["IsPullRequestBroken"] = true
|
||||||
|
@ -401,7 +401,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare
|
||||||
}
|
}
|
||||||
|
|
||||||
compareInfo, err := baseGitRepo.GetCompareInfo(pull.BaseRepo.RepoPath(),
|
compareInfo, err := baseGitRepo.GetCompareInfo(pull.BaseRepo.RepoPath(),
|
||||||
pull.MergeBase, pull.GetGitRefName(), true)
|
pull.MergeBase, pull.GetGitRefName(), true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "fatal: Not a valid object name") {
|
if strings.Contains(err.Error(), "fatal: Not a valid object name") {
|
||||||
ctx.Data["IsPullRequestBroken"] = true
|
ctx.Data["IsPullRequestBroken"] = true
|
||||||
|
@ -517,7 +517,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare
|
||||||
}
|
}
|
||||||
|
|
||||||
compareInfo, err := baseGitRepo.GetCompareInfo(pull.BaseRepo.RepoPath(),
|
compareInfo, err := baseGitRepo.GetCompareInfo(pull.BaseRepo.RepoPath(),
|
||||||
git.BranchPrefix+pull.BaseBranch, pull.GetGitRefName(), true)
|
git.BranchPrefix+pull.BaseBranch, pull.GetGitRefName(), true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "fatal: Not a valid object name") {
|
if strings.Contains(err.Error(), "fatal: Not a valid object name") {
|
||||||
ctx.Data["IsPullRequestBroken"] = true
|
ctx.Data["IsPullRequestBroken"] = true
|
||||||
|
@ -633,7 +633,7 @@ func ViewPullFiles(ctx *context.Context) {
|
||||||
ctx.Data["AfterCommitID"] = endCommitID
|
ctx.Data["AfterCommitID"] = endCommitID
|
||||||
|
|
||||||
diff, err := gitdiff.GetDiffRangeWithWhitespaceBehavior(gitRepo,
|
diff, err := gitdiff.GetDiffRangeWithWhitespaceBehavior(gitRepo,
|
||||||
startCommitID, endCommitID, setting.Git.MaxGitDiffLines,
|
startCommitID, endCommitID, ctx.FormString("skip-to"), setting.Git.MaxGitDiffLines,
|
||||||
setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles,
|
setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles,
|
||||||
gitdiff.GetWhitespaceFlag(ctx.Data["WhitespaceBehavior"].(string)), false)
|
gitdiff.GetWhitespaceFlag(ctx.Data["WhitespaceBehavior"].(string)), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -653,6 +653,7 @@ func getCommitFileLineCount(commit *git.Commit, filePath string) int {
|
||||||
|
|
||||||
// Diff represents a difference between two git trees.
|
// Diff represents a difference between two git trees.
|
||||||
type Diff struct {
|
type Diff struct {
|
||||||
|
Start, End string
|
||||||
NumFiles, TotalAddition, TotalDeletion int
|
NumFiles, TotalAddition, TotalDeletion int
|
||||||
Files []*DiffFile
|
Files []*DiffFile
|
||||||
IsIncomplete bool
|
IsIncomplete bool
|
||||||
|
@ -719,6 +720,9 @@ parsingLoop:
|
||||||
|
|
||||||
// TODO: Handle skipping first n files
|
// TODO: Handle skipping first n files
|
||||||
if len(diff.Files) >= maxFiles {
|
if len(diff.Files) >= maxFiles {
|
||||||
|
|
||||||
|
lastFile := createDiffFile(diff, line)
|
||||||
|
diff.End = lastFile.Name
|
||||||
diff.IsIncomplete = true
|
diff.IsIncomplete = true
|
||||||
_, err := io.Copy(io.Discard, reader)
|
_, err := io.Copy(io.Discard, reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1217,7 +1221,7 @@ func readFileName(rd *strings.Reader) (string, bool) {
|
||||||
// GetDiffRangeWithWhitespaceBehavior builds a Diff between two commits of a repository.
|
// GetDiffRangeWithWhitespaceBehavior builds a Diff between two commits of a repository.
|
||||||
// Passing the empty string as beforeCommitID returns a diff from the parent commit.
|
// Passing the empty string as beforeCommitID returns a diff from the parent commit.
|
||||||
// The whitespaceBehavior is either an empty string or a git flag
|
// The whitespaceBehavior is either an empty string or a git flag
|
||||||
func GetDiffRangeWithWhitespaceBehavior(gitRepo *git.Repository, beforeCommitID, afterCommitID string, maxLines, maxLineCharacters, maxFiles int, whitespaceBehavior string, directComparison bool) (*Diff, error) {
|
func GetDiffRangeWithWhitespaceBehavior(gitRepo *git.Repository, beforeCommitID, afterCommitID, skipTo string, maxLines, maxLineCharacters, maxFiles int, whitespaceBehavior string, directComparison bool) (*Diff, error) {
|
||||||
repoPath := gitRepo.Path
|
repoPath := gitRepo.Path
|
||||||
|
|
||||||
commit, err := gitRepo.GetCommit(afterCommitID)
|
commit, err := gitRepo.GetCommit(afterCommitID)
|
||||||
|
@ -1228,31 +1232,42 @@ func GetDiffRangeWithWhitespaceBehavior(gitRepo *git.Repository, beforeCommitID,
|
||||||
ctx, cancel := context.WithTimeout(git.DefaultContext, time.Duration(setting.Git.Timeout.Default)*time.Second)
|
ctx, cancel := context.WithTimeout(git.DefaultContext, time.Duration(setting.Git.Timeout.Default)*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
var cmd *exec.Cmd
|
argsLength := 6
|
||||||
|
if len(whitespaceBehavior) > 0 {
|
||||||
|
argsLength++
|
||||||
|
}
|
||||||
|
if len(skipTo) > 0 {
|
||||||
|
argsLength++
|
||||||
|
}
|
||||||
|
|
||||||
|
diffArgs := make([]string, 0, argsLength)
|
||||||
if (len(beforeCommitID) == 0 || beforeCommitID == git.EmptySHA) && commit.ParentCount() == 0 {
|
if (len(beforeCommitID) == 0 || beforeCommitID == git.EmptySHA) && commit.ParentCount() == 0 {
|
||||||
diffArgs := []string{"diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M"}
|
diffArgs = append(diffArgs, "diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M")
|
||||||
if len(whitespaceBehavior) != 0 {
|
if len(whitespaceBehavior) != 0 {
|
||||||
diffArgs = append(diffArgs, whitespaceBehavior)
|
diffArgs = append(diffArgs, whitespaceBehavior)
|
||||||
}
|
}
|
||||||
// append empty tree ref
|
// append empty tree ref
|
||||||
diffArgs = append(diffArgs, "4b825dc642cb6eb9a060e54bf8d69288fbee4904")
|
diffArgs = append(diffArgs, "4b825dc642cb6eb9a060e54bf8d69288fbee4904")
|
||||||
diffArgs = append(diffArgs, afterCommitID)
|
diffArgs = append(diffArgs, afterCommitID)
|
||||||
cmd = exec.CommandContext(ctx, git.GitExecutable, diffArgs...)
|
|
||||||
} else {
|
} else {
|
||||||
actualBeforeCommitID := beforeCommitID
|
actualBeforeCommitID := beforeCommitID
|
||||||
if len(actualBeforeCommitID) == 0 {
|
if len(actualBeforeCommitID) == 0 {
|
||||||
parentCommit, _ := commit.Parent(0)
|
parentCommit, _ := commit.Parent(0)
|
||||||
actualBeforeCommitID = parentCommit.ID.String()
|
actualBeforeCommitID = parentCommit.ID.String()
|
||||||
}
|
}
|
||||||
diffArgs := []string{"diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M"}
|
diffArgs = append(diffArgs, "diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M")
|
||||||
if len(whitespaceBehavior) != 0 {
|
if len(whitespaceBehavior) != 0 {
|
||||||
diffArgs = append(diffArgs, whitespaceBehavior)
|
diffArgs = append(diffArgs, whitespaceBehavior)
|
||||||
}
|
}
|
||||||
diffArgs = append(diffArgs, actualBeforeCommitID)
|
diffArgs = append(diffArgs, actualBeforeCommitID)
|
||||||
diffArgs = append(diffArgs, afterCommitID)
|
diffArgs = append(diffArgs, afterCommitID)
|
||||||
cmd = exec.CommandContext(ctx, git.GitExecutable, diffArgs...)
|
|
||||||
beforeCommitID = actualBeforeCommitID
|
beforeCommitID = actualBeforeCommitID
|
||||||
}
|
}
|
||||||
|
if skipTo != "" {
|
||||||
|
diffArgs = append(diffArgs, "--skip-to="+skipTo)
|
||||||
|
}
|
||||||
|
cmd := exec.CommandContext(ctx, git.GitExecutable, diffArgs...)
|
||||||
|
|
||||||
cmd.Dir = repoPath
|
cmd.Dir = repoPath
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
|
|
||||||
|
@ -1272,6 +1287,7 @@ func GetDiffRangeWithWhitespaceBehavior(gitRepo *git.Repository, beforeCommitID,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("ParsePatch: %v", err)
|
return nil, fmt.Errorf("ParsePatch: %v", err)
|
||||||
}
|
}
|
||||||
|
diff.Start = skipTo
|
||||||
|
|
||||||
var checker *git.CheckAttributeReader
|
var checker *git.CheckAttributeReader
|
||||||
|
|
||||||
|
@ -1299,7 +1315,7 @@ func GetDiffRangeWithWhitespaceBehavior(gitRepo *git.Repository, beforeCommitID,
|
||||||
log.Error("Unable to open checker for %s. Error: %v", afterCommitID, err)
|
log.Error("Unable to open checker for %s. Error: %v", afterCommitID, err)
|
||||||
} else {
|
} else {
|
||||||
go func() {
|
go func() {
|
||||||
err = checker.Run()
|
err := checker.Run()
|
||||||
if err != nil && err != ctx.Err() {
|
if err != nil && err != ctx.Err() {
|
||||||
log.Error("Unable to open checker for %s. Error: %v", afterCommitID, err)
|
log.Error("Unable to open checker for %s. Error: %v", afterCommitID, err)
|
||||||
}
|
}
|
||||||
|
@ -1382,8 +1398,8 @@ func GetDiffRangeWithWhitespaceBehavior(gitRepo *git.Repository, beforeCommitID,
|
||||||
|
|
||||||
// GetDiffCommitWithWhitespaceBehavior builds a Diff representing the given commitID.
|
// GetDiffCommitWithWhitespaceBehavior builds a Diff representing the given commitID.
|
||||||
// The whitespaceBehavior is either an empty string or a git flag
|
// The whitespaceBehavior is either an empty string or a git flag
|
||||||
func GetDiffCommitWithWhitespaceBehavior(gitRepo *git.Repository, commitID string, maxLines, maxLineCharacters, maxFiles int, whitespaceBehavior string, directComparison bool) (*Diff, error) {
|
func GetDiffCommitWithWhitespaceBehavior(gitRepo *git.Repository, commitID, skipTo string, maxLines, maxLineCharacters, maxFiles int, whitespaceBehavior string, directComparison bool) (*Diff, error) {
|
||||||
return GetDiffRangeWithWhitespaceBehavior(gitRepo, "", commitID, maxLines, maxLineCharacters, maxFiles, whitespaceBehavior, directComparison)
|
return GetDiffRangeWithWhitespaceBehavior(gitRepo, "", commitID, skipTo, maxLines, maxLineCharacters, maxFiles, whitespaceBehavior, directComparison)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommentAsDiff returns c.Patch as *Diff
|
// CommentAsDiff returns c.Patch as *Diff
|
||||||
|
|
|
@ -522,7 +522,7 @@ func TestGetDiffRangeWithWhitespaceBehavior(t *testing.T) {
|
||||||
}
|
}
|
||||||
defer gitRepo.Close()
|
defer gitRepo.Close()
|
||||||
for _, behavior := range []string{"-w", "--ignore-space-at-eol", "-b", ""} {
|
for _, behavior := range []string{"-w", "--ignore-space-at-eol", "-b", ""} {
|
||||||
diffs, err := GetDiffRangeWithWhitespaceBehavior(gitRepo, "559c156f8e0178b71cb44355428f24001b08fc68", "bd7063cc7c04689c4d082183d32a604ed27a24f9",
|
diffs, err := GetDiffRangeWithWhitespaceBehavior(gitRepo, "559c156f8e0178b71cb44355428f24001b08fc68", "bd7063cc7c04689c4d082183d32a604ed27a24f9", "",
|
||||||
setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffFiles, behavior, false)
|
setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffFiles, behavior, false)
|
||||||
assert.NoError(t, err, fmt.Sprintf("Error when diff with %s", behavior))
|
assert.NoError(t, err, fmt.Sprintf("Error when diff with %s", behavior))
|
||||||
for _, f := range diffs.Files {
|
for _, f := range diffs.Files {
|
||||||
|
|
|
@ -80,7 +80,7 @@ func NewPullRequest(repo *models.Repository, pull *models.Issue, labelIDs []int6
|
||||||
defer baseGitRepo.Close()
|
defer baseGitRepo.Close()
|
||||||
|
|
||||||
compareInfo, err := baseGitRepo.GetCompareInfo(pr.BaseRepo.RepoPath(),
|
compareInfo, err := baseGitRepo.GetCompareInfo(pr.BaseRepo.RepoPath(),
|
||||||
git.BranchPrefix+pr.BaseBranch, pr.GetGitRefName(), true)
|
git.BranchPrefix+pr.BaseBranch, pr.GetGitRefName(), true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,17 +42,25 @@
|
||||||
<a class="file mono" href="#diff-{{.Index}}">{{.Name}}</a>
|
<a class="file mono" href="#diff-{{.Index}}">{{.Name}}</a>
|
||||||
</li>
|
</li>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{if .Diff.IsIncomplete}}
|
||||||
|
<li id="diff-too-many-files-stats" class="pt-2">
|
||||||
|
<span class="file df ac sb">{{$.i18n.Tr "repo.diff.too_many_files"}}
|
||||||
|
<a class="ui basic tiny button" id="diff-show-more-files-stats" data-href="{{$.Link}}?skip-to={{.Diff.End}}&file-only=true">{{.i18n.Tr "repo.diff.show_more"}}</a>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
{{end}}
|
||||||
</ol>
|
</ol>
|
||||||
|
<div id="diff-file-boxes">
|
||||||
{{range $i, $file := .Diff.Files}}
|
{{range $i, $file := .Diff.Files}}
|
||||||
{{$blobBase := call $.GetBlobByPathForCommit $.BaseCommit $file.OldName}}
|
{{$blobBase := call $.GetBlobByPathForCommit $.BaseCommit $file.OldName}}
|
||||||
{{$blobHead := call $.GetBlobByPathForCommit $.HeadCommit $file.Name}}
|
{{$blobHead := call $.GetBlobByPathForCommit $.HeadCommit $file.Name}}
|
||||||
{{$isImage := or (call $.IsBlobAnImage $blobBase) (call $.IsBlobAnImage $blobHead)}}
|
{{$isImage := or (call $.IsBlobAnImage $blobBase) (call $.IsBlobAnImage $blobHead)}}
|
||||||
{{$isCsv := (call $.IsCsvFile $file)}}
|
{{$isCsv := (call $.IsCsvFile $file)}}
|
||||||
{{$showFileViewToggle := or $isImage (and (not $file.IsIncomplete) $isCsv)}}
|
{{$showFileViewToggle := or $isImage (and (not $file.IsIncomplete) $isCsv)}}
|
||||||
<div class="diff-file-box diff-box file-content {{TabSizeClass $.Editorconfig $file.Name}} mt-3" id="diff-{{.Index}}" {{if $file.IsGenerated}}data-folded="true"{{end}}>
|
<div class="diff-file-box diff-box file-content {{TabSizeClass $.Editorconfig $file.Name}} mt-3" id="diff-{{.Index}}" data-old-filename="{{$file.OldName}}" data-new-filename="{{$file.Name}}" {{if $file.IsGenerated}}data-folded="true"{{end}}>
|
||||||
<h4 class="diff-file-header sticky-2nd-row ui top attached normal header df ac sb">
|
<h4 class="diff-file-header sticky-2nd-row ui top attached normal header df ac sb">
|
||||||
<div class="fold-file df ac">
|
<div class="fold-file df ac">
|
||||||
<a role="button" class="chevron muted mr-2">
|
<a role="button" class="fold-file muted mr-2">
|
||||||
{{if $file.IsGenerated}}
|
{{if $file.IsGenerated}}
|
||||||
{{svg "octicon-chevron-right" 18}}
|
{{svg "octicon-chevron-right" 18}}
|
||||||
{{else}}
|
{{else}}
|
||||||
|
@ -135,12 +143,14 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{if .Diff.IsIncomplete}}
|
{{if .Diff.IsIncomplete}}
|
||||||
<div class="diff-file-box diff-box file-content mt-3">
|
<div class="diff-file-box diff-box file-content mt-3" id="diff-incomplete">
|
||||||
<h4 class="ui top attached normal header">
|
<h4 class="ui top attached normal header df ac sb">
|
||||||
{{$.i18n.Tr "repo.diff.too_many_files"}}
|
{{$.i18n.Tr "repo.diff.too_many_files"}}
|
||||||
|
<a class="ui basic tiny button" id="diff-show-more-files" data-href="{{$.Link}}?skip-to={{.Diff.End}}&file-only=true">{{.i18n.Tr "repo.diff.show_more"}}</a>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
</div>
|
||||||
|
|
||||||
{{if not $.Repository.IsArchived}}
|
{{if not $.Repository.IsArchived}}
|
||||||
<div class="hide" id="edit-content-form">
|
<div class="hide" id="edit-content-form">
|
||||||
|
|
24
web_src/js/features/diff.js
Normal file
24
web_src/js/features/diff.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
export function initDiffShowMore() {
|
||||||
|
$('#diff-files, #diff-file-boxes').on('click', '#diff-show-more-files, #diff-show-more-files-stats', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if ($(e.target).hasClass('disabled')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$('#diff-show-more-files, #diff-show-more-files-stats').addClass('disabled');
|
||||||
|
|
||||||
|
const url = $('#diff-show-more-files, #diff-show-more-files-stats').data('href');
|
||||||
|
$.ajax({
|
||||||
|
type: 'GET',
|
||||||
|
url,
|
||||||
|
}).done((resp) => {
|
||||||
|
if (!resp || resp.html === '' || resp.empty) {
|
||||||
|
$('#diff-show-more-files, #diff-show-more-files-stats').removeClass('disabled');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$('#diff-too-many-files-stats').remove();
|
||||||
|
$('#diff-files').append($(resp).find('#diff-files li'));
|
||||||
|
$('#diff-incomplete').replaceWith($(resp).find('#diff-file-boxes').children());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ import {initNotificationsTable, initNotificationCount} from './features/notifica
|
||||||
import {initLastCommitLoader} from './features/lastcommitloader.js';
|
import {initLastCommitLoader} from './features/lastcommitloader.js';
|
||||||
import {initIssueContentHistory} from './features/issue-content-history.js';
|
import {initIssueContentHistory} from './features/issue-content-history.js';
|
||||||
import {initStopwatch} from './features/stopwatch.js';
|
import {initStopwatch} from './features/stopwatch.js';
|
||||||
|
import {initDiffShowMore} from './features/diff.js';
|
||||||
import {showLineButton} from './code/linebutton.js';
|
import {showLineButton} from './code/linebutton.js';
|
||||||
import {initMarkupContent, initCommentContent} from './markup/content.js';
|
import {initMarkupContent, initCommentContent} from './markup/content.js';
|
||||||
import {stripTags, mqBinarySearch} from './utils.js';
|
import {stripTags, mqBinarySearch} from './utils.js';
|
||||||
|
@ -2881,6 +2882,7 @@ $(document).ready(async () => {
|
||||||
initFileViewToggle();
|
initFileViewToggle();
|
||||||
initReleaseEditor();
|
initReleaseEditor();
|
||||||
initRelease();
|
initRelease();
|
||||||
|
initDiffShowMore();
|
||||||
initIssueContentHistory();
|
initIssueContentHistory();
|
||||||
initAdminUserListSearchForm();
|
initAdminUserListSearchForm();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue