diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go
index 950979a6ed..c543d90e19 100644
--- a/routers/web/repo/pull.go
+++ b/routers/web/repo/pull.go
@@ -356,12 +356,46 @@ func setMergeTarget(ctx *context.Context, pull *issues_model.PullRequest) {
ctx.Data["BaseBranchLink"] = pull.GetBaseBranchLink()
}
-// PrepareMergedViewPullInfo show meta information for a merged pull request view page
-func PrepareMergedViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.CompareInfo {
+// GetPullDiffStats get Pull Requests diff stats
+func GetPullDiffStats(ctx *context.Context) {
+ issue := checkPullInfo(ctx)
pull := issue.PullRequest
- setMergeTarget(ctx, pull)
- ctx.Data["HasMerged"] = true
+ mergeBaseCommitID := GetMergedBaseCommitID(ctx, issue)
+
+ if ctx.Written() {
+ return
+ } else if mergeBaseCommitID == "" {
+ ctx.NotFound("PullFiles", nil)
+ return
+ }
+
+ headCommitID, err := ctx.Repo.GitRepo.GetRefCommitID(pull.GetGitRefName())
+ if err != nil {
+ ctx.ServerError("GetRefCommitID", err)
+ return
+ }
+
+ diffOptions := &gitdiff.DiffOptions{
+ BeforeCommitID: mergeBaseCommitID,
+ AfterCommitID: headCommitID,
+ MaxLines: setting.Git.MaxGitDiffLines,
+ MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters,
+ MaxFiles: setting.Git.MaxGitDiffFiles,
+ WhitespaceBehavior: gitdiff.GetWhitespaceFlag(ctx.Data["WhitespaceBehavior"].(string)),
+ }
+
+ diff, err := gitdiff.GetPullDiffStats(ctx.Repo.GitRepo, diffOptions)
+ if err != nil {
+ ctx.ServerError("GetPullDiffStats", err)
+ return
+ }
+
+ ctx.Data["Diff"] = diff
+}
+
+func GetMergedBaseCommitID(ctx *context.Context, issue *issues_model.Issue) string {
+ pull := issue.PullRequest
var baseCommit string
// Some migrated PR won't have any Base SHA and lose history, try to get one
@@ -401,6 +435,18 @@ func PrepareMergedViewPullInfo(ctx *context.Context, issue *issues_model.Issue)
baseCommit = pull.MergeBase
}
+ return baseCommit
+}
+
+// PrepareMergedViewPullInfo show meta information for a merged pull request view page
+func PrepareMergedViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.CompareInfo {
+ pull := issue.PullRequest
+
+ setMergeTarget(ctx, pull)
+ ctx.Data["HasMerged"] = true
+
+ baseCommit := GetMergedBaseCommitID(ctx, issue)
+
compareInfo, err := ctx.Repo.GitRepo.GetCompareInfo(ctx.Repo.Repository.RepoPath(),
baseCommit, pull.GetGitRefName(), false, false)
if err != nil {
diff --git a/routers/web/web.go b/routers/web/web.go
index 5dd7be120d..45c374e9c0 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -1277,9 +1277,10 @@ func registerRoutes(m *web.Route) {
})
m.Group("/pulls/{index}", func() {
+ m.Get("", repo.SetWhitespaceBehavior, repo.GetPullDiffStats, repo.ViewIssue)
m.Get(".diff", repo.DownloadPullDiff)
m.Get(".patch", repo.DownloadPullPatch)
- m.Get("/commits", context.RepoRef(), repo.ViewPullCommits)
+ m.Get("/commits", context.RepoRef(), repo.SetWhitespaceBehavior, repo.GetPullDiffStats, repo.ViewPullCommits)
m.Post("/merge", context.RepoMustNotBeArchived(), web.Bind(forms.MergePullRequestForm{}), repo.MergePullRequest)
m.Post("/cancel_auto_merge", context.RepoMustNotBeArchived(), repo.CancelAutoMergePullRequest)
m.Post("/update", repo.UpdatePullRequest)
diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go
index 9adf3b9400..38283680ae 100644
--- a/services/gitdiff/gitdiff.go
+++ b/services/gitdiff/gitdiff.go
@@ -1229,6 +1229,42 @@ func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff
return diff, nil
}
+type PullDiffStats struct {
+ TotalAddition, TotalDeletion int
+}
+
+// GetPullDiffStats
+func GetPullDiffStats(gitRepo *git.Repository, opts *DiffOptions) (*PullDiffStats, error) {
+ repoPath := gitRepo.Path
+
+ diff := &PullDiffStats{}
+
+ separator := "..."
+ if opts.DirectComparison {
+ separator = ".."
+ }
+
+ diffPaths := []string{opts.BeforeCommitID + separator + opts.AfterCommitID}
+ if len(opts.BeforeCommitID) == 0 || opts.BeforeCommitID == git.EmptySHA {
+ diffPaths = []string{git.EmptyTreeSHA, opts.AfterCommitID}
+ }
+
+ var err error
+
+ _, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(gitRepo.Ctx, repoPath, nil, diffPaths...)
+ if err != nil && strings.Contains(err.Error(), "no merge base") {
+ // 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...
+ diffPaths = []string{opts.BeforeCommitID, opts.AfterCommitID}
+ _, diff.TotalAddition, diff.TotalDeletion, err = git.GetDiffShortStat(gitRepo.Ctx, repoPath, nil, diffPaths...)
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ return diff, nil
+}
+
// SyncAndGetUserSpecificDiff is like GetDiff, except that user specific data such as which files the given user has already viewed on the given PR will also be set
// Additionally, the database asynchronously is updated if files have changed since the last review
func SyncAndGetUserSpecificDiff(ctx context.Context, userID int64, pull *issues_model.PullRequest, gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff, error) {
diff --git a/templates/repo/pulls/tab_menu.tmpl b/templates/repo/pulls/tab_menu.tmpl
index f44968c775..6c121bdd1f 100644
--- a/templates/repo/pulls/tab_menu.tmpl
+++ b/templates/repo/pulls/tab_menu.tmpl
@@ -14,4 +14,10 @@
{{$.locale.Tr "repo.pulls.tab_files"}}
{{if .NumFiles}}{{.NumFiles}}{{else}}-{{end}}
+
+ {{if .Diff.TotalAddition}}+{{.Diff.TotalAddition}}{{end}} {{if .Diff.TotalDeletion}}-{{.Diff.TotalDeletion}}{{end}}
+
+
+
+