浏览代码

Display pull request head branch even the branch deleted or repository deleted (#10413)

* Display pull request head branch even the branch deleted or repository deleted

* Merge getHeadRepo/loadHeadRepo and getBaseRepo/loadBaseRepo on pull and fill repo when pr.Issue.Repo is available

* retrieve sha from pull head when pull request branch deleted and fix tests

* Fix test

* Ensure MustHeadRepoName returns empty string if no head repo

Co-authored-by: zeripath <art27@cantab.net>
tags/v1.10.5
Lunny Xiao 4 年前
父节点
当前提交
5abe1c52de
没有帐户链接到提交者的电子邮件

+ 50
- 54
models/pull.go 查看文件

MergerID int64 `xorm:"INDEX"` MergerID int64 `xorm:"INDEX"`
Merger *User `xorm:"-"` Merger *User `xorm:"-"`
MergedUnix timeutil.TimeStamp `xorm:"updated INDEX"` MergedUnix timeutil.TimeStamp `xorm:"updated INDEX"`

isHeadRepoLoaded bool `xorm:"-"`
} }


// MustHeadUserName returns the HeadRepo's username if failed return blank // MustHeadUserName returns the HeadRepo's username if failed return blank
} }
return "" return ""
} }
if pr.HeadRepo == nil {
return ""
}
return pr.HeadRepo.OwnerName return pr.HeadRepo.OwnerName
} }


return pr.loadAttributes(x) return pr.loadAttributes(x)
} }


// LoadBaseRepo loads pull request base repository from database
func (pr *PullRequest) LoadBaseRepo() error {
if pr.BaseRepo == nil {
if pr.HeadRepoID == pr.BaseRepoID && pr.HeadRepo != nil {
pr.BaseRepo = pr.HeadRepo
return nil
func (pr *PullRequest) loadHeadRepo(e Engine) (err error) {
if !pr.isHeadRepoLoaded && pr.HeadRepo == nil && pr.HeadRepoID > 0 {
if pr.HeadRepoID == pr.BaseRepoID {
if pr.BaseRepo != nil {
pr.HeadRepo = pr.BaseRepo
return nil
} else if pr.Issue != nil && pr.Issue.Repo != nil {
pr.HeadRepo = pr.Issue.Repo
return nil
}
} }
var repo Repository
if has, err := x.ID(pr.BaseRepoID).Get(&repo); err != nil {
return err
} else if !has {
return ErrRepoNotExist{ID: pr.BaseRepoID}

pr.HeadRepo, err = getRepositoryByID(e, pr.HeadRepoID)
if err != nil && !IsErrRepoNotExist(err) { // Head repo maybe deleted, but it should still work
return fmt.Errorf("getRepositoryByID(head): %v", err)
} }
pr.BaseRepo = &repo
pr.isHeadRepoLoaded = true
} }
return nil return nil
} }


// LoadHeadRepo loads pull request head repository from database
// LoadHeadRepo loads the head repository
func (pr *PullRequest) LoadHeadRepo() error { func (pr *PullRequest) LoadHeadRepo() error {
if pr.HeadRepo == nil {
if pr.HeadRepoID == pr.BaseRepoID && pr.BaseRepo != nil {
pr.HeadRepo = pr.BaseRepo
return nil
}
var repo Repository
if has, err := x.ID(pr.HeadRepoID).Get(&repo); err != nil {
return err
} else if !has {
return ErrRepoNotExist{ID: pr.HeadRepoID}
}
pr.HeadRepo = &repo
return pr.loadHeadRepo(x)
}

// LoadBaseRepo loads the target repository
func (pr *PullRequest) LoadBaseRepo() error {
return pr.loadBaseRepo(x)
}

func (pr *PullRequest) loadBaseRepo(e Engine) (err error) {
if pr.BaseRepo != nil {
return nil
}

if pr.HeadRepoID == pr.BaseRepoID && pr.HeadRepo != nil {
pr.BaseRepo = pr.HeadRepo
return nil
}

if pr.Issue != nil && pr.Issue.Repo != nil {
pr.BaseRepo = pr.Issue.Repo
return nil
}

pr.BaseRepo, err = getRepositoryByID(e, pr.BaseRepoID)
if err != nil {
return fmt.Errorf("GetRepositoryByID(base): %v", err)
} }
return nil return nil
} }
return fmt.Sprintf("refs/pull/%d/head", pr.Index) return fmt.Sprintf("refs/pull/%d/head", pr.Index)
} }


func (pr *PullRequest) getHeadRepo(e Engine) (err error) {
pr.HeadRepo, err = getRepositoryByID(e, pr.HeadRepoID)
if err != nil && !IsErrRepoNotExist(err) {
return fmt.Errorf("getRepositoryByID(head): %v", err)
}
return nil
}

// GetHeadRepo loads the head repository
func (pr *PullRequest) GetHeadRepo() error {
return pr.getHeadRepo(x)
}

// GetBaseRepo loads the target repository
func (pr *PullRequest) GetBaseRepo() (err error) {
if pr.BaseRepo != nil {
return nil
}

pr.BaseRepo, err = GetRepositoryByID(pr.BaseRepoID)
if err != nil {
return fmt.Errorf("GetRepositoryByID(base): %v", err)
}
return nil
}

// IsChecking returns true if this pull request is still checking conflict. // IsChecking returns true if this pull request is still checking conflict.
func (pr *PullRequest) IsChecking() bool { func (pr *PullRequest) IsChecking() bool {
return pr.Status == PullRequestStatusChecking return pr.Status == PullRequestStatusChecking


// GetLastCommitStatus returns the last commit status for this pull request. // GetLastCommitStatus returns the last commit status for this pull request.
func (pr *PullRequest) GetLastCommitStatus() (status *CommitStatus, err error) { func (pr *PullRequest) GetLastCommitStatus() (status *CommitStatus, err error) {
if err = pr.GetHeadRepo(); err != nil {
if err = pr.LoadHeadRepo(); err != nil {
return nil, err return nil, err
} }


// IsHeadEqualWithBranch returns if the commits of branchName are available in pull request head // IsHeadEqualWithBranch returns if the commits of branchName are available in pull request head
func (pr *PullRequest) IsHeadEqualWithBranch(branchName string) (bool, error) { func (pr *PullRequest) IsHeadEqualWithBranch(branchName string) (bool, error) {
var err error var err error
if err = pr.GetBaseRepo(); err != nil {
if err = pr.LoadBaseRepo(); err != nil {
return false, err return false, err
} }
baseGitRepo, err := git.OpenRepository(pr.BaseRepo.RepoPath()) baseGitRepo, err := git.OpenRepository(pr.BaseRepo.RepoPath())
return false, err return false, err
} }


if err = pr.GetHeadRepo(); err != nil {
if err = pr.LoadHeadRepo(); err != nil {
return false, err return false, err
} }
headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath()) headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())

+ 1
- 1
models/pull_sign.go 查看文件



// SignMerge determines if we should sign a PR merge commit to the base repository // SignMerge determines if we should sign a PR merge commit to the base repository
func (pr *PullRequest) SignMerge(u *User, tmpBasePath, baseCommit, headCommit string) (bool, string, error) { func (pr *PullRequest) SignMerge(u *User, tmpBasePath, baseCommit, headCommit string) (bool, string, error) {
if err := pr.GetBaseRepo(); err != nil {
if err := pr.LoadBaseRepo(); err != nil {
log.Error("Unable to get Base Repo for pull request") log.Error("Unable to get Base Repo for pull request")
return false, "", err return false, "", err
} }

+ 5
- 5
models/pull_test.go 查看文件

assert.Equal(t, int64(2), pr.Issue.ID) assert.Equal(t, int64(2), pr.Issue.ID)
} }


func TestPullRequest_GetBaseRepo(t *testing.T) {
func TestPullRequest_LoadBaseRepo(t *testing.T) {
assert.NoError(t, PrepareTestDatabase()) assert.NoError(t, PrepareTestDatabase())
pr := AssertExistsAndLoadBean(t, &PullRequest{ID: 1}).(*PullRequest) pr := AssertExistsAndLoadBean(t, &PullRequest{ID: 1}).(*PullRequest)
assert.NoError(t, pr.GetBaseRepo())
assert.NoError(t, pr.LoadBaseRepo())
assert.NotNil(t, pr.BaseRepo) assert.NotNil(t, pr.BaseRepo)
assert.Equal(t, pr.BaseRepoID, pr.BaseRepo.ID) assert.Equal(t, pr.BaseRepoID, pr.BaseRepo.ID)
assert.NoError(t, pr.GetBaseRepo())
assert.NoError(t, pr.LoadBaseRepo())
assert.NotNil(t, pr.BaseRepo) assert.NotNil(t, pr.BaseRepo)
assert.Equal(t, pr.BaseRepoID, pr.BaseRepo.ID) assert.Equal(t, pr.BaseRepoID, pr.BaseRepo.ID)
} }


func TestPullRequest_GetHeadRepo(t *testing.T) {
func TestPullRequest_LoadHeadRepo(t *testing.T) {
assert.NoError(t, PrepareTestDatabase()) assert.NoError(t, PrepareTestDatabase())
pr := AssertExistsAndLoadBean(t, &PullRequest{ID: 1}).(*PullRequest) pr := AssertExistsAndLoadBean(t, &PullRequest{ID: 1}).(*PullRequest)
assert.NoError(t, pr.GetHeadRepo())
assert.NoError(t, pr.LoadHeadRepo())
assert.NotNil(t, pr.HeadRepo) assert.NotNil(t, pr.HeadRepo)
assert.Equal(t, pr.HeadRepoID, pr.HeadRepo.ID) assert.Equal(t, pr.HeadRepoID, pr.HeadRepo.ID)
} }

+ 59
- 62
modules/convert/pull.go 查看文件

baseBranch *git.Branch baseBranch *git.Branch
headBranch *git.Branch headBranch *git.Branch
baseCommit *git.Commit baseCommit *git.Commit
headCommit *git.Commit
err error err error
) )


} }


apiIssue := ToAPIIssue(pr.Issue) apiIssue := ToAPIIssue(pr.Issue)
if pr.BaseRepo == nil {
pr.BaseRepo, err = models.GetRepositoryByID(pr.BaseRepoID)
if err != nil {
log.Error("GetRepositoryById[%d]: %v", pr.ID, err)
return nil
}
if err := pr.LoadBaseRepo(); err != nil {
log.Error("GetRepositoryById[%d]: %v", pr.ID, err)
return nil
} }
if pr.HeadRepoID != 0 && pr.HeadRepo == nil {
pr.HeadRepo, err = models.GetRepositoryByID(pr.HeadRepoID)
if err != nil && !models.IsErrRepoNotExist(err) {
log.Error("GetRepositoryById[%d]: %v", pr.ID, err)
return nil


}
if err := pr.LoadHeadRepo(); err != nil {
log.Error("GetRepositoryById[%d]: %v", pr.ID, err)
return nil
} }


apiPullRequest := &api.PullRequest{ apiPullRequest := &api.PullRequest{
Deadline: apiIssue.Deadline, Deadline: apiIssue.Deadline,
Created: pr.Issue.CreatedUnix.AsTimePtr(), Created: pr.Issue.CreatedUnix.AsTimePtr(),
Updated: pr.Issue.UpdatedUnix.AsTimePtr(), Updated: pr.Issue.UpdatedUnix.AsTimePtr(),
}
baseBranch, err = repo_module.GetBranch(pr.BaseRepo, pr.BaseBranch)
if err != nil {
if git.IsErrBranchNotExist(err) {
apiPullRequest.Base = nil
} else {
log.Error("GetBranch[%s]: %v", pr.BaseBranch, err)
return nil
}
} else {
apiBaseBranchInfo := &api.PRBranchInfo{

Base: &api.PRBranchInfo{
Name: pr.BaseBranch, Name: pr.BaseBranch,
Ref: pr.BaseBranch, Ref: pr.BaseBranch,
RepoID: pr.BaseRepoID, RepoID: pr.BaseRepoID,
Repository: pr.BaseRepo.APIFormat(models.AccessModeNone), Repository: pr.BaseRepo.APIFormat(models.AccessModeNone),
}
},
Head: &api.PRBranchInfo{
Name: pr.HeadBranch,
Ref: fmt.Sprintf("refs/pull/%d/head", pr.Index),
RepoID: -1,
},
}

baseBranch, err = repo_module.GetBranch(pr.BaseRepo, pr.BaseBranch)
if err != nil && !git.IsErrBranchNotExist(err) {
log.Error("GetBranch[%s]: %v", pr.BaseBranch, err)
return nil
}

if err == nil {
baseCommit, err = baseBranch.GetCommit() baseCommit, err = baseBranch.GetCommit()
if err != nil {
if git.IsErrNotExist(err) {
apiBaseBranchInfo.Sha = ""
} else {
log.Error("GetCommit[%s]: %v", baseBranch.Name, err)
return nil
}
} else {
apiBaseBranchInfo.Sha = baseCommit.ID.String()
if err != nil && !git.IsErrNotExist(err) {
log.Error("GetCommit[%s]: %v", baseBranch.Name, err)
return nil
}

if err == nil {
apiPullRequest.Base.Sha = baseCommit.ID.String()
} }
apiPullRequest.Base = apiBaseBranchInfo
} }


if pr.HeadRepo != nil { if pr.HeadRepo != nil {
headBranch, err = repo_module.GetBranch(pr.HeadRepo, pr.HeadBranch)
apiPullRequest.Head.RepoID = pr.HeadRepo.ID
apiPullRequest.Head.Repository = pr.HeadRepo.APIFormat(models.AccessModeNone)

headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
if err != nil { if err != nil {
if git.IsErrBranchNotExist(err) {
apiPullRequest.Head = nil
} else {
log.Error("GetBranch[%s]: %v", pr.HeadBranch, err)
log.Error("OpenRepository[%s]: %v", pr.HeadRepo.RepoPath(), err)
return nil
}
defer headGitRepo.Close()

headBranch, err = headGitRepo.GetBranch(pr.HeadBranch)
if err != nil && !git.IsErrBranchNotExist(err) {
log.Error("GetBranch[%s]: %v", pr.HeadBranch, err)
return nil
}

if git.IsErrBranchNotExist(err) {
headCommitID, err := headGitRepo.GetRefCommitID(apiPullRequest.Head.Ref)
if err != nil && !git.IsErrNotExist(err) {
log.Error("GetCommit[%s]: %v", headBranch.Name, err)
return nil return nil
} }
if err == nil {
apiPullRequest.Head.Sha = headCommitID
}
} else { } else {
apiHeadBranchInfo := &api.PRBranchInfo{
Name: pr.HeadBranch,
Ref: pr.HeadBranch,
RepoID: pr.HeadRepoID,
Repository: pr.HeadRepo.APIFormat(models.AccessModeNone),
commit, err := headBranch.GetCommit()
if err != nil && !git.IsErrNotExist(err) {
log.Error("GetCommit[%s]: %v", headBranch.Name, err)
return nil
} }
headCommit, err = headBranch.GetCommit()
if err != nil {
if git.IsErrNotExist(err) {
apiHeadBranchInfo.Sha = ""
} else {
log.Error("GetCommit[%s]: %v", headBranch.Name, err)
return nil
}
} else {
apiHeadBranchInfo.Sha = headCommit.ID.String()
if err == nil {
apiPullRequest.Head.Ref = pr.HeadBranch
apiPullRequest.Head.Sha = commit.ID.String()
} }
apiPullRequest.Head = apiHeadBranchInfo
}
} else {
apiPullRequest.Head = &api.PRBranchInfo{
Name: pr.HeadBranch,
Ref: fmt.Sprintf("refs/pull/%d/head", pr.Index),
RepoID: -1,
} }
} }



+ 9
- 1
modules/convert/pull_test.go 查看文件

"testing" "testing"


"code.gitea.io/gitea/models" "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/structs"


"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestPullRequest_APIFormat(t *testing.T) { func TestPullRequest_APIFormat(t *testing.T) {
//with HeadRepo //with HeadRepo
assert.NoError(t, models.PrepareTestDatabase()) assert.NoError(t, models.PrepareTestDatabase())
headRepo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)
pr := models.AssertExistsAndLoadBean(t, &models.PullRequest{ID: 1}).(*models.PullRequest) pr := models.AssertExistsAndLoadBean(t, &models.PullRequest{ID: 1}).(*models.PullRequest)
assert.NoError(t, pr.LoadAttributes()) assert.NoError(t, pr.LoadAttributes())
assert.NoError(t, pr.LoadIssue()) assert.NoError(t, pr.LoadIssue())
apiPullRequest := ToAPIPullRequest(pr) apiPullRequest := ToAPIPullRequest(pr)
assert.NotNil(t, apiPullRequest) assert.NotNil(t, apiPullRequest)
assert.Nil(t, apiPullRequest.Head)
assert.EqualValues(t, &structs.PRBranchInfo{
Name: "branch1",
Ref: "refs/pull/2/head",
Sha: "4a357436d925b5c974181ff12a994538ddc5a269",
RepoID: 1,
Repository: headRepo.APIFormat(models.AccessModeNone),
}, apiPullRequest.Head)


//withOut HeadRepo //withOut HeadRepo
pr = models.AssertExistsAndLoadBean(t, &models.PullRequest{ID: 1}).(*models.PullRequest) pr = models.AssertExistsAndLoadBean(t, &models.PullRequest{ID: 1}).(*models.PullRequest)

+ 10
- 10
routers/api/v1/repo/pull.go 查看文件

ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
return return
} }
if err = prs[i].GetBaseRepo(); err != nil {
ctx.Error(http.StatusInternalServerError, "GetBaseRepo", err)
if err = prs[i].LoadBaseRepo(); err != nil {
ctx.Error(http.StatusInternalServerError, "LoadBaseRepo", err)
return return
} }
if err = prs[i].GetHeadRepo(); err != nil {
ctx.Error(http.StatusInternalServerError, "GetHeadRepo", err)
if err = prs[i].LoadHeadRepo(); err != nil {
ctx.Error(http.StatusInternalServerError, "LoadHeadRepo", err)
return return
} }
apiPrs[i] = convert.ToAPIPullRequest(prs[i]) apiPrs[i] = convert.ToAPIPullRequest(prs[i])
return return
} }


if err = pr.GetBaseRepo(); err != nil {
ctx.Error(http.StatusInternalServerError, "GetBaseRepo", err)
if err = pr.LoadBaseRepo(); err != nil {
ctx.Error(http.StatusInternalServerError, "LoadBaseRepo", err)
return return
} }
if err = pr.GetHeadRepo(); err != nil {
ctx.Error(http.StatusInternalServerError, "GetHeadRepo", err)
if err = pr.LoadHeadRepo(); err != nil {
ctx.Error(http.StatusInternalServerError, "LoadHeadRepo", err)
return return
} }
ctx.JSON(http.StatusOK, convert.ToAPIPullRequest(pr)) ctx.JSON(http.StatusOK, convert.ToAPIPullRequest(pr))
return return
} }


if err = pr.GetHeadRepo(); err != nil {
ctx.ServerError("GetHeadRepo", err)
if err = pr.LoadHeadRepo(); err != nil {
ctx.ServerError("LoadHeadRepo", err)
return return
} }



+ 4
- 4
routers/repo/issue.go 查看文件

ctx.Data["AllowMerge"] = false ctx.Data["AllowMerge"] = false


if ctx.IsSigned { if ctx.IsSigned {
if err := pull.GetHeadRepo(); err != nil {
log.Error("GetHeadRepo: %v", err)
if err := pull.LoadHeadRepo(); err != nil {
log.Error("LoadHeadRepo: %v", err)
} else if pull.HeadRepo != nil && pull.HeadBranch != pull.HeadRepo.DefaultBranch { } else if pull.HeadRepo != nil && pull.HeadBranch != pull.HeadRepo.DefaultBranch {
perm, err := models.GetUserRepoPermission(pull.HeadRepo, ctx.User) perm, err := models.GetUserRepoPermission(pull.HeadRepo, ctx.User)
if err != nil { if err != nil {
} }
} }


if err := pull.GetBaseRepo(); err != nil {
log.Error("GetBaseRepo: %v", err)
if err := pull.LoadBaseRepo(); err != nil {
log.Error("LoadBaseRepo: %v", err)
} }
perm, err := models.GetUserRepoPermission(pull.BaseRepo, ctx.User) perm, err := models.GetUserRepoPermission(pull.BaseRepo, ctx.User)
if err != nil { if err != nil {

+ 21
- 13
routers/repo/pull.go 查看文件

return nil return nil
} }


if err = issue.PullRequest.GetHeadRepo(); err != nil {
ctx.ServerError("GetHeadRepo", err)
if err = issue.PullRequest.LoadHeadRepo(); err != nil {
ctx.ServerError("LoadHeadRepo", err)
return nil return nil
} }


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
ctx.Data["BaseTarget"] = "deleted"
ctx.Data["BaseTarget"] = pull.BaseBranch
ctx.Data["NumCommits"] = 0 ctx.Data["NumCommits"] = 0
ctx.Data["NumFiles"] = 0 ctx.Data["NumFiles"] = 0
return nil return nil
repo := ctx.Repo.Repository repo := ctx.Repo.Repository
pull := issue.PullRequest pull := issue.PullRequest


if err := pull.GetHeadRepo(); err != nil {
ctx.ServerError("GetHeadRepo", err)
if err := pull.LoadHeadRepo(); err != nil {
ctx.ServerError("LoadHeadRepo", err)
return nil return nil
} }


if err := pull.GetBaseRepo(); err != nil {
ctx.ServerError("GetBaseRepo", err)
if err := pull.LoadBaseRepo(); err != nil {
ctx.ServerError("LoadBaseRepo", err)
return nil return nil
} }




if pull.HeadRepo == nil || !headBranchExist || headBranchSha != sha { if pull.HeadRepo == nil || !headBranchExist || headBranchSha != sha {
ctx.Data["IsPullRequestBroken"] = true ctx.Data["IsPullRequestBroken"] = true
ctx.Data["HeadTarget"] = "deleted"
if pull.IsSameRepo() {
ctx.Data["HeadTarget"] = pull.HeadBranch
} else {
if pull.HeadRepo == nil {
ctx.Data["HeadTarget"] = "<deleted>:" + pull.HeadBranch
} else {
ctx.Data["HeadTarget"] = pull.HeadRepo.OwnerName + ":" + pull.HeadBranch
}
}
} }


compareInfo, err := baseGitRepo.GetCompareInfo(pull.BaseRepo.RepoPath(), compareInfo, err := baseGitRepo.GetCompareInfo(pull.BaseRepo.RepoPath(),
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
ctx.Data["BaseTarget"] = "deleted"
ctx.Data["BaseTarget"] = pull.BaseBranch
ctx.Data["NumCommits"] = 0 ctx.Data["NumCommits"] = 0
ctx.Data["NumFiles"] = 0 ctx.Data["NumFiles"] = 0
return nil return nil
return return
} }


if err := pr.GetHeadRepo(); err != nil {
ctx.ServerError("GetHeadRepo", err)
if err := pr.LoadHeadRepo(); err != nil {
ctx.ServerError("LoadHeadRepo", err)
return return
} else if pr.HeadRepo == nil { } else if pr.HeadRepo == nil {
// Forked repository has already been deleted // Forked repository has already been deleted
ctx.NotFound("CleanUpPullRequest", nil) ctx.NotFound("CleanUpPullRequest", nil)
return return
} else if err = pr.GetBaseRepo(); err != nil {
ctx.ServerError("GetBaseRepo", err)
} else if err = pr.LoadBaseRepo(); err != nil {
ctx.ServerError("LoadBaseRepo", err)
return return
} else if err = pr.HeadRepo.GetOwner(); err != nil { } else if err = pr.HeadRepo.GetOwner(); err != nil {
ctx.ServerError("HeadRepo.GetOwner", err) ctx.ServerError("HeadRepo.GetOwner", err)

+ 13
- 17
services/pull/merge.go 查看文件

// Caller should check PR is ready to be merged (review and status checks) // Caller should check PR is ready to be merged (review and status checks)
// FIXME: add repoWorkingPull make sure two merges does not happen at same time. // FIXME: add repoWorkingPull make sure two merges does not happen at same time.
func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repository, mergeStyle models.MergeStyle, message string) (err error) { func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repository, mergeStyle models.MergeStyle, message string) (err error) {

if err = pr.GetHeadRepo(); err != nil {
log.Error("GetHeadRepo: %v", err)
return fmt.Errorf("GetHeadRepo: %v", err)
} else if err = pr.GetBaseRepo(); err != nil {
log.Error("GetBaseRepo: %v", err)
return fmt.Errorf("GetBaseRepo: %v", err)
if err = pr.LoadHeadRepo(); err != nil {
log.Error("LoadHeadRepo: %v", err)
return fmt.Errorf("LoadHeadRepo: %v", err)
} else if err = pr.LoadBaseRepo(); err != nil {
log.Error("LoadBaseRepo: %v", err)
return fmt.Errorf("LoadBaseRepo: %v", err)
} }


prUnit, err := pr.BaseRepo.GetUnit(models.UnitTypePullRequests) prUnit, err := pr.BaseRepo.GetUnit(models.UnitTypePullRequests)


// CheckPRReadyToMerge checks whether the PR is ready to be merged (reviews and status checks) // CheckPRReadyToMerge checks whether the PR is ready to be merged (reviews and status checks)
func CheckPRReadyToMerge(pr *models.PullRequest) (err error) { func CheckPRReadyToMerge(pr *models.PullRequest) (err error) {
if pr.BaseRepo == nil {
if err = pr.GetBaseRepo(); err != nil {
return fmt.Errorf("GetBaseRepo: %v", err)
}
if err = pr.LoadBaseRepo(); err != nil {
return fmt.Errorf("LoadBaseRepo: %v", err)
}

if err = pr.LoadProtectedBranch(); err != nil {
return fmt.Errorf("LoadProtectedBranch: %v", err)
} }
if pr.ProtectedBranch == nil { if pr.ProtectedBranch == nil {
if err = pr.LoadProtectedBranch(); err != nil {
return fmt.Errorf("LoadProtectedBranch: %v", err)
}
if pr.ProtectedBranch == nil {
return nil
}
return nil
} }


isPass, err := IsPullCommitStatusPass(pr) isPass, err := IsPullCommitStatusPass(pr)

+ 4
- 5
services/pull/pull.go 查看文件

// checkIfPRContentChanged checks if diff to target branch has changed by push // checkIfPRContentChanged checks if diff to target branch has changed by push
// A commit can be considered to leave the PR untouched if the patch/diff with its merge base is unchanged // A commit can be considered to leave the PR untouched if the patch/diff with its merge base is unchanged
func checkIfPRContentChanged(pr *models.PullRequest, oldCommitID, newCommitID string) (hasChanged bool, err error) { func checkIfPRContentChanged(pr *models.PullRequest, oldCommitID, newCommitID string) (hasChanged bool, err error) {

if err = pr.GetHeadRepo(); err != nil {
return false, fmt.Errorf("GetHeadRepo: %v", err)
if err = pr.LoadHeadRepo(); err != nil {
return false, fmt.Errorf("LoadHeadRepo: %v", err)
} else if pr.HeadRepo == nil { } else if pr.HeadRepo == nil {
// corrupt data assumed changed // corrupt data assumed changed
return true, nil return true, nil
} }


if err = pr.GetBaseRepo(); err != nil {
return false, fmt.Errorf("GetBaseRepo: %v", err)
if err = pr.LoadBaseRepo(); err != nil {
return false, fmt.Errorf("LoadBaseRepo: %v", err)
} }


headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath()) headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())

+ 2
- 2
services/pull/review.go 查看文件

return nil, fmt.Errorf("GetPullRequestByIssueID: %v", err) return nil, fmt.Errorf("GetPullRequestByIssueID: %v", err)
} }
pr := issue.PullRequest pr := issue.PullRequest
if err := pr.GetBaseRepo(); err != nil {
return nil, fmt.Errorf("GetHeadRepo: %v", err)
if err := pr.LoadBaseRepo(); err != nil {
return nil, fmt.Errorf("LoadHeadRepo: %v", err)
} }
gitRepo, err := git.OpenRepository(pr.BaseRepo.RepoPath()) gitRepo, err := git.OpenRepository(pr.BaseRepo.RepoPath())
if err != nil { if err != nil {

+ 6
- 6
services/pull/temp_repo.go 查看文件

) )


func createTemporaryRepo(pr *models.PullRequest) (string, error) { func createTemporaryRepo(pr *models.PullRequest) (string, error) {
if err := pr.GetHeadRepo(); err != nil {
log.Error("GetHeadRepo: %v", err)
return "", fmt.Errorf("GetHeadRepo: %v", err)
if err := pr.LoadHeadRepo(); err != nil {
log.Error("LoadHeadRepo: %v", err)
return "", fmt.Errorf("LoadHeadRepo: %v", err)
} else if pr.HeadRepo == nil { } else if pr.HeadRepo == nil {
log.Error("Pr %d HeadRepo %d does not exist", pr.ID, pr.HeadRepoID) log.Error("Pr %d HeadRepo %d does not exist", pr.ID, pr.HeadRepoID)
return "", &models.ErrRepoNotExist{ return "", &models.ErrRepoNotExist{
ID: pr.HeadRepoID, ID: pr.HeadRepoID,
} }
} else if err := pr.GetBaseRepo(); err != nil {
log.Error("GetBaseRepo: %v", err)
return "", fmt.Errorf("GetBaseRepo: %v", err)
} else if err := pr.LoadBaseRepo(); err != nil {
log.Error("LoadBaseRepo: %v", err)
return "", fmt.Errorf("LoadBaseRepo: %v", err)
} else if pr.BaseRepo == nil { } else if pr.BaseRepo == nil {
log.Error("Pr %d BaseRepo %d does not exist", pr.ID, pr.BaseRepoID) log.Error("Pr %d BaseRepo %d does not exist", pr.ID, pr.BaseRepoID)
return "", &models.ErrRepoNotExist{ return "", &models.ErrRepoNotExist{

正在加载...
取消
保存