chore: Refactor Is{Reference,Branch}Exist (#8425)
		
	- Instead of invoking a new git command to check if a reference exists, use the already opened git repository that uses a batch check to check if the reference exists. - Instead of invoking a new git command to check if a branch exists, use the already opened git repository that uses a batch check to check if the branch exists. - Do not depend on `IsReferenceExist` as its no longer used by any other function. - Specify `--quiet` to not waste Git's time on printing something we do not use. - Run it via `Run` so no buffers are created for stdout and stderr. - Add a test that verifies `IsBranchExist` works and does not work for other types of references. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8425 Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org> Co-authored-by: Gusted <postmaster@gusted.xyz> Co-committed-by: Gusted <postmaster@gusted.xyz>
This commit is contained in:
		
					parent
					
						
							
								212e8ac348
							
						
					
				
			
			
				commit
				
					
						74981d9e97
					
				
			
		
					 6 changed files with 21 additions and 13 deletions
				
			
		| 
						 | 
				
			
			@ -19,15 +19,9 @@ import (
 | 
			
		|||
// BranchPrefix base dir of the branch information file store on git
 | 
			
		||||
const BranchPrefix = "refs/heads/"
 | 
			
		||||
 | 
			
		||||
// IsReferenceExist returns true if given reference exists in the repository.
 | 
			
		||||
func IsReferenceExist(ctx context.Context, repoPath, name string) bool {
 | 
			
		||||
	_, _, err := NewCommand(ctx, "show-ref", "--verify").AddDashesAndList(name).RunStdString(&RunOpts{Dir: repoPath})
 | 
			
		||||
	return err == nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsBranchExist returns true if given branch exists in the repository.
 | 
			
		||||
func IsBranchExist(ctx context.Context, repoPath, name string) bool {
 | 
			
		||||
	return IsReferenceExist(ctx, repoPath, BranchPrefix+name)
 | 
			
		||||
	return NewCommand(ctx, "show-ref", "--verify", "--quiet").AddDashesAndList(BranchPrefix+name).Run(&RunOpts{Dir: repoPath}) == nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Branch represents a Git branch.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
// Copyright 2018 The Gitea Authors. All rights reserved.
 | 
			
		||||
// Copyright 2025 The Forgejo Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package git
 | 
			
		||||
| 
						 | 
				
			
			@ -195,3 +196,17 @@ func TestRepository_IsReferenceExist(t *testing.T) {
 | 
			
		|||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestIsBranchExist(t *testing.T) {
 | 
			
		||||
	repo1Path := filepath.Join(testReposDir, "repo1_bare")
 | 
			
		||||
 | 
			
		||||
	assert.True(t, IsBranchExist(t.Context(), repo1Path, "branch1"))
 | 
			
		||||
	assert.True(t, IsBranchExist(t.Context(), repo1Path, "branch2"))
 | 
			
		||||
	assert.True(t, IsBranchExist(t.Context(), repo1Path, "master"))
 | 
			
		||||
 | 
			
		||||
	assert.False(t, IsBranchExist(t.Context(), repo1Path, "HEAD"))
 | 
			
		||||
	assert.False(t, IsBranchExist(t.Context(), repo1Path, "153f451b9ee7fa1da317ab17a127e9fd9d384310"))
 | 
			
		||||
	assert.False(t, IsBranchExist(t.Context(), repo1Path, "153f451b9ee7fa1da317ab17a127e9fd9d384310"))
 | 
			
		||||
	assert.False(t, IsBranchExist(t.Context(), repo1Path, "signed-tag"))
 | 
			
		||||
	assert.False(t, IsBranchExist(t.Context(), repo1Path, "test"))
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -594,7 +594,7 @@ func CreateBranchProtection(ctx *context.APIContext) {
 | 
			
		|||
	isPlainRule := !git_model.IsRuleNameSpecial(ruleName)
 | 
			
		||||
	var isBranchExist bool
 | 
			
		||||
	if isPlainRule {
 | 
			
		||||
		isBranchExist = git.IsBranchExist(ctx.Req.Context(), ctx.Repo.Repository.RepoPath(), ruleName)
 | 
			
		||||
		isBranchExist = ctx.Repo.GitRepo.IsBranchExist(ruleName)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protectBranch, err := git_model.GetProtectedBranchRuleByName(ctx, repo.ID, ruleName)
 | 
			
		||||
| 
						 | 
				
			
			@ -982,7 +982,7 @@ func EditBranchProtection(ctx *context.APIContext) {
 | 
			
		|||
	isPlainRule := !git_model.IsRuleNameSpecial(bpName)
 | 
			
		||||
	var isBranchExist bool
 | 
			
		||||
	if isPlainRule {
 | 
			
		||||
		isBranchExist = git.IsBranchExist(ctx.Req.Context(), ctx.Repo.Repository.RepoPath(), bpName)
 | 
			
		||||
		isBranchExist = ctx.Repo.GitRepo.IsBranchExist(bpName)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if isBranchExist {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -638,7 +638,7 @@ func PrepareViewPullInfo(ctx *context.Context, issue *issues_model.Issue) *git.C
 | 
			
		|||
		if pull.Flow == issues_model.PullRequestFlowGithub {
 | 
			
		||||
			headBranchExist = headGitRepo.IsBranchExist(pull.HeadBranch)
 | 
			
		||||
		} else {
 | 
			
		||||
			headBranchExist = git.IsReferenceExist(ctx, baseGitRepo.Path, pull.GetGitRefName())
 | 
			
		||||
			headBranchExist = headGitRepo.IsReferenceExist(pull.GetGitRefName())
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if headBranchExist {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -162,7 +162,7 @@ func handlePullRequestAutoMerge(pullID int64, sha string) {
 | 
			
		|||
			return
 | 
			
		||||
		}
 | 
			
		||||
	case issues_model.PullRequestFlowAGit:
 | 
			
		||||
		headBranchExist := git.IsReferenceExist(ctx, baseGitRepo.Path, pr.GetGitRefName())
 | 
			
		||||
		headBranchExist := headGitRepo.IsReferenceExist(pr.GetGitRefName())
 | 
			
		||||
		if !headBranchExist {
 | 
			
		||||
			log.Warn("Head branch of auto merge %-v does not exist [HeadRepoID: %d, Branch(Agit): %s]", pr, pr.HeadRepoID, pr.HeadBranch)
 | 
			
		||||
			return
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,6 @@ import (
 | 
			
		|||
	"forgejo.org/models/db"
 | 
			
		||||
	git_model "forgejo.org/models/git"
 | 
			
		||||
	issues_model "forgejo.org/models/issues"
 | 
			
		||||
	"forgejo.org/modules/git"
 | 
			
		||||
	"forgejo.org/modules/gitrepo"
 | 
			
		||||
	"forgejo.org/modules/log"
 | 
			
		||||
	"forgejo.org/modules/structs"
 | 
			
		||||
| 
						 | 
				
			
			@ -105,7 +104,7 @@ func GetPullRequestCommitStatusState(ctx context.Context, pr *issues_model.PullR
 | 
			
		|||
	if pr.Flow == issues_model.PullRequestFlowGithub && !headGitRepo.IsBranchExist(pr.HeadBranch) {
 | 
			
		||||
		return "", errors.New("head branch does not exist, can not merge")
 | 
			
		||||
	}
 | 
			
		||||
	if pr.Flow == issues_model.PullRequestFlowAGit && !git.IsReferenceExist(ctx, headGitRepo.Path, pr.GetGitRefName()) {
 | 
			
		||||
	if pr.Flow == issues_model.PullRequestFlowAGit && !headGitRepo.IsReferenceExist(pr.GetGitRefName()) {
 | 
			
		||||
		return "", errors.New("head branch does not exist, can not merge")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue