}
// 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 (
remoteBranch string
tmpRemote string
}
// We have a common base - therefore we know that ... should work
- logs, err := NewCommand("log", baseCommitID+separator+headBranch, prettyLogFormat).RunInDirBytes(repo.Path)
- if err != nil {
- return nil, err
- }
- compareInfo.Commits, err = repo.parsePrettyFormatLogToList(logs)
- if err != nil {
- return nil, fmt.Errorf("parsePrettyFormatLogToList: %v", err)
+ if !fileOnly {
+ logs, err := NewCommand("log", baseCommitID+separator+headBranch, prettyLogFormat).RunInDirBytes(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+ compareInfo.Commits, err = repo.parsePrettyFormatLogToList(logs)
+ if err != nil {
+ return nil, fmt.Errorf("parsePrettyFormatLogToList: %v", err)
+ }
+ } else {
+ compareInfo.Commits = []*Commit{}
}
} else {
compareInfo.Commits = []*Commit{}
diff.file_byte_size = Size
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.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.vendored = vendored
diff.comment.placeholder = Leave a comment
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 {
headGitRepo.Close()
ctx.Error(http.StatusInternalServerError, "GetCompareInfo", err)
}
defer baseGitRepo.Close()
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 {
- 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 {
ctx.ServerError("GetCompareInfo", err)
err error
)
+ fileOnly := ctx.FormBool("file-only")
+
if ctx.Data["PageIsWiki"] != nil {
gitRepo, err = git.OpenRepository(ctx.Repo.Repository.WikiPath())
if err != nil {
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,
- commitID, setting.Git.MaxGitDiffLines,
+ commitID, ctx.FormString("skip-to"), setting.Git.MaxGitDiffLines,
setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles,
gitdiff.GetWhitespaceFlag(ctx.Data["WhitespaceBehavior"].(string)),
false)
setCompareContext(ctx, parentCommit, commit, headTarget)
ctx.Data["Title"] = commit.Summary() + " ยท " + base.ShortSha(commitID)
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)
ctx.Data["Verification"] = verification
ctx.Data["Author"] = models.ValidateCommitWithEmail(commit)
- ctx.Data["Diff"] = diff
ctx.Data["Parents"] = parents
ctx.Data["DiffNotAvailable"] = diff.NumFiles == 0
const (
tplCompare base.TplName = "repo/diff/compare"
tplBlobExcerpt base.TplName = "repo/diff/blob_excerpt"
+ tplDiffBox base.TplName = "repo/diff/box"
)
// setCompareContext sets context data.
baseRepo := ctx.Repo.Repository
ci := &CompareInfo{}
+ fileOnly := ctx.FormBool("file-only")
+
// Get compared branches information
// A full compare url is of the form:
//
if rootRepo != nil &&
rootRepo.ID != ci.HeadRepo.ID &&
rootRepo.ID != baseRepo.ID {
- perm, branches, tags, err := getBranchesAndTagsForRepo(ctx.User, rootRepo)
- if err != nil {
- ctx.ServerError("GetBranchesForRepo", err)
- return nil
- }
- if perm {
+ canRead := rootRepo.CheckUnitUser(ctx.User, models.UnitTypeCode)
+ if canRead {
ctx.Data["RootRepo"] = rootRepo
- ctx.Data["RootRepoBranches"] = branches
- ctx.Data["RootRepoTags"] = tags
+ if !fileOnly {
+ branches, tags, err := getBranchesAndTagsForRepo(ctx.User, rootRepo)
+ if err != nil {
+ ctx.ServerError("GetBranchesForRepo", err)
+ return nil
+ }
+
+ ctx.Data["RootRepoBranches"] = branches
+ ctx.Data["RootRepoTags"] = tags
+ }
}
}
ownForkRepo.ID != ci.HeadRepo.ID &&
ownForkRepo.ID != baseRepo.ID &&
(rootRepo == nil || ownForkRepo.ID != rootRepo.ID) {
- perm, branches, tags, err := getBranchesAndTagsForRepo(ctx.User, ownForkRepo)
- if err != nil {
- ctx.ServerError("GetBranchesForRepo", err)
- return nil
- }
- if perm {
+ canRead := ownForkRepo.CheckUnitUser(ctx.User, models.UnitTypeCode)
+ if canRead {
ctx.Data["OwnForkRepo"] = ownForkRepo
- ctx.Data["OwnForkRepoBranches"] = branches
- ctx.Data["OwnForkRepoTags"] = tags
+ if !fileOnly {
+ branches, tags, err := getBranchesAndTagsForRepo(ctx.User, ownForkRepo)
+ if err != nil {
+ ctx.ServerError("GetBranchesForRepo", err)
+ return nil
+ }
+ ctx.Data["OwnForkRepoBranches"] = branches
+ ctx.Data["OwnForkRepoTags"] = tags
+ }
}
}
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 {
ctx.ServerError("GetCompareInfo", err)
return nil
}
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)
if err != nil {
ctx.ServerError("GetDiffRangeWithWhitespaceBehavior", err)
return false
}
-func getBranchesAndTagsForRepo(user *models.User, repo *models.Repository) (bool, []string, []string, 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
- }
+func getBranchesAndTagsForRepo(user *models.User, repo *models.Repository) (branches, tags []string, err error) {
gitRepo, err := git.OpenRepository(repo.RepoPath())
if err != nil {
- return false, nil, nil, err
+ return nil, nil, err
}
defer gitRepo.Close()
- branches, _, err := gitRepo.GetBranches(0, 0)
+ branches, _, err = gitRepo.GetBranches(0, 0)
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 {
- 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
}
ctx.Data["Tags"] = baseTags
+ fileOnly := ctx.FormBool("file-only")
+ if fileOnly {
+ ctx.HTML(http.StatusOK, tplDiffBox)
+ return
+ }
+
headBranches, _, err := ci.HeadGitRepo.GetBranches(0, 0)
if err != nil {
ctx.ServerError("GetBranches", err)
ctx.Data["HasMerged"] = true
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 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
}
compareInfo, err := baseGitRepo.GetCompareInfo(pull.BaseRepo.RepoPath(),
- pull.MergeBase, pull.GetGitRefName(), true)
+ pull.MergeBase, pull.GetGitRefName(), true, false)
if err != nil {
if strings.Contains(err.Error(), "fatal: Not a valid object name") {
ctx.Data["IsPullRequestBroken"] = true
}
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 strings.Contains(err.Error(), "fatal: Not a valid object name") {
ctx.Data["IsPullRequestBroken"] = true
ctx.Data["AfterCommitID"] = endCommitID
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,
gitdiff.GetWhitespaceFlag(ctx.Data["WhitespaceBehavior"].(string)), false)
if err != nil {
// Diff represents a difference between two git trees.
type Diff struct {
+ Start, End string
NumFiles, TotalAddition, TotalDeletion int
Files []*DiffFile
IsIncomplete bool
// TODO: Handle skipping first n files
if len(diff.Files) >= maxFiles {
+
+ lastFile := createDiffFile(diff, line)
+ diff.End = lastFile.Name
diff.IsIncomplete = true
_, err := io.Copy(io.Discard, reader)
if err != nil {
// GetDiffRangeWithWhitespaceBehavior builds a Diff between two commits of a repository.
// Passing the empty string as beforeCommitID returns a diff from the parent commit.
// 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
commit, err := gitRepo.GetCommit(afterCommitID)
ctx, cancel := context.WithTimeout(git.DefaultContext, time.Duration(setting.Git.Timeout.Default)*time.Second)
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 {
- 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 {
diffArgs = append(diffArgs, whitespaceBehavior)
}
// append empty tree ref
diffArgs = append(diffArgs, "4b825dc642cb6eb9a060e54bf8d69288fbee4904")
diffArgs = append(diffArgs, afterCommitID)
- cmd = exec.CommandContext(ctx, git.GitExecutable, diffArgs...)
} else {
actualBeforeCommitID := beforeCommitID
if len(actualBeforeCommitID) == 0 {
parentCommit, _ := commit.Parent(0)
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 {
diffArgs = append(diffArgs, whitespaceBehavior)
}
diffArgs = append(diffArgs, actualBeforeCommitID)
diffArgs = append(diffArgs, afterCommitID)
- cmd = exec.CommandContext(ctx, git.GitExecutable, diffArgs...)
beforeCommitID = actualBeforeCommitID
}
+ if skipTo != "" {
+ diffArgs = append(diffArgs, "--skip-to="+skipTo)
+ }
+ cmd := exec.CommandContext(ctx, git.GitExecutable, diffArgs...)
+
cmd.Dir = repoPath
cmd.Stderr = os.Stderr
if err != nil {
return nil, fmt.Errorf("ParsePatch: %v", err)
}
+ diff.Start = skipTo
var checker *git.CheckAttributeReader
log.Error("Unable to open checker for %s. Error: %v", afterCommitID, err)
} else {
go func() {
- err = checker.Run()
+ err := checker.Run()
if err != nil && err != ctx.Err() {
log.Error("Unable to open checker for %s. Error: %v", afterCommitID, err)
}
// 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 string, maxLines, maxLineCharacters, maxFiles int, whitespaceBehavior string, directComparison bool) (*Diff, error) {
- return GetDiffRangeWithWhitespaceBehavior(gitRepo, "", commitID, maxLines, maxLineCharacters, maxFiles, whitespaceBehavior, directComparison)
+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
}
defer gitRepo.Close()
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)
assert.NoError(t, err, fmt.Sprintf("Error when diff with %s", behavior))
for _, f := range diffs.Files {
defer baseGitRepo.Close()
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 {
return err
}
<a class="file mono" href="#diff-{{.Index}}">{{.Name}}</a>
</li>
{{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>
- {{range $i, $file := .Diff.Files}}
- {{$blobBase := call $.GetBlobByPathForCommit $.BaseCommit $file.OldName}}
- {{$blobHead := call $.GetBlobByPathForCommit $.HeadCommit $file.Name}}
- {{$isImage := or (call $.IsBlobAnImage $blobBase) (call $.IsBlobAnImage $blobHead)}}
- {{$isCsv := (call $.IsCsvFile $file)}}
- {{$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}}>
- <h4 class="diff-file-header sticky-2nd-row ui top attached normal header df ac sb">
- <div class="fold-file df ac">
- <a role="button" class="chevron muted mr-2">
+ <div id="diff-file-boxes">
+ {{range $i, $file := .Diff.Files}}
+ {{$blobBase := call $.GetBlobByPathForCommit $.BaseCommit $file.OldName}}
+ {{$blobHead := call $.GetBlobByPathForCommit $.HeadCommit $file.Name}}
+ {{$isImage := or (call $.IsBlobAnImage $blobBase) (call $.IsBlobAnImage $blobHead)}}
+ {{$isCsv := (call $.IsCsvFile $file)}}
+ {{$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}}" 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">
+ <div class="fold-file df ac">
+ <a role="button" class="fold-file muted mr-2">
+ {{if $file.IsGenerated}}
+ {{svg "octicon-chevron-right" 18}}
+ {{else}}
+ {{svg "octicon-chevron-down" 18}}
+ {{end}}
+ </a>
+ <div class="bold df ac">
+ {{if $file.IsBin}}
+ <span class="ml-1 mr-3">
+ {{$.i18n.Tr "repo.diff.bin"}}
+ </span>
+ {{else}}
+ {{template "repo/diff/stats" dict "file" . "root" $}}
+ {{end}}
+ </div>
+ <span class="file mono">{{if $file.IsRenamed}}{{$file.OldName}} → {{end}}{{$file.Name}}{{if .IsLFSFile}} ({{$.i18n.Tr "repo.stored_lfs"}}){{end}}</span>
{{if $file.IsGenerated}}
- {{svg "octicon-chevron-right" 18}}
- {{else}}
- {{svg "octicon-chevron-down" 18}}
+ <span class="ui label ml-3">{{$.i18n.Tr "repo.diff.generated"}}</span>
{{end}}
- </a>
- <div class="bold df ac">
- {{if $file.IsBin}}
- <span class="ml-1 mr-3">
- {{$.i18n.Tr "repo.diff.bin"}}
- </span>
- {{else}}
- {{template "repo/diff/stats" dict "file" . "root" $}}
+ {{if $file.IsVendored}}
+ <span class="ui label ml-3">{{$.i18n.Tr "repo.diff.vendored"}}</span>
{{end}}
</div>
- <span class="file mono">{{if $file.IsRenamed}}{{$file.OldName}} → {{end}}{{$file.Name}}{{if .IsLFSFile}} ({{$.i18n.Tr "repo.stored_lfs"}}){{end}}</span>
- {{if $file.IsGenerated}}
- <span class="ui label ml-3">{{$.i18n.Tr "repo.diff.generated"}}</span>
- {{end}}
- {{if $file.IsVendored}}
- <span class="ui label ml-3">{{$.i18n.Tr "repo.diff.vendored"}}</span>
- {{end}}
- </div>
- <div class="diff-file-header-actions df ac">
- {{if $showFileViewToggle}}
- <div class="ui compact icon buttons">
- <span class="ui tiny basic button poping up file-view-toggle" data-toggle-selector="#diff-source-{{$i}}" data-content="{{$.i18n.Tr "repo.file_view_source"}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-code"}}</span>
- <span class="ui tiny basic button poping up file-view-toggle active" data-toggle-selector="#diff-rendered-{{$i}}" data-content="{{$.i18n.Tr "repo.file_view_rendered"}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-file"}}</span>
- </div>
- {{end}}
- {{if $file.IsProtected}}
- <span class="ui basic label">{{$.i18n.Tr "repo.diff.protected"}}</span>
- {{end}}
- {{if and (not $file.IsSubmodule) (not $.PageIsWiki)}}
- {{if $file.IsDeleted}}
- <a class="ui basic tiny button" rel="nofollow" href="{{EscapePound $.BeforeSourcePath}}/{{EscapePound .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
+ <div class="diff-file-header-actions df ac">
+ {{if $showFileViewToggle}}
+ <div class="ui compact icon buttons">
+ <span class="ui tiny basic button poping up file-view-toggle" data-toggle-selector="#diff-source-{{$i}}" data-content="{{$.i18n.Tr "repo.file_view_source"}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-code"}}</span>
+ <span class="ui tiny basic button poping up file-view-toggle active" data-toggle-selector="#diff-rendered-{{$i}}" data-content="{{$.i18n.Tr "repo.file_view_rendered"}}" data-position="bottom center" data-variation="tiny inverted">{{svg "octicon-file"}}</span>
+ </div>
+ {{end}}
+ {{if $file.IsProtected}}
+ <span class="ui basic label">{{$.i18n.Tr "repo.diff.protected"}}</span>
+ {{end}}
+ {{if and (not $file.IsSubmodule) (not $.PageIsWiki)}}
+ {{if $file.IsDeleted}}
+ <a class="ui basic tiny button" rel="nofollow" href="{{EscapePound $.BeforeSourcePath}}/{{EscapePound .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
+ {{else}}
+ <a class="ui basic tiny button" rel="nofollow" href="{{EscapePound $.SourcePath}}/{{EscapePound .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
+ {{end}}
+ {{end}}
+ </div>
+ </h4>
+ <div class="diff-file-body ui attached unstackable table segment">
+ <div id="diff-source-{{$i}}" class="file-body file-code code-diff{{if $.IsSplitStyle}} code-diff-split{{else}} code-diff-unified{{end}}{{if $showFileViewToggle}} hide{{end}}">
+ {{if or $file.IsIncomplete $file.IsBin}}
+ <div class="diff-file-body binary" style="padding: 5px 10px;">
+ {{if $file.IsIncomplete}}
+ {{if $file.IsIncompleteLineTooLong}}
+ {{$.i18n.Tr "repo.diff.file_suppressed_line_too_long"}}
+ {{else}}
+ {{$.i18n.Tr "repo.diff.file_suppressed"}}
+ {{end}}
+ {{else}}
+ {{$.i18n.Tr "repo.diff.bin_not_shown"}}
+ {{end}}
+ </div>
{{else}}
- <a class="ui basic tiny button" rel="nofollow" href="{{EscapePound $.SourcePath}}/{{EscapePound .Name}}">{{$.i18n.Tr "repo.diff.view_file"}}</a>
+ <table class="chroma">
+ {{if $.IsSplitStyle}}
+ {{template "repo/diff/section_split" dict "file" . "root" $}}
+ {{else}}
+ {{template "repo/diff/section_unified" dict "file" . "root" $}}
+ {{end}}
+ </table>
{{end}}
- {{end}}
- </div>
- </h4>
- <div class="diff-file-body ui attached unstackable table segment">
- <div id="diff-source-{{$i}}" class="file-body file-code code-diff{{if $.IsSplitStyle}} code-diff-split{{else}} code-diff-unified{{end}}{{if $showFileViewToggle}} hide{{end}}">
- {{if or $file.IsIncomplete $file.IsBin}}
- <div class="diff-file-body binary" style="padding: 5px 10px;">
- {{if $file.IsIncomplete}}
- {{if $file.IsIncompleteLineTooLong}}
- {{$.i18n.Tr "repo.diff.file_suppressed_line_too_long"}}
+ </div>
+ {{if $showFileViewToggle}}
+ <div id="diff-rendered-{{$i}}" class="file-body file-code {{if $.IsSplitStyle}} code-diff-split{{else}} code-diff-unified{{end}}">
+ <table class="chroma w-100">
+ {{if $isImage}}
+ {{template "repo/diff/image_diff" dict "file" . "root" $ "blobBase" $blobBase "blobHead" $blobHead}}
{{else}}
- {{$.i18n.Tr "repo.diff.file_suppressed"}}
+ {{template "repo/diff/csv_diff" dict "file" . "root" $}}
{{end}}
- {{else}}
- {{$.i18n.Tr "repo.diff.bin_not_shown"}}
- {{end}}
+ </table>
</div>
- {{else}}
- <table class="chroma">
- {{if $.IsSplitStyle}}
- {{template "repo/diff/section_split" dict "file" . "root" $}}
- {{else}}
- {{template "repo/diff/section_unified" dict "file" . "root" $}}
- {{end}}
- </table>
{{end}}
</div>
- {{if $showFileViewToggle}}
- <div id="diff-rendered-{{$i}}" class="file-body file-code {{if $.IsSplitStyle}} code-diff-split{{else}} code-diff-unified{{end}}">
- <table class="chroma w-100">
- {{if $isImage}}
- {{template "repo/diff/image_diff" dict "file" . "root" $ "blobBase" $blobBase "blobHead" $blobHead}}
- {{else}}
- {{template "repo/diff/csv_diff" dict "file" . "root" $}}
- {{end}}
- </table>
- </div>
- {{end}}
</div>
- </div>
- {{end}}
+ {{end}}
- {{if .Diff.IsIncomplete}}
- <div class="diff-file-box diff-box file-content mt-3">
- <h4 class="ui top attached normal header">
- {{$.i18n.Tr "repo.diff.too_many_files"}}
- </h4>
- </div>
- {{end}}
+ {{if .Diff.IsIncomplete}}
+ <div class="diff-file-box diff-box file-content mt-3" id="diff-incomplete">
+ <h4 class="ui top attached normal header df ac sb">
+ {{$.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>
+ </div>
+ {{end}}
+ </div>
{{if not $.Repository.IsArchived}}
<div class="hide" id="edit-content-form">
--- /dev/null
+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());
+ });
+ });
+}
import {initLastCommitLoader} from './features/lastcommitloader.js';
import {initIssueContentHistory} from './features/issue-content-history.js';
import {initStopwatch} from './features/stopwatch.js';
+import {initDiffShowMore} from './features/diff.js';
import {showLineButton} from './code/linebutton.js';
import {initMarkupContent, initCommentContent} from './markup/content.js';
import {stripTags, mqBinarySearch} from './utils.js';
initFileViewToggle();
initReleaseEditor();
initRelease();
+ initDiffShowMore();
initIssueContentHistory();
initAdminUserListSearchForm();