forked from NYANDEV/forgejo
Allow Loading of Diffs that are too large (#17739)
* Allow Loading of Diffs that are too large This PR allows the loading of diffs that are suppressed because the file is too large. It does not handle diffs of files which have lines which are too long. Fix #17738 Signed-off-by: Andrew Thornton <art27@cantab.net>
This commit is contained in:
parent
d710af6669
commit
8511eec4d4
8 changed files with 146 additions and 62 deletions
|
@ -2043,6 +2043,7 @@ 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 have 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.show_more = Show More
|
||||||
|
diff.load = Load Diff
|
||||||
diff.generated = generated
|
diff.generated = generated
|
||||||
diff.vendored = vendored
|
diff.vendored = vendored
|
||||||
diff.comment.placeholder = Leave a comment
|
diff.comment.placeholder = Leave a comment
|
||||||
|
|
|
@ -262,8 +262,6 @@ 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,13 +286,23 @@ func Diff(ctx *context.Context) {
|
||||||
commitID = commit.ID.String()
|
commitID = commit.ID.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
diff, err := gitdiff.GetDiffCommitWithWhitespaceBehavior(gitRepo,
|
fileOnly := ctx.FormBool("file-only")
|
||||||
commitID, ctx.FormString("skip-to"), setting.Git.MaxGitDiffLines,
|
maxLines, maxFiles := setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffFiles
|
||||||
setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles,
|
files := ctx.FormStrings("files")
|
||||||
gitdiff.GetWhitespaceFlag(ctx.Data["WhitespaceBehavior"].(string)),
|
if fileOnly && (len(files) == 2 || len(files) == 1) {
|
||||||
false)
|
maxLines, maxFiles = -1, -1
|
||||||
|
}
|
||||||
|
|
||||||
|
diff, err := gitdiff.GetDiff(gitRepo, &gitdiff.DiffOptions{
|
||||||
|
AfterCommitID: commitID,
|
||||||
|
SkipTo: ctx.FormString("skip-to"),
|
||||||
|
MaxLines: maxLines,
|
||||||
|
MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters,
|
||||||
|
MaxFiles: maxFiles,
|
||||||
|
WhitespaceBehavior: gitdiff.GetWhitespaceFlag(ctx.Data["WhitespaceBehavior"].(string)),
|
||||||
|
}, files...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.NotFound("GetDiffCommitWithWhitespaceBehavior", err)
|
ctx.NotFound("GetDiff", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,10 +333,6 @@ func Diff(ctx *context.Context) {
|
||||||
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
|
ctx.Data["Diff"] = diff
|
||||||
if fileOnly {
|
|
||||||
ctx.HTML(http.StatusOK, tplDiffBox)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
statuses, err := models.GetLatestCommitStatus(ctx.Repo.Repository.ID, commitID, db.ListOptions{})
|
statuses, err := models.GetLatestCommitStatus(ctx.Repo.Repository.ID, commitID, db.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -569,9 +569,23 @@ func PrepareCompareDiff(
|
||||||
beforeCommitID = ci.CompareInfo.BaseCommitID
|
beforeCommitID = ci.CompareInfo.BaseCommitID
|
||||||
}
|
}
|
||||||
|
|
||||||
diff, err := gitdiff.GetDiffRangeWithWhitespaceBehavior(ci.HeadGitRepo,
|
maxLines, maxFiles := setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffFiles
|
||||||
beforeCommitID, headCommitID, ctx.FormString("skip-to"), setting.Git.MaxGitDiffLines,
|
files := ctx.FormStrings("files")
|
||||||
setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, whitespaceBehavior, ci.DirectComparison)
|
if len(files) == 2 || len(files) == 1 {
|
||||||
|
maxLines, maxFiles = -1, -1
|
||||||
|
}
|
||||||
|
|
||||||
|
diff, err := gitdiff.GetDiff(ci.HeadGitRepo,
|
||||||
|
&gitdiff.DiffOptions{
|
||||||
|
BeforeCommitID: beforeCommitID,
|
||||||
|
AfterCommitID: headCommitID,
|
||||||
|
SkipTo: ctx.FormString("skip-to"),
|
||||||
|
MaxLines: maxLines,
|
||||||
|
MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters,
|
||||||
|
MaxFiles: maxFiles,
|
||||||
|
WhitespaceBehavior: whitespaceBehavior,
|
||||||
|
DirectComparison: ci.DirectComparison,
|
||||||
|
}, ctx.FormStrings("files")...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetDiffRangeWithWhitespaceBehavior", err)
|
ctx.ServerError("GetDiffRangeWithWhitespaceBehavior", err)
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -633,10 +633,24 @@ func ViewPullFiles(ctx *context.Context) {
|
||||||
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
|
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
|
||||||
ctx.Data["AfterCommitID"] = endCommitID
|
ctx.Data["AfterCommitID"] = endCommitID
|
||||||
|
|
||||||
diff, err := gitdiff.GetDiffRangeWithWhitespaceBehavior(gitRepo,
|
fileOnly := ctx.FormBool("file-only")
|
||||||
startCommitID, endCommitID, ctx.FormString("skip-to"), setting.Git.MaxGitDiffLines,
|
|
||||||
setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles,
|
maxLines, maxFiles := setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffFiles
|
||||||
gitdiff.GetWhitespaceFlag(ctx.Data["WhitespaceBehavior"].(string)), false)
|
files := ctx.FormStrings("files")
|
||||||
|
if fileOnly && (len(files) == 2 || len(files) == 1) {
|
||||||
|
maxLines, maxFiles = -1, -1
|
||||||
|
}
|
||||||
|
|
||||||
|
diff, err := gitdiff.GetDiff(gitRepo,
|
||||||
|
&gitdiff.DiffOptions{
|
||||||
|
BeforeCommitID: startCommitID,
|
||||||
|
AfterCommitID: endCommitID,
|
||||||
|
SkipTo: ctx.FormString("skip-to"),
|
||||||
|
MaxLines: maxLines,
|
||||||
|
MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters,
|
||||||
|
MaxFiles: maxFiles,
|
||||||
|
WhitespaceBehavior: gitdiff.GetWhitespaceFlag(ctx.Data["WhitespaceBehavior"].(string)),
|
||||||
|
}, ctx.FormStrings("files")...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.ServerError("GetDiffRangeWithWhitespaceBehavior", err)
|
ctx.ServerError("GetDiffRangeWithWhitespaceBehavior", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -695,6 +695,7 @@ const cmdDiffHead = "diff --git "
|
||||||
|
|
||||||
// ParsePatch builds a Diff object from a io.Reader and some parameters.
|
// ParsePatch builds a Diff object from a io.Reader and some parameters.
|
||||||
func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader, skipToFile string) (*Diff, error) {
|
func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader, skipToFile string) (*Diff, error) {
|
||||||
|
log.Debug("ParsePatch(%d, %d, %d, ..., %s)", maxLines, maxLineCharacters, maxFiles, skipToFile)
|
||||||
var curFile *DiffFile
|
var curFile *DiffFile
|
||||||
|
|
||||||
skipping := skipToFile != ""
|
skipping := skipToFile != ""
|
||||||
|
@ -726,7 +727,7 @@ parsingLoop:
|
||||||
return diff, fmt.Errorf("invalid first file line: %s", line)
|
return diff, fmt.Errorf("invalid first file line: %s", line)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(diff.Files) >= maxFiles {
|
if maxFiles > -1 && len(diff.Files) >= maxFiles {
|
||||||
lastFile := createDiffFile(diff, line)
|
lastFile := createDiffFile(diff, line)
|
||||||
diff.End = lastFile.Name
|
diff.End = lastFile.Name
|
||||||
diff.IsIncomplete = true
|
diff.IsIncomplete = true
|
||||||
|
@ -1038,7 +1039,7 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
|
||||||
|
|
||||||
switch lineBytes[0] {
|
switch lineBytes[0] {
|
||||||
case '@':
|
case '@':
|
||||||
if curFileLinesCount >= maxLines {
|
if maxLines > -1 && curFileLinesCount >= maxLines {
|
||||||
curFile.IsIncomplete = true
|
curFile.IsIncomplete = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -1075,7 +1076,7 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
|
||||||
rightLine = lineSectionInfo.RightIdx
|
rightLine = lineSectionInfo.RightIdx
|
||||||
continue
|
continue
|
||||||
case '\\':
|
case '\\':
|
||||||
if curFileLinesCount >= maxLines {
|
if maxLines > -1 && curFileLinesCount >= maxLines {
|
||||||
curFile.IsIncomplete = true
|
curFile.IsIncomplete = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -1090,7 +1091,7 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
|
||||||
case '+':
|
case '+':
|
||||||
curFileLinesCount++
|
curFileLinesCount++
|
||||||
curFile.Addition++
|
curFile.Addition++
|
||||||
if curFileLinesCount >= maxLines {
|
if maxLines > -1 && curFileLinesCount >= maxLines {
|
||||||
curFile.IsIncomplete = true
|
curFile.IsIncomplete = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -1114,7 +1115,7 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
|
||||||
case '-':
|
case '-':
|
||||||
curFileLinesCount++
|
curFileLinesCount++
|
||||||
curFile.Deletion++
|
curFile.Deletion++
|
||||||
if curFileLinesCount >= maxLines {
|
if maxLines > -1 && curFileLinesCount >= maxLines {
|
||||||
curFile.IsIncomplete = true
|
curFile.IsIncomplete = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -1134,7 +1135,7 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio
|
||||||
curSection.Lines = append(curSection.Lines, diffLine)
|
curSection.Lines = append(curSection.Lines, diffLine)
|
||||||
case ' ':
|
case ' ':
|
||||||
curFileLinesCount++
|
curFileLinesCount++
|
||||||
if curFileLinesCount >= maxLines {
|
if maxLines > -1 && curFileLinesCount >= maxLines {
|
||||||
curFile.IsIncomplete = true
|
curFile.IsIncomplete = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -1278,13 +1279,25 @@ func readFileName(rd *strings.Reader) (string, bool) {
|
||||||
return name[2:], ambiguity
|
return name[2:], ambiguity
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDiffRangeWithWhitespaceBehavior builds a Diff between two commits of a repository.
|
// DiffOptions represents the options for a DiffRange
|
||||||
|
type DiffOptions struct {
|
||||||
|
BeforeCommitID string
|
||||||
|
AfterCommitID string
|
||||||
|
SkipTo string
|
||||||
|
MaxLines int
|
||||||
|
MaxLineCharacters int
|
||||||
|
MaxFiles int
|
||||||
|
WhitespaceBehavior string
|
||||||
|
DirectComparison bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetDiff 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, skipTo string, maxLines, maxLineCharacters, maxFiles int, whitespaceBehavior string, directComparison bool) (*Diff, error) {
|
func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff, error) {
|
||||||
repoPath := gitRepo.Path
|
repoPath := gitRepo.Path
|
||||||
|
|
||||||
commit, err := gitRepo.GetCommit(afterCommitID)
|
commit, err := gitRepo.GetCommit(opts.AfterCommitID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -1293,45 +1306,54 @@ func GetDiffRangeWithWhitespaceBehavior(gitRepo *git.Repository, beforeCommitID,
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
argsLength := 6
|
argsLength := 6
|
||||||
if len(whitespaceBehavior) > 0 {
|
if len(opts.WhitespaceBehavior) > 0 {
|
||||||
argsLength++
|
argsLength++
|
||||||
}
|
}
|
||||||
if len(skipTo) > 0 {
|
if len(opts.SkipTo) > 0 {
|
||||||
argsLength++
|
argsLength++
|
||||||
}
|
}
|
||||||
|
if len(files) > 0 {
|
||||||
|
argsLength += len(files) + 1
|
||||||
|
}
|
||||||
|
|
||||||
diffArgs := make([]string, 0, argsLength)
|
diffArgs := make([]string, 0, argsLength)
|
||||||
if (len(beforeCommitID) == 0 || beforeCommitID == git.EmptySHA) && commit.ParentCount() == 0 {
|
if (len(opts.BeforeCommitID) == 0 || opts.BeforeCommitID == git.EmptySHA) && commit.ParentCount() == 0 {
|
||||||
diffArgs = append(diffArgs, "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(opts.WhitespaceBehavior) != 0 {
|
||||||
diffArgs = append(diffArgs, whitespaceBehavior)
|
diffArgs = append(diffArgs, opts.WhitespaceBehavior)
|
||||||
}
|
}
|
||||||
// append empty tree ref
|
// append empty tree ref
|
||||||
diffArgs = append(diffArgs, "4b825dc642cb6eb9a060e54bf8d69288fbee4904")
|
diffArgs = append(diffArgs, "4b825dc642cb6eb9a060e54bf8d69288fbee4904")
|
||||||
diffArgs = append(diffArgs, afterCommitID)
|
diffArgs = append(diffArgs, opts.AfterCommitID)
|
||||||
} else {
|
} else {
|
||||||
actualBeforeCommitID := beforeCommitID
|
actualBeforeCommitID := opts.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 = append(diffArgs, "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(opts.WhitespaceBehavior) != 0 {
|
||||||
diffArgs = append(diffArgs, whitespaceBehavior)
|
diffArgs = append(diffArgs, opts.WhitespaceBehavior)
|
||||||
}
|
}
|
||||||
diffArgs = append(diffArgs, actualBeforeCommitID)
|
diffArgs = append(diffArgs, actualBeforeCommitID)
|
||||||
diffArgs = append(diffArgs, afterCommitID)
|
diffArgs = append(diffArgs, opts.AfterCommitID)
|
||||||
beforeCommitID = actualBeforeCommitID
|
opts.BeforeCommitID = actualBeforeCommitID
|
||||||
}
|
}
|
||||||
|
|
||||||
// In git 2.31, git diff learned --skip-to which we can use to shortcut skip to file
|
// In git 2.31, git diff learned --skip-to which we can use to shortcut skip to file
|
||||||
// so if we are using at least this version of git we don't have to tell ParsePatch to do
|
// so if we are using at least this version of git we don't have to tell ParsePatch to do
|
||||||
// the skipping for us
|
// the skipping for us
|
||||||
parsePatchSkipToFile := skipTo
|
parsePatchSkipToFile := opts.SkipTo
|
||||||
if skipTo != "" && git.CheckGitVersionAtLeast("2.31") == nil {
|
if opts.SkipTo != "" && git.CheckGitVersionAtLeast("2.31") == nil {
|
||||||
diffArgs = append(diffArgs, "--skip-to="+skipTo)
|
diffArgs = append(diffArgs, "--skip-to="+opts.SkipTo)
|
||||||
parsePatchSkipToFile = ""
|
parsePatchSkipToFile = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(files) > 0 {
|
||||||
|
diffArgs = append(diffArgs, "--")
|
||||||
|
diffArgs = append(diffArgs, files...)
|
||||||
|
}
|
||||||
|
|
||||||
cmd := exec.CommandContext(ctx, git.GitExecutable, diffArgs...)
|
cmd := exec.CommandContext(ctx, git.GitExecutable, diffArgs...)
|
||||||
|
|
||||||
cmd.Dir = repoPath
|
cmd.Dir = repoPath
|
||||||
|
@ -1349,16 +1371,16 @@ func GetDiffRangeWithWhitespaceBehavior(gitRepo *git.Repository, beforeCommitID,
|
||||||
pid := process.GetManager().Add(fmt.Sprintf("GetDiffRange [repo_path: %s]", repoPath), cancel)
|
pid := process.GetManager().Add(fmt.Sprintf("GetDiffRange [repo_path: %s]", repoPath), cancel)
|
||||||
defer process.GetManager().Remove(pid)
|
defer process.GetManager().Remove(pid)
|
||||||
|
|
||||||
diff, err := ParsePatch(maxLines, maxLineCharacters, maxFiles, stdout, parsePatchSkipToFile)
|
diff, err := ParsePatch(opts.MaxLines, opts.MaxLineCharacters, opts.MaxFiles, stdout, parsePatchSkipToFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to ParsePatch: %w", err)
|
return nil, fmt.Errorf("unable to ParsePatch: %w", err)
|
||||||
}
|
}
|
||||||
diff.Start = skipTo
|
diff.Start = opts.SkipTo
|
||||||
|
|
||||||
var checker *git.CheckAttributeReader
|
var checker *git.CheckAttributeReader
|
||||||
|
|
||||||
if git.CheckGitVersionAtLeast("1.7.8") == nil {
|
if git.CheckGitVersionAtLeast("1.7.8") == nil {
|
||||||
indexFilename, worktree, deleteTemporaryFile, err := gitRepo.ReadTreeToTemporaryIndex(afterCommitID)
|
indexFilename, worktree, deleteTemporaryFile, err := gitRepo.ReadTreeToTemporaryIndex(opts.AfterCommitID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
defer deleteTemporaryFile()
|
defer deleteTemporaryFile()
|
||||||
|
|
||||||
|
@ -1370,12 +1392,12 @@ func GetDiffRangeWithWhitespaceBehavior(gitRepo *git.Repository, beforeCommitID,
|
||||||
}
|
}
|
||||||
ctx, cancel := context.WithCancel(git.DefaultContext)
|
ctx, cancel := context.WithCancel(git.DefaultContext)
|
||||||
if err := checker.Init(ctx); err != nil {
|
if err := checker.Init(ctx); err != nil {
|
||||||
log.Error("Unable to open checker for %s. Error: %v", afterCommitID, err)
|
log.Error("Unable to open checker for %s. Error: %v", opts.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", opts.AfterCommitID, err)
|
||||||
}
|
}
|
||||||
cancel()
|
cancel()
|
||||||
}()
|
}()
|
||||||
|
@ -1426,7 +1448,7 @@ func GetDiffRangeWithWhitespaceBehavior(gitRepo *git.Repository, beforeCommitID,
|
||||||
diffFile.IsGenerated = analyze.IsGenerated(diffFile.Name)
|
diffFile.IsGenerated = analyze.IsGenerated(diffFile.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
tailSection := diffFile.GetTailSection(gitRepo, beforeCommitID, afterCommitID)
|
tailSection := diffFile.GetTailSection(gitRepo, opts.BeforeCommitID, opts.AfterCommitID)
|
||||||
if tailSection != nil {
|
if tailSection != nil {
|
||||||
diffFile.Sections = append(diffFile.Sections, tailSection)
|
diffFile.Sections = append(diffFile.Sections, tailSection)
|
||||||
}
|
}
|
||||||
|
@ -1437,19 +1459,19 @@ func GetDiffRangeWithWhitespaceBehavior(gitRepo *git.Repository, beforeCommitID,
|
||||||
}
|
}
|
||||||
|
|
||||||
separator := "..."
|
separator := "..."
|
||||||
if directComparison {
|
if opts.DirectComparison {
|
||||||
separator = ".."
|
separator = ".."
|
||||||
}
|
}
|
||||||
|
|
||||||
shortstatArgs := []string{beforeCommitID + separator + afterCommitID}
|
shortstatArgs := []string{opts.BeforeCommitID + separator + opts.AfterCommitID}
|
||||||
if len(beforeCommitID) == 0 || beforeCommitID == git.EmptySHA {
|
if len(opts.BeforeCommitID) == 0 || opts.BeforeCommitID == git.EmptySHA {
|
||||||
shortstatArgs = []string{git.EmptyTreeSHA, afterCommitID}
|
shortstatArgs = []string{git.EmptyTreeSHA, opts.AfterCommitID}
|
||||||
}
|
}
|
||||||
diff.NumFiles, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(repoPath, shortstatArgs...)
|
diff.NumFiles, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(repoPath, shortstatArgs...)
|
||||||
if err != nil && strings.Contains(err.Error(), "no merge base") {
|
if err != nil && strings.Contains(err.Error(), "no merge base") {
|
||||||
// git >= 2.28 now returns an error if base and head have become unrelated.
|
// git >= 2.28 now returns an error if base and head have become unrelated.
|
||||||
// previously it would return the results of git diff --shortstat base head so let's try that...
|
// previously it would return the results of git diff --shortstat base head so let's try that...
|
||||||
shortstatArgs = []string{beforeCommitID, afterCommitID}
|
shortstatArgs = []string{opts.BeforeCommitID, opts.AfterCommitID}
|
||||||
diff.NumFiles, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(repoPath, shortstatArgs...)
|
diff.NumFiles, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(repoPath, shortstatArgs...)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1459,12 +1481,6 @@ func GetDiffRangeWithWhitespaceBehavior(gitRepo *git.Repository, beforeCommitID,
|
||||||
return diff, nil
|
return diff, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDiffCommitWithWhitespaceBehavior builds a Diff representing the given commitID.
|
|
||||||
// The whitespaceBehavior is either an empty string or a git flag
|
|
||||||
func GetDiffCommitWithWhitespaceBehavior(gitRepo *git.Repository, commitID, skipTo string, maxLines, maxLineCharacters, maxFiles int, whitespaceBehavior string, directComparison bool) (*Diff, error) {
|
|
||||||
return GetDiffRangeWithWhitespaceBehavior(gitRepo, "", commitID, skipTo, maxLines, maxLineCharacters, maxFiles, whitespaceBehavior, directComparison)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CommentAsDiff returns c.Patch as *Diff
|
// CommentAsDiff returns c.Patch as *Diff
|
||||||
func CommentAsDiff(c *models.Comment) (*Diff, error) {
|
func CommentAsDiff(c *models.Comment) (*Diff, error) {
|
||||||
diff, err := ParsePatch(setting.Git.MaxGitDiffLines,
|
diff, err := ParsePatch(setting.Git.MaxGitDiffLines,
|
||||||
|
|
|
@ -693,8 +693,15 @@ 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 := GetDiff(gitRepo,
|
||||||
setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffFiles, behavior, false)
|
&DiffOptions{
|
||||||
|
AfterCommitID: "bd7063cc7c04689c4d082183d32a604ed27a24f9",
|
||||||
|
BeforeCommitID: "559c156f8e0178b71cb44355428f24001b08fc68",
|
||||||
|
MaxLines: setting.Git.MaxGitDiffLines,
|
||||||
|
MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters,
|
||||||
|
MaxFiles: setting.Git.MaxGitDiffFiles,
|
||||||
|
WhitespaceBehavior: behavior,
|
||||||
|
})
|
||||||
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 {
|
||||||
assert.True(t, len(f.Sections) > 0, fmt.Sprintf("%s should have sections", f.Name))
|
assert.True(t, len(f.Sections) > 0, fmt.Sprintf("%s should have sections", f.Name))
|
||||||
|
|
|
@ -112,6 +112,7 @@
|
||||||
{{$.i18n.Tr "repo.diff.file_suppressed_line_too_long"}}
|
{{$.i18n.Tr "repo.diff.file_suppressed_line_too_long"}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{$.i18n.Tr "repo.diff.file_suppressed"}}
|
{{$.i18n.Tr "repo.diff.file_suppressed"}}
|
||||||
|
<a class="ui basic tiny button diff-show-more-button" data-href="{{$.Link}}?file-only=true&files={{$file.Name}}&files={{$file.OldName}}">{{$.i18n.Tr "repo.diff.load"}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{$.i18n.Tr "repo.diff.bin_not_shown"}}
|
{{$.i18n.Tr "repo.diff.bin_not_shown"}}
|
||||||
|
|
|
@ -94,13 +94,40 @@ export function initRepoDiffShowMore() {
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
url,
|
url,
|
||||||
}).done((resp) => {
|
}).done((resp) => {
|
||||||
if (!resp || resp.html === '' || resp.empty) {
|
if (!resp) {
|
||||||
$('#diff-show-more-files, #diff-show-more-files-stats').removeClass('disabled');
|
$('#diff-show-more-files, #diff-show-more-files-stats').removeClass('disabled');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$('#diff-too-many-files-stats').remove();
|
$('#diff-too-many-files-stats').remove();
|
||||||
$('#diff-files').append($(resp).find('#diff-files li'));
|
$('#diff-files').append($(resp).find('#diff-files li'));
|
||||||
$('#diff-incomplete').replaceWith($(resp).find('#diff-file-boxes').children());
|
$('#diff-incomplete').replaceWith($(resp).find('#diff-file-boxes').children());
|
||||||
|
}).fail(() => {
|
||||||
|
$('#diff-show-more-files, #diff-show-more-files-stats').removeClass('disabled');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
$(document).on('click', 'a.diff-show-more-button', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const $target = $(e.target);
|
||||||
|
|
||||||
|
if ($target.hasClass('disabled')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$target.addClass('disabled');
|
||||||
|
|
||||||
|
const url = $target.data('href');
|
||||||
|
$.ajax({
|
||||||
|
type: 'GET',
|
||||||
|
url,
|
||||||
|
}).done((resp) => {
|
||||||
|
if (!resp) {
|
||||||
|
$target.removeClass('disabled');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$target.parent().replaceWith($(resp).find('#diff-file-boxes .diff-file-body .file-body').children());
|
||||||
|
}).fail(() => {
|
||||||
|
$target.removeClass('disabled');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue