* Fix broken merge base migration v128 for merged PR * Allow PRs with deleted base branches to still show diff * as per @lunny Co-authored-by: Lauris BH <lauris@nix.lv>tags/v1.13.0-dev
@@ -200,6 +200,8 @@ var migrations = []Migration{ | |||||
NewMigration("Add Branch Protection Protected Files Column", addBranchProtectionProtectedFilesColumn), | NewMigration("Add Branch Protection Protected Files Column", addBranchProtectionProtectedFilesColumn), | ||||
// v133 -> v134 | // v133 -> v134 | ||||
NewMigration("Add EmailHash Table", addEmailHashTable), | NewMigration("Add EmailHash Table", addEmailHashTable), | ||||
// v134 -> v135 | |||||
NewMigration("Refix merge base for merged pull requests", refixMergeBase), | |||||
} | } | ||||
// Migrate database to current version | // Migrate database to current version | ||||
@@ -53,7 +53,7 @@ func fixMergeBase(x *xorm.Engine) error { | |||||
break | break | ||||
} | } | ||||
i += 50 | |||||
i += len(prs) | |||||
for _, pr := range prs { | for _, pr := range prs { | ||||
baseRepo := &Repository{ID: pr.BaseRepoID} | baseRepo := &Repository{ID: pr.BaseRepoID} | ||||
has, err := x.Table("repository").Get(baseRepo) | has, err := x.Table("repository").Get(baseRepo) | ||||
@@ -81,10 +81,22 @@ func fixMergeBase(x *xorm.Engine) error { | |||||
} | } | ||||
} | } | ||||
} else { | } else { | ||||
var err error | |||||
pr.MergeBase, err = git.NewCommand("merge-base", "--", pr.MergedCommitID+"^", gitRefName).RunInDir(repoPath) | |||||
parentsString, err := git.NewCommand("rev-list", "--parents", "-n", "1", pr.MergedCommitID).RunInDir(repoPath) | |||||
if err != nil { | |||||
log.Error("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) | |||||
continue | |||||
} | |||||
parents := strings.Split(strings.TrimSpace(parentsString), " ") | |||||
if len(parents) < 2 { | |||||
continue | |||||
} | |||||
args := append([]string{"merge-base", "--"}, parents[1:]...) | |||||
args = append(args, gitRefName) | |||||
pr.MergeBase, err = git.NewCommand(args...).RunInDir(repoPath) | |||||
if err != nil { | if err != nil { | ||||
log.Error("Unable to get merge base for merged PR ID %d, Index %d in %s/%s. Error: %", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) | |||||
log.Error("Unable to get merge base for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) | |||||
continue | continue | ||||
} | } | ||||
} | } | ||||
@@ -0,0 +1,96 @@ | |||||
// Copyright 2020 The Gitea Authors. All rights reserved. | |||||
// Use of this source code is governed by a MIT-style | |||||
// license that can be found in the LICENSE file. | |||||
package migrations | |||||
import ( | |||||
"fmt" | |||||
"path/filepath" | |||||
"strings" | |||||
"code.gitea.io/gitea/modules/git" | |||||
"code.gitea.io/gitea/modules/log" | |||||
"code.gitea.io/gitea/modules/setting" | |||||
"xorm.io/xorm" | |||||
) | |||||
func refixMergeBase(x *xorm.Engine) error { | |||||
type Repository struct { | |||||
ID int64 `xorm:"pk autoincr"` | |||||
OwnerID int64 `xorm:"UNIQUE(s) index"` | |||||
OwnerName string | |||||
LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"` | |||||
Name string `xorm:"INDEX NOT NULL"` | |||||
} | |||||
type PullRequest struct { | |||||
ID int64 `xorm:"pk autoincr"` | |||||
Index int64 | |||||
HeadRepoID int64 `xorm:"INDEX"` | |||||
BaseRepoID int64 `xorm:"INDEX"` | |||||
HeadBranch string | |||||
BaseBranch string | |||||
MergeBase string `xorm:"VARCHAR(40)"` | |||||
HasMerged bool `xorm:"INDEX"` | |||||
MergedCommitID string `xorm:"VARCHAR(40)"` | |||||
} | |||||
var limit = setting.Database.IterateBufferSize | |||||
if limit <= 0 { | |||||
limit = 50 | |||||
} | |||||
i := 0 | |||||
for { | |||||
prs := make([]PullRequest, 0, 50) | |||||
if err := x.Limit(limit, i).Asc("id").Where("has_merged = ?", true).Find(&prs); err != nil { | |||||
return fmt.Errorf("Find: %v", err) | |||||
} | |||||
if len(prs) == 0 { | |||||
break | |||||
} | |||||
i += len(prs) | |||||
for _, pr := range prs { | |||||
baseRepo := &Repository{ID: pr.BaseRepoID} | |||||
has, err := x.Table("repository").Get(baseRepo) | |||||
if err != nil { | |||||
return fmt.Errorf("Unable to get base repo %d %v", pr.BaseRepoID, err) | |||||
} | |||||
if !has { | |||||
log.Error("Missing base repo with id %d for PR ID %d", pr.BaseRepoID, pr.ID) | |||||
continue | |||||
} | |||||
userPath := filepath.Join(setting.RepoRootPath, strings.ToLower(baseRepo.OwnerName)) | |||||
repoPath := filepath.Join(userPath, strings.ToLower(baseRepo.Name)+".git") | |||||
gitRefName := fmt.Sprintf("refs/pull/%d/head", pr.Index) | |||||
parentsString, err := git.NewCommand("rev-list", "--parents", "-n", "1", pr.MergedCommitID).RunInDir(repoPath) | |||||
if err != nil { | |||||
log.Error("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) | |||||
continue | |||||
} | |||||
parents := strings.Split(strings.TrimSpace(parentsString), " ") | |||||
if len(parents) < 3 { | |||||
continue | |||||
} | |||||
// we should recalculate | |||||
args := append([]string{"merge-base", "--"}, parents[1:]...) | |||||
args = append(args, gitRefName) | |||||
pr.MergeBase, err = git.NewCommand(args...).RunInDir(repoPath) | |||||
if err != nil { | |||||
log.Error("Unable to get merge base for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err) | |||||
continue | |||||
} | |||||
pr.MergeBase = strings.TrimSpace(pr.MergeBase) | |||||
x.ID(pr.ID).Cols("merge_base").Update(pr) | |||||
} | |||||
} | |||||
return nil | |||||
} |
@@ -308,7 +308,6 @@ func PrepareMergedViewPullInfo(ctx *context.Context, issue *models.Issue) *git.C | |||||
compareInfo, err := ctx.Repo.GitRepo.GetCompareInfo(ctx.Repo.Repository.RepoPath(), | compareInfo, err := ctx.Repo.GitRepo.GetCompareInfo(ctx.Repo.Repository.RepoPath(), | ||||
pull.MergeBase, pull.GetGitRefName()) | pull.MergeBase, pull.GetGitRefName()) | ||||
if err != nil { | if err != nil { | ||||
if strings.Contains(err.Error(), "fatal: Not a valid object name") { | if strings.Contains(err.Error(), "fatal: Not a valid object name") { | ||||
ctx.Data["IsPullRequestBroken"] = true | ctx.Data["IsPullRequestBroken"] = true | ||||
@@ -360,9 +359,40 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare | |||||
ctx.Data["IsPullRequestBroken"] = true | ctx.Data["IsPullRequestBroken"] = true | ||||
ctx.Data["BaseTarget"] = pull.BaseBranch | ctx.Data["BaseTarget"] = pull.BaseBranch | ||||
ctx.Data["HeadTarget"] = pull.HeadBranch | ctx.Data["HeadTarget"] = pull.HeadBranch | ||||
ctx.Data["NumCommits"] = 0 | |||||
ctx.Data["NumFiles"] = 0 | |||||
return nil | |||||
sha, err := baseGitRepo.GetRefCommitID(pull.GetGitRefName()) | |||||
if err != nil { | |||||
ctx.ServerError(fmt.Sprintf("GetRefCommitID(%s)", pull.GetGitRefName()), 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) | |||||
} | |||||
compareInfo, err := baseGitRepo.GetCompareInfo(pull.BaseRepo.RepoPath(), | |||||
pull.MergeBase, pull.GetGitRefName()) | |||||
if err != nil { | |||||
if strings.Contains(err.Error(), "fatal: Not a valid object name") { | |||||
ctx.Data["IsPullRequestBroken"] = true | |||||
ctx.Data["BaseTarget"] = pull.BaseBranch | |||||
ctx.Data["NumCommits"] = 0 | |||||
ctx.Data["NumFiles"] = 0 | |||||
return nil | |||||
} | |||||
ctx.ServerError("GetCompareInfo", err) | |||||
return nil | |||||
} | |||||
ctx.Data["NumCommits"] = compareInfo.Commits.Len() | |||||
ctx.Data["NumFiles"] = compareInfo.NumFiles | |||||
return compareInfo | |||||
} | } | ||||
var headBranchExist bool | var headBranchExist bool | ||||