From c33886fd7ad1931648fd6dd7410217ee837fe33c Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Fri, 26 Sep 2025 10:03:24 -0700 Subject: [PATCH] improvements --- models/issues/pull.go | 6 ++++++ models/migrations/v1_12/v136.go | 21 ++++++++------------- modules/gitrepo/fetch.go | 29 +++++++++++++++++++++++++++++ services/pull/pull.go | 25 ++++++++++--------------- services/repository/branch.go | 7 ++----- 5 files changed, 55 insertions(+), 33 deletions(-) create mode 100644 modules/gitrepo/fetch.go diff --git a/models/issues/pull.go b/models/issues/pull.go index fb7dff3cc9..872163e11a 100644 --- a/models/issues/pull.go +++ b/models/issues/pull.go @@ -256,6 +256,9 @@ func (pr *PullRequest) LoadHeadRepo(ctx context.Context) (err error) { return fmt.Errorf("pr[%d].LoadHeadRepo[%d]: %w", pr.ID, pr.HeadRepoID, err) } pr.isHeadRepoLoaded = true + if pr.IsSameRepo() && pr.BaseRepo == nil { + pr.BaseRepo = pr.HeadRepo + } } return nil } @@ -322,6 +325,9 @@ func (pr *PullRequest) LoadBaseRepo(ctx context.Context) (err error) { if err != nil { return fmt.Errorf("pr[%d].LoadBaseRepo[%d]: %w", pr.ID, pr.BaseRepoID, err) } + if pr.IsSameRepo() && pr.HeadRepo == nil { + pr.HeadRepo = pr.BaseRepo + } return nil } diff --git a/models/migrations/v1_12/v136.go b/models/migrations/v1_12/v136.go index 91fca2dcc7..20b892b6cc 100644 --- a/models/migrations/v1_12/v136.go +++ b/models/migrations/v1_12/v136.go @@ -6,7 +6,6 @@ package v1_12 import ( "fmt" "math" - "strings" "time" repo_model "code.gitea.io/gitea/models/repo" @@ -18,19 +17,15 @@ import ( "xorm.io/xorm" ) -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"` -} - -func (r *Repository) RelativePath() string { - return fmt.Sprintf("%s/%s.git", strings.ToLower(r.OwnerName), strings.ToLower(r.Name)) -} - func AddCommitDivergenceToPulls(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"` IssueID int64 `xorm:"INDEX"` diff --git a/modules/gitrepo/fetch.go b/modules/gitrepo/fetch.go new file mode 100644 index 0000000000..2611a91806 --- /dev/null +++ b/modules/gitrepo/fetch.go @@ -0,0 +1,29 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package gitrepo + +import ( + "context" + "fmt" + + "code.gitea.io/gitea/modules/git/gitcmd" +) + +// FetchRemoteBranch fetches a remote branch into a local branch +func FetchRemoteBranch(ctx context.Context, repo Repository, localBranch string, remoteRepo Repository, remoteBranch string, args ...string) error { + _, _, err := gitcmd.NewCommand("fetch", "--no-tags", "--refmap="). + AddDynamicArguments(repoPath(remoteRepo)). + // + means force fetch + AddDynamicArguments(fmt.Sprintf("+refs/heads/%s:%s", remoteBranch, localBranch)). + RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)}) + return err +} + +func FetchRemoteCommit(ctx context.Context, repo, remoteRepo Repository, commitID string) error { + _, _, err := gitcmd.NewCommand("fetch", "--no-tags"). + AddDynamicArguments(repoPath(remoteRepo)). + AddDynamicArguments(commitID). + RunStdString(ctx, &gitcmd.RunOpts{Dir: repoPath(repo)}) + return err +} diff --git a/services/pull/pull.go b/services/pull/pull.go index 57958b9071..f51f85e7aa 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -560,8 +560,7 @@ func UpdatePullsRefs(ctx context.Context, repo *repo_model.Repository, update *r func UpdatePullRequestAgitFlowHead(ctx context.Context, pr *issues_model.PullRequest, commitID string) error { log.Trace("UpdateAgitPullRequestHead[%d]: update pull request head in base repo '%s'", pr.ID, pr.GetGitHeadRefName()) - _, _, err := gitcmd.NewCommand("update-ref").AddDynamicArguments(pr.GetGitHeadRefName(), commitID).RunStdString(ctx, &gitcmd.RunOpts{Dir: pr.BaseRepo.RepoPath()}) - return err + return gitrepo.UpdateRef(ctx, pr.BaseRepo, pr.GetGitHeadRefName(), commitID) } // UpdatePullRequestHeadRef updates the head reference of a pull request @@ -572,21 +571,17 @@ func UpdatePullRequestGithubFlowHead(ctx context.Context, pr *issues_model.PullR return err } - if err := gitrepo.UpdateRef(ctx, pr.BaseRepo, pr.GetGitHeadRefName(), pr.HeadCommitID); err != nil { - log.Error("Unable to update ref in base repository for PR[%d] Error: %v", pr.ID, err) + if !pr.IsSameRepo() { // for cross repository pull request + if err := pr.LoadHeadRepo(ctx); err != nil { + return err + } + + if err := gitrepo.FetchRemoteBranch(ctx, pr.BaseRepo, pr.GetGitHeadRefName(), pr.HeadRepo, pr.HeadBranch); err != nil { + return err + } } - // for cross repository pull request - if err := pr.LoadHeadRepo(ctx); err != nil { - return err - } - - _, _, err := gitcmd.NewCommand("fetch", "--no-tags", "--refmap="). - AddDynamicArguments(pr.HeadRepo.RepoPath()). - // + means force fetch - AddDynamicArguments(fmt.Sprintf("+refs/heads/%s:%s", pr.HeadBranch, pr.GetGitHeadRefName())). - RunStdString(ctx, &gitcmd.RunOpts{Dir: pr.BaseRepo.RepoPath()}) - return err + return gitrepo.UpdateRef(ctx, pr.BaseRepo, pr.GetGitHeadRefName(), pr.HeadCommitID) } // retargetBranchPulls change target branch for all pull requests whose base branch is the branch diff --git a/services/repository/branch.go b/services/repository/branch.go index 6c10210d5b..a8a0c8b0f0 100644 --- a/services/repository/branch.go +++ b/services/repository/branch.go @@ -19,7 +19,6 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/git" - "code.gitea.io/gitea/modules/git/gitcmd" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/json" @@ -719,10 +718,8 @@ func GetBranchDivergingInfo(ctx reqctx.RequestContext, baseRepo *repo_model.Repo // we need fetch the necessary commits from the head repo first if it's not the same repository if baseRepo.ID != headRepo.ID { - if _, _, err := gitcmd.NewCommand("fetch", "--no-tags"). - AddDynamicArguments(headRepo.RepoPath()). - AddDynamicArguments(headGitBranch.CommitID). - RunStdString(ctx, &gitcmd.RunOpts{Dir: baseRepo.RepoPath()}); err != nil { + // git default will gc the commit in 2 weeks, so it's safe to do the compare + if err := gitrepo.FetchRemoteCommit(ctx, baseRepo, headRepo, headGitBranch.CommitID); err != nil { return nil, err } }