diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2021-06-14 12:07:50 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2021-06-14 12:32:33 +0300 |
commit | eef84a6ab29c2ca39a09d5df799434e3044aeb7f (patch) | |
tree | cefd08d46e43785eb60e5c3f6094b5bca3ba9e73 | |
parent | 2bcaef7238179d2f277ddbf4e10308b5c0db6bfe (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.go | 79 |
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 } |