* 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.21.12.1
| @@ -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 | ||||