]> source.dussan.org Git - gitea.git/commitdiff
Branches not at ref commit ID should not be listed as Merged (#9614)
authorzeripath <art27@cantab.net>
Tue, 7 Jan 2020 17:06:14 +0000 (17:06 +0000)
committerGitHub <noreply@github.com>
Tue, 7 Jan 2020 17:06:14 +0000 (17:06 +0000)
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

integrations/gitea-repositories-meta/user2/repo1.git/objects/00/750edc07d6415dcc07ae0351e9397b0222b7ba [new file with mode: 0644]
integrations/gitea-repositories-meta/user2/repo1.git/objects/4a/357436d925b5c974181ff12a994538ddc5a269 [new file with mode: 0644]
integrations/gitea-repositories-meta/user2/repo1.git/objects/dc/7a8ba127fee870dd683310ce660dfe59333a1b [new file with mode: 0644]
integrations/gitea-repositories-meta/user2/repo1.git/refs/pull/3/head [new file with mode: 0644]
models/pull.go
routers/repo/branch.go
routers/repo/issue.go
routers/repo/pull.go
templates/repo/branch/list.tmpl
templates/repo/issue/view_content/pull.tmpl

diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/00/750edc07d6415dcc07ae0351e9397b0222b7ba b/integrations/gitea-repositories-meta/user2/repo1.git/objects/00/750edc07d6415dcc07ae0351e9397b0222b7ba
new file mode 100644 (file)
index 0000000..d3c45d5
Binary files /dev/null and b/integrations/gitea-repositories-meta/user2/repo1.git/objects/00/750edc07d6415dcc07ae0351e9397b0222b7ba differ
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/4a/357436d925b5c974181ff12a994538ddc5a269 b/integrations/gitea-repositories-meta/user2/repo1.git/objects/4a/357436d925b5c974181ff12a994538ddc5a269
new file mode 100644 (file)
index 0000000..bf97d00
Binary files /dev/null and b/integrations/gitea-repositories-meta/user2/repo1.git/objects/4a/357436d925b5c974181ff12a994538ddc5a269 differ
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/objects/dc/7a8ba127fee870dd683310ce660dfe59333a1b b/integrations/gitea-repositories-meta/user2/repo1.git/objects/dc/7a8ba127fee870dd683310ce660dfe59333a1b
new file mode 100644 (file)
index 0000000..7678d67
Binary files /dev/null and b/integrations/gitea-repositories-meta/user2/repo1.git/objects/dc/7a8ba127fee870dd683310ce660dfe59333a1b differ
diff --git a/integrations/gitea-repositories-meta/user2/repo1.git/refs/pull/3/head b/integrations/gitea-repositories-meta/user2/repo1.git/refs/pull/3/head
new file mode 100644 (file)
index 0000000..98593d6
--- /dev/null
@@ -0,0 +1 @@
+4a357436d925b5c974181ff12a994538ddc5a269
index 9a8777aca3037662cb5edfecd1cba67e0c4b2ca9..f86892cbfc924525ca32be0b935a775204383419 100644 (file)
@@ -122,7 +122,7 @@ func (pr *PullRequest) LoadHeadRepo() error {
                if has, err := x.ID(pr.HeadRepoID).Get(&repo); err != nil {
                        return err
                } else if !has {
-                       return ErrRepoNotExist{ID: pr.BaseRepoID}
+                       return ErrRepoNotExist{ID: pr.HeadRepoID}
                }
                pr.HeadRepo = &repo
        }
index b0a1efc5b92b53e482aee0f5479a40583410d35d..df6e0bf21f6c71872a97cb3e2cae18558d7eb64e 100644 (file)
@@ -16,6 +16,7 @@ import (
        "code.gitea.io/gitea/modules/log"
        "code.gitea.io/gitea/modules/repofiles"
        "code.gitea.io/gitea/modules/util"
+       "gopkg.in/src-d/go-git.v4/plumbing"
 )
 
 const (
@@ -33,6 +34,7 @@ type Branch struct {
        CommitsAhead      int
        CommitsBehind     int
        LatestPullRequest *models.PullRequest
+       MergeMovedOn      bool
 }
 
 // Branches render repository branch page
@@ -185,6 +187,12 @@ func loadBranches(ctx *context.Context) []*Branch {
                return nil
        }
 
+       repoIDToRepo := map[int64]*models.Repository{}
+       repoIDToRepo[ctx.Repo.Repository.ID] = ctx.Repo.Repository
+
+       repoIDToGitRepo := map[int64]*git.Repository{}
+       repoIDToGitRepo[ctx.Repo.Repository.ID] = ctx.Repo.GitRepo
+
        branches := make([]*Branch, len(rawBranches))
        for i := range rawBranches {
                commit, err := rawBranches[i].GetCommit()
@@ -213,11 +221,46 @@ func loadBranches(ctx *context.Context) []*Branch {
                        ctx.ServerError("GetLatestPullRequestByHeadInfo", err)
                        return nil
                }
+               headCommit := commit.ID.String()
+
+               mergeMovedOn := false
                if pr != nil {
+                       pr.HeadRepo = ctx.Repo.Repository
                        if err := pr.LoadIssue(); err != nil {
                                ctx.ServerError("pr.LoadIssue", err)
                                return nil
                        }
+                       if repo, ok := repoIDToRepo[pr.BaseRepoID]; ok {
+                               pr.BaseRepo = repo
+                       } else if err := pr.LoadBaseRepo(); err != nil {
+                               ctx.ServerError("pr.LoadBaseRepo", err)
+                               return nil
+                       } else {
+                               repoIDToRepo[pr.BaseRepoID] = pr.BaseRepo
+                       }
+
+                       if pr.HasMerged {
+                               baseGitRepo, ok := repoIDToGitRepo[pr.BaseRepoID]
+                               if !ok {
+                                       baseGitRepo, err = git.OpenRepository(pr.BaseRepo.RepoPath())
+                                       if err != nil {
+                                               ctx.ServerError("OpenRepository", err)
+                                               return nil
+                                       }
+                                       defer baseGitRepo.Close()
+                                       repoIDToGitRepo[pr.BaseRepoID] = baseGitRepo
+                               }
+                               pullCommit, err := baseGitRepo.GetRefCommitID(pr.GetGitRefName())
+                               if err != nil && err != plumbing.ErrReferenceNotFound {
+                                       ctx.ServerError("GetBranchCommitID", err)
+                                       return nil
+                               }
+                               if err == nil && headCommit != pullCommit {
+                                       // the head has moved on from the merge - we shouldn't delete
+                                       mergeMovedOn = true
+                               }
+                       }
+
                }
 
                isIncluded := divergence.Ahead == 0 && ctx.Repo.Repository.DefaultBranch != branchName
@@ -230,6 +273,7 @@ func loadBranches(ctx *context.Context) []*Branch {
                        CommitsAhead:      divergence.Ahead,
                        CommitsBehind:     divergence.Behind,
                        LatestPullRequest: pr,
+                       MergeMovedOn:      mergeMovedOn,
                }
        }
 
index 46020acb6dfbc6885946624cb4ad839ec95178cd..0a78e06b41ace26881d241b7ec0aef7d8ce27ff7 100644 (file)
@@ -966,7 +966,10 @@ func ViewIssue(ctx *context.Context) {
                        ctx.Data["IsBlockedByRejection"] = pull.ProtectedBranch.MergeBlockedByRejectedReview(pull)
                        ctx.Data["GrantedApprovals"] = cnt
                }
-               ctx.Data["IsPullBranchDeletable"] = canDelete && pull.HeadRepo != nil && git.IsBranchExist(pull.HeadRepo.RepoPath(), pull.HeadBranch)
+               ctx.Data["IsPullBranchDeletable"] = canDelete &&
+                       pull.HeadRepo != nil &&
+                       git.IsBranchExist(pull.HeadRepo.RepoPath(), pull.HeadBranch) &&
+                       (!pull.HasMerged || ctx.Data["HeadBranchCommitID"] == ctx.Data["PullHeadCommitID"])
 
                ctx.Data["PullReviewers"], err = models.GetReviewersByIssueID(issue.ID)
                if err != nil {
index 418c2e9438bd5033aae4915578a783d4a35baaf2..1a5c4a036f24d5d11ef35fbd5cb876cc5f9df6ff 100644 (file)
@@ -330,25 +330,37 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare
        repo := ctx.Repo.Repository
        pull := issue.PullRequest
 
-       var err error
-       if err = pull.GetHeadRepo(); err != nil {
+       if err := pull.GetHeadRepo(); err != nil {
                ctx.ServerError("GetHeadRepo", err)
                return nil
        }
 
+       if err := pull.GetBaseRepo(); err != nil {
+               ctx.ServerError("GetBaseRepo", err)
+               return nil
+       }
+
        setMergeTarget(ctx, pull)
 
-       if err = pull.LoadProtectedBranch(); err != nil {
+       if err := pull.LoadProtectedBranch(); err != nil {
                ctx.ServerError("GetLatestCommitStatus", err)
                return nil
        }
        ctx.Data["EnableStatusCheck"] = pull.ProtectedBranch != nil && pull.ProtectedBranch.EnableStatusCheck
 
-       var headGitRepo *git.Repository
+       baseGitRepo, err := git.OpenRepository(pull.BaseRepo.RepoPath())
+       if err != nil {
+               ctx.ServerError("OpenRepository", err)
+               return nil
+       }
+       defer baseGitRepo.Close()
        var headBranchExist bool
+       var headBranchSha string
        // HeadRepo may be missing
        if pull.HeadRepo != nil {
-               headGitRepo, err = git.OpenRepository(pull.HeadRepo.RepoPath())
+               var err error
+
+               headGitRepo, err := git.OpenRepository(pull.HeadRepo.RepoPath())
                if err != nil {
                        ctx.ServerError("OpenRepository", err)
                        return nil
@@ -358,46 +370,53 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare
                headBranchExist = headGitRepo.IsBranchExist(pull.HeadBranch)
 
                if headBranchExist {
-                       sha, err := headGitRepo.GetBranchCommitID(pull.HeadBranch)
+                       headBranchSha, err = headGitRepo.GetBranchCommitID(pull.HeadBranch)
                        if err != nil {
                                ctx.ServerError("GetBranchCommitID", err)
                                return nil
                        }
+               }
+       }
 
-                       commitStatuses, err := models.GetLatestCommitStatus(repo, sha, 0)
-                       if err != nil {
-                               ctx.ServerError("GetLatestCommitStatus", err)
-                               return nil
-                       }
-                       if len(commitStatuses) > 0 {
-                               ctx.Data["LatestCommitStatuses"] = commitStatuses
-                               ctx.Data["LatestCommitStatus"] = models.CalcCommitStatus(commitStatuses)
-                       }
+       sha, err := baseGitRepo.GetRefCommitID(pull.GetGitRefName())
+       if err != nil {
+               ctx.ServerError(fmt.Sprintf("GetRefCommitID(%s)", pull.GetGitRefName()), err)
+               return nil
+       }
 
-                       if pull.ProtectedBranch != nil && pull.ProtectedBranch.EnableStatusCheck {
-                               ctx.Data["is_context_required"] = func(context string) bool {
-                                       for _, c := range pull.ProtectedBranch.StatusCheckContexts {
-                                               if c == context {
-                                                       return true
-                                               }
-                                       }
-                                       return false
+       commitStatuses, err := models.GetLatestCommitStatus(repo, sha, 0)
+       if err != nil {
+               ctx.ServerError("GetLatestCommitStatus", err)
+               return nil
+       }
+       if len(commitStatuses) > 0 {
+               ctx.Data["LatestCommitStatuses"] = commitStatuses
+               ctx.Data["LatestCommitStatus"] = models.CalcCommitStatus(commitStatuses)
+       }
+
+       if pull.ProtectedBranch != nil && pull.ProtectedBranch.EnableStatusCheck {
+               ctx.Data["is_context_required"] = func(context string) bool {
+                       for _, c := range pull.ProtectedBranch.StatusCheckContexts {
+                               if c == context {
+                                       return true
                                }
-                               ctx.Data["IsRequiredStatusCheckSuccess"] = pull_service.IsCommitStatusContextSuccess(commitStatuses, pull.ProtectedBranch.StatusCheckContexts)
                        }
+                       return false
                }
+               ctx.Data["IsRequiredStatusCheckSuccess"] = pull_service.IsCommitStatusContextSuccess(commitStatuses, pull.ProtectedBranch.StatusCheckContexts)
        }
 
-       if pull.HeadRepo == nil || !headBranchExist {
+       ctx.Data["HeadBranchMovedOn"] = headBranchSha != sha
+       ctx.Data["HeadBranchCommitID"] = headBranchSha
+       ctx.Data["PullHeadCommitID"] = sha
+
+       if pull.HeadRepo == nil || !headBranchExist || headBranchSha != sha {
                ctx.Data["IsPullRequestBroken"] = true
                ctx.Data["HeadTarget"] = "deleted"
-               ctx.Data["NumCommits"] = 0
-               ctx.Data["NumFiles"] = 0
-               return nil
        }
 
-       compareInfo, err := headGitRepo.GetCompareInfo(models.RepoPath(repo.Owner.Name, repo.Name),
-               pull.BaseBranch, pull.HeadBranch)
+       compareInfo, err := baseGitRepo.GetCompareInfo(pull.BaseRepo.RepoPath(),
+               pull.BaseBranch, pull.GetGitRefName())
        if err != nil {
                if strings.Contains(err.Error(), "fatal: Not a valid object name") {
                        ctx.Data["IsPullRequestBroken"] = true
index 8fb365d8055a1aea8f2442216362d96d42f01f79..073516f25fe6e7c0628723862a16311cce683cf1 100644 (file)
                                                                                                <button id="new-pull-request" class="ui compact basic button">{{$.i18n.Tr "repo.pulls.compare_changes"}}</button>
                                                                                        </a>
                                                                                        {{end}}
+                                                                               {{else if and .LatestPullRequest.HasMerged .MergeMovedOn}}
+                                                                                       {{if and (not .IsDeleted) $.AllowsPulls (gt .CommitsAhead 0)}}
+                                                                                       <a href="{{$.RepoLink}}/compare/{{$.DefaultBranch | EscapePound}}...{{if ne $.Repository.Owner.Name $.Owner.Name}}{{$.Owner.Name}}:{{end}}{{.Name | EscapePound}}">
+                                                                                               <button id="new-pull-request" class="ui compact basic button">{{$.i18n.Tr "repo.pulls.compare_changes"}}</button>
+                                                                                       </a>
+                                                                                       {{end}}
                                                                                {{else}}
                                                                                        <a href="{{$.RepoLink}}/pulls/{{.LatestPullRequest.Issue.Index}}">#{{.LatestPullRequest.Issue.Index}}</a>
                                                                                        {{if .LatestPullRequest.HasMerged}}
index cec10a620ea62611219992b2dab227b8958f18f8..2dc76dcf2e3878d632f7f5659722f2b05737688e 100644 (file)
@@ -72,7 +72,7 @@
                                                {{$.i18n.Tr "repo.pulls.reopen_to_merge"}}
                                        {{end}}
                                </div>
-                               {{if .IsPullBranchDeletable}}
+                               {{if and .IsPullBranchDeletable ( not .IsPullRequestBroken )}}
                                        <div class="ui divider"></div>
                                        <div>
                                                <a class="delete-button ui red button" href="" data-url="{{.DeleteBranchLink}}">{{$.i18n.Tr "repo.branch.delete" .HeadTarget}}</a>
                                <div class="item text red">
                                        <span class="octicon octicon-x"></span>
                                {{$.i18n.Tr "repo.pulls.blocked_by_rejection"}}
-                               </div>                  
+                               </div>
                        {{else if .Issue.PullRequest.IsChecking}}
                                <div class="item text yellow">
                                        <span class="octicon octicon-sync"></span>