From ccffd885339855f18c46deb293ea02f12fe099d4 Mon Sep 17 00:00:00 2001 From: Gabriel Mazetto Date: Mon, 28 Feb 2022 20:57:46 +0100 Subject: Repository: allow opting for --mirror for CreateRepositoryFromURL Changelog: added --- .../repository/create_repository_from_url.go | 10 ++- .../repository/create_repository_from_url_test.go | 74 +++++++++++++++++++++- .../gitaly/service/repository/testhelper_test.go | 10 +++ 3 files changed, 89 insertions(+), 5 deletions(-) (limited to 'internal/gitaly/service') diff --git a/internal/gitaly/service/repository/create_repository_from_url.go b/internal/gitaly/service/repository/create_repository_from_url.go index 1280d78fb..1079aea85 100644 --- a/internal/gitaly/service/repository/create_repository_from_url.go +++ b/internal/gitaly/service/repository/create_repository_from_url.go @@ -18,7 +18,7 @@ import ( func (s *server) cloneFromURLCommand( ctx context.Context, - repoURL, repoHost, repositoryFullPath, authorizationToken string, + repoURL, repoHost, repositoryFullPath, authorizationToken string, mirror bool, opts ...git.CmdOpt, ) (*command.Command, error) { u, err := url.Parse(repoURL) @@ -29,10 +29,15 @@ func (s *server) cloneFromURLCommand( var config []git.ConfigPair cloneFlags := []git.Option{ - git.Flag{Name: "--bare"}, git.Flag{Name: "--quiet"}, } + if mirror { + cloneFlags = append(cloneFlags, git.Flag{Name: "--mirror"}) + } else { + cloneFlags = append(cloneFlags, git.Flag{Name: "--bare"}) + } + if u.User != nil { pwd, set := u.User.Password() @@ -92,6 +97,7 @@ func (s *server) CreateRepositoryFromURL(ctx context.Context, req *gitalypb.Crea req.GetHttpHost(), targetPath, req.GetHttpAuthorizationHeader(), + req.GetMirror(), git.WithStderr(&stderr), git.WithDisabledHooks(), ) diff --git a/internal/gitaly/service/repository/create_repository_from_url_test.go b/internal/gitaly/service/repository/create_repository_from_url_test.go index cb30a8d2d..19472412f 100644 --- a/internal/gitaly/service/repository/create_repository_from_url_test.go +++ b/internal/gitaly/service/repository/create_repository_from_url_test.go @@ -19,7 +19,7 @@ import ( "google.golang.org/grpc/codes" ) -func TestCreateRepotitoryFromURL_successful(t *testing.T) { +func TestCreateRepositoryFromURL_successful(t *testing.T) { t.Parallel() ctx := testhelper.Context(t) @@ -59,6 +59,55 @@ func TestCreateRepotitoryFromURL_successful(t *testing.T) { require.True(t, os.IsNotExist(err), "hooks directory should not have been created") } +func TestCreateRepositoryFromURL_successfulWithOptionalParameters(t *testing.T) { + t.Parallel() + ctx := testhelper.Context(t) + + cfg, _, repoPath, client := setupRepositoryServiceFromMirror(ctx, t) + gitCmdFactory := gittest.NewCommandFactory(t, cfg) + + importedRepo := &gitalypb.Repository{ + RelativePath: "imports/test-repo-imported-mirror.git", + StorageName: cfg.Storages[0].Name, + } + + user := "username123" + password := "password321localhost" + port, stopGitServer := gitServerWithBasicAuth(ctx, t, gitCmdFactory, user, password, repoPath) + defer func() { + require.NoError(t, stopGitServer()) + }() + + url := fmt.Sprintf("http://%s:%s@localhost:%d/%s", user, password, port, filepath.Base(repoPath)) + host := "www.example.com" + authToken := "GL-Geo EhEhKSUk_385GSLnS7BI:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoie1wic2NvcGVcIjpcInJvb3QvZ2l0bGFiLWNlXCJ9IiwianRpIjoiNmQ4ZDM1NGQtZjUxYS00MDQ5LWExZjctMjUyMjk4YmQwMTI4IiwiaWF0IjoxNjQyMDk1MzY5LCJuYmYiOjE2NDIwOTUzNjQsImV4cCI6MTY0MjA5NTk2OX0.YEpfzg8305dUqkYOiB7_dhbL0FVSaUPgpSpMuKrgNrg" + mirror := true + + req := &gitalypb.CreateRepositoryFromURLRequest{ + Repository: importedRepo, + Url: url, + HttpHost: host, + HttpAuthorizationHeader: authToken, + Mirror: mirror, + } + + _, err := client.CreateRepositoryFromURL(ctx, req) + require.NoError(t, err) + + importedRepoPath := filepath.Join(cfg.Storages[0].Path, gittest.GetReplicaPath(ctx, t, cfg, importedRepo)) + + gittest.Exec(t, cfg, "-C", importedRepoPath, "fsck") + + remotes := gittest.Exec(t, cfg, "-C", importedRepoPath, "remote") + require.NotContains(t, string(remotes), "origin") + + references := gittest.Exec(t, cfg, "-C", importedRepoPath, "show-ref", "--abbrev") + require.Contains(t, string(references), "refs/merge-requests") + + _, err = os.Lstat(filepath.Join(importedRepoPath, "hooks")) + require.True(t, os.IsNotExist(err), "hooks directory should not have been created") +} + func TestCreateRepositoryFromURL_existingTarget(t *testing.T) { t.Parallel() ctx := testhelper.Context(t) @@ -147,15 +196,17 @@ func TestServer_CloneFromURLCommand(t *testing.T) { cfg := testcfg.Build(t) s := server{cfg: cfg, gitCmdFactory: gittest.NewCommandFactory(t, cfg)} - cmd, err := s.cloneFromURLCommand(ctx, url, host, repositoryFullPath, authToken, git.WithDisabledHooks()) + cmd, err := s.cloneFromURLCommand(ctx, url, host, repositoryFullPath, authToken, false, git.WithDisabledHooks()) require.NoError(t, err) + expectedBareFlag := "--bare" expectedScrubbedURL := "https://192.0.2.1/secretrepo.git" expectedBasicAuthHeader := fmt.Sprintf("Authorization: Basic %s", base64.StdEncoding.EncodeToString([]byte("user:pass!?@"))) expectedAuthHeader := fmt.Sprintf("http.extraHeader=%s", expectedBasicAuthHeader) expectedHostHeader := "http.extraHeader=Host: www.example.com" args := cmd.Args() + require.Contains(t, args, expectedBareFlag) require.Contains(t, args, expectedScrubbedURL) require.Contains(t, args, expectedAuthHeader) require.Contains(t, args, expectedHostHeader) @@ -172,7 +223,7 @@ func TestServer_CloneFromURLCommand_withToken(t *testing.T) { cfg := testcfg.Build(t) s := server{cfg: cfg, gitCmdFactory: gittest.NewCommandFactory(t, cfg)} - cmd, err := s.cloneFromURLCommand(ctx, url, "", repositoryFullPath, authToken, git.WithDisabledHooks()) + cmd, err := s.cloneFromURLCommand(ctx, url, "", repositoryFullPath, authToken, false, git.WithDisabledHooks()) require.NoError(t, err) expectedScrubbedURL := "https://www.example.com/secretrepo.git" @@ -184,6 +235,23 @@ func TestServer_CloneFromURLCommand_withToken(t *testing.T) { require.Contains(t, args, expectedHeader) } +func TestServer_CloneFromURLCommand_withMirror(t *testing.T) { + t.Parallel() + ctx := testhelper.Context(t) + + repositoryFullPath := "full/path/to/repository" + url := "https://www.example.com/secretrepo.git" + + cfg := testcfg.Build(t) + s := server{cfg: cfg, gitCmdFactory: gittest.NewCommandFactory(t, cfg)} + cmd, err := s.cloneFromURLCommand(ctx, url, "", repositoryFullPath, "", true, git.WithDisabledHooks()) + require.NoError(t, err) + + args := cmd.Args() + require.Contains(t, args, "--mirror") + require.NotContains(t, args, "--bare") +} + func gitServerWithBasicAuth(ctx context.Context, t testing.TB, gitCmdFactory git.CommandFactory, user, pass, repoPath string) (int, func() error) { return gittest.HTTPServer(ctx, t, gitCmdFactory, repoPath, basicAuthMiddleware(t, user, pass)) } diff --git a/internal/gitaly/service/repository/testhelper_test.go b/internal/gitaly/service/repository/testhelper_test.go index 69c0b0448..bd289de33 100644 --- a/internal/gitaly/service/repository/testhelper_test.go +++ b/internal/gitaly/service/repository/testhelper_test.go @@ -158,6 +158,16 @@ func setupRepositoryService(ctx context.Context, t testing.TB, opts ...testserve return cfg, repo, repoPath, client } +// Sets up a repository that has been cloned using `--mirror` which contains GitLab internal references +func setupRepositoryServiceFromMirror(ctx context.Context, t testing.TB, opts ...testserver.GitalyServerOpt) (config.Cfg, *gitalypb.Repository, string, gitalypb.RepositoryServiceClient) { + cfg, client := setupRepositoryServiceWithoutRepo(t, opts...) + + repo, repoPath := gittest.CreateRepository(ctx, t, cfg, gittest.CreateRepositoryConfig{ + Seed: gittest.SeedGitLabTestMirror, + }) + return cfg, repo, repoPath, client +} + func setupRepositoryServiceWithoutRepo(t testing.TB, opts ...testserver.GitalyServerOpt) (config.Cfg, gitalypb.RepositoryServiceClient) { cfg := testcfg.Build(t) -- cgit v1.2.3