Skip to content

Decouple diff stats query from actual diffing #33810

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 8, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions modules/git/repo_compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,15 +176,15 @@ func (repo *Repository) GetDiffNumChangedFiles(base, head string, directComparis

// GetDiffShortStat counts number of changed files, number of additions and deletions
func (repo *Repository) GetDiffShortStat(base, head string) (numFiles, totalAdditions, totalDeletions int, err error) {
numFiles, totalAdditions, totalDeletions, err = GetDiffShortStat(repo.Ctx, repo.Path, nil, base+"..."+head)
numFiles, totalAdditions, totalDeletions, err = GetDiffWithShortStat(repo.Ctx, repo.Path, nil, base+"..."+head)
if err != nil && strings.Contains(err.Error(), "no merge base") {
return GetDiffShortStat(repo.Ctx, repo.Path, nil, base, head)
return GetDiffWithShortStat(repo.Ctx, repo.Path, nil, base, head)
}
return numFiles, totalAdditions, totalDeletions, err
}

// GetDiffShortStat counts number of changed files, number of additions and deletions
func GetDiffShortStat(ctx context.Context, repoPath string, trustedArgs TrustedCmdArgs, dynamicArgs ...string) (numFiles, totalAdditions, totalDeletions int, err error) {
// GetDiffWithShortStat counts number of changed files, number of additions and deletions
func GetDiffWithShortStat(ctx context.Context, repoPath string, trustedArgs TrustedCmdArgs, dynamicArgs ...string) (numFiles, totalAdditions, totalDeletions int, err error) {
// Now if we call:
// $ git diff --shortstat 1ebb35b98889ff77299f24d82da426b434b0cca0...788b8b1440462d477f45b0088875
// we get:
Expand Down
8 changes: 7 additions & 1 deletion routers/api/v1/repo/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -1591,6 +1591,7 @@ func GetPullRequestFiles(ctx *context.APIContext) {
maxLines := setting.Git.MaxGitDiffLines

// FIXME: If there are too many files in the repo, may cause some unpredictable issues.
// FIXME: it doesn't need to call "GetDiff" to do various parsing and highlighting
diff, err := gitdiff.GetDiff(ctx, baseGitRepo,
&gitdiff.DiffOptions{
BeforeCommitID: startCommitID,
Expand All @@ -1606,9 +1607,14 @@ func GetPullRequestFiles(ctx *context.APIContext) {
return
}

diffShortStat, err := gitdiff.GetDiffShortStat(baseGitRepo, startCommitID, endCommitID)
if err != nil {
ctx.APIErrorInternal(err)
return
}
listOptions := utils.GetListOptions(ctx)

totalNumberOfFiles := diff.NumFiles
totalNumberOfFiles := diffShortStat.NumFiles
totalNumberOfPages := int(math.Ceil(float64(totalNumberOfFiles) / float64(listOptions.PageSize)))

start, limit := listOptions.GetSkipTake()
Expand Down
9 changes: 7 additions & 2 deletions routers/web/repo/commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,12 +321,17 @@ func Diff(ctx *context.Context) {
MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters,
MaxFiles: maxFiles,
WhitespaceBehavior: gitdiff.GetWhitespaceFlag(ctx.Data["WhitespaceBehavior"].(string)),
FileOnly: fileOnly,
}, files...)
if err != nil {
ctx.NotFound(err)
return
}
diffShortStat, err := gitdiff.GetDiffShortStat(gitRepo, "", commitID)
if err != nil {
ctx.ServerError("GetDiffShortStat", err)
return
}
ctx.Data["DiffShortStat"] = diffShortStat

parents := make([]string, commit.ParentCount())
for i := 0; i < commit.ParentCount(); i++ {
Expand Down Expand Up @@ -383,7 +388,7 @@ func Diff(ctx *context.Context) {
ctx.Data["Verification"] = verification
ctx.Data["Author"] = user_model.ValidateCommitWithEmail(ctx, commit)
ctx.Data["Parents"] = parents
ctx.Data["DiffNotAvailable"] = diff.NumFiles == 0
ctx.Data["DiffNotAvailable"] = diffShortStat.NumFiles == 0

if err := asymkey_model.CalculateTrustStatus(verification, ctx.Repo.Repository.GetTrustModel(), func(user *user_model.User) (bool, error) {
return repo_model.IsOwnerMemberCollaborator(ctx, ctx.Repo.Repository, user.ID)
Expand Down
11 changes: 8 additions & 3 deletions routers/web/repo/compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -624,14 +624,19 @@ func PrepareCompareDiff(
MaxFiles: maxFiles,
WhitespaceBehavior: whitespaceBehavior,
DirectComparison: ci.DirectComparison,
FileOnly: fileOnly,
}, ctx.FormStrings("files")...)
if err != nil {
ctx.ServerError("GetDiffRangeWithWhitespaceBehavior", err)
ctx.ServerError("GetDiff", err)
return false
}
diffShortStat, err := gitdiff.GetDiffShortStat(ci.HeadGitRepo, beforeCommitID, headCommitID)
if err != nil {
ctx.ServerError("GetDiffShortStat", err)
return false
}
ctx.Data["DiffShortStat"] = diffShortStat
ctx.Data["Diff"] = diff
ctx.Data["DiffNotAvailable"] = diff.NumFiles == 0
ctx.Data["DiffNotAvailable"] = diffShortStat.NumFiles == 0

if !fileOnly {
diffTree, err := gitdiff.GetDiffTree(ctx, ci.HeadGitRepo, false, beforeCommitID, headCommitID)
Expand Down
2 changes: 1 addition & 1 deletion routers/web/repo/editor.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ func DiffPreviewPost(ctx *context.Context) {
return
}

if diff.NumFiles != 0 {
if len(diff.Files) != 0 {
ctx.Data["File"] = diff.Files[0]
}

Expand Down
44 changes: 21 additions & 23 deletions routers/web/repo/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,22 +200,13 @@ func GetPullDiffStats(ctx *context.Context) {
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)
diffShortStat, err := gitdiff.GetDiffShortStat(ctx.Repo.GitRepo, mergeBaseCommitID, headCommitID)
if err != nil {
ctx.ServerError("GetPullDiffStats", err)
ctx.ServerError("GetDiffWithShortStat", err)
return
}

ctx.Data["Diff"] = diff
ctx.Data["DiffShortStat"] = diffShortStat
}

func GetMergedBaseCommitID(ctx *context.Context, issue *issues_model.Issue) string {
Expand Down Expand Up @@ -752,36 +743,43 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi
MaxLineCharacters: setting.Git.MaxGitDiffLineCharacters,
MaxFiles: maxFiles,
WhitespaceBehavior: gitdiff.GetWhitespaceFlag(ctx.Data["WhitespaceBehavior"].(string)),
FileOnly: fileOnly,
}

if !willShowSpecifiedCommit {
diffOptions.BeforeCommitID = startCommitID
}

var methodWithError string
var diff *gitdiff.Diff
shouldGetUserSpecificDiff := false
diff, err := gitdiff.GetDiff(ctx, gitRepo, diffOptions, files...)
if err != nil {
ctx.ServerError("GetDiff", err)
return
}

// if we're not logged in or only a single commit (or commit range) is shown we
// have to load only the diff and not get the viewed information
// as the viewed information is designed to be loaded only on latest PR
// diff and if you're signed in.
shouldGetUserSpecificDiff := false
if !ctx.IsSigned || willShowSpecifiedCommit || willShowSpecifiedCommitRange {
diff, err = gitdiff.GetDiff(ctx, gitRepo, diffOptions, files...)
methodWithError = "GetDiff"
// do nothing
} else {
diff, err = gitdiff.SyncAndGetUserSpecificDiff(ctx, ctx.Doer.ID, pull, gitRepo, diffOptions, files...)
methodWithError = "SyncAndGetUserSpecificDiff"
shouldGetUserSpecificDiff = true
err = gitdiff.SyncAndGetUserSpecificDiff(ctx, ctx.Doer.ID, pull, gitRepo, diff, diffOptions, files...)
if err != nil {
ctx.ServerError("SyncAndGetUserSpecificDiff", err)
return
}
}

diffShortStat, err := gitdiff.GetDiffShortStat(ctx.Repo.GitRepo, startCommitID, endCommitID)
if err != nil {
ctx.ServerError(methodWithError, err)
ctx.ServerError("GetDiffWithShortStat", err)
return
}
ctx.Data["DiffShortStat"] = diffShortStat

ctx.PageData["prReview"] = map[string]any{
"numberOfFiles": diff.NumFiles,
"numberOfFiles": diffShortStat.NumFiles,
"numberOfViewedFiles": diff.NumViewedFiles,
}

Expand Down Expand Up @@ -840,7 +838,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi
}

ctx.Data["Diff"] = diff
ctx.Data["DiffNotAvailable"] = diff.NumFiles == 0
ctx.Data["DiffNotAvailable"] = diffShortStat.NumFiles == 0

baseCommit, err := ctx.Repo.GitRepo.GetCommit(startCommitID)
if err != nil {
Expand Down
10 changes: 4 additions & 6 deletions services/convert/git_commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,17 +210,15 @@ func ToCommit(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Rep

// Get diff stats for commit
if opts.Stat {
diff, err := gitdiff.GetDiff(ctx, gitRepo, &gitdiff.DiffOptions{
AfterCommitID: commit.ID.String(),
})
diffShortStat, err := gitdiff.GetDiffShortStat(gitRepo, "", commit.ID.String())
if err != nil {
return nil, err
}

res.Stats = &api.CommitStats{
Total: diff.TotalAddition + diff.TotalDeletion,
Additions: diff.TotalAddition,
Deletions: diff.TotalDeletion,
Total: diffShortStat.TotalAddition + diffShortStat.TotalDeletion,
Additions: diffShortStat.TotalAddition,
Deletions: diffShortStat.TotalDeletion,
}
}

Expand Down
Loading