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:
authorPatrick Steinhardt <psteinhardt@gitlab.com>2021-09-14 08:38:40 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2021-09-14 08:38:40 +0300
commit07a81867515f925c6108033d2bb05aebfcf14bd0 (patch)
tree0c24dba206efcf831bf43fe6f99443d1a313043c
parent29b7edea2d34492f181d6cc6d501cc9ae50abe53 (diff)
parentd9a22a99a362e0a451da42ab6f5b77711f056290 (diff)
Merge branch 'revert_3817' into 'master'
Revert "Merge branch 'extract_default_branch' into 'master'" See merge request gitlab-org/gitaly!3868
-rw-r--r--internal/git/localrepo/refs.go40
-rw-r--r--internal/git/localrepo/refs_test.go82
-rw-r--r--internal/git/repository.go7
-rw-r--r--internal/gitaly/service/commit/commits_by_message.go5
-rw-r--r--internal/gitaly/service/commit/find_all_commits.go1
-rw-r--r--internal/gitaly/service/commit/find_all_commits_test.go1
-rw-r--r--internal/gitaly/service/commit/find_commits.go4
-rw-r--r--internal/gitaly/service/commit/languages.go5
-rw-r--r--internal/gitaly/service/commit/list_files.go13
-rw-r--r--internal/gitaly/service/commit/list_files_test.go12
-rw-r--r--internal/gitaly/service/commit/server.go3
-rw-r--r--internal/gitaly/service/operations/apply_patch.go9
-rw-r--r--internal/gitaly/service/operations/apply_patch_test.go7
-rw-r--r--internal/gitaly/service/ref/refs.go103
-rw-r--r--internal/gitaly/service/ref/refs_test.go117
-rw-r--r--internal/gitaly/service/remote/fetch_internal_remote.go7
-rw-r--r--internal/gitaly/service/remote/update_remote_mirror.go7
17 files changed, 251 insertions, 172 deletions
diff --git a/internal/git/localrepo/refs.go b/internal/git/localrepo/refs.go
index 264bee4d2..ac9c69fd1 100644
--- a/internal/git/localrepo/refs.go
+++ b/internal/git/localrepo/refs.go
@@ -266,43 +266,3 @@ func (repo *Repo) GetRemoteReferences(ctx context.Context, remote string, opts .
return refs, nil
}
-
-// GetDefaultBranch determines the default branch name
-func (repo *Repo) GetDefaultBranch(ctx context.Context) (git.ReferenceName, error) {
- 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 {
- // If the ref pointed at by HEAD doesn't exist, the rev-parse fails
- // returning the string `"HEAD"`
- if headRef == "HEAD" {
- ok, err := repo.HasRevision(ctx, git.DefaultRef.Revision())
- if err != nil {
- return "", err
- }
- if ok {
- return git.DefaultRef, nil
- }
-
- ok, err = repo.HasRevision(ctx, git.LegacyDefaultRef.Revision())
- if err != nil {
- return "", err
- }
- if ok {
- return git.LegacyDefaultRef, nil
- }
-
- return "", git.ErrNoDefaultBranch
- }
- return "", err
- }
-
- return git.ReferenceName(headRef), nil
-}
diff --git a/internal/git/localrepo/refs_test.go b/internal/git/localrepo/refs_test.go
index 652df1a80..a99384e42 100644
--- a/internal/git/localrepo/refs_test.go
+++ b/internal/git/localrepo/refs_test.go
@@ -454,85 +454,3 @@ func TestRepo_UpdateRef(t *testing.T) {
})
}
}
-
-func TestGetDefaultBranch(t *testing.T) {
- const testOID = "1a0b36b3cdad1d2ee32457c102a8c0b7056fa863"
-
- for _, tc := range []struct {
- desc string
- repo func(t *testing.T) *Repo
- expectedName git.ReferenceName
- expectedErr error
- }{
- {
- desc: "default ref",
- repo: func(t *testing.T) *Repo {
- repo, repoPath := setupRepo(t, true)
- oid := gittest.WriteCommit(t, repo.cfg, repoPath, gittest.WithParents(), gittest.WithBranch("apple"))
- gittest.WriteCommit(t, repo.cfg, repoPath, gittest.WithParents(oid), gittest.WithBranch("main"))
- return repo
- },
- expectedName: git.DefaultRef,
- },
- {
- desc: "legacy default ref",
- repo: func(t *testing.T) *Repo {
- repo, repoPath := setupRepo(t, true)
- oid := gittest.WriteCommit(t, repo.cfg, repoPath, gittest.WithParents(), gittest.WithBranch("apple"))
- gittest.WriteCommit(t, repo.cfg, repoPath, gittest.WithParents(oid), gittest.WithBranch("master"))
- return repo
- },
- expectedName: git.LegacyDefaultRef,
- },
- {
- desc: "no branches",
- repo: func(t *testing.T) *Repo {
- repo, _ := setupRepo(t, true)
- return repo
- },
- expectedErr: git.ErrNoDefaultBranch,
- },
- {
- desc: "no default branches",
- repo: func(t *testing.T) *Repo {
- repo, repoPath := setupRepo(t, true)
- oid := gittest.WriteCommit(t, repo.cfg, repoPath, gittest.WithParents(), gittest.WithBranch("apple"))
- gittest.WriteCommit(t, repo.cfg, repoPath, gittest.WithParents(oid), gittest.WithBranch("banana"))
- return repo
- },
- expectedErr: git.ErrNoDefaultBranch,
- },
- {
- desc: "test repo default",
- repo: func(t *testing.T) *Repo {
- repo, _ := setupRepo(t, false)
- return repo
- },
- expectedName: git.LegacyDefaultRef,
- },
- {
- desc: "test repo HEAD set",
- repo: func(t *testing.T) *Repo {
- repo, repoPath := setupRepo(t, false)
- gittest.Exec(t, repo.cfg, "-C", repoPath, "update-ref", "refs/heads/feature", testOID)
- gittest.Exec(t, repo.cfg, "-C", repoPath, "symbolic-ref", "HEAD", "refs/heads/feature")
- return repo
- },
- expectedName: git.NewReferenceNameFromBranchName("feature"),
- },
- } {
- t.Run(tc.desc, func(t *testing.T) {
- ctx, cancel := testhelper.Context()
- defer cancel()
-
- name, err := tc.repo(t).GetDefaultBranch(ctx)
- if tc.expectedErr != nil {
- require.Equal(t, tc.expectedErr, err)
- return
- }
-
- require.NoError(t, err)
- require.Equal(t, tc.expectedName, name)
- })
- }
-}
diff --git a/internal/git/repository.go b/internal/git/repository.go
index 3ebe6cec4..e5f5b25d5 100644
--- a/internal/git/repository.go
+++ b/internal/git/repository.go
@@ -13,12 +13,12 @@ const DefaultBranch = "main"
// DefaultRef is the reference that GitLab will use if HEAD of the bare repository
// is not found, or other edge cases to detect the default branch.
-const DefaultRef = ReferenceName("refs/heads/" + DefaultBranch)
+var DefaultRef = []byte("refs/heads/" + DefaultBranch)
// LegacyDefaultRef is the reference that used to be the default HEAD of the bare
// repository. If the default reference is not found, Gitaly will still test the
// legacy default.
-const LegacyDefaultRef = ReferenceName("refs/heads/master")
+var LegacyDefaultRef = []byte("refs/heads/master")
var (
// ErrReferenceNotFound represents an error when a reference was not
@@ -32,9 +32,6 @@ var (
ErrAlreadyExists = errors.New("already exists")
// ErrNotFound represents an error when the resource can't be found.
ErrNotFound = errors.New("not found")
- // ErrNoDefaultBranch represents an error when the repository has no
- // default branch
- ErrNoDefaultBranch = errors.New("no default branch")
)
// Repository is the common interface of different repository implementations.
diff --git a/internal/gitaly/service/commit/commits_by_message.go b/internal/gitaly/service/commit/commits_by_message.go
index 6353cf0ee..63a8898c9 100644
--- a/internal/gitaly/service/commit/commits_by_message.go
+++ b/internal/gitaly/service/commit/commits_by_message.go
@@ -53,11 +53,12 @@ func (s *server) commitsByMessage(in *gitalypb.CommitsByMessageRequest, stream g
revision := in.GetRevision()
if len(revision) == 0 {
- defaultBranch, err := repo.GetDefaultBranch(ctx)
+ var err error
+
+ revision, err = defaultBranchName(ctx, repo)
if err != nil {
return err
}
- revision = []byte(defaultBranch)
}
var paths []string
diff --git a/internal/gitaly/service/commit/find_all_commits.go b/internal/gitaly/service/commit/find_all_commits.go
index 26d13e8dc..796c7185b 100644
--- a/internal/gitaly/service/commit/find_all_commits.go
+++ b/internal/gitaly/service/commit/find_all_commits.go
@@ -10,7 +10,6 @@ import (
)
// We declare this function in variables so that we can override them in our tests
-//nolint:staticcheck // FindBranchNames is deprecated but the tests are difficult to refactor
var _findBranchNamesFunc = ref.FindBranchNames
func (s *server) FindAllCommits(in *gitalypb.FindAllCommitsRequest, stream gitalypb.CommitService_FindAllCommitsServer) error {
diff --git a/internal/gitaly/service/commit/find_all_commits_test.go b/internal/gitaly/service/commit/find_all_commits_test.go
index 893b33af8..ba7b7ff06 100644
--- a/internal/gitaly/service/commit/find_all_commits_test.go
+++ b/internal/gitaly/service/commit/find_all_commits_test.go
@@ -16,7 +16,6 @@ import (
func TestSuccessfulFindAllCommitsRequest(t *testing.T) {
defer func() {
- //nolint:staticcheck // FindBranchNames is deprecated but the tests are difficult to refactor
_findBranchNamesFunc = ref.FindBranchNames
}()
diff --git a/internal/gitaly/service/commit/find_commits.go b/internal/gitaly/service/commit/find_commits.go
index 6f6f63b4d..6367aa35d 100644
--- a/internal/gitaly/service/commit/find_commits.go
+++ b/internal/gitaly/service/commit/find_commits.go
@@ -29,11 +29,11 @@ func (s *server) FindCommits(req *gitalypb.FindCommitsRequest, stream gitalypb.C
// Use Gitaly's default branch lookup function because that is already
// migrated.
if revision := req.Revision; len(revision) == 0 && !req.GetAll() {
- defaultBranch, err := repo.GetDefaultBranch(ctx)
+ var err error
+ req.Revision, err = defaultBranchName(ctx, repo)
if err != nil {
return helper.ErrInternal(fmt.Errorf("defaultBranchName: %v", err))
}
- req.Revision = []byte(defaultBranch)
}
// Clients might send empty paths. That is an error
for _, path := range req.Paths {
diff --git a/internal/gitaly/service/commit/languages.go b/internal/gitaly/service/commit/languages.go
index b9ef474d4..fc65f3aef 100644
--- a/internal/gitaly/service/commit/languages.go
+++ b/internal/gitaly/service/commit/languages.go
@@ -10,6 +10,7 @@ import (
"strings"
"gitlab.com/gitlab-org/gitaly/v14/internal/git"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/service/ref"
"gitlab.com/gitlab-org/gitaly/v14/internal/helper"
"gitlab.com/gitlab-org/gitaly/v14/internal/helper/text"
"gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
@@ -26,11 +27,11 @@ func (s *server) CommitLanguages(ctx context.Context, req *gitalypb.CommitLangua
revision := string(req.Revision)
if revision == "" {
- defaultBranch, err := repo.GetDefaultBranch(ctx)
+ defaultBranch, err := ref.DefaultBranchName(ctx, repo)
if err != nil {
return nil, err
}
- revision = defaultBranch.String()
+ revision = string(defaultBranch)
}
commitID, err := s.lookupRevision(ctx, repo, revision)
diff --git a/internal/gitaly/service/commit/list_files.go b/internal/gitaly/service/commit/list_files.go
index d06c4db8a..7b1cf8b71 100644
--- a/internal/gitaly/service/commit/list_files.go
+++ b/internal/gitaly/service/commit/list_files.go
@@ -1,7 +1,6 @@
package commit
import (
- "errors"
"io"
"github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus"
@@ -30,14 +29,16 @@ func (s *server) ListFiles(in *gitalypb.ListFilesRequest, stream gitalypb.Commit
revision := string(in.GetRevision())
if len(revision) == 0 {
- defaultBranch, err := repo.GetDefaultBranch(stream.Context())
- if errors.Is(err, git.ErrNoDefaultBranch) {
- return helper.ErrFailedPreconditionf("repository does not have a default branch")
- } else if err != nil {
+ defaultBranch, err := defaultBranchName(stream.Context(), repo)
+ if err != nil {
return helper.ErrNotFoundf("revision not found %q", revision)
}
- revision = defaultBranch.String()
+ if len(defaultBranch) == 0 {
+ return helper.ErrFailedPreconditionf("repository does not have a default branch")
+ }
+
+ revision = string(defaultBranch)
}
contained, err := s.localrepo(repo).HasRevision(stream.Context(), git.Revision(revision))
diff --git a/internal/gitaly/service/commit/list_files_test.go b/internal/gitaly/service/commit/list_files_test.go
index e0f69a92b..f07fd7658 100644
--- a/internal/gitaly/service/commit/list_files_test.go
+++ b/internal/gitaly/service/commit/list_files_test.go
@@ -1,11 +1,14 @@
package commit
import (
+ "context"
"io"
"testing"
"github.com/stretchr/testify/require"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/git"
"gitlab.com/gitlab-org/gitaly/v14/internal/git/gittest"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/service/ref"
"gitlab.com/gitlab-org/gitaly/v14/internal/testhelper"
"gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
"google.golang.org/grpc/codes"
@@ -37,9 +40,14 @@ var defaultFiles = [][]byte{
}
func TestListFiles_success(t *testing.T) {
- cfg, repo, repoPath, client := setupCommitServiceWithRepo(t, true)
+ defaultBranchName = func(context.Context, git.RepositoryExecutor) ([]byte, error) {
+ return []byte("test-do-not-touch"), nil
+ }
+ defer func() {
+ defaultBranchName = ref.DefaultBranchName
+ }()
- gittest.Exec(t, cfg, "-C", repoPath, "symbolic-ref", "HEAD", "refs/heads/test-do-not-touch")
+ _, repo, _, client := setupCommitServiceWithRepo(t, true)
tests := []struct {
desc string
diff --git a/internal/gitaly/service/commit/server.go b/internal/gitaly/service/commit/server.go
index 1ada86a09..6669091e0 100644
--- a/internal/gitaly/service/commit/server.go
+++ b/internal/gitaly/service/commit/server.go
@@ -7,6 +7,7 @@ import (
"gitlab.com/gitlab-org/gitaly/v14/internal/git/repository"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/linguist"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/service/ref"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/storage"
"gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
)
@@ -20,6 +21,8 @@ type server struct {
catfileCache catfile.Cache
}
+var defaultBranchName = ref.DefaultBranchName
+
// NewServer creates a new instance of a grpc CommitServiceServer
func NewServer(
cfg config.Cfg,
diff --git a/internal/gitaly/service/operations/apply_patch.go b/internal/gitaly/service/operations/apply_patch.go
index a2f2c0d73..e4370a346 100644
--- a/internal/gitaly/service/operations/apply_patch.go
+++ b/internal/gitaly/service/operations/apply_patch.go
@@ -11,6 +11,7 @@ import (
"github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus"
"gitlab.com/gitlab-org/gitaly/v14/internal/git"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/service/ref"
"gitlab.com/gitlab-org/gitaly/v14/internal/helper"
"gitlab.com/gitlab-org/gitaly/v14/internal/helper/text"
"gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
@@ -19,6 +20,8 @@ import (
"google.golang.org/grpc/status"
)
+var errNoDefaultBranch = errors.New("no default branch")
+
func (s *Server) UserApplyPatch(stream gitalypb.OperationService_UserApplyPatchServer) error {
firstRequest, err := stream.Recv()
if err != nil {
@@ -57,13 +60,15 @@ func (s *Server) userApplyPatch(ctx context.Context, header *gitalypb.UserApplyP
return fmt.Errorf("resolve target branch: %w", err)
}
- defaultBranch, err := repo.GetDefaultBranch(ctx)
+ defaultBranch, err := ref.DefaultBranchName(ctx, repo)
if err != nil {
return fmt.Errorf("default branch name: %w", err)
+ } else if defaultBranch == nil {
+ return errNoDefaultBranch
}
branchCreated = true
- parentCommitID, err = repo.ResolveRevision(ctx, defaultBranch.Revision()+"^{commit}")
+ parentCommitID, err = repo.ResolveRevision(ctx, git.Revision(defaultBranch)+"^{commit}")
if err != nil {
return fmt.Errorf("resolve default branch commit: %w", err)
}
diff --git a/internal/gitaly/service/operations/apply_patch_test.go b/internal/gitaly/service/operations/apply_patch_test.go
index bd35bbb83..da7f23268 100644
--- a/internal/gitaly/service/operations/apply_patch_test.go
+++ b/internal/gitaly/service/operations/apply_patch_test.go
@@ -117,7 +117,7 @@ To restore the original branch and stop patching, run "git am --abort".
createFile("file", "base-content"),
},
},
- error: status.Error(codes.Internal, "default branch name: no default branch"),
+ error: status.Error(codes.Internal, "no default branch"),
},
{
desc: "creating a new branch from HEAD works",
@@ -294,11 +294,6 @@ 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 {
diff --git a/internal/gitaly/service/ref/refs.go b/internal/gitaly/service/ref/refs.go
index c9fd8d56a..3a8e15c0f 100644
--- a/internal/gitaly/service/ref/refs.go
+++ b/internal/gitaly/service/ref/refs.go
@@ -21,6 +21,13 @@ const (
tagFormat = "%(objectname) %(objecttype) %(refname:lstrip=2)"
)
+var (
+ // We declare the following functions in variables so that we can override them in our tests
+ headReference = _headReference
+ // FindBranchNames is exported to be used in other packages
+ FindBranchNames = _findBranchNames
+)
+
type findRefsOpts struct {
cmdArgs []git.Option
delim byte
@@ -56,10 +63,7 @@ func (s *server) findRefs(ctx context.Context, writer lines.Sender, repo git.Rep
return cmd.Wait()
}
-// FindBranchNames returns all branch names.
-//
-// Deprecated: Use localrepo.Repo.GetBranches instead.
-func FindBranchNames(ctx context.Context, repo git.RepositoryExecutor) ([][]byte, error) {
+func _findBranchNames(ctx context.Context, repo git.RepositoryExecutor) ([][]byte, error) {
var names [][]byte
cmd, err := repo.Exec(ctx, git.SubCmd{
@@ -87,6 +91,38 @@ func FindBranchNames(ctx context.Context, repo git.RepositoryExecutor) ([][]byte
return names, nil
}
+func _headReference(ctx context.Context, repo git.RepositoryExecutor) ([]byte, 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"},
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ scanner := bufio.NewScanner(cmd)
+ scanner.Scan()
+ if err := scanner.Err(); err != nil {
+ return nil, err
+ }
+ headRef = scanner.Bytes()
+
+ 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, nil
+ }
+
+ return nil, err
+ }
+
+ return headRef, nil
+}
+
// SetDefaultBranchRef overwrites the default branch ref for the repository
func SetDefaultBranchRef(ctx context.Context, repo git.RepositoryExecutor, ref string, cfg config.Cfg) error {
if err := repo.ExecAndWait(ctx, git.SubCmd{
@@ -98,16 +134,65 @@ func SetDefaultBranchRef(ctx context.Context, repo git.RepositoryExecutor, ref s
return nil
}
+// DefaultBranchName looks up the name of the default branch given a repoPath
+func DefaultBranchName(ctx context.Context, repo git.RepositoryExecutor) ([]byte, error) {
+ branches, err := FindBranchNames(ctx, repo)
+ if err != nil {
+ return nil, err
+ }
+
+ // Return empty ref name if there are no branches
+ if len(branches) == 0 {
+ return nil, nil
+ }
+
+ // Return first branch name if there's only one
+ if len(branches) == 1 {
+ return branches[0], nil
+ }
+
+ hasDefaultRef, hasLegacyDefaultRef := false, false
+ headRef, err := headReference(ctx, repo)
+ if err != nil {
+ return nil, err
+ }
+
+ for _, branch := range branches {
+ // Return HEAD if it exists and corresponds to a branch
+ if headRef != nil && bytes.Equal(headRef, branch) {
+ return headRef, nil
+ }
+
+ if bytes.Equal(branch, git.DefaultRef) {
+ hasDefaultRef = true
+ }
+
+ hasLegacyDefaultRef = hasLegacyDefaultRef || bytes.Equal(branch, git.LegacyDefaultRef)
+ }
+
+ // Return the default ref if it exists
+ if hasDefaultRef {
+ return git.DefaultRef, nil
+ }
+
+ if hasLegacyDefaultRef {
+ return git.LegacyDefaultRef, nil
+ }
+
+ // If all else fails, return the first branch name
+ return branches[0], nil
+}
+
// FindDefaultBranchName returns the default branch name for the given repository
func (s *server) FindDefaultBranchName(ctx context.Context, in *gitalypb.FindDefaultBranchNameRequest) (*gitalypb.FindDefaultBranchNameResponse, error) {
repo := s.localrepo(in.GetRepository())
- defaultBranch, err := repo.GetDefaultBranch(ctx)
- if err != nil && !errors.Is(err, git.ErrNoDefaultBranch) {
+ defaultBranchName, err := DefaultBranchName(ctx, repo)
+ if err != nil {
return nil, helper.ErrInternal(err)
}
- return &gitalypb.FindDefaultBranchNameResponse{Name: []byte(defaultBranch)}, nil
+ return &gitalypb.FindDefaultBranchNameResponse{Name: defaultBranchName}, nil
}
func parseSortKey(sortKey gitalypb.FindLocalBranchesRequest_SortBy) string {
@@ -171,12 +256,12 @@ func (s *server) findAllBranches(in *gitalypb.FindAllBranchesRequest, stream git
patterns := []string{"refs/heads", "refs/remotes"}
if in.MergedOnly {
- defaultBranch, err := repo.GetDefaultBranch(stream.Context())
+ defaultBranchName, err := DefaultBranchName(stream.Context(), repo)
if err != nil {
return err
}
- args = append(args, git.Flag{Name: fmt.Sprintf("--merged=%s", defaultBranch.String())})
+ args = append(args, git.Flag{Name: fmt.Sprintf("--merged=%s", string(defaultBranchName))})
if len(in.MergedBranches) > 0 {
patterns = nil
diff --git a/internal/gitaly/service/ref/refs_test.go b/internal/gitaly/service/ref/refs_test.go
index d7560ec4c..d83e0d731 100644
--- a/internal/gitaly/service/ref/refs_test.go
+++ b/internal/gitaly/service/ref/refs_test.go
@@ -3,8 +3,10 @@ package ref
import (
"bufio"
"bytes"
+ "context"
"fmt"
"io"
+ "io/ioutil"
"strings"
"testing"
@@ -218,6 +220,37 @@ func TestInvalidRepoFindAllTagNamesRequest(t *testing.T) {
}
}
+func TestHeadReference(t *testing.T) {
+ cfg, repo, _ := testcfg.BuildWithRepo(t)
+
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+
+ headRef, err := headReference(ctx, localrepo.NewTestRepo(t, cfg, repo))
+ require.NoError(t, err)
+
+ require.Equal(t, git.LegacyDefaultRef, headRef)
+}
+
+func TestHeadReferenceWithNonExistingHead(t *testing.T) {
+ cfg, repo, repoPath := testcfg.BuildWithRepo(t)
+
+ // Write bad HEAD
+ require.NoError(t, ioutil.WriteFile(repoPath+"/HEAD", []byte("ref: refs/heads/nonexisting"), 0o644))
+ defer func() {
+ // Restore HEAD
+ require.NoError(t, ioutil.WriteFile(repoPath+"/HEAD", []byte("ref: refs/heads/master"), 0o644))
+ }()
+
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+ headRef, err := headReference(ctx, localrepo.NewTestRepo(t, cfg, repo))
+ require.NoError(t, err)
+ if headRef != nil {
+ t.Fatal("Expected HEAD reference to be nil, got '", string(headRef), "'")
+ }
+}
+
func TestSetDefaultBranchRef(t *testing.T) {
cfg, repoProto, _ := testcfg.BuildWithRepo(t)
repo := localrepo.NewTestRepo(t, cfg, repoProto)
@@ -235,7 +268,7 @@ func TestSetDefaultBranchRef(t *testing.T) {
{
desc: "unknown ref",
ref: "refs/heads/non_existent_ref",
- expectedRef: git.LegacyDefaultRef.String(),
+ expectedRef: string(git.LegacyDefaultRef),
},
}
@@ -246,14 +279,88 @@ func TestSetDefaultBranchRef(t *testing.T) {
require.NoError(t, SetDefaultBranchRef(ctx, repo, tc.ref, cfg))
- newRef, err := repo.GetDefaultBranch(ctx)
+ newRef, err := DefaultBranchName(ctx, repo)
require.NoError(t, err)
- require.Equal(t, tc.expectedRef, newRef.String())
+ require.Equal(t, tc.expectedRef, string(newRef))
})
}
}
+func TestDefaultBranchName(t *testing.T) {
+ // We are going to override these functions during this test. Restore them after we're done
+ defer func() {
+ FindBranchNames = _findBranchNames
+ headReference = _headReference
+ }()
+
+ cfg, repoProto, _ := testcfg.BuildWithRepo(t)
+ repo := localrepo.NewTestRepo(t, cfg, repoProto)
+
+ testCases := []struct {
+ desc string
+ findBranchNames func(context.Context, git.RepositoryExecutor) ([][]byte, error)
+ headReference func(context.Context, git.RepositoryExecutor) ([]byte, error)
+ expected []byte
+ }{
+ {
+ desc: "Get first branch when only one branch exists",
+ expected: []byte("refs/heads/foo"),
+ findBranchNames: func(context.Context, git.RepositoryExecutor) ([][]byte, error) {
+ return [][]byte{[]byte("refs/heads/foo")}, nil
+ },
+ headReference: func(context.Context, git.RepositoryExecutor) ([]byte, error) { return nil, nil },
+ },
+ {
+ desc: "Get empy ref if no branches exists",
+ expected: nil,
+ findBranchNames: func(context.Context, git.RepositoryExecutor) ([][]byte, error) {
+ return [][]byte{}, nil
+ },
+ headReference: func(context.Context, git.RepositoryExecutor) ([]byte, error) { return nil, nil },
+ },
+ {
+ desc: "Get the name of the head reference when more than one branch exists",
+ expected: []byte("refs/heads/bar"),
+ findBranchNames: func(context.Context, git.RepositoryExecutor) ([][]byte, error) {
+ return [][]byte{[]byte("refs/heads/foo"), []byte("refs/heads/bar")}, nil
+ },
+ headReference: func(context.Context, git.RepositoryExecutor) ([]byte, error) {
+ return []byte("refs/heads/bar"), nil
+ },
+ },
+ {
+ desc: "Get `ref/heads/master` when several branches exist",
+ expected: git.LegacyDefaultRef,
+ findBranchNames: func(context.Context, git.RepositoryExecutor) ([][]byte, error) {
+ return [][]byte{[]byte("refs/heads/foo"), []byte("refs/heads/master"), []byte("refs/heads/bar")}, nil
+ },
+ headReference: func(context.Context, git.RepositoryExecutor) ([]byte, error) { return nil, nil },
+ },
+ {
+ desc: "Get the name of the first branch when several branches exists and no other conditions are met",
+ expected: []byte("refs/heads/foo"),
+ findBranchNames: func(context.Context, git.RepositoryExecutor) ([][]byte, error) {
+ return [][]byte{[]byte("refs/heads/foo"), []byte("refs/heads/bar"), []byte("refs/heads/baz")}, nil
+ },
+ headReference: func(context.Context, git.RepositoryExecutor) ([]byte, error) { return nil, nil },
+ },
+ }
+
+ for _, testCase := range testCases {
+ FindBranchNames = testCase.findBranchNames
+ headReference = testCase.headReference
+
+ ctx, cancel := testhelper.Context()
+ defer cancel()
+ defaultBranch, err := DefaultBranchName(ctx, repo)
+ require.NoError(t, err)
+ if !bytes.Equal(defaultBranch, testCase.expected) {
+ t.Fatalf("%s: expected %s, got %s instead", testCase.desc, testCase.expected, defaultBranch)
+ }
+ }
+}
+
func TestSuccessfulFindDefaultBranchName(t *testing.T) {
cfg, repo, repoPath, client := setupRefService(t)
rpcRequest := &gitalypb.FindDefaultBranchNameRequest{Repository: repo}
@@ -268,7 +375,7 @@ func TestSuccessfulFindDefaultBranchName(t *testing.T) {
r, err := client.FindDefaultBranchName(ctx, rpcRequest)
require.NoError(t, err)
- require.Equal(t, r.GetName(), []byte(git.DefaultRef))
+ require.Equal(t, r.GetName(), git.DefaultRef)
}
func TestSuccessfulFindDefaultBranchNameLegacy(t *testing.T) {
@@ -280,7 +387,7 @@ func TestSuccessfulFindDefaultBranchNameLegacy(t *testing.T) {
r, err := client.FindDefaultBranchName(ctx, rpcRequest)
require.NoError(t, err)
- require.Equal(t, r.GetName(), []byte(git.LegacyDefaultRef))
+ require.Equal(t, r.GetName(), git.LegacyDefaultRef)
}
func TestEmptyFindDefaultBranchNameRequest(t *testing.T) {
diff --git a/internal/gitaly/service/remote/fetch_internal_remote.go b/internal/gitaly/service/remote/fetch_internal_remote.go
index c49b530c1..7eafcf23b 100644
--- a/internal/gitaly/service/remote/fetch_internal_remote.go
+++ b/internal/gitaly/service/remote/fetch_internal_remote.go
@@ -8,7 +8,6 @@ import (
"github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus"
"gitlab.com/gitlab-org/gitaly/v14/client"
- "gitlab.com/gitlab-org/gitaly/v14/internal/git"
"gitlab.com/gitlab-org/gitaly/v14/internal/git/localrepo"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/config"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/service/ref"
@@ -62,12 +61,12 @@ func FetchInternalRemote(
return status.Errorf(codes.Internal, "FetchInternalRemote: remote default branch: %v", err)
}
- defaultBranch, err := repo.GetDefaultBranch(ctx)
- if err != nil && !errors.Is(err, git.ErrNoDefaultBranch) {
+ defaultBranch, err := ref.DefaultBranchName(ctx, repo)
+ if err != nil {
return status.Errorf(codes.Internal, "FetchInternalRemote: default branch: %v", err)
}
- if defaultBranch.String() != string(remoteDefaultBranch) {
+ if !bytes.Equal(defaultBranch, remoteDefaultBranch) {
if err := ref.SetDefaultBranchRef(ctx, repo, string(remoteDefaultBranch), cfg); err != nil {
return status.Errorf(codes.Internal, "FetchInternalRemote: set default branch: %v", err)
}
diff --git a/internal/gitaly/service/remote/update_remote_mirror.go b/internal/gitaly/service/remote/update_remote_mirror.go
index 3fd6e5a16..8ab8f4ac9 100644
--- a/internal/gitaly/service/remote/update_remote_mirror.go
+++ b/internal/gitaly/service/remote/update_remote_mirror.go
@@ -10,6 +10,7 @@ import (
"gitlab.com/gitlab-org/gitaly/v14/internal/git"
"gitlab.com/gitlab-org/gitaly/v14/internal/git/localrepo"
+ "gitlab.com/gitlab-org/gitaly/v14/internal/gitaly/service/ref"
"gitlab.com/gitlab-org/gitaly/v14/internal/helper"
"gitlab.com/gitlab-org/gitaly/v14/internal/helper/text"
"gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
@@ -102,8 +103,8 @@ func (s *server) updateRemoteMirror(stream gitalypb.RemoteService_UpdateRemoteMi
return fmt.Errorf("get local references: %w", err)
}
- defaultBranch, err := repo.GetDefaultBranch(ctx)
- if err != nil && !errors.Is(err, git.ErrNoDefaultBranch) {
+ defaultBranch, err := ref.DefaultBranchName(ctx, repo)
+ if err != nil {
return fmt.Errorf("get default branch: %w", err)
}
@@ -194,7 +195,7 @@ func (s *server) updateRemoteMirror(stream gitalypb.RemoteService_UpdateRemoteMi
}
refspecs = append(refspecs, prefix+reference.String())
- if reference == defaultBranch {
+ if reference == git.ReferenceName(defaultBranch) {
// The default branch needs to be pushed in the first batch of refspecs as some features
// depend on it existing in the repository. The default branch may not exist in the repo
// yet if this is the first mirroring push.