diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2023-06-07 16:25:30 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2023-06-07 16:25:30 +0300 |
commit | e5d3bdf14db2f202c8d3679a75474f4760ac45c7 (patch) | |
tree | df3473049e7e9f52f049b027394c9f7517534ffa | |
parent | 1934b9991139b48ed58d78dc89b35c262acd5150 (diff) | |
parent | 7c60bca26b57df5630ca0bc77e284dfe63adb3c3 (diff) |
Merge branch 'pks-locator-improve-invalid-repo-reporting' into 'master'
config/locator: Improve error reporting for invalid repositories
See merge request https://gitlab.com/gitlab-org/gitaly/-/merge_requests/5891
Merged-by: Patrick Steinhardt <psteinhardt@gitlab.com>
Approved-by: Pavlo Strokov <pstrokov@gitlab.com>
Reviewed-by: Patrick Steinhardt <psteinhardt@gitlab.com>
Reviewed-by: Pavlo Strokov <pstrokov@gitlab.com>
Reviewed-by: Justin Tobler <jtobler@gitlab.com>
73 files changed, 407 insertions, 403 deletions
diff --git a/internal/backup/repository.go b/internal/backup/repository.go index 957c4b64d..d43574645 100644 --- a/internal/backup/repository.go +++ b/internal/backup/repository.go @@ -263,15 +263,19 @@ func newLocalRepository( // IsEmpty returns true if the repository has no branches. func (r *localRepository) IsEmpty(ctx context.Context) (bool, error) { - path, err := r.locator.GetPath(r.repo) + path, err := r.locator.GetRepoPath(r.repo, storage.WithRepositoryVerificationSkipped()) if err != nil { return false, fmt.Errorf("local repository: is empty: %w", err) } - if !storage.IsGitDirectory(path) { - // Backups do not currently differentiate between non-existent and - // empty. See https://gitlab.com/gitlab-org/gitlab/-/issues/357044 - return true, nil + if err := storage.ValidateRepository(path); err != nil { + if errors.Is(err, storage.ErrRepositoryNotFound) { + // Backups do not currently differentiate between non-existent and + // empty. See https://gitlab.com/gitlab-org/gitlab/-/issues/357044 + return true, nil + } + + return false, fmt.Errorf("local repository: verifying repository: %w", err) } hasBranches, err := r.repo.HasBranches(ctx) diff --git a/internal/cli/gitaly/hooks_test.go b/internal/cli/gitaly/hooks_test.go index 6e92e1028..2ea14ddc6 100644 --- a/internal/cli/gitaly/hooks_test.go +++ b/internal/cli/gitaly/hooks_test.go @@ -2,6 +2,7 @@ package gitaly import ( "bytes" + "fmt" "io" "io/fs" "os/exec" @@ -14,6 +15,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/config" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service/setup" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" internalclient "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/client" "gitlab.com/gitlab-org/gitaly/v16/internal/helper/perm" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" @@ -116,7 +118,7 @@ func TestSetHooksSubcommand(t *testing.T) { }, hooks: testhelper.MustCreateCustomHooksTar(t), expectedErr: testhelper.GitalyOrPraefect( - "getting repo path: GetRepoPath: not a git repository:", + fmt.Sprintf("getting repo path: %s", storage.ErrRepositoryNotFound), "rpc error: code = NotFound desc = mutator call: route repository mutator: get repository id: repository \"default\"/\"non-existent\" not found\n", ), }, diff --git a/internal/cli/praefect/subcmd_remove_repository_test.go b/internal/cli/praefect/subcmd_remove_repository_test.go index a89ab27ed..57cdc9ddb 100644 --- a/internal/cli/praefect/subcmd_remove_repository_test.go +++ b/internal/cli/praefect/subcmd_remove_repository_test.go @@ -188,8 +188,8 @@ func TestRemoveRepositorySubcommand(t *testing.T) { require.NoError(t, err) require.False(t, repositoryExists(t, repo)) // Repo is still present on-disk on the Gitaly nodes. - require.True(t, storage.IsGitDirectory(filepath.Join(g1Cfg.Storages[0].Path, replicaPath))) - require.True(t, storage.IsGitDirectory(filepath.Join(g2Cfg.Storages[0].Path, replicaPath))) + require.NoError(t, storage.ValidateRepository(filepath.Join(g1Cfg.Storages[0].Path, replicaPath))) + require.NoError(t, storage.ValidateRepository(filepath.Join(g2Cfg.Storages[0].Path, replicaPath))) }, assertOutput: func(t *testing.T, out string, repo *gitalypb.Repository) { assert.Contains(t, out, "Repository found in the database.\n") diff --git a/internal/cli/praefect/subcmd_track_repository.go b/internal/cli/praefect/subcmd_track_repository.go index 1c28cbe28..d8381194b 100644 --- a/internal/cli/praefect/subcmd_track_repository.go +++ b/internal/cli/praefect/subcmd_track_repository.go @@ -12,10 +12,10 @@ import ( "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" glcli "gitlab.com/gitlab-org/gitaly/v16/internal/cli" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/middleware/metadatahandler" "gitlab.com/gitlab-org/gitaly/v16/internal/log" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/commonerr" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/config" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore/glsql" @@ -275,7 +275,7 @@ func (req *trackRepositoryRequest) trackRepository( ) (int64, error) { repositoryID, err := ds.ReserveRepositoryID(ctx, req.VirtualStorage, req.RelativePath) if err != nil { - if errors.Is(err, commonerr.ErrRepositoryAlreadyExists) { + if errors.Is(err, storage.ErrRepositoryAlreadyExists) { fmt.Fprintf(w, "repository is already tracked in praefect database") return 0, nil } diff --git a/internal/git/localrepo/paths_test.go b/internal/git/localrepo/paths_test.go index dcd216527..b87c56e5c 100644 --- a/internal/git/localrepo/paths_test.go +++ b/internal/git/localrepo/paths_test.go @@ -10,6 +10,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/git/localrepo" "gitlab.com/gitlab-org/gitaly/v16/internal/git/quarantine" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/config" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/helper/perm" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" @@ -44,7 +45,7 @@ func TestRepo_Path(t *testing.T) { require.NoError(t, os.RemoveAll(repoPath)) _, err := repo.Path() - require.Equal(t, structerr.NewNotFound("GetRepoPath: not a git repository: %q", repoPath), err) + require.Equal(t, structerr.NewNotFound("%w", storage.ErrRepositoryNotFound).WithMetadata("repository_path", repoPath), err) }) t.Run("non-git repository", func(t *testing.T) { @@ -59,7 +60,7 @@ func TestRepo_Path(t *testing.T) { require.NoError(t, os.MkdirAll(repoPath, perm.PublicDir)) _, err := repo.Path() - require.Equal(t, structerr.NewNotFound("GetRepoPath: not a git repository: %q", repoPath), err) + require.Equal(t, structerr.NewFailedPrecondition("%w: %q does not exist", storage.ErrRepositoryNotValid, "objects").WithMetadata("repository_path", repoPath), err) }) } diff --git a/internal/git/localrepo/remote_extra_test.go b/internal/git/localrepo/remote_extra_test.go index 69772479c..20cc997ed 100644 --- a/internal/git/localrepo/remote_extra_test.go +++ b/internal/git/localrepo/remote_extra_test.go @@ -13,6 +13,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service/hook" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service/repository" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service/ssh" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testcfg" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testserver" @@ -186,7 +187,7 @@ func TestRepo_FetchInternal(t *testing.T) { require.Error(t, err) require.IsType(t, err, localrepo.FetchFailedError{}) - expectedMsg := "GetRepoPath: not a git repository" + expectedMsg := storage.ErrRepositoryNotFound.Error() if testhelper.IsPraefectEnabled() { expectedMsg = `repository \"default\"/\"does/not/exist\" not found` } diff --git a/internal/git/objectpool/create.go b/internal/git/objectpool/create.go index 18323e05d..4f4787b1a 100644 --- a/internal/git/objectpool/create.go +++ b/internal/git/objectpool/create.go @@ -32,7 +32,7 @@ func Create( proto *gitalypb.ObjectPool, sourceRepo *localrepo.Repo, ) (*ObjectPool, error) { - objectPoolPath, err := locator.GetPath(proto.GetRepository()) + objectPoolPath, err := locator.GetRepoPath(proto.GetRepository(), storage.WithRepositoryVerificationSkipped()) if err != nil { return nil, err } diff --git a/internal/git/objectpool/pool.go b/internal/git/objectpool/pool.go index 3f4206888..720204320 100644 --- a/internal/git/objectpool/pool.go +++ b/internal/git/objectpool/pool.go @@ -52,7 +52,7 @@ func FromProto( housekeepingManager housekeeping.Manager, proto *gitalypb.ObjectPool, ) (*ObjectPool, error) { - poolPath, err := locator.GetPath(proto.GetRepository()) + poolPath, err := locator.GetRepoPath(proto.GetRepository(), storage.WithRepositoryVerificationSkipped()) if err != nil { return nil, err } @@ -117,7 +117,7 @@ func (o *ObjectPool) IsValid() bool { return false } - return storage.IsGitDirectory(path) + return storage.ValidateRepository(path) == nil } // Remove will remove the pool, and all its contents without preparing and/or @@ -220,7 +220,7 @@ func objectPathRelativeToStorage(locator storage.Locator, storageName, path, rep poolObjectDirFullPath := filepath.Join(objectDirPath, path) - if !storage.IsGitDirectory(filepath.Dir(poolObjectDirFullPath)) { + if storage.ValidateRepository(filepath.Dir(poolObjectDirFullPath)) != nil { return "", ErrInvalidPoolRepository } diff --git a/internal/git/quarantine/quarantine.go b/internal/git/quarantine/quarantine.go index b6d569c55..115de6ace 100644 --- a/internal/git/quarantine/quarantine.go +++ b/internal/git/quarantine/quarantine.go @@ -33,7 +33,7 @@ type Dir struct { // New creates a new quarantine directory and returns the directory. The repository is cleaned // up when the user invokes the Migrate() functionality on the Dir. func New(ctx context.Context, repo *gitalypb.Repository, locator storage.Locator) (*Dir, error) { - repoPath, err := locator.GetPath(repo) + repoPath, err := locator.GetRepoPath(repo, storage.WithRepositoryVerificationSkipped()) if err != nil { return nil, structerr.NewInternal("getting repo path: %w", err) } @@ -89,7 +89,7 @@ func (d *Dir) QuarantinedRepo() *gitalypb.Repository { // Migrate migrates all objects part of the quarantine directory into the main repository and thus // makes them generally available. This implementation follows the git.git's `tmp_objdir_migrate()`. func (d *Dir) Migrate() error { - repoPath, err := d.locator.GetPath(d.repo) + repoPath, err := d.locator.GetRepoPath(d.repo, storage.WithRepositoryVerificationSkipped()) if err != nil { return fmt.Errorf("migrating quarantine: %w", err) } diff --git a/internal/gitaly/config/locator.go b/internal/gitaly/config/locator.go index a69d947c8..539ead41d 100644 --- a/internal/gitaly/config/locator.go +++ b/internal/gitaly/config/locator.go @@ -44,22 +44,6 @@ func (l *configLocator) GetRepoPath(repo storage.Repository, opts ...storage.Get opt(&cfg) } - repoPath, err := l.GetPath(repo) - if err != nil { - return "", err - } - - if cfg.SkipRepositoryVerification || storage.IsGitDirectory(repoPath) { - return repoPath, nil - } - - return "", structerr.NewNotFound("GetRepoPath: not a git repository: %q", repoPath) -} - -// GetPath returns the path of the repo passed as first argument. An error is -// returned when either the storage can't be found or the path includes -// constructs trying to perform directory traversal. -func (l *configLocator) GetPath(repo storage.Repository) (string, error) { storagePath, err := l.GetStorageByName(repo.GetStorageName()) if err != nil { return "", err @@ -67,22 +51,30 @@ func (l *configLocator) GetPath(repo storage.Repository) (string, error) { if _, err := os.Stat(storagePath); err != nil { if os.IsNotExist(err) { - return "", structerr.NewNotFound("GetPath: does not exist: %w", err) + return "", structerr.NewNotFound("storage does not exist").WithMetadata("storage_path", storagePath) } - return "", structerr.NewInternal("GetPath: storage path: %w", err) + return "", structerr.New("storage path: %w", err).WithMetadata("storage_path", storagePath) } relativePath := repo.GetRelativePath() if len(relativePath) == 0 { - err := structerr.NewInvalidArgument("GetPath: relative path missing") + err := structerr.NewInvalidArgument("relative path is not set") return "", err } if _, err := storage.ValidateRelativePath(storagePath, relativePath); err != nil { - return "", structerr.NewInvalidArgument("GetRepoPath: %w", err) + return "", structerr.NewInvalidArgument("%w", err).WithMetadata("relative_path", relativePath) + } + + repoPath := filepath.Join(storagePath, relativePath) + + if !cfg.SkipRepositoryVerification { + if err := storage.ValidateRepository(repoPath); err != nil { + return "", err + } } - return filepath.Join(storagePath, relativePath), nil + return repoPath, nil } // GetStorageByName will return the path for the storage, which is fetched by diff --git a/internal/gitaly/config/locator_test.go b/internal/gitaly/config/locator_test.go index 94af343d4..e3b596373 100644 --- a/internal/gitaly/config/locator_test.go +++ b/internal/gitaly/config/locator_test.go @@ -1,12 +1,9 @@ package config_test import ( - "fmt" - "io/fs" "os" "path/filepath" "strings" - "syscall" "testing" "github.com/stretchr/testify/require" @@ -62,28 +59,25 @@ func TestConfigLocator_GetRepoPath(t *testing.T) { expErr: structerr.NewInvalidArgument(`GetStorageByName: no such storage: "invalid"`), }, { - desc: "storage doesn't exist on disk", - repo: &gitalypb.Repository{StorageName: cfg.Storages[1].Name, RelativePath: repo.RelativePath}, - expErr: structerr.NewNotFound(`GetPath: does not exist: %w`, &fs.PathError{ - Op: "stat", - Path: cfg.Storages[1].Path, - Err: syscall.ENOENT, - }), + desc: "storage doesn't exist on disk", + repo: &gitalypb.Repository{StorageName: cfg.Storages[1].Name, RelativePath: repo.RelativePath}, + expErr: structerr.NewNotFound("storage does not exist").WithMetadata("storage_path", cfg.Storages[1].Path), }, { desc: "relative path is empty", repo: &gitalypb.Repository{StorageName: storageName, RelativePath: ""}, - expErr: structerr.NewInvalidArgument("GetPath: relative path missing"), + expErr: structerr.NewInvalidArgument("relative path is not set"), }, { desc: "unknown relative path", repo: &gitalypb.Repository{StorageName: storageName, RelativePath: "invalid"}, - expErr: structerr.NewNotFound(`GetRepoPath: not a git repository: %q`, filepath.Join(cfg.Storages[0].Path, "invalid")), + expErr: structerr.NewNotFound("%w", storage.ErrRepositoryNotFound).WithMetadata("repository_path", filepath.Join(cfg.Storages[0].Path, "invalid")), }, { - desc: "path exists but not a git repository", - repo: &gitalypb.Repository{StorageName: storageName, RelativePath: notRepositoryFolder}, - expErr: structerr.NewNotFound(`GetRepoPath: not a git repository: %q`, filepath.Join(cfg.Storages[0].Path, notRepositoryFolder)), + desc: "path exists but not a git repository", + repo: &gitalypb.Repository{StorageName: storageName, RelativePath: notRepositoryFolder}, + expErr: structerr.NewFailedPrecondition("%w: %q does not exist", storage.ErrRepositoryNotValid, "objects"). + WithMetadata("repository_path", filepath.Join(cfg.Storages[0].Path, notRepositoryFolder)), }, { desc: "unknown relative path without repo verification", @@ -100,7 +94,7 @@ func TestConfigLocator_GetRepoPath(t *testing.T) { { desc: "relative path escapes parent folder", repo: &gitalypb.Repository{StorageName: storageName, RelativePath: "../.."}, - expErr: structerr.NewInvalidArgument(`GetRepoPath: %w`, fmt.Errorf("relative path escapes root directory")), + expErr: structerr.NewInvalidArgument("%w", storage.ErrRelativePathEscapesRoot).WithMetadata("relative_path", "../.."), }, { desc: "proper repository path", @@ -116,98 +110,6 @@ func TestConfigLocator_GetRepoPath(t *testing.T) { } } -func TestConfigLocator_GetPath(t *testing.T) { - t.Parallel() - const storageName = "exists" - ctx := testhelper.Context(t) - cfg := testcfg.Build(t, testcfg.WithStorages(storageName, "removed")) - cfg.SocketPath = testserver.RunGitalyServer(t, cfg, setup.RegisterAll) - repo, _ := gittest.CreateRepository(t, ctx, cfg) - - // The storage name still present in the storages list, but not on the disk. - require.NoError(t, os.RemoveAll(cfg.Storages[1].Path)) - - // The repository path exists on the disk, but it is not a git repository. - const notRepositoryFolder = "not-a-git-repo" - require.NoError(t, os.MkdirAll(filepath.Join(cfg.Storages[0].Path, notRepositoryFolder), perm.SharedDir)) - - for _, tc := range []struct { - desc string - repo *gitalypb.Repository - path string - }{ - { - desc: "proper repository path", - repo: repo, - path: filepath.Join(cfg.Storages[0].Path, repo.RelativePath), - }, - { - desc: "path doesn't exist", - repo: &gitalypb.Repository{StorageName: storageName, RelativePath: "doesnt/exist"}, - path: filepath.Join(cfg.Storages[0].Path, "doesnt/exist"), - }, - { - desc: "path exists but not a git repository", - repo: &gitalypb.Repository{StorageName: storageName, RelativePath: notRepositoryFolder}, - path: filepath.Join(cfg.Storages[0].Path, notRepositoryFolder), - }, - { - desc: "relative path includes travels", - repo: &gitalypb.Repository{StorageName: storageName, RelativePath: "some/../other"}, - path: filepath.Join(cfg.Storages[0].Path, "other"), - }, - } { - t.Run(tc.desc, func(t *testing.T) { - locator := config.NewLocator(cfg) - path, err := locator.GetPath(tc.repo) - require.NoError(t, err) - require.Equal(t, tc.path, path) - }) - } - - for _, tc := range []struct { - desc string - repo *gitalypb.Repository - expErr error - }{ - { - desc: "storage is empty", - repo: &gitalypb.Repository{RelativePath: repo.RelativePath}, - expErr: structerr.NewInvalidArgument(`GetStorageByName: no such storage: ""`), - }, - { - desc: "unknown storage", - repo: &gitalypb.Repository{StorageName: "invalid", RelativePath: repo.RelativePath}, - expErr: structerr.NewInvalidArgument(`GetStorageByName: no such storage: "invalid"`), - }, - { - desc: "storage doesn't exist on disk", - repo: &gitalypb.Repository{StorageName: cfg.Storages[1].Name, RelativePath: repo.RelativePath}, - expErr: structerr.NewNotFound(`GetPath: does not exist: %w`, &fs.PathError{ - Op: "stat", - Path: cfg.Storages[1].Path, - Err: syscall.ENOENT, - }), - }, - { - desc: "relative path is empty", - repo: &gitalypb.Repository{StorageName: storageName, RelativePath: ""}, - expErr: structerr.NewInvalidArgument("GetPath: relative path missing"), - }, - { - desc: "relative path escapes parent folder", - repo: &gitalypb.Repository{StorageName: storageName, RelativePath: "../.."}, - expErr: structerr.NewInvalidArgument(`GetRepoPath: %w`, fmt.Errorf("relative path escapes root directory")), - }, - } { - t.Run(tc.desc, func(t *testing.T) { - locator := config.NewLocator(cfg) - _, err := locator.GetPath(tc.repo) - require.Equal(t, tc.expErr, err) - }) - } -} - func TestConfigLocator_CacheDir(t *testing.T) { t.Parallel() const storageName = "exists" diff --git a/internal/gitaly/hook/custom.go b/internal/gitaly/hook/custom.go index 6ccf968a0..c4faf0680 100644 --- a/internal/gitaly/hook/custom.go +++ b/internal/gitaly/hook/custom.go @@ -11,6 +11,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/command" "gitlab.com/gitlab-org/gitaly/v16/internal/git" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/helper/env" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" "golang.org/x/sys/unix" @@ -159,7 +160,7 @@ func isValidHook(path string) bool { } func (m *GitLabHookManager) customHooksEnv(ctx context.Context, payload git.HooksPayload, pushOptions []string, envs []string) ([]string, error) { - repoPath, err := m.locator.GetPath(payload.Repo) + repoPath, err := m.locator.GetRepoPath(payload.Repo, storage.WithRepositoryVerificationSkipped()) if err != nil { return nil, err } diff --git a/internal/gitaly/hook/testhelper_test.go b/internal/gitaly/hook/testhelper_test.go index 69e0b2ea5..935aef1f5 100644 --- a/internal/gitaly/hook/testhelper_test.go +++ b/internal/gitaly/hook/testhelper_test.go @@ -22,7 +22,7 @@ func TestMain(m *testing.M) { } func getExpectedEnv(tb testing.TB, ctx context.Context, locator storage.Locator, gitCmdFactory git.CommandFactory, repo *gitalypb.Repository) []string { - repoPath, err := locator.GetPath(repo) + repoPath, err := locator.GetRepoPath(repo, storage.WithRepositoryVerificationSkipped()) require.NoError(tb, err) expectedEnv := map[string]string{ diff --git a/internal/gitaly/linguist/linguist_test.go b/internal/gitaly/linguist/linguist_test.go index da96b7d25..c70b2a790 100644 --- a/internal/gitaly/linguist/linguist_test.go +++ b/internal/gitaly/linguist/linguist_test.go @@ -13,6 +13,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v16/internal/git/localrepo" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/config" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/helper/perm" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testcfg" @@ -509,7 +510,7 @@ func TestInstance_Stats(t *testing.T) { return repoProto, repoPath, git.ObjectID("b1bb1d1b0b1d1b00") }, - expectedErr: "GetRepoPath: not a git repository", + expectedErr: storage.ErrRepositoryNotFound.Error(), }, { desc: "missing commit", diff --git a/internal/gitaly/maintenance/optimize.go b/internal/gitaly/maintenance/optimize.go index fdd9bd1e8..9d866827d 100644 --- a/internal/gitaly/maintenance/optimize.go +++ b/internal/gitaly/maintenance/optimize.go @@ -148,7 +148,7 @@ func walkReposShuffled( return err } - if !fi.IsDir() || !storage.IsGitDirectory(path) { + if !fi.IsDir() || storage.ValidateRepository(path) != nil { continue } walker.skipDir() diff --git a/internal/gitaly/repoutil/create.go b/internal/gitaly/repoutil/create.go index d070dc855..faade627f 100644 --- a/internal/gitaly/repoutil/create.go +++ b/internal/gitaly/repoutil/create.go @@ -69,7 +69,7 @@ func Create( seedRepository func(repository *gitalypb.Repository) error, options ...CreateOption, ) error { - targetPath, err := locator.GetPath(repository) + targetPath, err := locator.GetRepoPath(repository, storage.WithRepositoryVerificationSkipped()) if err != nil { return structerr.NewInvalidArgument("locate repository: %w", err) } diff --git a/internal/gitaly/repoutil/create_test.go b/internal/gitaly/repoutil/create_test.go index 97ae936a2..1728caac2 100644 --- a/internal/gitaly/repoutil/create_test.go +++ b/internal/gitaly/repoutil/create_test.go @@ -14,6 +14,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v16/internal/git/stats" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/config" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/transaction" "gitlab.com/gitlab-org/gitaly/v16/internal/helper/perm" "gitlab.com/gitlab-org/gitaly/v16/internal/helper/text" @@ -333,7 +334,7 @@ func TestCreate(t *testing.T) { ctx = peer.NewContext(ctx, &peer.Peer{}) } - repoPath, err := locator.GetPath(repo) + repoPath, err := locator.GetRepoPath(repo, storage.WithRepositoryVerificationSkipped()) require.NoError(t, err) if tc.setup != nil { @@ -349,7 +350,7 @@ func TestCreate(t *testing.T) { require.Equal(t, repo.StorageName, tempRepo.StorageName) require.True(t, strings.HasPrefix(tempRepo.RelativePath, "+gitaly/tmp/repo")) - tempRepoPath, err := locator.GetPath(tempRepo) + tempRepoPath, err := locator.GetRepoPath(tempRepo, storage.WithRepositoryVerificationSkipped()) require.NoError(t, err) if tc.seed != nil { @@ -365,7 +366,7 @@ func TestCreate(t *testing.T) { var tempRepoPath string if tempRepo != nil { - tempRepoPath, err = locator.GetPath(tempRepo) + tempRepoPath, err = locator.GetRepoPath(tempRepo, storage.WithRepositoryVerificationSkipped()) require.NoError(t, err) } diff --git a/internal/gitaly/repoutil/lock.go b/internal/gitaly/repoutil/lock.go index 6d902b830..097374e61 100644 --- a/internal/gitaly/repoutil/lock.go +++ b/internal/gitaly/repoutil/lock.go @@ -20,7 +20,7 @@ import ( // Returns the error safe.ErrFileAlreadyLocked if the repository is already // locked. func Lock(ctx context.Context, locator storage.Locator, repository storage.Repository) (func(), error) { - path, err := locator.GetPath(repository) + path, err := locator.GetRepoPath(repository, storage.WithRepositoryVerificationSkipped()) if err != nil { return nil, err } diff --git a/internal/gitaly/repoutil/lock_test.go b/internal/gitaly/repoutil/lock_test.go index 888aba9a0..956b50e58 100644 --- a/internal/gitaly/repoutil/lock_test.go +++ b/internal/gitaly/repoutil/lock_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/config" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/safe" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testcfg" @@ -24,7 +25,7 @@ func TestLock(t *testing.T) { RelativePath: gittest.NewRepositoryName(t), } - repoPath, err := locator.GetPath(repo) + repoPath, err := locator.GetRepoPath(repo, storage.WithRepositoryVerificationSkipped()) require.NoError(t, err) unlock, err := Lock(ctx, locator, repo) diff --git a/internal/gitaly/repoutil/remove.go b/internal/gitaly/repoutil/remove.go index 924135946..75a2ce998 100644 --- a/internal/gitaly/repoutil/remove.go +++ b/internal/gitaly/repoutil/remove.go @@ -23,7 +23,7 @@ func Remove( txManager transaction.Manager, repository storage.Repository, ) error { - path, err := locator.GetPath(repository) + path, err := locator.GetRepoPath(repository, storage.WithRepositoryVerificationSkipped()) if err != nil { return structerr.NewInternal("%w", err) } diff --git a/internal/gitaly/service/blob/get_blob_test.go b/internal/gitaly/service/blob/get_blob_test.go index 80be7715b..ed859b6fe 100644 --- a/internal/gitaly/service/blob/get_blob_test.go +++ b/internal/gitaly/service/blob/get_blob_test.go @@ -186,10 +186,13 @@ func TestGetBlob_invalidRequest(t *testing.T) { }, Oid: oid, }, - expectedErr: structerr.NewNotFound(testhelper.GitalyOrPraefect( - fmt.Sprintf("create object reader: GetRepoPath: not a git repository: %q", filepath.Join(cfg.Storages[0].Path, "path")), - fmt.Sprintf("accessor call: route repository accessor: consistent storages: repository %q/%q not found", cfg.Storages[0].Name, "path"), - )), + expectedErr: testhelper.GitalyOrPraefect( + testhelper.WithInterceptedMetadata( + structerr.NewNotFound("create object reader: repository not found"), + "repository_path", filepath.Join(cfg.Storages[0].Path, "path"), + ), + structerr.NewNotFound("accessor call: route repository accessor: consistent storages: repository %q/%q not found", cfg.Storages[0].Name, "path"), + ), }, { desc: "missing object ID", diff --git a/internal/gitaly/service/commit/isancestor_test.go b/internal/gitaly/service/commit/isancestor_test.go index 2ef8054f9..9cb8d88ec 100644 --- a/internal/gitaly/service/commit/isancestor_test.go +++ b/internal/gitaly/service/commit/isancestor_test.go @@ -10,7 +10,9 @@ import ( "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v16/internal/git" "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/helper/text" + "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" "google.golang.org/grpc/codes" @@ -60,10 +62,13 @@ func TestCommitIsAncestorFailure(t *testing.T) { AncestorId: "b83d6e391c22777fca1ed3012fce84f633d7fed0", ChildId: "8a0f2ee90d940bfb0ba1e14e8214b0649056e4ab", }, - expectedErr: status.Error(codes.NotFound, testhelper.GitalyOrPraefect( - `GetRepoPath: not a git repository: "`+cfg.Storages[0].Path+`/fake-path"`, - `accessor call: route repository accessor: consistent storages: repository "default"/"fake-path" not found`, - )), + expectedErr: testhelper.GitalyOrPraefect( + testhelper.WithInterceptedMetadata( + structerr.NewNotFound("%w", storage.ErrRepositoryNotFound), + "repository_path", filepath.Join(cfg.Storages[0].Path, "fake-path"), + ), + structerr.NewNotFound("accessor call: route repository accessor: consistent storages: repository %q/%q not found", cfg.Storages[0].Name, "fake-path"), + ), }, } diff --git a/internal/gitaly/service/commit/stats_test.go b/internal/gitaly/service/commit/stats_test.go index 2cfae4277..b1921aa76 100644 --- a/internal/gitaly/service/commit/stats_test.go +++ b/internal/gitaly/service/commit/stats_test.go @@ -3,12 +3,12 @@ package commit import ( - "fmt" "path/filepath" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" @@ -108,24 +108,13 @@ func TestCommitStatsFailure(t *testing.T) { }, Revision: []byte("test-do-not-touch"), }, - expectedErr: structerr.NewNotFound(testhelper.GitalyOrPraefect( - fmt.Sprintf("GetRepoPath: not a git repository: %q", filepath.Join(cfg.Storages[0].Path, "bar.git")), - "accessor call: route repository accessor: consistent storages: repository \"default\"/\"bar.git\" not found", - )), - }, - { - desc: "repo not found", - request: &gitalypb.CommitStatsRequest{ - Repository: &gitalypb.Repository{ - StorageName: repo.GetStorageName(), - RelativePath: "bar.git", - }, - Revision: []byte("test-do-not-touch"), - }, - expectedErr: structerr.NewNotFound(testhelper.GitalyOrPraefect( - fmt.Sprintf("GetRepoPath: not a git repository: %q", filepath.Join(cfg.Storages[0].Path, "bar.git")), - "accessor call: route repository accessor: consistent storages: repository \"default\"/\"bar.git\" not found", - )), + expectedErr: testhelper.GitalyOrPraefect( + testhelper.WithInterceptedMetadata( + structerr.NewNotFound("%w", storage.ErrRepositoryNotFound), + "repository_path", filepath.Join(cfg.Storages[0].Path, "bar.git"), + ), + structerr.NewNotFound("accessor call: route repository accessor: consistent storages: repository %q/%q not found", cfg.Storages[0].Name, "bar.git"), + ), }, { desc: "storage not found", diff --git a/internal/gitaly/service/conflicts/list_conflict_files.go b/internal/gitaly/service/conflicts/list_conflict_files.go index bc416c445..babd98c33 100644 --- a/internal/gitaly/service/conflicts/list_conflict_files.go +++ b/internal/gitaly/service/conflicts/list_conflict_files.go @@ -13,6 +13,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/git/localrepo" "gitlab.com/gitlab-org/gitaly/v16/internal/git2go" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" "gitlab.com/gitlab-org/gitaly/v16/streamio" @@ -37,7 +38,7 @@ func (s *server) ListConflictFiles(request *gitalypb.ListConflictFilesRequest, s return structerr.NewFailedPrecondition("could not lookup 'their' OID: %w", err) } - repoPath, err := s.locator.GetPath(request.Repository) + repoPath, err := s.locator.GetRepoPath(request.Repository, storage.WithRepositoryVerificationSkipped()) if err != nil { return err } diff --git a/internal/gitaly/service/diff/find_changed_paths_test.go b/internal/gitaly/service/diff/find_changed_paths_test.go index 46b997703..e99329fae 100644 --- a/internal/gitaly/service/diff/find_changed_paths_test.go +++ b/internal/gitaly/service/diff/find_changed_paths_test.go @@ -1,13 +1,13 @@ package diff import ( - "fmt" "io" "path/filepath" "testing" "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" @@ -970,10 +970,13 @@ func TestFindChangedPathsRequest_failing(t *testing.T) { desc: "Repo not found", repo: &gitalypb.Repository{StorageName: cfg.Storages[0].Name, RelativePath: "bar.git"}, commits: []string{newCommit.String(), oldCommit.String()}, - err: structerr.NewNotFound(testhelper.GitalyOrPraefect( - fmt.Sprintf("GetRepoPath: not a git repository: %q", filepath.Join(cfg.Storages[0].Path, "bar.git")), - `accessor call: route repository accessor: consistent storages: repository "default"/"bar.git" not found`, - )), + err: testhelper.GitalyOrPraefect( + testhelper.WithInterceptedMetadata( + structerr.NewNotFound("%w", storage.ErrRepositoryNotFound), + "repository_path", filepath.Join(cfg.Storages[0].Path, "bar.git"), + ), + structerr.NewNotFound("accessor call: route repository accessor: consistent storages: repository %q/%q not found", cfg.Storages[0].Name, "bar.git"), + ), }, { desc: "Storage not found", diff --git a/internal/gitaly/service/diff/numstat_test.go b/internal/gitaly/service/diff/numstat_test.go index 476e78e3a..8546330e3 100644 --- a/internal/gitaly/service/diff/numstat_test.go +++ b/internal/gitaly/service/diff/numstat_test.go @@ -4,10 +4,13 @@ package diff import ( "io" + "path/filepath" "testing" "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/diff" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" + "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" "google.golang.org/grpc/codes" @@ -144,10 +147,13 @@ func TestFailedDiffStatsRequest(t *testing.T) { repo: &gitalypb.Repository{StorageName: repo.GetStorageName(), RelativePath: "bar.git"}, leftCommitID: "e4003da16c1c2c3fc4567700121b17bf8e591c6c", rightCommitID: "8a0f2ee90d940bfb0ba1e14e8214b0649056e4ab", - expectedErr: status.Error(codes.NotFound, testhelper.GitalyOrPraefect( - `GetRepoPath: not a git repository: "`+cfg.Storages[0].Path+`/bar.git"`, - `accessor call: route repository accessor: consistent storages: repository "default"/"bar.git" not found`, - )), + expectedErr: testhelper.GitalyOrPraefect( + testhelper.WithInterceptedMetadata( + structerr.NewNotFound("%w", storage.ErrRepositoryNotFound), + "repository_path", filepath.Join(cfg.Storages[0].Path, "bar.git"), + ), + structerr.NewNotFound("accessor call: route repository accessor: consistent storages: repository %q/%q not found", cfg.Storages[0].Name, "bar.git"), + ), }, { desc: "storage not found", diff --git a/internal/gitaly/service/internalgitaly/walkrepos.go b/internal/gitaly/service/internalgitaly/walkrepos.go index d10faffcd..a92c84374 100644 --- a/internal/gitaly/service/internalgitaly/walkrepos.go +++ b/internal/gitaly/service/internalgitaly/walkrepos.go @@ -50,7 +50,7 @@ func walkStorage(ctx context.Context, storagePath string, stream gitalypb.Intern // keep walking } - if storage.IsGitDirectory(path) { + if storage.ValidateRepository(path) == nil { relPath, err := filepath.Rel(storagePath, path) if err != nil { return err diff --git a/internal/gitaly/service/objectpool/delete_test.go b/internal/gitaly/service/objectpool/delete_test.go index aa0d2b7f3..483d31945 100644 --- a/internal/gitaly/service/objectpool/delete_test.go +++ b/internal/gitaly/service/objectpool/delete_test.go @@ -72,7 +72,10 @@ func TestDelete(t *testing.T) { desc: "path traversing fails", relativePath: validPoolPath + "/../../../../..", expectedErr: testhelper.GitalyOrPraefect( - structerr.NewInvalidArgument("GetRepoPath: %w", storage.ErrRelativePathEscapesRoot), + testhelper.WithInterceptedMetadata( + structerr.NewInvalidArgument("%w", storage.ErrRelativePathEscapesRoot), + "relative_path", validPoolPath+"/../../../../..", + ), errInvalidPoolDir, ), }, diff --git a/internal/gitaly/service/operations/apply_patch_test.go b/internal/gitaly/service/operations/apply_patch_test.go index 09bdeb0a1..68ff120ec 100644 --- a/internal/gitaly/service/operations/apply_patch_test.go +++ b/internal/gitaly/service/operations/apply_patch_test.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "os" + "path/filepath" "strings" "testing" "testing/iotest" @@ -15,6 +16,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/git" "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v16/internal/git/localrepo" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/transaction" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/backchannel" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/metadata" @@ -87,13 +89,12 @@ To restore the original branch and stop patching, run "git am --abort". desc: "non-existent repository", targetBranch: git.DefaultBranch, nonExistentRepository: true, - expectedErr: func() error { - if testhelper.IsPraefectEnabled() { - return status.Errorf(codes.NotFound, "mutator call: route repository mutator: get repository id: repository %q/%q not found", cfg.Storages[0].Name, "doesnt-exist") - } - - return status.Errorf(codes.NotFound, "GetRepoPath: not a git repository: \"%s/%s\"", cfg.Storages[0].Path, "doesnt-exist") - }(), + expectedErr: testhelper.GitalyOrPraefect( + testhelper.WithInterceptedMetadata( + structerr.NewNotFound("%w", storage.ErrRepositoryNotFound), "repository_path", filepath.Join(cfg.Storages[0].Path, "doesnt-exist"), + ), + structerr.NewNotFound("mutator call: route repository mutator: get repository id: repository %q/%q not found", cfg.Storages[0].Name, "doesnt-exist"), + ), }, { desc: "creating the first branch does not work", diff --git a/internal/gitaly/service/operations/commit_files_test.go b/internal/gitaly/service/operations/commit_files_test.go index 5f8e3e979..6dd6586e4 100644 --- a/internal/gitaly/service/operations/commit_files_test.go +++ b/internal/gitaly/service/operations/commit_files_test.go @@ -1693,7 +1693,7 @@ func TestUserCommitFilesFailsIfRepositoryMissing(t *testing.T) { require.Contains(t, err.Error(), "mutator call: route repository mutator: get repository id") require.Contains(t, err.Error(), "not found") } else { - require.Contains(t, err.Error(), "GetRepoPath: not a git repository") + require.Contains(t, err.Error(), "repository not found") } } diff --git a/internal/gitaly/service/operations/merge.go b/internal/gitaly/service/operations/merge.go index 8d5359fb8..b390bfc06 100644 --- a/internal/gitaly/service/operations/merge.go +++ b/internal/gitaly/service/operations/merge.go @@ -15,6 +15,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/git2go" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/hook" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" ) @@ -392,7 +393,7 @@ func (s *Server) UserMergeToRef(ctx context.Context, request *gitalypb.UserMerge return nil, structerr.NewInvalidArgument("%w", err) } - repoPath, err := s.locator.GetPath(request.Repository) + repoPath, err := s.locator.GetRepoPath(request.Repository, storage.WithRepositoryVerificationSkipped()) if err != nil { return nil, err } diff --git a/internal/gitaly/service/ref/find_refs_by_oid_test.go b/internal/gitaly/service/ref/find_refs_by_oid_test.go index d1eaeac86..ab0a612bb 100644 --- a/internal/gitaly/service/ref/find_refs_by_oid_test.go +++ b/internal/gitaly/service/ref/find_refs_by_oid_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" @@ -149,9 +150,12 @@ func TestFindRefsByOID_failure(t *testing.T) { require.NoError(t, os.RemoveAll(filepath.Join(repoPath, "objects"))) return &gitalypb.FindRefsByOIDRequest{ - Repository: repo, - Oid: oid.String(), - }, structerr.NewNotFound("GetRepoPath: not a git repository: %q", repoPath) + Repository: repo, + Oid: oid.String(), + }, testhelper.WithInterceptedMetadata( + structerr.NewFailedPrecondition("%w: %q does not exist", storage.ErrRepositoryNotValid, "objects"), + "repository_path", repoPath, + ) }, }, { @@ -162,9 +166,12 @@ func TestFindRefsByOID_failure(t *testing.T) { require.NoError(t, os.RemoveAll(repoPath)) return &gitalypb.FindRefsByOIDRequest{ - Repository: repo, - Oid: oid.String(), - }, structerr.NewNotFound("GetRepoPath: not a git repository: %q", repoPath) + Repository: repo, + Oid: oid.String(), + }, testhelper.WithInterceptedMetadata( + structerr.NewNotFound("%w", storage.ErrRepositoryNotFound), + "repository_path", repoPath, + ) }, }, { diff --git a/internal/gitaly/service/ref/refs_test.go b/internal/gitaly/service/ref/refs_test.go index 418c8ccbf..bc23154b8 100644 --- a/internal/gitaly/service/ref/refs_test.go +++ b/internal/gitaly/service/ref/refs_test.go @@ -5,6 +5,7 @@ package ref import ( "context" "io" + "path/filepath" "strings" "testing" @@ -13,6 +14,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v16/internal/git/localrepo" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/config" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" @@ -184,10 +186,13 @@ func TestFindDefaultBranchName(t *testing.T) { request: &gitalypb.FindDefaultBranchNameRequest{ Repository: &gitalypb.Repository{StorageName: cfg.Storages[0].Name, RelativePath: "made/up/path"}, }, - expectedErr: status.Error(codes.NotFound, testhelper.GitalyOrPraefect( - `get default branch: GetRepoPath: not a git repository: "`+cfg.Storages[0].Path+`/made/up/path"`, - `accessor call: route repository accessor: consistent storages: repository "default"/"made/up/path" not found`, - )), + expectedErr: testhelper.GitalyOrPraefect( + testhelper.WithInterceptedMetadata( + structerr.NewNotFound("get default branch: %w", storage.ErrRepositoryNotFound), + "repository_path", filepath.Join(cfg.Storages[0].Path, "made/up/path"), + ), + structerr.NewNotFound("accessor call: route repository accessor: consistent storages: repository %q/%q not found", cfg.Storages[0].Name, "made/up/path"), + ), } }, }, @@ -483,10 +488,13 @@ func TestFindLocalBranches_validate(t *testing.T) { { desc: "repository doesn't exist on disk", repo: &gitalypb.Repository{StorageName: cfg.Storages[0].Name, RelativePath: "made/up/path"}, - expectedErr: status.Error(codes.NotFound, testhelper.GitalyOrPraefect( - `creating object reader: GetRepoPath: not a git repository: "`+cfg.Storages[0].Path+`/made/up/path"`, - `accessor call: route repository accessor: consistent storages: repository "default"/"made/up/path" not found`, - )), + expectedErr: testhelper.GitalyOrPraefect( + testhelper.WithInterceptedMetadata( + structerr.NewNotFound("creating object reader: %w", storage.ErrRepositoryNotFound), + "repository_path", filepath.Join(cfg.Storages[0].Path, "made/up/path"), + ), + structerr.NewNotFound("accessor call: route repository accessor: consistent storages: repository %q/%q not found", cfg.Storages[0].Name, "made/up/path"), + ), }, { desc: "unknown storage", diff --git a/internal/gitaly/service/repository/apply_gitattributes_test.go b/internal/gitaly/service/repository/apply_gitattributes_test.go index 897c20938..b84478075 100644 --- a/internal/gitaly/service/repository/apply_gitattributes_test.go +++ b/internal/gitaly/service/repository/apply_gitattributes_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/backchannel" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/metadata" "gitlab.com/gitlab-org/gitaly/v16/internal/helper/perm" @@ -268,10 +269,13 @@ func TestApplyGitattributes_failure(t *testing.T) { RelativePath: "bar", }, revision: []byte("master"), - expectedErr: structerr.NewNotFound(testhelper.GitalyOrPraefect( - `GetRepoPath: not a git repository: "`+cfg.Storages[0].Path+`/bar"`, - `mutator call: route repository mutator: get repository id: repository "default"/"bar" not found`, - )), + expectedErr: testhelper.GitalyOrPraefect( + testhelper.WithInterceptedMetadata( + structerr.NewNotFound("%w", storage.ErrRepositoryNotFound), + "repository_path", filepath.Join(cfg.Storages[0].Path, "bar"), + ), + structerr.NewNotFound(`mutator call: route repository mutator: get repository id: repository "default"/"bar" not found`), + ), }, { desc: "no revision provided", diff --git a/internal/gitaly/service/repository/config.go b/internal/gitaly/service/repository/config.go index 16e6405fa..ff3e19e19 100644 --- a/internal/gitaly/service/repository/config.go +++ b/internal/gitaly/service/repository/config.go @@ -6,6 +6,7 @@ import ( "path/filepath" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" "gitlab.com/gitlab-org/gitaly/v16/streamio" @@ -20,7 +21,7 @@ func (s *server) GetConfig( if err := service.ValidateRepository(repository); err != nil { return structerr.NewInvalidArgument("%w", err) } - repoPath, err := s.locator.GetPath(repository) + repoPath, err := s.locator.GetRepoPath(repository, storage.WithRepositoryVerificationSkipped()) if err != nil { return err } diff --git a/internal/gitaly/service/repository/create_fork.go b/internal/gitaly/service/repository/create_fork.go index f6345e19f..65853e49a 100644 --- a/internal/gitaly/service/repository/create_fork.go +++ b/internal/gitaly/service/repository/create_fork.go @@ -8,6 +8,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/git" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/repoutil" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" ) @@ -24,7 +25,7 @@ func (s *server) CreateFork(ctx context.Context, req *gitalypb.CreateForkRequest sourceRepository := req.SourceRepository if err := repoutil.Create(ctx, s.locator, s.gitCmdFactory, s.txManager, targetRepository, func(repo *gitalypb.Repository) error { - targetPath, err := s.locator.GetPath(repo) + targetPath, err := s.locator.GetRepoPath(repo, storage.WithRepositoryVerificationSkipped()) if err != nil { return err } diff --git a/internal/gitaly/service/repository/create_repository_from_bundle_test.go b/internal/gitaly/service/repository/create_repository_from_bundle_test.go index 7278be7ce..49d6d5166 100644 --- a/internal/gitaly/service/repository/create_repository_from_bundle_test.go +++ b/internal/gitaly/service/repository/create_repository_from_bundle_test.go @@ -84,7 +84,7 @@ func TestCreateRepositoryFromBundle_successful(t *testing.T) { require.NoError(t, err) importedRepo := localrepo.NewTestRepo(t, cfg, importedRepoProto) - importedRepoPath, err := locator.GetPath(gittest.RewrittenRepository(t, ctx, cfg, importedRepoProto)) + importedRepoPath, err := locator.GetRepoPath(gittest.RewrittenRepository(t, ctx, cfg, importedRepoProto), storage.WithRepositoryVerificationSkipped()) require.NoError(t, err) defer func() { require.NoError(t, os.RemoveAll(importedRepoPath)) }() diff --git a/internal/gitaly/service/repository/create_repository_from_snapshot.go b/internal/gitaly/service/repository/create_repository_from_snapshot.go index f741aca54..936650e68 100644 --- a/internal/gitaly/service/repository/create_repository_from_snapshot.go +++ b/internal/gitaly/service/repository/create_repository_from_snapshot.go @@ -11,6 +11,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/command" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/repoutil" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" "gitlab.com/gitlab-org/labkit/correlation" @@ -127,7 +128,7 @@ func (s *server) CreateRepositoryFromSnapshot(ctx context.Context, in *gitalypb. } if err := repoutil.Create(ctx, s.locator, s.gitCmdFactory, s.txManager, repository, func(repo *gitalypb.Repository) error { - path, err := s.locator.GetPath(repo) + path, err := s.locator.GetRepoPath(repo, storage.WithRepositoryVerificationSkipped()) if err != nil { return structerr.NewInternal("getting repo path: %w", err) } diff --git a/internal/gitaly/service/repository/create_repository_from_url.go b/internal/gitaly/service/repository/create_repository_from_url.go index 0ef15ac3b..98f9b5eb9 100644 --- a/internal/gitaly/service/repository/create_repository_from_url.go +++ b/internal/gitaly/service/repository/create_repository_from_url.go @@ -11,6 +11,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/git" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/repoutil" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" ) @@ -82,7 +83,7 @@ func (s *server) CreateRepositoryFromURL(ctx context.Context, req *gitalypb.Crea } if err := repoutil.Create(ctx, s.locator, s.gitCmdFactory, s.txManager, req.GetRepository(), func(repo *gitalypb.Repository) error { - targetPath, err := s.locator.GetPath(repo) + targetPath, err := s.locator.GetRepoPath(repo, storage.WithRepositoryVerificationSkipped()) if err != nil { return fmt.Errorf("getting temporary repository path: %w", err) } diff --git a/internal/gitaly/service/repository/fetch_bundle_test.go b/internal/gitaly/service/repository/fetch_bundle_test.go index b7eed4669..aefc5f41c 100644 --- a/internal/gitaly/service/repository/fetch_bundle_test.go +++ b/internal/gitaly/service/repository/fetch_bundle_test.go @@ -12,7 +12,9 @@ import ( "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" gitalyhook "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/hook" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/metadata" + "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testcfg" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testserver" @@ -155,10 +157,13 @@ func TestServer_FetchBundle_validation(t *testing.T) { RelativePath: "unknown", }, }, - expectedErr: status.Error(codes.NotFound, testhelper.GitalyOrPraefect( - `GetRepoPath: not a git repository: "`+cfg.Storages[0].Path+`/unknown"`, - `mutator call: route repository mutator: get repository id: repository "default"/"unknown" not found`, - )), + expectedErr: testhelper.GitalyOrPraefect( + testhelper.WithInterceptedMetadata( + structerr.NewNotFound("%w", storage.ErrRepositoryNotFound), + "repository_path", filepath.Join(cfg.Storages[0].Path, "unknown"), + ), + structerr.NewNotFound(`mutator call: route repository mutator: get repository id: repository "default"/"unknown" not found`), + ), }, } { t.Run(tc.desc, func(t *testing.T) { diff --git a/internal/gitaly/service/repository/fullpath_test.go b/internal/gitaly/service/repository/fullpath_test.go index fe06ea544..e61489a97 100644 --- a/internal/gitaly/service/repository/fullpath_test.go +++ b/internal/gitaly/service/repository/fullpath_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" - "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/config" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/helper/text" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" @@ -63,8 +63,6 @@ func TestSetFullPath(t *testing.T) { RelativePath: "/path/to/repo.git", StorageName: cfg.Storages[0].Name, } - repoPath, err := config.NewLocator(cfg).GetPath(repo) - require.NoError(t, err) response, err := client.SetFullPath(ctx, &gitalypb.SetFullPathRequest{ Repository: repo, @@ -73,7 +71,7 @@ func TestSetFullPath(t *testing.T) { require.Nil(t, response) - expectedErr := fmt.Sprintf("rpc error: code = NotFound desc = setting config: GetRepoPath: not a git repository: %q", repoPath) + expectedErr := fmt.Sprintf("rpc error: code = NotFound desc = setting config: %s", storage.ErrRepositoryNotFound) if testhelper.IsPraefectEnabled() { expectedErr = `rpc error: code = NotFound desc = mutator call: route repository mutator: get repository id: repository "default"/"/path/to/repo.git" not found` } @@ -169,15 +167,13 @@ func TestFullPath(t *testing.T) { RelativePath: "/path/to/repo.git", StorageName: cfg.Storages[0].Name, } - repoPath, err := config.NewLocator(cfg).GetPath(repo) - require.NoError(t, err) response, err := client.FullPath(ctx, &gitalypb.FullPathRequest{ Repository: repo, }) require.Nil(t, response) - expectedErr := fmt.Sprintf("rpc error: code = NotFound desc = fetch config: GetRepoPath: not a git repository: %q", repoPath) + expectedErr := fmt.Sprintf("rpc error: code = NotFound desc = fetch config: %s", storage.ErrRepositoryNotFound) if testhelper.IsPraefectEnabled() { expectedErr = `rpc error: code = NotFound desc = accessor call: route repository accessor: consistent storages: repository "default"/"/path/to/repo.git" not found` } diff --git a/internal/gitaly/service/repository/license_test.go b/internal/gitaly/service/repository/license_test.go index 01a703def..4b93e16f5 100644 --- a/internal/gitaly/service/repository/license_test.go +++ b/internal/gitaly/service/repository/license_test.go @@ -12,6 +12,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/featureflag" "gitlab.com/gitlab-org/gitaly/v16/internal/git/catfile" "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testcfg" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testserver" @@ -64,7 +65,7 @@ func TestFindLicense_successful(t *testing.T) { setup: func(t *testing.T, repoPath string) { require.NoError(t, os.RemoveAll(repoPath)) }, - errorContains: "GetRepoPath: not a git repository", + errorContains: storage.ErrRepositoryNotFound.Error(), }, { desc: "empty if no license file in repo", diff --git a/internal/gitaly/service/repository/object_format_test.go b/internal/gitaly/service/repository/object_format_test.go index d80a2a655..a99b3b966 100644 --- a/internal/gitaly/service/repository/object_format_test.go +++ b/internal/gitaly/service/repository/object_format_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v16/internal/errors" "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/helper/perm" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" @@ -85,8 +86,9 @@ func TestObjectFormat(t *testing.T) { }, }, expectedErr: testhelper.GitalyOrPraefect( - structerr.NewNotFound( - "GetRepoPath: not a git repository: %q", filepath.Join(cfg.Storages[0].Path, "nonexistent.git"), + testhelper.WithInterceptedMetadata( + structerr.NewNotFound("%w", storage.ErrRepositoryNotFound), + "repository_path", filepath.Join(cfg.Storages[0].Path, "nonexistent.git"), ), structerr.NewNotFound( "accessor call: route repository accessor: consistent storages: repository %q/%q not found", diff --git a/internal/gitaly/service/repository/optimize_test.go b/internal/gitaly/service/repository/optimize_test.go index 54a509d80..af5751686 100644 --- a/internal/gitaly/service/repository/optimize_test.go +++ b/internal/gitaly/service/repository/optimize_test.go @@ -17,6 +17,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/git/housekeeping" "gitlab.com/gitlab-org/gitaly/v16/internal/git/localrepo" "gitlab.com/gitlab-org/gitaly/v16/internal/git/stats" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/helper/perm" "gitlab.com/gitlab-org/gitaly/v16/internal/helper/text" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" @@ -364,10 +365,13 @@ func TestOptimizeRepository_validation(t *testing.T) { RelativePath: "path/not/exist", }, }, - expectedErr: structerr.NewNotFound(testhelper.GitalyOrPraefect( - fmt.Sprintf(`GetRepoPath: not a git repository: "%s/path/not/exist"`, cfg.Storages[0].Path), - `routing repository maintenance: getting repository metadata: repository not found`, - )), + expectedErr: testhelper.GitalyOrPraefect( + testhelper.WithInterceptedMetadata( + structerr.NewNotFound("%w", storage.ErrRepositoryNotFound), + "repository_path", filepath.Join(cfg.Storages[0].Path, "path/not/exist"), + ), + structerr.NewNotFound("routing repository maintenance: getting repository metadata: %w", storage.ErrRepositoryNotFound), + ), }, { desc: "invalid optimization strategy", diff --git a/internal/gitaly/service/repository/prune_unreachable_objects_test.go b/internal/gitaly/service/repository/prune_unreachable_objects_test.go index 4c64a1d68..310e4e7ec 100644 --- a/internal/gitaly/service/repository/prune_unreachable_objects_test.go +++ b/internal/gitaly/service/repository/prune_unreachable_objects_test.go @@ -11,6 +11,7 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v16/internal/git/localrepo" "gitlab.com/gitlab-org/gitaly/v16/internal/git/stats" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" @@ -43,7 +44,13 @@ func TestPruneUnreachableObjects(t *testing.T) { _, err := client.PruneUnreachableObjects(ctx, &gitalypb.PruneUnreachableObjectsRequest{ Repository: repo, }) - testhelper.RequireGrpcError(t, structerr.NewNotFound("GetRepoPath: not a git repository: %q", repoPath), err) + testhelper.RequireGrpcError(t, + testhelper.WithInterceptedMetadata( + structerr.NewNotFound("%w", storage.ErrRepositoryNotFound), + "repository_path", repoPath, + ), + err, + ) }) t.Run("empty repository", func(t *testing.T) { diff --git a/internal/gitaly/service/repository/rename.go b/internal/gitaly/service/repository/rename.go index 3c7ec054f..ab68ef51b 100644 --- a/internal/gitaly/service/repository/rename.go +++ b/internal/gitaly/service/repository/rename.go @@ -9,6 +9,7 @@ import ( "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/helper/perm" "gitlab.com/gitlab-org/gitaly/v16/internal/safe" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" @@ -38,7 +39,7 @@ func (s *server) renameRepository(ctx context.Context, sourceRepo, targetRepo *g return structerr.NewInvalidArgument("%w", err) } - targetPath, err := s.locator.GetPath(targetRepo) + targetPath, err := s.locator.GetRepoPath(targetRepo, storage.WithRepositoryVerificationSkipped()) if err != nil { return structerr.NewInvalidArgument("%w", err) } diff --git a/internal/gitaly/service/repository/rename_test.go b/internal/gitaly/service/repository/rename_test.go index 221533938..876ae5db1 100644 --- a/internal/gitaly/service/repository/rename_test.go +++ b/internal/gitaly/service/repository/rename_test.go @@ -1,14 +1,13 @@ package repository import ( - "fmt" "path/filepath" - "strings" "testing" "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" + "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" "google.golang.org/grpc/codes" @@ -53,7 +52,7 @@ func TestRenameRepositorySuccess(t *testing.T) { } require.DirExists(t, newDirectory) - require.True(t, storage.IsGitDirectory(newDirectory), "moved Git repository has been corrupted") + require.NoError(t, storage.ValidateRepository(newDirectory), "moved Git repository has been corrupted") // ensure the git directory that got renamed contains the original commit. gittest.RequireObjectExists(t, cfg, newDirectory, commitID) } @@ -85,8 +84,7 @@ func TestRenameRepositoryInvalidRequest(t *testing.T) { ctx := testhelper.Context(t) cfg, client := setupRepositoryServiceWithoutRepo(t) - repo, repoPath := gittest.CreateRepository(t, ctx, cfg) - storagePath := strings.TrimSuffix(repoPath, "/"+repo.RelativePath) + repo, _ := gittest.CreateRepository(t, ctx, cfg) testCases := []struct { desc string @@ -106,7 +104,13 @@ func TestRenameRepositoryInvalidRequest(t *testing.T) { { desc: "destination relative path contains path traversal", req: &gitalypb.RenameRepositoryRequest{Repository: repo, RelativePath: "../usr/bin"}, - exp: status.Error(codes.InvalidArgument, "GetRepoPath: relative path escapes root directory"), + exp: testhelper.GitalyOrPraefect( + testhelper.WithInterceptedMetadata( + structerr.NewInvalidArgument("%w", storage.ErrRelativePathEscapesRoot), + "relative_path", "../usr/bin", + ), + structerr.NewInvalidArgument("GetRepoPath: %w", storage.ErrRelativePathEscapesRoot), + ), }, { desc: "repository storage doesn't exist", @@ -116,7 +120,13 @@ func TestRenameRepositoryInvalidRequest(t *testing.T) { { desc: "repository relative path doesn't exist", req: &gitalypb.RenameRepositoryRequest{Repository: &gitalypb.Repository{StorageName: repo.StorageName, RelativePath: "stub"}, RelativePath: "non-existent/directory"}, - exp: status.Error(codes.NotFound, fmt.Sprintf(`GetRepoPath: not a git repository: "%s/stub"`, testhelper.GitalyOrPraefect(storagePath, repo.GetStorageName()))), + exp: testhelper.GitalyOrPraefect( + testhelper.WithInterceptedMetadata( + structerr.NewNotFound("%w", storage.ErrRepositoryNotFound), + "repository_path", filepath.Join(cfg.Storages[0].Path, "stub"), + ), + structerr.NewNotFound(`GetRepoPath: not a git repository: "%s/stub"`, repo.GetStorageName()), + ), }, } diff --git a/internal/gitaly/service/repository/replicate.go b/internal/gitaly/service/repository/replicate.go index 74d13cf6b..429c46103 100644 --- a/internal/gitaly/service/repository/replicate.go +++ b/internal/gitaly/service/repository/replicate.go @@ -39,12 +39,12 @@ func (s *server) ReplicateRepository(ctx context.Context, in *gitalypb.Replicate return nil, structerr.NewInvalidArgument("%w", err) } - repoPath, err := s.locator.GetPath(in.GetRepository()) + repoPath, err := s.locator.GetRepoPath(in.GetRepository(), storage.WithRepositoryVerificationSkipped()) if err != nil { return nil, structerr.NewInternal("%w", err) } - if !storage.IsGitDirectory(repoPath) { + if err := storage.ValidateRepository(repoPath); err != nil { if err = s.create(ctx, in, repoPath); err != nil { if errors.Is(err, ErrInvalidSourceRepository) { return nil, ErrInvalidSourceRepository @@ -175,11 +175,18 @@ func (s *server) extractSnapshot(ctx context.Context, source, target *gitalypb.R // platforms. firstBytes, err := stream.Recv() if err != nil { - if structerr.GRPCCode(err) == codes.NotFound && strings.Contains(err.Error(), "GetRepoPath: not a git repository:") { + switch { + case structerr.GRPCCode(err) == codes.NotFound && strings.Contains(err.Error(), "GetRepoPath: not a git repository:"): + // The error condition exists for backwards compatibility purposes, only, + // and can be removed in the next release. return ErrInvalidSourceRepository + case structerr.GRPCCode(err) == codes.NotFound && strings.Contains(err.Error(), storage.ErrRepositoryNotFound.Error()): + return ErrInvalidSourceRepository + case structerr.GRPCCode(err) == codes.FailedPrecondition && strings.Contains(err.Error(), storage.ErrRepositoryNotValid.Error()): + return ErrInvalidSourceRepository + default: + return fmt.Errorf("first snapshot read: %w", err) } - - return fmt.Errorf("first snapshot read: %w", err) } snapshotReader := io.MultiReader( @@ -190,7 +197,7 @@ func (s *server) extractSnapshot(ctx context.Context, source, target *gitalypb.R }), ) - targetPath, err := s.locator.GetPath(target) + targetPath, err := s.locator.GetRepoPath(target, storage.WithRepositoryVerificationSkipped()) if err != nil { return fmt.Errorf("target path: %w", err) } diff --git a/internal/gitaly/service/repository/repository_exists.go b/internal/gitaly/service/repository/repository_exists.go index ab30a921e..1ebf1c190 100644 --- a/internal/gitaly/service/repository/repository_exists.go +++ b/internal/gitaly/service/repository/repository_exists.go @@ -13,10 +13,12 @@ func (s *server) RepositoryExists(ctx context.Context, in *gitalypb.RepositoryEx if err := service.ValidateRepository(in.GetRepository()); err != nil { return nil, structerr.NewInvalidArgument("%w", err) } - path, err := s.locator.GetPath(in.Repository) + path, err := s.locator.GetRepoPath(in.Repository, storage.WithRepositoryVerificationSkipped()) if err != nil { return nil, err } - return &gitalypb.RepositoryExistsResponse{Exists: storage.IsGitDirectory(path)}, nil + // TODO: we really should only be checking whether the repository actually doesn't exist. If + // it does, but is not a valid Git repository, we should be returning an error here. + return &gitalypb.RepositoryExistsResponse{Exists: storage.ValidateRepository(path) == nil}, nil } diff --git a/internal/gitaly/service/repository/repository_exists_test.go b/internal/gitaly/service/repository/repository_exists_test.go index b325388be..70a93c51c 100644 --- a/internal/gitaly/service/repository/repository_exists_test.go +++ b/internal/gitaly/service/repository/repository_exists_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/require" gitalyerrors "gitlab.com/gitlab-org/gitaly/v16/internal/errors" "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" + "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testcfg" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" @@ -113,7 +114,10 @@ func TestRepositoryExists(t *testing.T) { return nil } - return status.Errorf(codes.NotFound, "GetPath: does not exist: stat %s: no such file or directory", cfg.Storages[2].Path) + return testhelper.WithInterceptedMetadata( + structerr.NewNotFound("storage does not exist"), + "storage_path", cfg.Storages[2].Path, + ) }(), }, } @@ -121,7 +125,7 @@ func TestRepositoryExists(t *testing.T) { for _, tc := range queries { t.Run(tc.desc, func(t *testing.T) { response, err := client.RepositoryExists(ctx, tc.request) - testhelper.ProtoEqual(t, tc.expectedErr, err) + testhelper.RequireGrpcError(t, tc.expectedErr, err) if err != nil { // Ignore the response message if there was an error return diff --git a/internal/gitaly/service/repository/repository_info_test.go b/internal/gitaly/service/repository/repository_info_test.go index 50fb1f35c..6cdf979cf 100644 --- a/internal/gitaly/service/repository/repository_info_test.go +++ b/internal/gitaly/service/repository/repository_info_test.go @@ -12,6 +12,7 @@ import ( gitalyerrors "gitlab.com/gitlab-org/gitaly/v16/internal/errors" "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v16/internal/git/stats" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/helper/perm" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" @@ -74,7 +75,10 @@ func TestRepositoryInfo(t *testing.T) { }, }, expectedErr: testhelper.GitalyOrPraefect( - structerr.NewNotFound("GetRepoPath: not a git repository: %q", filepath.Join(cfg.Storages[0].Path, "does", "not", "exist")), + testhelper.WithInterceptedMetadata( + structerr.NewNotFound("%w", storage.ErrRepositoryNotFound), + "repository_path", filepath.Join(cfg.Storages[0].Path, "does", "not", "exist"), + ), structerr.NewNotFound( "accessor call: route repository accessor: consistent storages: repository %q/%q not found", cfg.Storages[0].Name, diff --git a/internal/gitaly/service/smarthttp/inforefs_test.go b/internal/gitaly/service/smarthttp/inforefs_test.go index 364f132ba..84e4769aa 100644 --- a/internal/gitaly/service/smarthttp/inforefs_test.go +++ b/internal/gitaly/service/smarthttp/inforefs_test.go @@ -18,7 +18,9 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v16/internal/git/stats" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/config" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/helper/perm" + "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testcfg" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testserver" @@ -149,10 +151,12 @@ func TestInfoRefsUploadPack_validate(t *testing.T) { StorageName: cfg.Storages[0].Name, RelativePath: "doesnt/exist", }}, - expectedErr: status.Error(codes.NotFound, testhelper.GitalyOrPraefect( - `GetRepoPath: not a git repository: "`+cfg.Storages[0].Path+`/doesnt/exist"`, - `accessor call: route repository accessor: consistent storages: repository "default"/"doesnt/exist" not found`, - )), + expectedErr: testhelper.GitalyOrPraefect( + testhelper.WithInterceptedMetadata( + structerr.NewNotFound("%w", storage.ErrRepositoryNotFound), "repository_path", filepath.Join(cfg.Storages[0].Path, "doesnt/exist"), + ), + structerr.NewNotFound("accessor call: route repository accessor: consistent storages: repository %q/%q not found", cfg.Storages[0].Name, "doesnt/exist"), + ), }, } { _, err := makeInfoRefsUploadPackRequest(t, ctx, serverSocketPath, cfg.Auth.Token, tc.req) @@ -336,10 +340,13 @@ func TestInfoRefsReceivePack_validate(t *testing.T) { StorageName: cfg.Storages[0].Name, RelativePath: "testdata/scratch/another_repo", }}, - expectedErr: status.Error(codes.NotFound, testhelper.GitalyOrPraefect( - `GetRepoPath: not a git repository: "`+cfg.Storages[0].Path+`/testdata/scratch/another_repo"`, - `accessor call: route repository accessor: consistent storages: repository "default"/"testdata/scratch/another_repo" not found`, - )), + expectedErr: testhelper.GitalyOrPraefect( + testhelper.WithInterceptedMetadata( + structerr.NewNotFound("%w", storage.ErrRepositoryNotFound), + "repository_path", filepath.Join(cfg.Storages[0].Path, "testdata/scratch/another_repo"), + ), + structerr.NewNotFound("accessor call: route repository accessor: consistent storages: repository %q/%q not found", cfg.Storages[0].Name, "testdata/scratch/another_repo"), + ), }, } { _, err := makeInfoRefsReceivePackRequest(t, ctx, serverSocketPath, cfg.Auth.Token, tc.req) diff --git a/internal/gitaly/service/ssh/upload_pack_test.go b/internal/gitaly/service/ssh/upload_pack_test.go index 811a91303..2c84f778f 100644 --- a/internal/gitaly/service/ssh/upload_pack_test.go +++ b/internal/gitaly/service/ssh/upload_pack_test.go @@ -797,7 +797,7 @@ func TestUploadPack_gitFailure(t *testing.T) { client := newSSHClient(t, cfg.SocketPath) - // Writing an invalid config will allow repo to pass the `IsGitDirectory` check but still + // Writing an invalid config will allow repo to pass the `ValidateRepository` check but still // trigger an error when git tries to access the repo. require.NoError(t, os.WriteFile(filepath.Join(repoPath, "config"), []byte("Not a valid gitconfig"), perm.SharedFile)) diff --git a/internal/gitaly/storage/locator.go b/internal/gitaly/storage/locator.go index 550802c0f..8d6e17adb 100644 --- a/internal/gitaly/storage/locator.go +++ b/internal/gitaly/storage/locator.go @@ -7,6 +7,46 @@ import ( "os" "path/filepath" "strings" + + "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" +) + +// RepositoryNotFoundError is returned when attempting to operate on a repository that does not +// exist in the virtual storage. +type RepositoryNotFoundError struct { + virtualStorage string + relativePath string +} + +// NewRepositoryNotFoundError returns a new repository not found error for the given repository. +func NewRepositoryNotFoundError(virtualStorage string, relativePath string) error { + return RepositoryNotFoundError{virtualStorage: virtualStorage, relativePath: relativePath} +} + +// Error returns the error message. +func (err RepositoryNotFoundError) Error() string { + return fmt.Sprintf("repository %q/%q not found", err.virtualStorage, err.relativePath) +} + +var ( + // ErrRepositoryNotFound is returned when operating on a repository that doesn't exist. + // + // This somewhat duplicates the above RepositoryNotFoundError but doesn't specify which + // repository was not found. With repository IDs in use, the virtual storage and relative + // path won't be available everywhere anymore. + ErrRepositoryNotFound = errors.New("repository not found") + + // ErrRepositoryAlreadyExists is returned when attempting to create a repository that + // already exists. + ErrRepositoryAlreadyExists = errors.New("repository already exists") + + // ErrRepositoryNotValid is returned when operating on a path that is not a valid Git + // repository. + ErrRepositoryNotValid = errors.New("repository not valid") + + // ErrRelativePathEscapesRoot is returned when a relative path is passed that escapes the + // storage's root directory. + ErrRelativePathEscapesRoot = errors.New("relative path escapes root directory") ) // Repository represents a storage-scoped repository. @@ -31,10 +71,6 @@ type Locator interface { // will be skipped. The errors returned are gRPC errors with relevant error codes and should be // passed back to gRPC without further decoration. GetRepoPath(repo Repository, opts ...GetRepoPathOption) (string, error) - // GetPath returns the path of the repo passed as first argument. An error is - // returned when either the storage can't be found or the path includes - // constructs trying to perform directory traversal. - GetPath(repo Repository) (string, error) // GetStorageByName will return the path for the storage, which is fetched by // its key. An error is return if it cannot be found. GetStorageByName(storageName string) (string, error) @@ -65,9 +101,6 @@ func WithRepositoryVerificationSkipped() GetRepoPathOption { } } -//nolint:revive // This is unintentionally missing documentation. -var ErrRelativePathEscapesRoot = errors.New("relative path escapes root directory") - // ValidateRelativePath validates a relative path by joining it with rootDir and verifying the result // is either rootDir or a path within rootDir. Returns clean relative path from rootDir to relativePath // or an ErrRelativePathEscapesRoot if the resulting path is not contained within rootDir. @@ -80,16 +113,32 @@ func ValidateRelativePath(rootDir, relativePath string) (string, error) { return filepath.Rel(rootDir, absPath) } -// IsGitDirectory checks if the directory passed as first argument looks like -// a valid git directory. -func IsGitDirectory(dir string) bool { - if dir == "" { - return false +// ValidateRepository validates whether the given path points to a valid Git repository. This +// function returns: +// +// - ErrRepositoryNotExist when the path cannot be found. +// - ErrRepositoryNotValid when the repository is not a valid Git repository. +// - An unspecified error when stat(3P)ing files fails due to other reasons. +func ValidateRepository(path string) error { + if path == "" { + return structerr.NewInvalidArgument("repository path is empty") + } + + if _, err := os.Stat(path); err != nil { + if errors.Is(err, os.ErrNotExist) { + return structerr.NewNotFound("%w", ErrRepositoryNotFound).WithMetadata("repository_path", path) + } + + return structerr.New("statting repository: %w", err).WithMetadata("repository_path", path) } for _, element := range []string{"objects", "refs", "HEAD"} { - if _, err := os.Stat(filepath.Join(dir, element)); err != nil { - return false + if _, err := os.Stat(filepath.Join(path, element)); err != nil { + if errors.Is(err, os.ErrNotExist) { + return structerr.NewFailedPrecondition("%w: %q does not exist", ErrRepositoryNotValid, element).WithMetadata("repository_path", path) + } + + return structerr.New("statting %q: %w", element, err).WithMetadata("repository_path", path) } } @@ -101,9 +150,9 @@ func IsGitDirectory(dir string) bool { // git gc runs for a long time while keeping open the packed-refs file. // Running stat() on the file causes the kernel to revalidate the cached // directory entry. We don't actually care if this file exists. - _, _ = os.Stat(filepath.Join(dir, "packed-refs")) + _, _ = os.Stat(filepath.Join(path, "packed-refs")) - return true + return nil } // QuarantineDirectoryPrefix returns a prefix for use in the temporary directory. The prefix is diff --git a/internal/praefect/commonerr/error.go b/internal/praefect/commonerr/error.go deleted file mode 100644 index d113f4485..000000000 --- a/internal/praefect/commonerr/error.go +++ /dev/null @@ -1,35 +0,0 @@ -// Package commonerr contains common errors between different Praefect components. Ideally -// this package's contents would be in praefect's root package but this is not possible at the moment -// due to cyclic imports. -package commonerr - -import ( - "errors" - "fmt" -) - -// RepositoryNotFoundError is returned when attempting to operate on a repository -// that does not exist in the virtual storage. -type RepositoryNotFoundError struct { - virtualStorage string - relativePath string -} - -// NewRepositoryNotFoundError returns a new repository not found error for the given repository. -func NewRepositoryNotFoundError(virtualStorage string, relativePath string) error { - return RepositoryNotFoundError{virtualStorage: virtualStorage, relativePath: relativePath} -} - -// Error returns the error message. -func (err RepositoryNotFoundError) Error() string { - return fmt.Sprintf("repository %q/%q not found", err.virtualStorage, err.relativePath) -} - -// ErrRepositoryNotFound is returned when operating on a repository that doesn't exist. -// -// This somewhat duplicates the above RepositoryNotFoundError but doesn't specify which repository was not found. -// With repository IDs in use, the virtual storage and relative path won't be available everywhere anymore. -var ErrRepositoryNotFound = errors.New("repository not found") - -// ErrRepositoryAlreadyExists is returned when attempting to create a repository that already exists. -var ErrRepositoryAlreadyExists = errors.New("repository already exists") diff --git a/internal/praefect/coordinator.go b/internal/praefect/coordinator.go index 24eb35825..bab8957c0 100644 --- a/internal/praefect/coordinator.go +++ b/internal/praefect/coordinator.go @@ -12,11 +12,11 @@ import ( "github.com/sirupsen/logrus" gitalyerrors "gitlab.com/gitlab-org/gitaly/v16/internal/errors" "gitlab.com/gitlab-org/gitaly/v16/internal/featureflag" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/metadata" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/middleware/metadatahandler" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/proxy" "gitlab.com/gitlab-org/gitaly/v16/internal/helper" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/commonerr" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/config" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/metrics" @@ -263,11 +263,11 @@ func (c *Coordinator) directRepositoryScopedMessage(ctx context.Context, call gr } if err != nil { - if errors.As(err, new(commonerr.RepositoryNotFoundError)) { + if errors.As(err, new(storage.RepositoryNotFoundError)) { return nil, structerr.NewNotFound("%w", err) } - if errors.Is(err, commonerr.ErrRepositoryNotFound) { + if errors.Is(err, storage.ErrRepositoryNotFound) { return nil, structerr.NewNotFound("%w", err) } @@ -407,7 +407,7 @@ func (c *Coordinator) mutatorStreamParameters(ctx context.Context, call grpcCall // ReplicateRepository RPC should also be able to replicate if repository ID already exists in Praefect. if call.fullMethodName == "/gitaly.RepositoryService/ReplicateRepository" && - errors.Is(err, commonerr.ErrRepositoryAlreadyExists) { + errors.Is(err, storage.ErrRepositoryAlreadyExists) { change = datastore.UpdateRepo route, err = c.router.RouteRepositoryMutator(ctx, virtualStorage, targetRepo.RelativePath, additionalRepoRelativePath) } @@ -702,7 +702,7 @@ func (c *Coordinator) StreamDirector(ctx context.Context, fullMethodName string, return nil, structerr.NewInvalidArgument("%w", err) } - if errors.Is(err, commonerr.ErrRepositoryAlreadyExists) { + if errors.Is(err, storage.ErrRepositoryAlreadyExists) { return nil, structerr.NewAlreadyExists("%w", err) } diff --git a/internal/praefect/coordinator_test.go b/internal/praefect/coordinator_test.go index d843f382a..150b87ece 100644 --- a/internal/praefect/coordinator_test.go +++ b/internal/praefect/coordinator_test.go @@ -25,10 +25,10 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" gconfig "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/config" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" gitaly_metadata "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/metadata" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/middleware/metadatahandler" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/proxy" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/commonerr" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/config" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/nodes" @@ -303,7 +303,7 @@ func TestStreamDirectorMutator(t *testing.T) { request: &gitalypb.UserCreateTagRequest{ Repository: targetRepo, }, - expectedErr: structerr.NewNotFound("%w", fmt.Errorf("mutator call: route repository mutator: %w", fmt.Errorf("get repository id: %w", commonerr.NewRepositoryNotFoundError(targetRepo.StorageName, targetRepo.RelativePath)))), + expectedErr: structerr.NewNotFound("%w", fmt.Errorf("mutator call: route repository mutator: %w", fmt.Errorf("get repository id: %w", storage.NewRepositoryNotFoundError(targetRepo.StorageName, targetRepo.RelativePath)))), } }, }, @@ -334,7 +334,7 @@ func TestStreamDirectorMutator(t *testing.T) { expectedErr: structerr.NewNotFound("%w", fmt.Errorf("mutator call: route repository mutator: %w", fmt.Errorf("resolve additional replica path: %w", fmt.Errorf("get additional repository id: %w", - commonerr.NewRepositoryNotFoundError(additionalRepo.StorageName, additionalRepo.RelativePath), + storage.NewRepositoryNotFoundError(additionalRepo.StorageName, additionalRepo.RelativePath), ), ), )), @@ -696,7 +696,7 @@ func TestStreamDirectorMutator_ReplicateRepository(t *testing.T) { router := mockRouter{ // Simulate scenario where target repository already exists and error is returned. routeRepositoryCreation: func(ctx context.Context, virtualStorage, relativePath, additionalRepoRelativePath string) (RepositoryMutatorRoute, error) { - return RepositoryMutatorRoute{}, fmt.Errorf("reserve repository id: %w", commonerr.ErrRepositoryAlreadyExists) + return RepositoryMutatorRoute{}, fmt.Errorf("reserve repository id: %w", storage.ErrRepositoryAlreadyExists) }, // Pass through normally to handle route creation. routeRepositoryMutator: func(ctx context.Context, virtualStorage, relativePath, additionalRepoRelativePath string) (RepositoryMutatorRoute, error) { @@ -1086,10 +1086,10 @@ func TestStreamDirectorAccessor(t *testing.T) { desc: "repository not found", router: mockRouter{ routeRepositoryAccessorFunc: func(_ context.Context, virtualStorage, relativePath string, _ bool) (RepositoryAccessorRoute, error) { - return RepositoryAccessorRoute{}, commonerr.NewRepositoryNotFoundError(virtualStorage, relativePath) + return RepositoryAccessorRoute{}, storage.NewRepositoryNotFoundError(virtualStorage, relativePath) }, }, - error: structerr.NewNotFound("%w", fmt.Errorf("accessor call: route repository accessor: %w", commonerr.NewRepositoryNotFoundError(targetRepo.StorageName, targetRepo.RelativePath))), + error: structerr.NewNotFound("%w", fmt.Errorf("accessor call: route repository accessor: %w", storage.NewRepositoryNotFoundError(targetRepo.StorageName, targetRepo.RelativePath))), }, } { t.Run(tc.desc, func(t *testing.T) { diff --git a/internal/praefect/datastore/assignment_test.go b/internal/praefect/datastore/assignment_test.go index 1f97fe40e..73ec3c8d8 100644 --- a/internal/praefect/datastore/assignment_test.go +++ b/internal/praefect/datastore/assignment_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/stretchr/testify/require" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/commonerr" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore/glsql" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testdb" @@ -83,7 +83,7 @@ func TestAssignmentStore_GetHostAssignments(t *testing.T) { rs := NewPostgresRepositoryStore(db, nil) for _, assignment := range tc.existingAssignments { repositoryID, err := rs.GetRepositoryID(ctx, assignment.virtualStorage, assignment.relativePath) - if errors.Is(err, commonerr.NewRepositoryNotFoundError(assignment.virtualStorage, assignment.relativePath)) { + if errors.Is(err, storage.NewRepositoryNotFoundError(assignment.virtualStorage, assignment.relativePath)) { repositoryID, err = rs.ReserveRepositoryID(ctx, assignment.virtualStorage, assignment.relativePath) require.NoError(t, err) @@ -99,7 +99,7 @@ func TestAssignmentStore_GetHostAssignments(t *testing.T) { repositoryID, err := rs.GetRepositoryID(ctx, tc.virtualStorage, "relative-path") if err != nil { - require.Equal(t, commonerr.NewRepositoryNotFoundError(tc.virtualStorage, "relative-path"), err) + require.Equal(t, storage.NewRepositoryNotFoundError(tc.virtualStorage, "relative-path"), err) } actualAssignments, err := NewAssignmentStore( diff --git a/internal/praefect/datastore/repository_store.go b/internal/praefect/datastore/repository_store.go index 968daf15a..c6a41dff3 100644 --- a/internal/praefect/datastore/repository_store.go +++ b/internal/praefect/datastore/repository_store.go @@ -10,7 +10,7 @@ import ( "time" "gitlab.com/gitlab-org/gitaly/v16/internal/datastructure" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/commonerr" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore/glsql" ) @@ -90,7 +90,7 @@ type RepositoryStore interface { // SetGeneration sets the repository's generation on the given storage. If the generation is higher // than the virtual storage's generation, it is set to match as well to guarantee monotonic increments. SetGeneration(ctx context.Context, repositoryID int64, storage, relativePath string, generation int) error - // GetReplicaPath gets the replica path of a repository. Returns a commonerr.ErrRepositoryNotFound if a record + // GetReplicaPath gets the replica path of a repository. Returns a storage.ErrRepositoryNotFound if a record // for the repository ID is not found. GetReplicaPath(ctx context.Context, repositoryID int64) (string, error) // GetReplicatedGeneration returns the generation propagated by applying the replication. If the generation would @@ -110,7 +110,7 @@ type RepositoryStore interface { // SetAuthoritativeReplica sets the given replica of a repsitory as the authoritative one by setting its generation as the latest one. SetAuthoritativeReplica(ctx context.Context, virtualStorage, relativePath, storage string) error // DeleteRepository deletes the database records associated with the repository. It returns the replica path and the storages - // which are known to have a replica at the time of deletion. commonerr.RepositoryNotFoundError is returned when + // which are known to have a replica at the time of deletion. storage.RepositoryNotFoundError is returned when // the repository is not tracked by the Praefect datastore. DeleteRepository(ctx context.Context, virtualStorage, relativePath string) (string, []string, error) // DeleteAllRepositories deletes the database records associated with @@ -282,7 +282,7 @@ SELECT } if !repositoryExists { - return commonerr.ErrRepositoryNotFound + return storage.ErrRepositoryNotFound } if !repositoryUpdated { @@ -326,7 +326,7 @@ ON CONFLICT (repository_id, storage) DO UPDATE SET } // SetAuthoritativeReplica sets the given replica of a repsitory as the authoritative one by setting its generation as the latest one. -func (rs *PostgresRepositoryStore) SetAuthoritativeReplica(ctx context.Context, virtualStorage, relativePath, storage string) error { +func (rs *PostgresRepositoryStore) SetAuthoritativeReplica(ctx context.Context, virtualStorage, relativePath, storageName string) error { result, err := rs.db.ExecContext(ctx, ` WITH updated_repository AS ( UPDATE repositories @@ -342,7 +342,7 @@ FROM updated_repository ON CONFLICT (virtual_storage, relative_path, storage) DO UPDATE SET repository_id = EXCLUDED.repository_id, generation = EXCLUDED.generation - `, virtualStorage, relativePath, storage) + `, virtualStorage, relativePath, storageName) if err != nil { return fmt.Errorf("exec: %w", err) } @@ -350,7 +350,7 @@ ON CONFLICT (virtual_storage, relative_path, storage) DO UPDATE if rowsAffected, err := result.RowsAffected(); err != nil { return fmt.Errorf("rows affected: %w", err) } else if rowsAffected == 0 { - return commonerr.NewRepositoryNotFoundError(virtualStorage, relativePath) + return storage.NewRepositoryNotFoundError(virtualStorage, relativePath) } return nil @@ -513,7 +513,7 @@ GROUP BY replica_path `, virtualStorage, relativePath, ).Scan(&replicaPath, &storages); err != nil { if errors.Is(err, sql.ErrNoRows) { - return "", nil, commonerr.NewRepositoryNotFoundError(virtualStorage, relativePath) + return "", nil, storage.NewRepositoryNotFoundError(virtualStorage, relativePath) } return "", nil, fmt.Errorf("scan: %w", err) @@ -590,7 +590,7 @@ WHERE repository_id = (SELECT repository_id FROM repository) `, virtualStorage, relativePath, newRelativePath) if err != nil { if glsql.IsUniqueViolation(err, "repository_lookup_index") { - return commonerr.ErrRepositoryAlreadyExists + return storage.ErrRepositoryAlreadyExists } return fmt.Errorf("query: %w", err) @@ -599,7 +599,7 @@ WHERE repository_id = (SELECT repository_id FROM repository) if rowsAffected, err := result.RowsAffected(); err != nil { return fmt.Errorf("rows affected: %w", err) } else if rowsAffected == 0 { - return commonerr.ErrRepositoryNotFound + return storage.ErrRepositoryNotFound } return nil @@ -662,8 +662,8 @@ WHERE repositories.virtual_storage = $1 AND repositories.relative_path = $2 GROUP BY replica_path `, virtualStorage, relativePath) - if errors.Is(err, commonerr.ErrRepositoryNotFound) { - return "", nil, commonerr.NewRepositoryNotFoundError(virtualStorage, relativePath) + if errors.Is(err, storage.ErrRepositoryNotFound) { + return "", nil, storage.NewRepositoryNotFoundError(virtualStorage, relativePath) } return replicaPath, storages, err @@ -676,7 +676,7 @@ func (rs *PostgresRepositoryStore) getConsistentStorages(ctx context.Context, qu if err := rs.db.QueryRowContext(ctx, query, params...).Scan(&replicaPath, &storages); err != nil { if errors.Is(err, sql.ErrNoRows) { - return "", nil, commonerr.ErrRepositoryNotFound + return "", nil, storage.ErrRepositoryNotFound } return "", nil, fmt.Errorf("query: %w", err) @@ -787,7 +787,7 @@ func (rs *PostgresRepositoryStore) GetRepositoryMetadata(ctx context.Context, re } if len(metadata) == 0 { - return RepositoryMetadata{}, commonerr.ErrRepositoryNotFound + return RepositoryMetadata{}, storage.ErrRepositoryNotFound } return metadata[0], nil @@ -808,7 +808,7 @@ func (rs *PostgresRepositoryStore) GetRepositoryMetadataByPath(ctx context.Conte } if len(metadata) == 0 { - return RepositoryMetadata{}, commonerr.ErrRepositoryNotFound + return RepositoryMetadata{}, storage.ErrRepositoryNotFound } return metadata[0], nil @@ -990,7 +990,7 @@ WHERE NOT EXISTS ( ) `, virtualStorage, relativePath).Scan(&id); err != nil { if errors.Is(err, sql.ErrNoRows) { - return 0, commonerr.ErrRepositoryAlreadyExists + return 0, storage.ErrRepositoryAlreadyExists } return 0, fmt.Errorf("scan: %w", err) @@ -1010,7 +1010,7 @@ WHERE virtual_storage = $1 AND relative_path = $2 `, virtualStorage, relativePath).Scan(&id); err != nil { if errors.Is(err, sql.ErrNoRows) { - return 0, commonerr.NewRepositoryNotFoundError(virtualStorage, relativePath) + return 0, storage.NewRepositoryNotFoundError(virtualStorage, relativePath) } return 0, fmt.Errorf("scan: %w", err) @@ -1019,7 +1019,7 @@ AND relative_path = $2 return id, nil } -// GetReplicaPath gets the replica path of a repository. Returns a commonerr.ErrRepositoryNotFound if a record +// GetReplicaPath gets the replica path of a repository. Returns a storage.ErrRepositoryNotFound if a record // for the repository ID is not found. func (rs *PostgresRepositoryStore) GetReplicaPath(ctx context.Context, repositoryID int64) (string, error) { var replicaPath string @@ -1027,7 +1027,7 @@ func (rs *PostgresRepositoryStore) GetReplicaPath(ctx context.Context, repositor ctx, "SELECT replica_path FROM repositories WHERE repository_id = $1", repositoryID, ).Scan(&replicaPath); err != nil { if errors.Is(err, sql.ErrNoRows) { - return "", commonerr.ErrRepositoryNotFound + return "", storage.ErrRepositoryNotFound } return "", fmt.Errorf("scan: %w", err) diff --git a/internal/praefect/datastore/repository_store_test.go b/internal/praefect/datastore/repository_store_test.go index c1a59cb98..5ca18d27b 100644 --- a/internal/praefect/datastore/repository_store_test.go +++ b/internal/praefect/datastore/repository_store_test.go @@ -8,7 +8,7 @@ import ( "time" "github.com/stretchr/testify/require" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/commonerr" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore/glsql" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testdb" @@ -133,7 +133,7 @@ func TestRepositoryStore_Postgres(t *testing.T) { require.Equal(t, rs.IncrementGeneration(ctx, 1, "primary", []string{"secondary-1"}), - commonerr.ErrRepositoryNotFound, + storage.ErrRepositoryNotFound, ) requireState(t, ctx, db, virtualStorageState{}, storageState{}) }) @@ -358,7 +358,7 @@ func TestRepositoryStore_Postgres(t *testing.T) { rs := newRepositoryStore(t, nil) require.Equal(t, - commonerr.NewRepositoryNotFoundError(vs, repo), + storage.NewRepositoryNotFoundError(vs, repo), rs.SetAuthoritativeReplica(ctx, vs, repo, stor), ) }) @@ -752,7 +752,7 @@ func TestRepositoryStore_Postgres(t *testing.T) { rs := newRepositoryStore(t, nil) replicaPath, storages, err := rs.DeleteRepository(ctx, vs, repo) - require.Equal(t, commonerr.NewRepositoryNotFoundError(vs, repo), err) + require.Equal(t, storage.NewRepositoryNotFoundError(vs, repo), err) require.Empty(t, replicaPath) require.Empty(t, storages) }) @@ -898,7 +898,7 @@ func TestRepositoryStore_Postgres(t *testing.T) { rs := newRepositoryStore(t, nil) require.Equal(t, - commonerr.ErrRepositoryNotFound, + storage.ErrRepositoryNotFound, rs.RenameRepositoryInPlace(ctx, vs, repo, "new-relative-path"), ) }) @@ -910,7 +910,7 @@ func TestRepositoryStore_Postgres(t *testing.T) { require.NoError(t, rs.CreateRepository(ctx, 2, vs, "relative-path-2", "replica-path-2", "primary", nil, nil, true, false)) require.Equal(t, - commonerr.ErrRepositoryAlreadyExists, + storage.ErrRepositoryAlreadyExists, rs.RenameRepositoryInPlace(ctx, vs, "relative-path-1", "relative-path-2"), ) }) @@ -1007,12 +1007,12 @@ func TestRepositoryStore_Postgres(t *testing.T) { t.Run("no records", func(t *testing.T) { replicaPath, secondaries, err := rs.GetConsistentStorages(ctx, vs, repo) - require.Equal(t, commonerr.NewRepositoryNotFoundError(vs, repo), err) + require.Equal(t, storage.NewRepositoryNotFoundError(vs, repo), err) require.Empty(t, replicaPath) require.Empty(t, secondaries) replicaPath, secondaries, err = rs.GetConsistentStoragesByRepositoryID(ctx, 1) - require.Equal(t, commonerr.ErrRepositoryNotFound, err) + require.Equal(t, storage.ErrRepositoryNotFound, err) require.Empty(t, replicaPath) require.Empty(t, secondaries) }) @@ -1101,12 +1101,12 @@ func TestRepositoryStore_Postgres(t *testing.T) { requireState(t, ctx, db, virtualStorageState{}, storageState{}) replicaPath, secondaries, err := rs.GetConsistentStorages(ctx, vs, repo) - require.Equal(t, commonerr.NewRepositoryNotFoundError(vs, repo), err) + require.Equal(t, storage.NewRepositoryNotFoundError(vs, repo), err) require.Empty(t, secondaries) require.Empty(t, replicaPath) replicaPath, secondaries, err = rs.GetConsistentStoragesByRepositoryID(ctx, 1) - require.Equal(t, commonerr.ErrRepositoryNotFound, err) + require.Equal(t, storage.ErrRepositoryNotFound, err) require.Empty(t, secondaries) require.Empty(t, replicaPath) }) @@ -1208,7 +1208,7 @@ func TestRepositoryStore_Postgres(t *testing.T) { require.NoError(t, rs.CreateRepository(ctx, id, vs, repo, "replica-path", stor, nil, nil, false, false)) id, err = rs.ReserveRepositoryID(ctx, vs, repo) - require.Equal(t, commonerr.ErrRepositoryAlreadyExists, err) + require.Equal(t, storage.ErrRepositoryAlreadyExists, err) require.Equal(t, int64(0), id) id, err = rs.ReserveRepositoryID(ctx, vs, repo+"-2") @@ -1220,7 +1220,7 @@ func TestRepositoryStore_Postgres(t *testing.T) { rs := newRepositoryStore(t, nil) id, err := rs.GetRepositoryID(ctx, vs, repo) - require.Equal(t, commonerr.NewRepositoryNotFoundError(vs, repo), err) + require.Equal(t, storage.NewRepositoryNotFoundError(vs, repo), err) require.Equal(t, int64(0), id) require.NoError(t, rs.CreateRepository(ctx, 1, vs, repo, "replica-path", stor, nil, nil, false, false)) @@ -1234,7 +1234,7 @@ func TestRepositoryStore_Postgres(t *testing.T) { rs := newRepositoryStore(t, nil) replicaPath, err := rs.GetReplicaPath(ctx, 1) - require.Equal(t, err, commonerr.ErrRepositoryNotFound) + require.Equal(t, err, storage.ErrRepositoryNotFound) require.Empty(t, replicaPath) require.NoError(t, rs.CreateRepository(ctx, 1, vs, repo, "replica-path", stor, nil, nil, false, false)) @@ -1669,7 +1669,7 @@ func TestPostgresRepositoryStore_GetRepositoryMetadata(t *testing.T) { var expectedErr error if tc.nonExistentRepository { - expectedErr = commonerr.ErrRepositoryNotFound + expectedErr = storage.ErrRepositoryNotFound expectedMetadata = RepositoryMetadata{} } diff --git a/internal/praefect/datastore/storage_provider_test.go b/internal/praefect/datastore/storage_provider_test.go index 410195c8a..abe683fbe 100644 --- a/internal/praefect/datastore/storage_provider_test.go +++ b/internal/praefect/datastore/storage_provider_test.go @@ -16,7 +16,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v16/internal/datastructure" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/commonerr" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore/glsql" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testdb" @@ -101,7 +101,7 @@ func TestCachingStorageProvider_GetSyncedNodes(t *testing.T) { cache.Connected() _, _, err = cache.GetConsistentStorages(ctx, "vs", "/repo/path") - require.Equal(t, commonerr.NewRepositoryNotFoundError("vs", "/repo/path"), err) + require.Equal(t, storage.NewRepositoryNotFoundError("vs", "/repo/path"), err) // "populate" metric is not set as there was an error and we don't want this result to be cached err = testutil.CollectAndCompare(cache, strings.NewReader(` diff --git a/internal/praefect/nodes/manager.go b/internal/praefect/nodes/manager.go index e6260f7e1..6894d61ee 100644 --- a/internal/praefect/nodes/manager.go +++ b/internal/praefect/nodes/manager.go @@ -13,10 +13,10 @@ import ( "github.com/sirupsen/logrus" gitalyauth "gitlab.com/gitlab-org/gitaly/v16/auth" "gitlab.com/gitlab-org/gitaly/v16/internal/datastructure" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/client" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/proxy" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/sidechannel" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/commonerr" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/config" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/metrics" @@ -274,7 +274,7 @@ func (n *Mgr) GetPrimary(ctx context.Context, virtualStorage string, _ int64) (s //nolint:revive // This is unintentionally missing documentation. func (n *Mgr) GetSyncedNode(ctx context.Context, virtualStorageName, repoPath string) (Node, error) { _, upToDateStorages, err := n.csg.GetConsistentStorages(ctx, virtualStorageName, repoPath) - if err != nil && !errors.As(err, new(commonerr.RepositoryNotFoundError)) { + if err != nil && !errors.As(err, new(storage.RepositoryNotFoundError)) { return nil, err } diff --git a/internal/praefect/nodes/per_repository.go b/internal/praefect/nodes/per_repository.go index 254724198..a7e2b97d3 100644 --- a/internal/praefect/nodes/per_repository.go +++ b/internal/praefect/nodes/per_repository.go @@ -8,7 +8,7 @@ import ( "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus" "github.com/sirupsen/logrus" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/commonerr" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore/glsql" ) @@ -103,7 +103,7 @@ WHERE snapshot.repository_id = $1 repositoryID, ).Scan(¤t, &previous); err != nil { if errors.Is(err, sql.ErrNoRows) { - return "", commonerr.ErrRepositoryNotFound + return "", storage.ErrRepositoryNotFound } return "", fmt.Errorf("scan: %w", err) diff --git a/internal/praefect/nodes/per_repository_test.go b/internal/praefect/nodes/per_repository_test.go index 93d5ef806..1e96737b3 100644 --- a/internal/praefect/nodes/per_repository_test.go +++ b/internal/praefect/nodes/per_repository_test.go @@ -8,7 +8,7 @@ import ( "github.com/sirupsen/logrus/hooks/test" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/commonerr" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testdb" @@ -476,7 +476,7 @@ func TestPerRepositoryElector(t *testing.T) { desc: "repository does not exist", steps: steps{ { - error: commonerr.ErrRepositoryNotFound, + error: storage.ErrRepositoryNotFound, primary: noPrimary(), noBlockedQuery: true, }, @@ -514,7 +514,7 @@ func TestPerRepositoryElector(t *testing.T) { for _, event := range tc.existingJobs { repositoryID, err := rs.GetRepositoryID(ctx, event.Job.VirtualStorage, event.Job.RelativePath) if err != nil { - require.Equal(t, commonerr.NewRepositoryNotFoundError(event.Job.VirtualStorage, event.Job.RelativePath), err) + require.Equal(t, storage.NewRepositoryNotFoundError(event.Job.VirtualStorage, event.Job.RelativePath), err) } event.Job.RepositoryID = repositoryID diff --git a/internal/praefect/reconciler/reconciler_test.go b/internal/praefect/reconciler/reconciler_test.go index bf68e4898..f421df15e 100644 --- a/internal/praefect/reconciler/reconciler_test.go +++ b/internal/praefect/reconciler/reconciler_test.go @@ -9,10 +9,10 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/stretchr/testify/require" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/grpc/middleware/metadatahandler" "gitlab.com/gitlab-org/gitaly/v16/internal/helper" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/commonerr" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testdb" @@ -1041,7 +1041,7 @@ func TestReconciler(t *testing.T) { var err error existing.Job.RepositoryID, err = rs.GetRepositoryID(ctx, existing.Job.VirtualStorage, existing.Job.RelativePath) if err != nil { - require.Equal(t, commonerr.NewRepositoryNotFoundError(existing.Job.VirtualStorage, existing.Job.RelativePath), err) + require.Equal(t, storage.NewRepositoryNotFoundError(existing.Job.VirtualStorage, existing.Job.RelativePath), err) } var id int64 @@ -1099,7 +1099,7 @@ func TestReconciler(t *testing.T) { for i, job := range jobs { id, err := rs.GetRepositoryID(ctx, job.VirtualStorage, job.RelativePath) if err != nil { - require.Equal(t, commonerr.NewRepositoryNotFoundError(job.VirtualStorage, job.RelativePath), err) + require.Equal(t, storage.NewRepositoryNotFoundError(job.VirtualStorage, job.RelativePath), err) } jobs[i].RepositoryID = id diff --git a/internal/praefect/remove_repository.go b/internal/praefect/remove_repository.go index 2d8c9a17c..12c1805bd 100644 --- a/internal/praefect/remove_repository.go +++ b/internal/praefect/remove_repository.go @@ -9,7 +9,7 @@ import ( "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus/ctxlogrus" "github.com/sirupsen/logrus" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/commonerr" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" @@ -63,9 +63,9 @@ func removeRepositoryHandler(rs datastore.RepositoryStore, conns Connections, pa virtualStorage := repo.StorageName replicaPath, storages, err := rs.DeleteRepository(ctx, virtualStorage, repo.RelativePath) if err != nil { - if errors.As(err, new(commonerr.RepositoryNotFoundError)) { + if errors.As(err, new(storage.RepositoryNotFoundError)) { if errorOnNotFound { - if errors.As(err, new(commonerr.RepositoryNotFoundError)) { + if errors.As(err, new(storage.RepositoryNotFoundError)) { return structerr.NewNotFound("repository does not exist") } } diff --git a/internal/praefect/rename_repository.go b/internal/praefect/rename_repository.go index b7c849460..2c2adc5b7 100644 --- a/internal/praefect/rename_repository.go +++ b/internal/praefect/rename_repository.go @@ -6,7 +6,6 @@ import ( "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/service" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/commonerr" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" @@ -59,13 +58,13 @@ func RenameRepositoryHandler(virtualStoragesNames []string, rs datastore.Reposit req.GetRepository().GetRelativePath(), req.GetRelativePath(), ); err != nil { - if errors.Is(err, commonerr.ErrRepositoryNotFound) { + if errors.Is(err, storage.ErrRepositoryNotFound) { return structerr.NewNotFound( `GetRepoPath: not a git repository: "%s/%s"`, req.GetRepository().GetStorageName(), req.GetRepository().GetRelativePath(), ) - } else if errors.Is(err, commonerr.ErrRepositoryAlreadyExists) { + } else if errors.Is(err, storage.ErrRepositoryAlreadyExists) { return structerr.NewAlreadyExists("target repo exists already") } diff --git a/internal/praefect/replicator_test.go b/internal/praefect/replicator_test.go index b78fca253..d983c1f41 100644 --- a/internal/praefect/replicator_test.go +++ b/internal/praefect/replicator_test.go @@ -572,7 +572,7 @@ func TestProcessBacklog_Success(t *testing.T) { <-replMgrDone require.NoDirExists(t, fullNewPath1, "repository must be moved from %q to the new location", fullNewPath1) - require.True(t, storage.IsGitDirectory(fullNewPath2), "repository must exist at new last RenameRepository location") + require.NoError(t, storage.ValidateRepository(fullNewPath2), "repository must exist at new last RenameRepository location") } func TestReplMgrProcessBacklog_OnlyHealthyNodes(t *testing.T) { diff --git a/internal/praefect/router_node_manager.go b/internal/praefect/router_node_manager.go index 0159a9cd1..2fc2bae61 100644 --- a/internal/praefect/router_node_manager.go +++ b/internal/praefect/router_node_manager.go @@ -6,7 +6,7 @@ import ( "fmt" "gitlab.com/gitlab-org/gitaly/v16/internal/datastructure" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/commonerr" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/nodes" ) @@ -86,7 +86,7 @@ func (r *nodeManagerRouter) RouteRepositoryMutator(ctx context.Context, virtualS // paths of repositories and thus returns an empty string. This breaks the tests. Instead, we'll just keep // using the relative path in NodeManagerRouter. _, consistentStorages, err := r.rs.GetConsistentStorages(ctx, virtualStorage, relativePath) - if err != nil && !errors.As(err, new(commonerr.RepositoryNotFoundError)) { + if err != nil && !errors.As(err, new(storage.RepositoryNotFoundError)) { return RepositoryMutatorRoute{}, fmt.Errorf("consistent storages: %w", err) } diff --git a/internal/praefect/router_per_repository_test.go b/internal/praefect/router_per_repository_test.go index 75c67a941..dc68d0dfe 100644 --- a/internal/praefect/router_per_repository_test.go +++ b/internal/praefect/router_per_repository_test.go @@ -9,7 +9,6 @@ import ( "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/commonerr" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/nodes" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" @@ -841,7 +840,7 @@ func TestPerRepositoryRouterRouteRepositoryCreation(t *testing.T) { primaryPick: 0, repositoryExists: true, expectedPrimaryCandidates: []int{3}, - expectedErr: fmt.Errorf("reserve repository id: %w", commonerr.ErrRepositoryAlreadyExists), + expectedErr: fmt.Errorf("reserve repository id: %w", storage.ErrRepositoryAlreadyExists), }, { desc: "additional repository doesn't exist", diff --git a/internal/praefect/service/info/metadata.go b/internal/praefect/service/info/metadata.go index b3820f67d..2e204512a 100644 --- a/internal/praefect/service/info/metadata.go +++ b/internal/praefect/service/info/metadata.go @@ -4,7 +4,7 @@ import ( "context" "errors" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/commonerr" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore" "gitlab.com/gitlab-org/gitaly/v16/internal/structerr" "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb" @@ -29,7 +29,7 @@ func (s *Server) GetRepositoryMetadata(ctx context.Context, req *gitalypb.GetRep metadata, err := getMetadata() if err != nil { - if errors.Is(err, commonerr.ErrRepositoryNotFound) { + if errors.Is(err, storage.ErrRepositoryNotFound) { return nil, structerr.NewNotFound("%w", err) } diff --git a/internal/praefect/service/info/server.go b/internal/praefect/service/info/server.go index e7e76915e..c099d2528 100644 --- a/internal/praefect/service/info/server.go +++ b/internal/praefect/service/info/server.go @@ -4,7 +4,7 @@ import ( "context" "errors" - "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/commonerr" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/config" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/datastore" "gitlab.com/gitlab-org/gitaly/v16/internal/praefect/service" @@ -80,7 +80,7 @@ func (s *Server) SetAuthoritativeStorage(ctx context.Context, req *gitalypb.SetA } if err := s.rs.SetAuthoritativeReplica(ctx, req.VirtualStorage, req.RelativePath, req.AuthoritativeStorage); err != nil { - if errors.As(err, &commonerr.RepositoryNotFoundError{}) { + if errors.As(err, &storage.RepositoryNotFoundError{}) { return nil, structerr.NewInvalidArgument("repository %q does not exist on virtual storage %q", req.RelativePath, req.VirtualStorage) } diff --git a/internal/tempdir/tempdir_test.go b/internal/tempdir/tempdir_test.go index 6d89ad083..61aaba1eb 100644 --- a/internal/tempdir/tempdir_test.go +++ b/internal/tempdir/tempdir_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/config" + "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage" "gitlab.com/gitlab-org/gitaly/v16/internal/helper/perm" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper" "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testcfg" @@ -24,7 +25,7 @@ func TestNewRepositorySuccess(t *testing.T) { require.Equal(t, cfg.Storages[0].Name, repo.StorageName) require.Contains(t, repo.RelativePath, tmpRootPrefix) - calculatedPath, err := locator.GetPath(repo) + calculatedPath, err := locator.GetRepoPath(repo, storage.WithRepositoryVerificationSkipped()) require.NoError(t, err) require.Equal(t, tempDir.Path(), calculatedPath) |