diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2021-05-19 11:46:08 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2021-05-19 19:44:10 +0300 |
commit | c28412f83bfb074908189c8bd42e3ea632a06efb (patch) | |
tree | a0d095035d5a4df2408758de3ef040b19424cdeb | |
parent | f18374c18d47f322f5a540fa4dddec7696f4f4d3 (diff) |
repository: Replicate gitconfig
When replicating repositories, we do not currently replicate the
gitconfig. This is quite important to do though given that the gitconfig
may influence various different aspects of Git and may thus cause
mismatching results if it is different across replicas. Even if we
eventually remove the `AddConfig()` and `DeleteConfig()` RPCs, we'd
still want to replicate it given that different Git versions may end up
with different defaults and thus with different gitconfig files.
Implement replication of gitconfig files. As the `GetConfig()` RPC which
we require for this has only been introduced in this same commit series,
we need to play it safe and for now ignore all errors returned by it to
guard against the case where the remote Gitaly instance doesn't yet
support it. This workaround can be dropped in the next release cycle.
Changelog: added
-rw-r--r-- | internal/gitaly/service/repository/replicate.go | 42 | ||||
-rw-r--r-- | internal/gitaly/service/repository/replicate_test.go | 9 |
2 files changed, 51 insertions, 0 deletions
diff --git a/internal/gitaly/service/repository/replicate.go b/internal/gitaly/service/repository/replicate.go index e1daa27d5..6d7354c5a 100644 --- a/internal/gitaly/service/repository/replicate.go +++ b/internal/gitaly/service/repository/replicate.go @@ -57,6 +57,7 @@ func (s *server) ReplicateRepository(ctx context.Context, in *gitalypb.Replicate outgoingCtx := helper.IncomingToOutgoing(ctx) syncFuncs := []func(context.Context, *gitalypb.ReplicateRepositoryRequest) error{ + s.syncGitconfig, s.syncInfoAttributes, s.syncRepository, } @@ -209,6 +210,47 @@ func (s *server) syncRepository(ctx context.Context, in *gitalypb.ReplicateRepos return nil } +func (s *server) syncGitconfig(ctx context.Context, in *gitalypb.ReplicateRepositoryRequest) error { + repoClient, err := s.newRepoClient(ctx, in.GetSource().GetStorageName()) + if err != nil { + return err + } + + repoPath, err := s.locator.GetRepoPath(in.GetRepository()) + if err != nil { + return err + } + + // At the point of implementing this, the `GetConfig` RPC hasn't been deployed yet and is + // thus not available for general use. In theory, we'd have to wait for this release cycle + // to finish, and only afterwards would we be able to implement replication of the + // gitconfig. In order to allow us to iterate fast, we just try to call `GetConfig()`, but + // ignore any errors for the case where the target Gitaly node doesn't support the RPC yet. + // TODO: Remove this hack and properly return the error in the next release cycle. + if err := func() error { + stream, err := repoClient.GetConfig(ctx, &gitalypb.GetConfigRequest{ + Repository: in.GetSource(), + }) + if err != nil { + return err + } + + configPath := filepath.Join(repoPath, "config") + if err := writeFile(configPath, 0644, streamio.NewReader(func() ([]byte, error) { + resp, err := stream.Recv() + return resp.GetData(), err + })); err != nil { + return err + } + + return nil + }(); err != nil { + ctxlogrus.Extract(ctx).WithError(err).Warn("synchronizing gitconfig failed") + } + + return nil +} + func (s *server) syncInfoAttributes(ctx context.Context, in *gitalypb.ReplicateRepositoryRequest) error { repoClient, err := s.newRepoClient(ctx, in.GetSource().GetStorageName()) if err != nil { diff --git a/internal/gitaly/service/repository/replicate_test.go b/internal/gitaly/service/repository/replicate_test.go index 84a61240e..131392911 100644 --- a/internal/gitaly/service/repository/replicate_test.go +++ b/internal/gitaly/service/repository/replicate_test.go @@ -47,6 +47,11 @@ func TestReplicateRepository(t *testing.T) { attrData := []byte("*.pbxproj binary\n") require.NoError(t, ioutil.WriteFile(attrFilePath, attrData, 0644)) + // Write a modified gitconfig + gittest.Exec(t, cfg, "-C", repoPath, "config", "please.replicate", "me") + configData := testhelper.MustReadFile(t, filepath.Join(repoPath, "config")) + require.Contains(t, string(configData), "[please]\n\treplicate = me\n") + targetRepo := *repo targetRepo.StorageName = cfg.Storages[1].Name @@ -68,6 +73,10 @@ func TestReplicateRepository(t *testing.T) { replicatedAttrData := testhelper.MustReadFile(t, replicatedAttrFilePath) require.Equal(t, string(attrData), string(replicatedAttrData), "info/attributes files must match") + replicatedConfigPath := filepath.Join(targetRepoPath, "config") + replicatedConfigData := testhelper.MustReadFile(t, replicatedConfigPath) + require.Equal(t, string(configData), string(replicatedConfigData), "config files must match") + // create another branch gittest.WriteCommit(t, cfg, repoPath, gittest.WithBranch("branch")) _, err = client.ReplicateRepository(injectedCtx, &gitalypb.ReplicateRepositoryRequest{ |