Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Fargher <jfargher@gitlab.com>2021-09-01 00:50:46 +0300
committerJames Fargher <jfargher@gitlab.com>2021-09-13 02:28:19 +0300
commitca7d181569f43d422ce3b1930fbbdecbe8f6ddbe (patch)
treecd77ad95c9e1e103eb9ea7c22ddf8cd054081c21
parent41ef120b71f1e22065ea5ab422658abf4024e614 (diff)
Only use HEAD to determine default branch
The original default branch logic would select the only branch that existed, or arbitrarily choose the first branch if it couldn't find a better option. In addition it was dereferencing to the commit even though no callees were using the object ID. Here we're changing this logic to more heavily rely on HEAD and only ever falling back to default branches if they exist, without dereferencing to the commit. Changelog: changed
-rw-r--r--internal/git/localrepo/refs.go93
-rw-r--r--internal/git/localrepo/refs_test.go10
-rw-r--r--internal/gitaly/service/operations/apply_patch_test.go5
3 files changed, 34 insertions, 74 deletions
diff --git a/internal/git/localrepo/refs.go b/internal/git/localrepo/refs.go
index 7b9788eb3..6471513dc 100644
--- a/internal/git/localrepo/refs.go
+++ b/internal/git/localrepo/refs.go
@@ -269,75 +269,40 @@ func (repo *Repo) GetRemoteReferences(ctx context.Context, remote string, opts .
// GetDefaultBranch determines the default branch name
func (repo *Repo) GetDefaultBranch(ctx context.Context) (git.ReferenceName, error) {
- branches, err := repo.GetBranches(ctx)
- if err != nil {
- return "", err
- }
- switch len(branches) {
- case 0:
- return "", nil
- case 1:
- return branches[0].Name, nil
- }
-
- headReference, err := repo.headReference(ctx)
- if err != nil {
- return "", err
- }
-
- var defaultRef, legacyDefaultRef git.ReferenceName
- for _, branch := range branches {
- if len(headReference) != 0 && headReference == branch.Name {
- return branch.Name, nil
- }
-
- if string(git.DefaultRef) == branch.Name.String() {
- defaultRef = branch.Name
- }
-
- if string(git.LegacyDefaultRef) == branch.Name.String() {
- legacyDefaultRef = branch.Name
- }
- }
-
- if len(defaultRef) != 0 {
- return defaultRef, nil
- }
-
- if len(legacyDefaultRef) != 0 {
- return legacyDefaultRef, nil
- }
-
- // If all else fails, return the first branch name
- return branches[0].Name, nil
-}
-
-func (repo *Repo) headReference(ctx context.Context) (git.ReferenceName, error) {
- var headRef []byte
-
- cmd, err := repo.Exec(ctx, git.SubCmd{
- Name: "rev-parse",
- Flags: []git.Option{git.Flag{Name: "--symbolic-full-name"}},
- Args: []string{"HEAD"},
- })
+ var stdout bytes.Buffer
+ err := repo.ExecAndWait(ctx,
+ git.SubCmd{
+ Name: "rev-parse",
+ Flags: []git.Option{git.Flag{Name: "--symbolic-full-name"}},
+ Args: []string{"HEAD"},
+ },
+ git.WithStdout(&stdout),
+ )
+ headRef := strings.TrimSpace(stdout.String())
if err != nil {
- return "", err
- }
+ // If the ref pointed at by HEAD doesn't exist, the rev-parse fails
+ // returning the string `"HEAD"`
+ if headRef == "HEAD" {
+ defaultRef := git.ReferenceName(git.DefaultRef)
+ ok, err := repo.HasRevision(ctx, defaultRef.Revision())
+ if err != nil {
+ return "", err
+ }
+ if ok {
+ return defaultRef, nil
+ }
- scanner := bufio.NewScanner(cmd)
- scanner.Scan()
- if err := scanner.Err(); err != nil {
- return "", err
- }
- headRef = scanner.Bytes()
+ legacyDefaultRef := git.ReferenceName(git.LegacyDefaultRef)
+ ok, err = repo.HasRevision(ctx, legacyDefaultRef.Revision())
+ if err != nil {
+ return "", err
+ }
+ if ok {
+ return legacyDefaultRef, nil
+ }
- if err := cmd.Wait(); err != nil {
- // If the ref pointed at by HEAD doesn't exist, the rev-parse fails
- // returning the string `"HEAD"`, so we return `nil` without error.
- if bytes.Equal(headRef, []byte("HEAD")) {
return "", nil
}
-
return "", err
}
diff --git a/internal/git/localrepo/refs_test.go b/internal/git/localrepo/refs_test.go
index ebfde348d..37b9aebe1 100644
--- a/internal/git/localrepo/refs_test.go
+++ b/internal/git/localrepo/refs_test.go
@@ -491,15 +491,6 @@ func TestGetDefaultBranch(t *testing.T) {
},
},
{
- desc: "one branch",
- repo: func(t *testing.T) *Repo {
- repo, repoPath := setupRepo(t, true)
- gittest.WriteCommit(t, repo.cfg, repoPath, gittest.WithParents(), gittest.WithBranch("apple"))
- return repo
- },
- expectedName: git.NewReferenceNameFromBranchName("apple"),
- },
- {
desc: "no default branches",
repo: func(t *testing.T) *Repo {
repo, repoPath := setupRepo(t, true)
@@ -507,7 +498,6 @@ func TestGetDefaultBranch(t *testing.T) {
gittest.WriteCommit(t, repo.cfg, repoPath, gittest.WithParents(oid), gittest.WithBranch("banana"))
return repo
},
- expectedName: git.NewReferenceNameFromBranchName("apple"),
},
{
desc: "test repo default",
diff --git a/internal/gitaly/service/operations/apply_patch_test.go b/internal/gitaly/service/operations/apply_patch_test.go
index da7f23268..27220fb8c 100644
--- a/internal/gitaly/service/operations/apply_patch_test.go
+++ b/internal/gitaly/service/operations/apply_patch_test.go
@@ -294,6 +294,11 @@ To restore the original branch and stop patching, run "git am --abort".
if baseCommit != "" {
require.NoError(t, repo.UpdateRef(ctx, tc.baseReference, baseCommit, git.ZeroOID))
+
+ // Now that the repo has a ref, setup the default branch
+ if _, ok := tc.baseReference.Branch(); ok {
+ gittest.Exec(t, cfg, "-C", repoPath, "symbolic-ref", "HEAD", tc.baseReference.String())
+ }
}
if tc.extraBranches != nil {