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-06-14 12:07:50 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2021-06-14 12:32:33 +0300
commiteef84a6ab29c2ca39a09d5df799434e3044aeb7f (patch)
treecefd08d46e43785eb60e5c3f6094b5bca3ba9e73
parent2bcaef7238179d2f277ddbf4e10308b5c0db6bfe (diff)
remote: Make `FetchInternalRemote()` callable without a server
We'll need to be able to call `FetchInternalRemote()` on the same Gitaly node without creating a connection to the remote service. Split out the logic of `FetchInternalRemote()` into a separate non-receiver function to allow for this.
-rw-r--r--internal/gitaly/service/remote/fetch_internal_remote.go79
1 files changed, 53 insertions, 26 deletions
diff --git a/internal/gitaly/service/remote/fetch_internal_remote.go b/internal/gitaly/service/remote/fetch_internal_remote.go
index f6cf0a6b0..5c72264c1 100644
--- a/internal/gitaly/service/remote/fetch_internal_remote.go
+++ b/internal/gitaly/service/remote/fetch_internal_remote.go
@@ -9,6 +9,8 @@ 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"
"gitlab.com/gitlab-org/gitaly/v14/internal/gitalyssh"
"gitlab.com/gitlab-org/gitaly/v14/internal/helper"
@@ -22,17 +24,30 @@ const (
mirrorRefSpec = "+refs/*:refs/*"
)
-// FetchInternalRemote fetches another Gitaly repository set as a remote
-func (s *server) FetchInternalRemote(ctx context.Context, req *gitalypb.FetchInternalRemoteRequest) (*gitalypb.FetchInternalRemoteResponse, error) {
- if err := validateFetchInternalRemoteRequest(req); err != nil {
- return nil, status.Errorf(codes.InvalidArgument, "FetchInternalRemote: %v", err)
+type fetchFailedError struct {
+ stderr string
+ err error
+}
+
+func (e fetchFailedError) Error() string {
+ if e.stderr != "" {
+ return fmt.Sprintf("FetchInternalRemote: fetch: %v, stderr: %q", e.err, e.stderr)
}
- repo := s.localrepo(req.GetRepository())
+ return fmt.Sprintf("FetchInternalRemote: fetch: %v", e.err)
+}
- env, err := gitalyssh.UploadPackEnv(ctx, s.cfg, &gitalypb.SSHUploadPackRequest{Repository: req.RemoteRepository})
+// FetchInternalRemote fetches another Gitaly repository set as a remote
+func FetchInternalRemote(
+ ctx context.Context,
+ cfg config.Cfg,
+ conns *client.Pool,
+ repo *localrepo.Repo,
+ remoteRepo *gitalypb.Repository,
+) error {
+ env, err := gitalyssh.UploadPackEnv(ctx, cfg, &gitalypb.SSHUploadPackRequest{Repository: remoteRepo})
if err != nil {
- return nil, fmt.Errorf("upload pack environment: %w", err)
+ return fmt.Errorf("upload pack environment: %w", err)
}
stderr := &bytes.Buffer{}
@@ -44,7 +59,7 @@ func (s *server) FetchInternalRemote(ctx context.Context, req *gitalypb.FetchInt
options := []git.CmdOpt{
git.WithEnv(env...),
git.WithStderr(stderr),
- git.WithRefTxHook(ctx, repo, s.cfg),
+ git.WithRefTxHook(ctx, repo, cfg),
}
cmd, err := repo.Exec(ctx,
@@ -56,39 +71,51 @@ func (s *server) FetchInternalRemote(ctx context.Context, req *gitalypb.FetchInt
options...,
)
if err != nil {
- return nil, fmt.Errorf("create git fetch: %w", err)
+ return fmt.Errorf("create git fetch: %w", err)
}
if err := cmd.Wait(); err != nil {
- if featureflag.IsDisabled(ctx, featureflag.FetchInternalRemoteErrors) {
- // Design quirk: if the fetch fails, this RPC returns Result: false, but no error.
- ctxlogrus.Extract(ctx).WithError(err).WithField("stderr", stderr.String()).Warn("git fetch failed")
- return &gitalypb.FetchInternalRemoteResponse{Result: false}, nil
- }
-
- errMsg := stderr.String()
- if errMsg != "" {
- return nil, fmt.Errorf("FetchInternalRemote: fetch: %w, stderr: %q", err, errMsg)
- }
-
- return nil, fmt.Errorf("FetchInternalRemote: fetch: %w", err)
+ return fetchFailedError{stderr.String(), err}
}
- remoteDefaultBranch, err := getRemoteDefaultBranch(ctx, req.RemoteRepository, s.conns)
+ remoteDefaultBranch, err := getRemoteDefaultBranch(ctx, remoteRepo, conns)
if err != nil {
- return nil, status.Errorf(codes.Internal, "FetchInternalRemote: remote default branch: %v", err)
+ return status.Errorf(codes.Internal, "FetchInternalRemote: remote default branch: %v", err)
}
defaultBranch, err := ref.DefaultBranchName(ctx, repo)
if err != nil {
- return nil, status.Errorf(codes.Internal, "FetchInternalRemote: default branch: %v", err)
+ return status.Errorf(codes.Internal, "FetchInternalRemote: default branch: %v", err)
}
if !bytes.Equal(defaultBranch, remoteDefaultBranch) {
- if err := ref.SetDefaultBranchRef(ctx, repo, string(remoteDefaultBranch), s.cfg); err != nil {
- return nil, status.Errorf(codes.Internal, "FetchInternalRemote: set default branch: %v", err)
+ if err := ref.SetDefaultBranchRef(ctx, repo, string(remoteDefaultBranch), cfg); err != nil {
+ return status.Errorf(codes.Internal, "FetchInternalRemote: set default branch: %v", err)
}
}
+ return nil
+}
+
+// FetchInternalRemote fetches another Gitaly repository set as a remote
+func (s *server) FetchInternalRemote(ctx context.Context, req *gitalypb.FetchInternalRemoteRequest) (*gitalypb.FetchInternalRemoteResponse, error) {
+ if err := validateFetchInternalRemoteRequest(req); err != nil {
+ return nil, status.Errorf(codes.InvalidArgument, "FetchInternalRemote: %v", err)
+ }
+
+ repo := s.localrepo(req.GetRepository())
+
+ if err := FetchInternalRemote(ctx, s.cfg, s.conns, repo, req.RemoteRepository); err != nil {
+ var fetchErr fetchFailedError
+
+ if featureflag.IsDisabled(ctx, featureflag.FetchInternalRemoteErrors) && errors.As(err, &fetchErr) {
+ // Design quirk: if the fetch fails, this RPC returns Result: false, but no error.
+ ctxlogrus.Extract(ctx).WithError(fetchErr.err).WithField("stderr", fetchErr.stderr).Warn("git fetch failed")
+ return &gitalypb.FetchInternalRemoteResponse{Result: false}, nil
+ }
+
+ return nil, err
+ }
+
return &gitalypb.FetchInternalRemoteResponse{Result: true}, nil
}