Skip to content

Commit e5d8e2d

Browse files
authored
Branches not at ref commit ID should not be listed as Merged (#9614)
Once a branch has been merged if the commit ID no longer equals that of the pulls ref commit id don't offer to delete the branch on the pull screen and don't list it as merged on branches. Fix #9201 When looking at the pull page we should also get the commits from the refs/pulls/x/head Fix #9158
1 parent 9406368 commit e5d8e2d

File tree

10 files changed

+107
-34
lines changed

10 files changed

+107
-34
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
4a357436d925b5c974181ff12a994538ddc5a269

models/pull.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ func (pr *PullRequest) LoadHeadRepo() error {
122122
if has, err := x.ID(pr.HeadRepoID).Get(&repo); err != nil {
123123
return err
124124
} else if !has {
125-
return ErrRepoNotExist{ID: pr.BaseRepoID}
125+
return ErrRepoNotExist{ID: pr.HeadRepoID}
126126
}
127127
pr.HeadRepo = &repo
128128
}

routers/repo/branch.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"code.gitea.io/gitea/modules/log"
1717
"code.gitea.io/gitea/modules/repofiles"
1818
"code.gitea.io/gitea/modules/util"
19+
"gopkg.in/src-d/go-git.v4/plumbing"
1920
)
2021

2122
const (
@@ -33,6 +34,7 @@ type Branch struct {
3334
CommitsAhead int
3435
CommitsBehind int
3536
LatestPullRequest *models.PullRequest
37+
MergeMovedOn bool
3638
}
3739

3840
// Branches render repository branch page
@@ -185,6 +187,12 @@ func loadBranches(ctx *context.Context) []*Branch {
185187
return nil
186188
}
187189

190+
repoIDToRepo := map[int64]*models.Repository{}
191+
repoIDToRepo[ctx.Repo.Repository.ID] = ctx.Repo.Repository
192+
193+
repoIDToGitRepo := map[int64]*git.Repository{}
194+
repoIDToGitRepo[ctx.Repo.Repository.ID] = ctx.Repo.GitRepo
195+
188196
branches := make([]*Branch, len(rawBranches))
189197
for i := range rawBranches {
190198
commit, err := rawBranches[i].GetCommit()
@@ -213,11 +221,46 @@ func loadBranches(ctx *context.Context) []*Branch {
213221
ctx.ServerError("GetLatestPullRequestByHeadInfo", err)
214222
return nil
215223
}
224+
headCommit := commit.ID.String()
225+
226+
mergeMovedOn := false
216227
if pr != nil {
228+
pr.HeadRepo = ctx.Repo.Repository
217229
if err := pr.LoadIssue(); err != nil {
218230
ctx.ServerError("pr.LoadIssue", err)
219231
return nil
220232
}
233+
if repo, ok := repoIDToRepo[pr.BaseRepoID]; ok {
234+
pr.BaseRepo = repo
235+
} else if err := pr.LoadBaseRepo(); err != nil {
236+
ctx.ServerError("pr.LoadBaseRepo", err)
237+
return nil
238+
} else {
239+
repoIDToRepo[pr.BaseRepoID] = pr.BaseRepo
240+
}
241+
242+
if pr.HasMerged {
243+
baseGitRepo, ok := repoIDToGitRepo[pr.BaseRepoID]
244+
if !ok {
245+
baseGitRepo, err = git.OpenRepository(pr.BaseRepo.RepoPath())
246+
if err != nil {
247+
ctx.ServerError("OpenRepository", err)
248+
return nil
249+
}
250+
defer baseGitRepo.Close()
251+
repoIDToGitRepo[pr.BaseRepoID] = baseGitRepo
252+
}
253+
pullCommit, err := baseGitRepo.GetRefCommitID(pr.GetGitRefName())
254+
if err != nil && err != plumbing.ErrReferenceNotFound {
255+
ctx.ServerError("GetBranchCommitID", err)
256+
return nil
257+
}
258+
if err == nil && headCommit != pullCommit {
259+
// the head has moved on from the merge - we shouldn't delete
260+
mergeMovedOn = true
261+
}
262+
}
263+
221264
}
222265

223266
isIncluded := divergence.Ahead == 0 && ctx.Repo.Repository.DefaultBranch != branchName
@@ -230,6 +273,7 @@ func loadBranches(ctx *context.Context) []*Branch {
230273
CommitsAhead: divergence.Ahead,
231274
CommitsBehind: divergence.Behind,
232275
LatestPullRequest: pr,
276+
MergeMovedOn: mergeMovedOn,
233277
}
234278
}
235279

routers/repo/issue.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -966,7 +966,10 @@ func ViewIssue(ctx *context.Context) {
966966
ctx.Data["IsBlockedByRejection"] = pull.ProtectedBranch.MergeBlockedByRejectedReview(pull)
967967
ctx.Data["GrantedApprovals"] = cnt
968968
}
969-
ctx.Data["IsPullBranchDeletable"] = canDelete && pull.HeadRepo != nil && git.IsBranchExist(pull.HeadRepo.RepoPath(), pull.HeadBranch)
969+
ctx.Data["IsPullBranchDeletable"] = canDelete &&
970+
pull.HeadRepo != nil &&
971+
git.IsBranchExist(pull.HeadRepo.RepoPath(), pull.HeadBranch) &&
972+
(!pull.HasMerged || ctx.Data["HeadBranchCommitID"] == ctx.Data["PullHeadCommitID"])
970973

971974
ctx.Data["PullReviewers"], err = models.GetReviewersByIssueID(issue.ID)
972975
if err != nil {

routers/repo/pull.go

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -330,25 +330,37 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare
330330
repo := ctx.Repo.Repository
331331
pull := issue.PullRequest
332332

333-
var err error
334-
if err = pull.GetHeadRepo(); err != nil {
333+
if err := pull.GetHeadRepo(); err != nil {
335334
ctx.ServerError("GetHeadRepo", err)
336335
return nil
337336
}
338337

338+
if err := pull.GetBaseRepo(); err != nil {
339+
ctx.ServerError("GetBaseRepo", err)
340+
return nil
341+
}
342+
339343
setMergeTarget(ctx, pull)
340344

341-
if err = pull.LoadProtectedBranch(); err != nil {
345+
if err := pull.LoadProtectedBranch(); err != nil {
342346
ctx.ServerError("GetLatestCommitStatus", err)
343347
return nil
344348
}
345349
ctx.Data["EnableStatusCheck"] = pull.ProtectedBranch != nil && pull.ProtectedBranch.EnableStatusCheck
346350

347-
var headGitRepo *git.Repository
351+
baseGitRepo, err := git.OpenRepository(pull.BaseRepo.RepoPath())
352+
if err != nil {
353+
ctx.ServerError("OpenRepository", err)
354+
return nil
355+
}
356+
defer baseGitRepo.Close()
348357
var headBranchExist bool
358+
var headBranchSha string
349359
// HeadRepo may be missing
350360
if pull.HeadRepo != nil {
351-
headGitRepo, err = git.OpenRepository(pull.HeadRepo.RepoPath())
361+
var err error
362+
363+
headGitRepo, err := git.OpenRepository(pull.HeadRepo.RepoPath())
352364
if err != nil {
353365
ctx.ServerError("OpenRepository", err)
354366
return nil
@@ -358,46 +370,53 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare
358370
headBranchExist = headGitRepo.IsBranchExist(pull.HeadBranch)
359371

360372
if headBranchExist {
361-
sha, err := headGitRepo.GetBranchCommitID(pull.HeadBranch)
373+
headBranchSha, err = headGitRepo.GetBranchCommitID(pull.HeadBranch)
362374
if err != nil {
363375
ctx.ServerError("GetBranchCommitID", err)
364376
return nil
365377
}
378+
}
379+
}
366380

367-
commitStatuses, err := models.GetLatestCommitStatus(repo, sha, 0)
368-
if err != nil {
369-
ctx.ServerError("GetLatestCommitStatus", err)
370-
return nil
371-
}
372-
if len(commitStatuses) > 0 {
373-
ctx.Data["LatestCommitStatuses"] = commitStatuses
374-
ctx.Data["LatestCommitStatus"] = models.CalcCommitStatus(commitStatuses)
375-
}
381+
sha, err := baseGitRepo.GetRefCommitID(pull.GetGitRefName())
382+
if err != nil {
383+
ctx.ServerError(fmt.Sprintf("GetRefCommitID(%s)", pull.GetGitRefName()), err)
384+
return nil
385+
}
376386

377-
if pull.ProtectedBranch != nil && pull.ProtectedBranch.EnableStatusCheck {
378-
ctx.Data["is_context_required"] = func(context string) bool {
379-
for _, c := range pull.ProtectedBranch.StatusCheckContexts {
380-
if c == context {
381-
return true
382-
}
383-
}
384-
return false
387+
commitStatuses, err := models.GetLatestCommitStatus(repo, sha, 0)
388+
if err != nil {
389+
ctx.ServerError("GetLatestCommitStatus", err)
390+
return nil
391+
}
392+
if len(commitStatuses) > 0 {
393+
ctx.Data["LatestCommitStatuses"] = commitStatuses
394+
ctx.Data["LatestCommitStatus"] = models.CalcCommitStatus(commitStatuses)
395+
}
396+
397+
if pull.ProtectedBranch != nil && pull.ProtectedBranch.EnableStatusCheck {
398+
ctx.Data["is_context_required"] = func(context string) bool {
399+
for _, c := range pull.ProtectedBranch.StatusCheckContexts {
400+
if c == context {
401+
return true
385402
}
386-
ctx.Data["IsRequiredStatusCheckSuccess"] = pull_service.IsCommitStatusContextSuccess(commitStatuses, pull.ProtectedBranch.StatusCheckContexts)
387403
}
404+
return false
388405
}
406+
ctx.Data["IsRequiredStatusCheckSuccess"] = pull_service.IsCommitStatusContextSuccess(commitStatuses, pull.ProtectedBranch.StatusCheckContexts)
389407
}
390408

391-
if pull.HeadRepo == nil || !headBranchExist {
409+
ctx.Data["HeadBranchMovedOn"] = headBranchSha != sha
410+
ctx.Data["HeadBranchCommitID"] = headBranchSha
411+
ctx.Data["PullHeadCommitID"] = sha
412+
413+
if pull.HeadRepo == nil || !headBranchExist || headBranchSha != sha {
392414
ctx.Data["IsPullRequestBroken"] = true
393415
ctx.Data["HeadTarget"] = "deleted"
394-
ctx.Data["NumCommits"] = 0
395-
ctx.Data["NumFiles"] = 0
396-
return nil
397416
}
398417

399-
compareInfo, err := headGitRepo.GetCompareInfo(models.RepoPath(repo.Owner.Name, repo.Name),
400-
pull.BaseBranch, pull.HeadBranch)
418+
compareInfo, err := baseGitRepo.GetCompareInfo(pull.BaseRepo.RepoPath(),
419+
pull.BaseBranch, pull.GetGitRefName())
401420
if err != nil {
402421
if strings.Contains(err.Error(), "fatal: Not a valid object name") {
403422
ctx.Data["IsPullRequestBroken"] = true

templates/repo/branch/list.tmpl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@
8484
<button id="new-pull-request" class="ui compact basic button">{{$.i18n.Tr "repo.pulls.compare_changes"}}</button>
8585
</a>
8686
{{end}}
87+
{{else if and .LatestPullRequest.HasMerged .MergeMovedOn}}
88+
{{if and (not .IsDeleted) $.AllowsPulls (gt .CommitsAhead 0)}}
89+
<a href="{{$.RepoLink}}/compare/{{$.DefaultBranch | EscapePound}}...{{if ne $.Repository.Owner.Name $.Owner.Name}}{{$.Owner.Name}}:{{end}}{{.Name | EscapePound}}">
90+
<button id="new-pull-request" class="ui compact basic button">{{$.i18n.Tr "repo.pulls.compare_changes"}}</button>
91+
</a>
92+
{{end}}
8793
{{else}}
8894
<a href="{{$.RepoLink}}/pulls/{{.LatestPullRequest.Issue.Index}}">#{{.LatestPullRequest.Issue.Index}}</a>
8995
{{if .LatestPullRequest.HasMerged}}

templates/repo/issue/view_content/pull.tmpl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
{{$.i18n.Tr "repo.pulls.reopen_to_merge"}}
7373
{{end}}
7474
</div>
75-
{{if .IsPullBranchDeletable}}
75+
{{if and .IsPullBranchDeletable ( not .IsPullRequestBroken )}}
7676
<div class="ui divider"></div>
7777
<div>
7878
<a class="delete-button ui red button" href="" data-url="{{.DeleteBranchLink}}">{{$.i18n.Tr "repo.branch.delete" .HeadTarget}}</a>
@@ -105,7 +105,7 @@
105105
<div class="item text red">
106106
<span class="octicon octicon-x"></span>
107107
{{$.i18n.Tr "repo.pulls.blocked_by_rejection"}}
108-
</div>
108+
</div>
109109
{{else if .Issue.PullRequest.IsChecking}}
110110
<div class="item text yellow">
111111
<span class="octicon octicon-sync"></span>

0 commit comments

Comments
 (0)