Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSami Hiltunen <shiltunen@gitlab.com>2023-06-22 15:52:24 +0300
committerSami Hiltunen <shiltunen@gitlab.com>2023-06-22 15:52:24 +0300
commit8d7e76612ceb321f8868d9c7d6ba2fc9b237ada3 (patch)
treeb79320ee9d4291a882b70dfcdc39241e614527f5
parentfa12d031b2ee607a9b7519f8610a6b83a21fb52e (diff)
parentc63a4a908100edccb8591f1be251a5f15d9ef983 (diff)
Merge branch 'backup_repository_rpc' into 'master'
Add BackupRepository RPC Closes #4940 See merge request https://gitlab.com/gitlab-org/gitaly/-/merge_requests/5925 Merged-by: Sami Hiltunen <shiltunen@gitlab.com> Approved-by: Sami Hiltunen <shiltunen@gitlab.com> Reviewed-by: Justin Tobler <jtobler@gitlab.com> Co-authored-by: James Fargher <jfargher@gitlab.com>
-rw-r--r--internal/backup/backup.go17
-rw-r--r--internal/backup/backup_test.go15
-rw-r--r--internal/cli/gitaly/serve.go17
-rw-r--r--internal/git/localrepo/remote_extra_test.go2
-rw-r--r--internal/git/remoterepo/testhelper_test.go2
-rw-r--r--internal/gitaly/config/config.go31
-rw-r--r--internal/gitaly/config/config_test.go60
-rw-r--r--internal/gitaly/service/blob/testhelper_test.go2
-rw-r--r--internal/gitaly/service/cleanup/testhelper_test.go2
-rw-r--r--internal/gitaly/service/commit/testhelper_test.go2
-rw-r--r--internal/gitaly/service/conflicts/testhelper_test.go2
-rw-r--r--internal/gitaly/service/dependencies.go13
-rw-r--r--internal/gitaly/service/diff/testhelper_test.go2
-rw-r--r--internal/gitaly/service/hook/testhelper_test.go2
-rw-r--r--internal/gitaly/service/objectpool/testhelper_test.go2
-rw-r--r--internal/gitaly/service/operations/testhelper_test.go2
-rw-r--r--internal/gitaly/service/ref/delete_refs_test.go2
-rw-r--r--internal/gitaly/service/ref/testhelper_test.go2
-rw-r--r--internal/gitaly/service/remote/testhelper_test.go2
-rw-r--r--internal/gitaly/service/remote/update_remote_mirror_test.go2
-rw-r--r--internal/gitaly/service/repository/backup_repository.go62
-rw-r--r--internal/gitaly/service/repository/backup_repository_test.go188
-rw-r--r--internal/gitaly/service/repository/server.go7
-rw-r--r--internal/gitaly/service/repository/testhelper_test.go2
-rw-r--r--internal/gitaly/service/setup/register.go2
-rw-r--r--internal/gitaly/service/smarthttp/testhelper_test.go2
-rw-r--r--internal/gitaly/service/ssh/testhelper_test.go2
-rw-r--r--internal/praefect/info_service_test.go2
-rw-r--r--internal/praefect/verifier_test.go2
-rw-r--r--internal/testhelper/testserver/gitaly.go21
-rw-r--r--proto/go/gitalypb/repository.pb.go522
-rw-r--r--proto/go/gitalypb/repository_grpc.pb.go42
-rw-r--r--proto/repository.proto26
33 files changed, 895 insertions, 166 deletions
diff --git a/internal/backup/backup.go b/internal/backup/backup.go
index 8d1ef1abe..79117bf24 100644
--- a/internal/backup/backup.go
+++ b/internal/backup/backup.go
@@ -202,13 +202,22 @@ func (mgr *Manager) RemoveAllRepositories(ctx context.Context, req *RemoveAllRep
// CreateRequest is the request to create a backup
type CreateRequest struct {
- Server storage.ServerInfo
- Repository *gitalypb.Repository
+ // Server contains gitaly server connection information required to call
+ // RPCs in the non-local backup.Manager configuration.
+ Server storage.ServerInfo
+ // Repository is the repository to be backed up.
+ Repository *gitalypb.Repository
+ // VanityRepository is used to determine the backup path.
+ VanityRepository *gitalypb.Repository
+ // Incremental when true will create an increment on the specified full backup.
Incremental bool
}
// Create creates a repository backup.
func (mgr *Manager) Create(ctx context.Context, req *CreateRequest) error {
+ if req.VanityRepository == nil {
+ req.VanityRepository = req.Repository
+ }
repo, err := mgr.repositoryFactory(ctx, req.Repository, req.Server)
if err != nil {
return fmt.Errorf("manager: %w", err)
@@ -223,12 +232,12 @@ func (mgr *Manager) Create(ctx context.Context, req *CreateRequest) error {
var step *Step
if req.Incremental {
var err error
- step, err = mgr.locator.BeginIncremental(ctx, req.Repository, mgr.backupID)
+ step, err = mgr.locator.BeginIncremental(ctx, req.VanityRepository, mgr.backupID)
if err != nil {
return fmt.Errorf("manager: %w", err)
}
} else {
- step = mgr.locator.BeginFull(ctx, req.Repository, mgr.backupID)
+ step = mgr.locator.BeginFull(ctx, req.VanityRepository, mgr.backupID)
}
refs, err := repo.ListRefs(ctx)
diff --git a/internal/backup/backup_test.go b/internal/backup/backup_test.go
index bc5b6676b..b10820b56 100644
--- a/internal/backup/backup_test.go
+++ b/internal/backup/backup_test.go
@@ -159,10 +159,14 @@ func TestManager_Create(t *testing.T) {
t.Run(tc.desc, func(t *testing.T) {
repo, repoPath := tc.setup(t)
backupRoot := testhelper.TempDir(t)
+ vanityRepo := &gitalypb.Repository{
+ RelativePath: "some/path.git",
+ StorageName: "some_storage",
+ }
- refsPath := joinBackupPath(t, backupRoot, repo, backupID, "001.refs")
- bundlePath := joinBackupPath(t, backupRoot, repo, backupID, "001.bundle")
- customHooksPath := joinBackupPath(t, backupRoot, repo, backupID, "001.custom_hooks.tar")
+ refsPath := joinBackupPath(t, backupRoot, vanityRepo, backupID, "001.refs")
+ bundlePath := joinBackupPath(t, backupRoot, vanityRepo, backupID, "001.bundle")
+ customHooksPath := joinBackupPath(t, backupRoot, vanityRepo, backupID, "001.custom_hooks.tar")
sink := backup.NewFilesystemSink(backupRoot)
locator, err := backup.ResolveLocator("pointer", sink)
@@ -170,8 +174,9 @@ func TestManager_Create(t *testing.T) {
fsBackup := managerTC.setup(t, sink, locator)
err = fsBackup.Create(ctx, &backup.CreateRequest{
- Server: storage.ServerInfo{Address: cfg.SocketPath, Token: cfg.Auth.Token},
- Repository: repo,
+ Server: storage.ServerInfo{Address: cfg.SocketPath, Token: cfg.Auth.Token},
+ Repository: repo,
+ VanityRepository: vanityRepo,
})
if tc.err == nil {
require.NoError(t, err)
diff --git a/internal/cli/gitaly/serve.go b/internal/cli/gitaly/serve.go
index a4ae23e81..5706adf6b 100644
--- a/internal/cli/gitaly/serve.go
+++ b/internal/cli/gitaly/serve.go
@@ -14,6 +14,7 @@ import (
"github.com/urfave/cli/v2"
"gitlab.com/gitlab-org/gitaly/v16"
"gitlab.com/gitlab-org/gitaly/v16/client"
+ "gitlab.com/gitlab-org/gitaly/v16/internal/backup"
"gitlab.com/gitlab-org/gitaly/v16/internal/bootstrap"
"gitlab.com/gitlab-org/gitaly/v16/internal/bootstrap/starter"
"gitlab.com/gitlab-org/gitaly/v16/internal/cache"
@@ -306,6 +307,20 @@ func run(cfg config.Cfg) error {
concurrencyTracker := hook.NewConcurrencyTracker()
prometheus.MustRegister(concurrencyTracker)
+ var backupSink backup.Sink
+ var backupLocator backup.Locator
+ if cfg.Backup.GoCloudURL != "" {
+ var err error
+ backupSink, err = backup.ResolveSink(ctx, cfg.Backup.GoCloudURL)
+ if err != nil {
+ return fmt.Errorf("resolve backup sink: %w", err)
+ }
+ backupLocator, err = backup.ResolveLocator(cfg.Backup.Layout, backupSink)
+ if err != nil {
+ return fmt.Errorf("resolve backup locator: %w", err)
+ }
+ }
+
for _, c := range []starter.Config{
{Name: starter.Unix, Addr: cfg.SocketPath, HandoverOnUpgrade: true},
{Name: starter.Unix, Addr: cfg.InternalSocketPath(), HandoverOnUpgrade: false},
@@ -344,6 +359,8 @@ func run(cfg config.Cfg) error {
Git2goExecutor: git2goExecutor,
UpdaterWithHooks: updaterWithHooks,
HousekeepingManager: housekeepingManager,
+ BackupSink: backupSink,
+ BackupLocator: backupLocator,
})
b.RegisterStarter(starter.New(c, srv))
}
diff --git a/internal/git/localrepo/remote_extra_test.go b/internal/git/localrepo/remote_extra_test.go
index 47bb4172b..743d438d7 100644
--- a/internal/git/localrepo/remote_extra_test.go
+++ b/internal/git/localrepo/remote_extra_test.go
@@ -51,6 +51,8 @@ func TestRepo_FetchInternal(t *testing.T) {
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
}, testserver.WithGitCommandFactory(protocolDetectingFactory))
diff --git a/internal/git/remoterepo/testhelper_test.go b/internal/git/remoterepo/testhelper_test.go
index 9e9645487..32b95f78e 100644
--- a/internal/git/remoterepo/testhelper_test.go
+++ b/internal/git/remoterepo/testhelper_test.go
@@ -32,6 +32,8 @@ func setupGitalyServer(t *testing.T) config.Cfg {
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
gitalypb.RegisterCommitServiceServer(srv, commit.NewServer(
deps.GetCfg(),
diff --git a/internal/gitaly/config/config.go b/internal/gitaly/config/config.go
index 3854a9f63..ffd0a4272 100644
--- a/internal/gitaly/config/config.go
+++ b/internal/gitaly/config/config.go
@@ -112,6 +112,7 @@ type Cfg struct {
Cgroups cgroups.Config `toml:"cgroups,omitempty" json:"cgroups"`
PackObjectsCache StreamCacheConfig `toml:"pack_objects_cache,omitempty" json:"pack_objects_cache"`
PackObjectsLimiting PackObjectsLimiting `toml:"pack_objects_limiting,omitempty" json:"pack_objects_limiting"`
+ Backup BackupConfig `toml:"backup,omitempty" json:"backup"`
}
// TLS configuration
@@ -419,6 +420,31 @@ func (pol PackObjectsLimiting) Validate() error {
AsError()
}
+// BackupConfig configures server-side backups.
+type BackupConfig struct {
+ // GoCloudURL is the blob storage GoCloud URL that will be used to store
+ // server-side backups.
+ GoCloudURL string `toml:"go_cloud_url,omitempty" json:"go_cloud_url,omitempty"`
+ // Layout determines how backup files are located.
+ Layout string `toml:"layout,omitempty" json:"layout,omitempty"`
+}
+
+// Validate runs validation on all fields and returns any errors found.
+func (bc BackupConfig) Validate() error {
+ if bc.GoCloudURL == "" {
+ return nil
+ }
+ var errs cfgerror.ValidationErrors
+
+ if _, err := url.Parse(bc.GoCloudURL); err != nil {
+ errs = errs.Append(err, "go_cloud_url")
+ }
+
+ return errs.
+ Append(cfgerror.NotBlank(bc.Layout), "layout").
+ AsError()
+}
+
// StreamCacheConfig contains settings for a streamcache instance.
type StreamCacheConfig struct {
Enabled bool `toml:"enabled" json:"enabled"` // Default: false
@@ -577,6 +603,7 @@ func (cfg *Cfg) ValidateV2() error {
{field: "cgroups", validate: cfg.Cgroups.Validate},
{field: "pack_objects_cache", validate: cfg.PackObjectsCache.Validate},
{field: "pack_objects_limiting", validate: cfg.PackObjectsLimiting.Validate},
+ {field: "backup", validate: cfg.Backup.Validate},
} {
var fields []string
if check.field != "" {
@@ -615,6 +642,10 @@ func (cfg *Cfg) setDefaults() error {
cfg.Cgroups.FallbackToOldVersion()
+ if cfg.Backup.Layout == "" {
+ cfg.Backup.Layout = "pointer"
+ }
+
return nil
}
diff --git a/internal/gitaly/config/config_test.go b/internal/gitaly/config/config_test.go
index 7697bf0d3..c9962ab88 100644
--- a/internal/gitaly/config/config_test.go
+++ b/internal/gitaly/config/config_test.go
@@ -2056,6 +2056,66 @@ func TestGitlab_Validate(t *testing.T) {
}
}
+func TestBackupConfig_Validate(t *testing.T) {
+ t.Parallel()
+
+ for _, tc := range []struct {
+ name string
+ backupConfig BackupConfig
+ expectedErr error
+ }{
+ {
+ name: "empty",
+ },
+ {
+ name: "valid",
+ backupConfig: BackupConfig{
+ GoCloudURL: "s3://my-bucket",
+ Layout: "pointer",
+ },
+ },
+ {
+ name: "go_cloud_url invalid",
+ backupConfig: BackupConfig{
+ GoCloudURL: "%invalid%",
+ Layout: "pointer",
+ },
+ expectedErr: cfgerror.ValidationErrors{
+ cfgerror.NewValidationError(
+ &url.Error{
+ Op: "parse",
+ URL: "%invalid%",
+ Err: url.EscapeError("%in"),
+ },
+ "go_cloud_url",
+ ),
+ },
+ },
+ {
+ name: "layout missing",
+ backupConfig: BackupConfig{
+ GoCloudURL: "s3://my-bucket",
+ Layout: "",
+ },
+ expectedErr: cfgerror.ValidationErrors{
+ cfgerror.NewValidationError(
+ cfgerror.ErrBlankOrEmpty,
+ "layout",
+ ),
+ },
+ },
+ } {
+ tc := tc
+
+ t.Run(tc.name, func(t *testing.T) {
+ t.Parallel()
+
+ err := tc.backupConfig.Validate()
+ require.Equal(t, tc.expectedErr, err)
+ })
+ }
+}
+
func TestStreamCacheConfig_Validate(t *testing.T) {
t.Parallel()
diff --git a/internal/gitaly/service/blob/testhelper_test.go b/internal/gitaly/service/blob/testhelper_test.go
index eb34361fe..aeb43915f 100644
--- a/internal/gitaly/service/blob/testhelper_test.go
+++ b/internal/gitaly/service/blob/testhelper_test.go
@@ -38,6 +38,8 @@ func setup(tb testing.TB, ctx context.Context) (config.Cfg, gitalypb.BlobService
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
})
cfg.SocketPath = addr
diff --git a/internal/gitaly/service/cleanup/testhelper_test.go b/internal/gitaly/service/cleanup/testhelper_test.go
index aeb621d3f..a37bf796e 100644
--- a/internal/gitaly/service/cleanup/testhelper_test.go
+++ b/internal/gitaly/service/cleanup/testhelper_test.go
@@ -57,6 +57,8 @@ func runCleanupServiceServer(t *testing.T, cfg config.Cfg) string {
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
})
}
diff --git a/internal/gitaly/service/commit/testhelper_test.go b/internal/gitaly/service/commit/testhelper_test.go
index 9428bddd8..cf22b52e3 100644
--- a/internal/gitaly/service/commit/testhelper_test.go
+++ b/internal/gitaly/service/commit/testhelper_test.go
@@ -85,6 +85,8 @@ func startTestServices(tb testing.TB, cfg config.Cfg, opts ...testserver.GitalyS
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
}, opts...)
}
diff --git a/internal/gitaly/service/conflicts/testhelper_test.go b/internal/gitaly/service/conflicts/testhelper_test.go
index 75eaf1cfa..413eef849 100644
--- a/internal/gitaly/service/conflicts/testhelper_test.go
+++ b/internal/gitaly/service/conflicts/testhelper_test.go
@@ -58,6 +58,8 @@ func runConflictsServer(tb testing.TB, cfg config.Cfg, hookManager hook.Manager)
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
gitalypb.RegisterSSHServiceServer(srv, ssh.NewServer(
deps.GetLocator(),
diff --git a/internal/gitaly/service/dependencies.go b/internal/gitaly/service/dependencies.go
index 78563c647..136ec6288 100644
--- a/internal/gitaly/service/dependencies.go
+++ b/internal/gitaly/service/dependencies.go
@@ -2,6 +2,7 @@ package service
import (
"gitlab.com/gitlab-org/gitaly/v16/client"
+ "gitlab.com/gitlab-org/gitaly/v16/internal/backup"
"gitlab.com/gitlab-org/gitaly/v16/internal/cache"
"gitlab.com/gitlab-org/gitaly/v16/internal/git"
"gitlab.com/gitlab-org/gitaly/v16/internal/git/catfile"
@@ -39,6 +40,8 @@ type Dependencies struct {
UpdaterWithHooks *updateref.UpdaterWithHooks
HousekeepingManager housekeeping.Manager
PartitionManager *storagemgr.PartitionManager
+ BackupSink backup.Sink
+ BackupLocator backup.Locator
}
// GetCfg returns service configuration.
@@ -130,3 +133,13 @@ func (dc *Dependencies) GetPackObjectsLimiter() limithandler.Limiter {
func (dc *Dependencies) GetPartitionManager() *storagemgr.PartitionManager {
return dc.PartitionManager
}
+
+// GetBackupSink returns the backup.Sink.
+func (dc *Dependencies) GetBackupSink() backup.Sink {
+ return dc.BackupSink
+}
+
+// GetBackupLocator returns the backup.Locator.
+func (dc *Dependencies) GetBackupLocator() backup.Locator {
+ return dc.BackupLocator
+}
diff --git a/internal/gitaly/service/diff/testhelper_test.go b/internal/gitaly/service/diff/testhelper_test.go
index 234aae21b..c13fa72ef 100644
--- a/internal/gitaly/service/diff/testhelper_test.go
+++ b/internal/gitaly/service/diff/testhelper_test.go
@@ -49,6 +49,8 @@ func setupDiffServiceWithoutRepo(tb testing.TB, opt ...testserver.GitalyServerOp
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
}, opt...)
cfg.SocketPath = addr
diff --git a/internal/gitaly/service/hook/testhelper_test.go b/internal/gitaly/service/hook/testhelper_test.go
index dae029546..7e579a701 100644
--- a/internal/gitaly/service/hook/testhelper_test.go
+++ b/internal/gitaly/service/hook/testhelper_test.go
@@ -76,6 +76,8 @@ func runHooksServer(tb testing.TB, cfg config.Cfg, opts []serverOption, serverOp
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
}, serverOpts...)
}
diff --git a/internal/gitaly/service/objectpool/testhelper_test.go b/internal/gitaly/service/objectpool/testhelper_test.go
index d35966459..62b713f56 100644
--- a/internal/gitaly/service/objectpool/testhelper_test.go
+++ b/internal/gitaly/service/objectpool/testhelper_test.go
@@ -87,6 +87,8 @@ func runObjectPoolServer(t *testing.T, cfg config.Cfg, locator storage.Locator,
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
}, append(opts, testserver.WithLocator(locator), testserver.WithLogger(logger))...)
}
diff --git a/internal/gitaly/service/operations/testhelper_test.go b/internal/gitaly/service/operations/testhelper_test.go
index 893ce149d..90b0d873f 100644
--- a/internal/gitaly/service/operations/testhelper_test.go
+++ b/internal/gitaly/service/operations/testhelper_test.go
@@ -119,6 +119,8 @@ func runOperationServiceServer(tb testing.TB, cfg config.Cfg, options ...testser
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
gitalypb.RegisterRefServiceServer(srv, ref.NewServer(
deps.GetLocator(),
diff --git a/internal/gitaly/service/ref/delete_refs_test.go b/internal/gitaly/service/ref/delete_refs_test.go
index e770cd095..bba8b94ad 100644
--- a/internal/gitaly/service/ref/delete_refs_test.go
+++ b/internal/gitaly/service/ref/delete_refs_test.go
@@ -121,6 +121,8 @@ func TestDeleteRefs_transaction(t *testing.T) {
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
gitalypb.RegisterHookServiceServer(srv, hookservice.NewServer(
deps.GetHookManager(),
diff --git a/internal/gitaly/service/ref/testhelper_test.go b/internal/gitaly/service/ref/testhelper_test.go
index 80e4b0b8d..9b0a77852 100644
--- a/internal/gitaly/service/ref/testhelper_test.go
+++ b/internal/gitaly/service/ref/testhelper_test.go
@@ -82,6 +82,8 @@ func runRefServiceServer(tb testing.TB, cfg config.Cfg) string {
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
})
}
diff --git a/internal/gitaly/service/remote/testhelper_test.go b/internal/gitaly/service/remote/testhelper_test.go
index d1c03eeca..da5681147 100644
--- a/internal/gitaly/service/remote/testhelper_test.go
+++ b/internal/gitaly/service/remote/testhelper_test.go
@@ -41,6 +41,8 @@ func setupRemoteService(t *testing.T, ctx context.Context, opts ...testserver.Gi
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
}, opts...)
cfg.SocketPath = addr
diff --git a/internal/gitaly/service/remote/update_remote_mirror_test.go b/internal/gitaly/service/remote/update_remote_mirror_test.go
index ea007b60f..6a1f58a55 100644
--- a/internal/gitaly/service/remote/update_remote_mirror_test.go
+++ b/internal/gitaly/service/remote/update_remote_mirror_test.go
@@ -589,6 +589,8 @@ func TestUpdateRemoteMirror(t *testing.T) {
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
})
cfg.SocketPath = addr
diff --git a/internal/gitaly/service/repository/backup_repository.go b/internal/gitaly/service/repository/backup_repository.go
new file mode 100644
index 000000000..8e9eea55f
--- /dev/null
+++ b/internal/gitaly/service/repository/backup_repository.go
@@ -0,0 +1,62 @@
+package repository
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ "gitlab.com/gitlab-org/gitaly/v16/internal/backup"
+ "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"
+)
+
+func (s *server) BackupRepository(ctx context.Context, in *gitalypb.BackupRepositoryRequest) (*gitalypb.BackupRepositoryResponse, error) {
+ if s.backupSink == nil || s.backupLocator == nil {
+ return nil, structerr.NewFailedPrecondition("backup repository: server-side backups are not configured")
+ }
+ if err := s.validateBackupRepositoryRequest(in); err != nil {
+ return nil, structerr.NewInvalidArgument("backup repository: %w", err)
+ }
+
+ manager := backup.NewManagerLocal(
+ s.backupSink,
+ s.backupLocator,
+ s.locator,
+ s.gitCmdFactory,
+ s.catfileCache,
+ s.txManager,
+ in.BackupId,
+ )
+
+ err := manager.Create(ctx, &backup.CreateRequest{
+ Repository: in.Repository,
+ VanityRepository: in.VanityRepository,
+ })
+
+ switch {
+ case errors.Is(err, backup.ErrSkipped):
+ return nil, structerr.NewFailedPrecondition("backup repository: %w", err).WithDetail(
+ &gitalypb.BackupRepositoryResponse_SkippedError{},
+ )
+ case err != nil:
+ return nil, structerr.NewInternal("backup repository: %w", err)
+ }
+
+ return &gitalypb.BackupRepositoryResponse{}, nil
+}
+
+func (s *server) validateBackupRepositoryRequest(in *gitalypb.BackupRepositoryRequest) error {
+ if in.GetBackupId() == "" {
+ return fmt.Errorf("empty BackupId")
+ }
+ if err := s.locator.ValidateRepository(in.GetRepository()); err != nil {
+ return err
+ }
+ if err := s.locator.ValidateRepository(in.GetVanityRepository(),
+ storage.WithSkipRepositoryExistenceCheck(),
+ ); err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/internal/gitaly/service/repository/backup_repository_test.go b/internal/gitaly/service/repository/backup_repository_test.go
new file mode 100644
index 000000000..82d76ce91
--- /dev/null
+++ b/internal/gitaly/service/repository/backup_repository_test.go
@@ -0,0 +1,188 @@
+package repository
+
+import (
+ "context"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+ "gitlab.com/gitlab-org/gitaly/v16/internal/backup"
+ "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/config"
+ "gitlab.com/gitlab-org/gitaly/v16/internal/structerr"
+ "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper"
+ "gitlab.com/gitlab-org/gitaly/v16/internal/testhelper/testserver"
+ "gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb"
+)
+
+func TestServerBackupRepository(t *testing.T) {
+ t.Parallel()
+ ctx := testhelper.Context(t)
+
+ type setupData struct {
+ cfg config.Cfg
+ client gitalypb.RepositoryServiceClient
+ repo *gitalypb.Repository
+ backupID string
+ }
+
+ for _, tc := range []struct {
+ desc string
+ setup func(t *testing.T, ctx context.Context, backupSink backup.Sink, backupLocator backup.Locator) setupData
+ expectedErr error
+ }{
+ {
+ desc: "success",
+ setup: func(t *testing.T, ctx context.Context, backupSink backup.Sink, backupLocator backup.Locator) setupData {
+ cfg, client := setupRepositoryServiceWithoutRepo(t,
+ testserver.WithBackupSink(backupSink),
+ testserver.WithBackupLocator(backupLocator),
+ )
+
+ repo, repoPath := gittest.CreateRepository(t, ctx, cfg)
+ gittest.WriteCommit(t, cfg, repoPath, gittest.WithBranch(git.DefaultBranch))
+
+ return setupData{
+ cfg: cfg,
+ client: client,
+ repo: repo,
+ backupID: "abc123",
+ }
+ },
+ },
+ {
+ desc: "missing backup ID",
+ setup: func(t *testing.T, ctx context.Context, backupSink backup.Sink, backupLocator backup.Locator) setupData {
+ cfg, client := setupRepositoryServiceWithoutRepo(t,
+ testserver.WithBackupSink(backupSink),
+ testserver.WithBackupLocator(backupLocator),
+ )
+
+ repo, repoPath := gittest.CreateRepository(t, ctx, cfg)
+ gittest.WriteCommit(t, cfg, repoPath, gittest.WithBranch(git.DefaultBranch))
+
+ return setupData{
+ cfg: cfg,
+ client: client,
+ repo: repo,
+ backupID: "",
+ }
+ },
+ expectedErr: structerr.NewInvalidArgument("backup repository: empty BackupId"),
+ },
+ {
+ desc: "missing repository",
+ setup: func(t *testing.T, ctx context.Context, backupSink backup.Sink, backupLocator backup.Locator) setupData {
+ cfg, client := setupRepositoryServiceWithoutRepo(t,
+ testserver.WithBackupSink(backupSink),
+ testserver.WithBackupLocator(backupLocator),
+ )
+
+ return setupData{
+ cfg: cfg,
+ client: client,
+ repo: nil,
+ backupID: "abc123",
+ }
+ },
+ expectedErr: structerr.NewInvalidArgument(testhelper.GitalyOrPraefect(
+ "backup repository: repository not set",
+ "repo scoped: repository not set",
+ )),
+ },
+ {
+ desc: "repository with no branches",
+ setup: func(t *testing.T, ctx context.Context, backupSink backup.Sink, backupLocator backup.Locator) setupData {
+ cfg, client := setupRepositoryServiceWithoutRepo(t,
+ testserver.WithBackupSink(backupSink),
+ testserver.WithBackupLocator(backupLocator),
+ )
+
+ repo, _ := gittest.CreateRepository(t, ctx, cfg)
+
+ return setupData{
+ cfg: cfg,
+ client: client,
+ repo: repo,
+ backupID: "abc123",
+ }
+ },
+ expectedErr: structerr.NewFailedPrecondition("backup repository: manager: repository empty: repository skipped").WithDetail(
+ &gitalypb.BackupRepositoryResponse_SkippedError{},
+ ),
+ },
+ {
+ desc: "missing backup sink",
+ setup: func(t *testing.T, ctx context.Context, backupSink backup.Sink, backupLocator backup.Locator) setupData {
+ cfg, client := setupRepositoryServiceWithoutRepo(t,
+ testserver.WithBackupLocator(backupLocator),
+ )
+
+ repo, _ := gittest.CreateRepository(t, ctx, cfg)
+
+ return setupData{
+ cfg: cfg,
+ client: client,
+ repo: repo,
+ backupID: "abc123",
+ }
+ },
+ expectedErr: structerr.NewFailedPrecondition("backup repository: server-side backups are not configured"),
+ },
+ {
+ desc: "missing backup locator",
+ setup: func(t *testing.T, ctx context.Context, backupSink backup.Sink, backupLocator backup.Locator) setupData {
+ cfg, client := setupRepositoryServiceWithoutRepo(t,
+ testserver.WithBackupSink(backupSink),
+ )
+
+ repo, _ := gittest.CreateRepository(t, ctx, cfg)
+
+ return setupData{
+ cfg: cfg,
+ client: client,
+ repo: repo,
+ backupID: "abc123",
+ }
+ },
+ expectedErr: structerr.NewFailedPrecondition("backup repository: server-side backups are not configured"),
+ },
+ } {
+ tc := tc
+
+ t.Run(tc.desc, func(t *testing.T) {
+ t.Parallel()
+
+ backupRoot := testhelper.TempDir(t)
+ backupSink, err := backup.ResolveSink(ctx, backupRoot)
+ require.NoError(t, err)
+
+ backupLocator, err := backup.ResolveLocator("pointer", backupSink)
+ require.NoError(t, err)
+
+ data := tc.setup(t, ctx, backupSink, backupLocator)
+
+ response, err := data.client.BackupRepository(ctx, &gitalypb.BackupRepositoryRequest{
+ Repository: data.repo,
+ VanityRepository: data.repo,
+ BackupId: data.backupID,
+ })
+ if tc.expectedErr != nil {
+ testhelper.RequireGrpcError(t, tc.expectedErr, err)
+ return
+ }
+
+ require.NoError(t, err)
+ testhelper.ProtoEqual(t, &gitalypb.BackupRepositoryResponse{}, response)
+
+ relativePath := strings.TrimSuffix(data.repo.GetRelativePath(), ".git")
+ bundlePath := filepath.Join(relativePath, data.backupID, "001.bundle")
+
+ bundle, err := backupSink.GetReader(ctx, bundlePath)
+ require.NoError(t, err)
+ testhelper.MustClose(t, bundle)
+ })
+ }
+}
diff --git a/internal/gitaly/service/repository/server.go b/internal/gitaly/service/repository/server.go
index efaa0e929..0265fadb6 100644
--- a/internal/gitaly/service/repository/server.go
+++ b/internal/gitaly/service/repository/server.go
@@ -4,6 +4,7 @@ import (
"context"
"gitlab.com/gitlab-org/gitaly/v16/client"
+ "gitlab.com/gitlab-org/gitaly/v16/internal/backup"
"gitlab.com/gitlab-org/gitaly/v16/internal/git"
"gitlab.com/gitlab-org/gitaly/v16/internal/git/catfile"
"gitlab.com/gitlab-org/gitaly/v16/internal/git/housekeeping"
@@ -29,6 +30,8 @@ type server struct {
catfileCache catfile.Cache
git2goExecutor *git2go.Executor
housekeepingManager housekeeping.Manager
+ backupSink backup.Sink
+ backupLocator backup.Locator
licenseCache *unarycache.Cache[git.ObjectID, *gitalypb.FindLicenseResponse]
}
@@ -43,6 +46,8 @@ func NewServer(
connsPool *client.Pool,
git2goExecutor *git2go.Executor,
housekeepingManager housekeeping.Manager,
+ backupSink backup.Sink,
+ backupLocator backup.Locator,
) gitalypb.RepositoryServiceServer {
return &server{
locator: locator,
@@ -54,6 +59,8 @@ func NewServer(
catfileCache: catfileCache,
git2goExecutor: git2goExecutor,
housekeepingManager: housekeepingManager,
+ backupSink: backupSink,
+ backupLocator: backupLocator,
licenseCache: newLicenseCache(),
}
diff --git a/internal/gitaly/service/repository/testhelper_test.go b/internal/gitaly/service/repository/testhelper_test.go
index 5df7c55b4..757fb0f7d 100644
--- a/internal/gitaly/service/repository/testhelper_test.go
+++ b/internal/gitaly/service/repository/testhelper_test.go
@@ -66,6 +66,8 @@ func runRepositoryService(tb testing.TB, cfg config.Cfg, opts ...testserver.Gita
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
gitalypb.RegisterHookServiceServer(srv, hookservice.NewServer(
deps.GetHookManager(),
diff --git a/internal/gitaly/service/setup/register.go b/internal/gitaly/service/setup/register.go
index a9a50863f..a51219a76 100644
--- a/internal/gitaly/service/setup/register.go
+++ b/internal/gitaly/service/setup/register.go
@@ -99,6 +99,8 @@ func RegisterAll(srv *grpc.Server, deps *service.Dependencies) {
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
gitalypb.RegisterSSHServiceServer(srv, ssh.NewServer(
deps.GetLocator(),
diff --git a/internal/gitaly/service/smarthttp/testhelper_test.go b/internal/gitaly/service/smarthttp/testhelper_test.go
index cb55094d1..585a4bc6a 100644
--- a/internal/gitaly/service/smarthttp/testhelper_test.go
+++ b/internal/gitaly/service/smarthttp/testhelper_test.go
@@ -46,6 +46,8 @@ func startSmartHTTPServerWithOptions(t *testing.T, cfg config.Cfg, opts []Server
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
gitalypb.RegisterObjectPoolServiceServer(srv, objectpool.NewServer(
deps.GetLocator(),
diff --git a/internal/gitaly/service/ssh/testhelper_test.go b/internal/gitaly/service/ssh/testhelper_test.go
index f869ccbcb..c7ededf68 100644
--- a/internal/gitaly/service/ssh/testhelper_test.go
+++ b/internal/gitaly/service/ssh/testhelper_test.go
@@ -52,6 +52,8 @@ func startSSHServerWithOptions(t *testing.T, cfg config.Cfg, opts []ServerOpt, s
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
gitalypb.RegisterObjectPoolServiceServer(srv, objectpool.NewServer(
deps.GetLocator(),
diff --git a/internal/praefect/info_service_test.go b/internal/praefect/info_service_test.go
index 882f95f4f..45cf4c589 100644
--- a/internal/praefect/info_service_test.go
+++ b/internal/praefect/info_service_test.go
@@ -45,6 +45,8 @@ func TestInfoService_RepositoryReplicas(t *testing.T) {
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
))
}, testserver.WithDisablePraefect())
cfgNodes = append(cfgNodes, &config.Node{
diff --git a/internal/praefect/verifier_test.go b/internal/praefect/verifier_test.go
index f7938c34a..d4f6a1ca2 100644
--- a/internal/praefect/verifier_test.go
+++ b/internal/praefect/verifier_test.go
@@ -486,6 +486,8 @@ func TestVerifier(t *testing.T) {
deps.GetConnsPool(),
deps.GetGit2goExecutor(),
deps.GetHousekeepingManager(),
+ deps.GetBackupSink(),
+ deps.GetBackupLocator(),
)})
}
}
diff --git a/internal/testhelper/testserver/gitaly.go b/internal/testhelper/testserver/gitaly.go
index f515249d0..251b037b4 100644
--- a/internal/testhelper/testserver/gitaly.go
+++ b/internal/testhelper/testserver/gitaly.go
@@ -11,6 +11,7 @@ import (
"github.com/stretchr/testify/require"
gitalyauth "gitlab.com/gitlab-org/gitaly/v16/auth"
"gitlab.com/gitlab-org/gitaly/v16/client"
+ "gitlab.com/gitlab-org/gitaly/v16/internal/backup"
"gitlab.com/gitlab-org/gitaly/v16/internal/cache"
"gitlab.com/gitlab-org/gitaly/v16/internal/git"
"gitlab.com/gitlab-org/gitaly/v16/internal/git/catfile"
@@ -268,6 +269,8 @@ type gitalyServerDeps struct {
git2goExecutor *git2go.Executor
updaterWithHooks *updateref.UpdaterWithHooks
housekeepingManager housekeeping.Manager
+ backupSink backup.Sink
+ backupLocator backup.Locator
}
func (gsd *gitalyServerDeps) createDependencies(tb testing.TB, cfg config.Cfg) *service.Dependencies {
@@ -382,6 +385,8 @@ func (gsd *gitalyServerDeps) createDependencies(tb testing.TB, cfg config.Cfg) *
UpdaterWithHooks: gsd.updaterWithHooks,
HousekeepingManager: gsd.housekeepingManager,
PartitionManager: partitionManager,
+ BackupSink: gsd.backupSink,
+ BackupLocator: gsd.backupLocator,
}
}
@@ -487,3 +492,19 @@ func WithHousekeepingManager(manager housekeeping.Manager) GitalyServerOpt {
return deps
}
}
+
+// WithBackupSink sets the backup.Sink that will be used for Gitaly services
+func WithBackupSink(backupSink backup.Sink) GitalyServerOpt {
+ return func(deps gitalyServerDeps) gitalyServerDeps {
+ deps.backupSink = backupSink
+ return deps
+ }
+}
+
+// WithBackupLocator sets the backup.Locator that will be used for Gitaly services
+func WithBackupLocator(backupLocator backup.Locator) GitalyServerOpt {
+ return func(deps gitalyServerDeps) gitalyServerDeps {
+ deps.backupLocator = backupLocator
+ return deps
+ }
+}
diff --git a/proto/go/gitalypb/repository.pb.go b/proto/go/gitalypb/repository.pb.go
index 9cac82eb7..5ac1b82f7 100644
--- a/proto/go/gitalypb/repository.pb.go
+++ b/proto/go/gitalypb/repository.pb.go
@@ -4762,6 +4762,112 @@ func (*RemoveAllResponse) Descriptor() ([]byte, []int) {
return file_repository_proto_rawDescGZIP(), []int{82}
}
+// BackupRepository is a request for the BackupRepository RPC.
+type BackupRepositoryRequest struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // Repository is the repository to be backed up.
+ Repository *Repository `protobuf:"bytes,1,opt,name=repository,proto3" json:"repository,omitempty"`
+ // VanityRepository is used to determine the backup path.
+ VanityRepository *Repository `protobuf:"bytes,2,opt,name=vanity_repository,json=vanityRepository,proto3" json:"vanity_repository,omitempty"`
+ // BackupId is the label used to identify this backup when restoring.
+ BackupId string `protobuf:"bytes,3,opt,name=backup_id,json=backupId,proto3" json:"backup_id,omitempty"`
+}
+
+func (x *BackupRepositoryRequest) Reset() {
+ *x = BackupRepositoryRequest{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_repository_proto_msgTypes[83]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *BackupRepositoryRequest) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*BackupRepositoryRequest) ProtoMessage() {}
+
+func (x *BackupRepositoryRequest) ProtoReflect() protoreflect.Message {
+ mi := &file_repository_proto_msgTypes[83]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use BackupRepositoryRequest.ProtoReflect.Descriptor instead.
+func (*BackupRepositoryRequest) Descriptor() ([]byte, []int) {
+ return file_repository_proto_rawDescGZIP(), []int{83}
+}
+
+func (x *BackupRepositoryRequest) GetRepository() *Repository {
+ if x != nil {
+ return x.Repository
+ }
+ return nil
+}
+
+func (x *BackupRepositoryRequest) GetVanityRepository() *Repository {
+ if x != nil {
+ return x.VanityRepository
+ }
+ return nil
+}
+
+func (x *BackupRepositoryRequest) GetBackupId() string {
+ if x != nil {
+ return x.BackupId
+ }
+ return ""
+}
+
+// BackupRepositoryResponse is a response for the BackupRepository RPC.
+type BackupRepositoryResponse struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *BackupRepositoryResponse) Reset() {
+ *x = BackupRepositoryResponse{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_repository_proto_msgTypes[84]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *BackupRepositoryResponse) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*BackupRepositoryResponse) ProtoMessage() {}
+
+func (x *BackupRepositoryResponse) ProtoReflect() protoreflect.Message {
+ mi := &file_repository_proto_msgTypes[84]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use BackupRepositoryResponse.ProtoReflect.Descriptor instead.
+func (*BackupRepositoryResponse) Descriptor() ([]byte, []int) {
+ return file_repository_proto_rawDescGZIP(), []int{84}
+}
+
// ReferencesInfo hosts information about references.
type RepositoryInfoResponse_ReferencesInfo struct {
state protoimpl.MessageState
@@ -4786,7 +4892,7 @@ type RepositoryInfoResponse_ReferencesInfo struct {
func (x *RepositoryInfoResponse_ReferencesInfo) Reset() {
*x = RepositoryInfoResponse_ReferencesInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_repository_proto_msgTypes[83]
+ mi := &file_repository_proto_msgTypes[85]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -4799,7 +4905,7 @@ func (x *RepositoryInfoResponse_ReferencesInfo) String() string {
func (*RepositoryInfoResponse_ReferencesInfo) ProtoMessage() {}
func (x *RepositoryInfoResponse_ReferencesInfo) ProtoReflect() protoreflect.Message {
- mi := &file_repository_proto_msgTypes[83]
+ mi := &file_repository_proto_msgTypes[85]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -4865,7 +4971,7 @@ type RepositoryInfoResponse_ObjectsInfo struct {
func (x *RepositoryInfoResponse_ObjectsInfo) Reset() {
*x = RepositoryInfoResponse_ObjectsInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_repository_proto_msgTypes[84]
+ mi := &file_repository_proto_msgTypes[86]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -4878,7 +4984,7 @@ func (x *RepositoryInfoResponse_ObjectsInfo) String() string {
func (*RepositoryInfoResponse_ObjectsInfo) ProtoMessage() {}
func (x *RepositoryInfoResponse_ObjectsInfo) ProtoReflect() protoreflect.Message {
- mi := &file_repository_proto_msgTypes[84]
+ mi := &file_repository_proto_msgTypes[86]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -4949,7 +5055,7 @@ type GetRawChangesResponse_RawChange struct {
func (x *GetRawChangesResponse_RawChange) Reset() {
*x = GetRawChangesResponse_RawChange{}
if protoimpl.UnsafeEnabled {
- mi := &file_repository_proto_msgTypes[85]
+ mi := &file_repository_proto_msgTypes[87]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -4962,7 +5068,7 @@ func (x *GetRawChangesResponse_RawChange) String() string {
func (*GetRawChangesResponse_RawChange) ProtoMessage() {}
func (x *GetRawChangesResponse_RawChange) ProtoReflect() protoreflect.Message {
- mi := &file_repository_proto_msgTypes[85]
+ mi := &file_repository_proto_msgTypes[87]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -5034,6 +5140,45 @@ func (x *GetRawChangesResponse_RawChange) GetOldPathBytes() []byte {
return nil
}
+// SkippedError is returned when the repository backup has been skipped.
+type BackupRepositoryResponse_SkippedError struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *BackupRepositoryResponse_SkippedError) Reset() {
+ *x = BackupRepositoryResponse_SkippedError{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_repository_proto_msgTypes[88]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *BackupRepositoryResponse_SkippedError) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*BackupRepositoryResponse_SkippedError) ProtoMessage() {}
+
+func (x *BackupRepositoryResponse_SkippedError) ProtoReflect() protoreflect.Message {
+ mi := &file_repository_proto_msgTypes[88]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use BackupRepositoryResponse_SkippedError.ProtoReflect.Descriptor instead.
+func (*BackupRepositoryResponse_SkippedError) Descriptor() ([]byte, []int) {
+ return file_repository_proto_rawDescGZIP(), []int{84, 0}
+}
+
var File_repository_proto protoreflect.FileDescriptor
var file_repository_proto_rawDesc = []byte{
@@ -5564,7 +5709,21 @@ var file_repository_proto_rawDesc = []byte{
0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x4e,
0x61, 0x6d, 0x65, 0x22, 0x13, 0x0a, 0x11, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x41, 0x6c, 0x6c,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0x8f, 0x1e, 0x0a, 0x11, 0x52, 0x65, 0x70,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb1, 0x01, 0x0a, 0x17, 0x42, 0x61, 0x63,
+ 0x6b, 0x75, 0x70, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71,
+ 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
+ 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c,
+ 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x42, 0x04, 0x98, 0xc6,
+ 0x2c, 0x01, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x3f,
+ 0x0a, 0x11, 0x76, 0x61, 0x6e, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
+ 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61,
+ 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x10, 0x76,
+ 0x61, 0x6e, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12,
+ 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x09, 0x52, 0x08, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x49, 0x64, 0x22, 0x2a, 0x0a, 0x18,
+ 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x0e, 0x0a, 0x0c, 0x53, 0x6b, 0x69, 0x70,
+ 0x70, 0x65, 0x64, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x32, 0xee, 0x1e, 0x0a, 0x11, 0x52, 0x65, 0x70,
0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d,
0x0a, 0x10, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x45, 0x78, 0x69, 0x73,
0x74, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f,
@@ -5805,11 +5964,17 @@ var file_repository_proto_rawDesc = []byte{
0x18, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x41,
0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x69, 0x74, 0x61,
0x6c, 0x79, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x73, 0x70,
- 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x80, 0x98, 0x28, 0x01, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69,
- 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2d,
- 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2f, 0x76, 0x31, 0x36, 0x2f, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x70, 0x62,
- 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+ 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x04, 0x80, 0x98, 0x28, 0x01, 0x12, 0x5d, 0x0a, 0x10, 0x42, 0x61,
+ 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x1f,
+ 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52, 0x65,
+ 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+ 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x42, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x52,
+ 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+ 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74,
+ 0x6c, 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2d, 0x6f,
+ 0x72, 0x67, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2f, 0x76, 0x31, 0x36, 0x2f, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x70, 0x62, 0x62,
+ 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -5825,7 +5990,7 @@ func file_repository_proto_rawDescGZIP() []byte {
}
var file_repository_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
-var file_repository_proto_msgTypes = make([]protoimpl.MessageInfo, 86)
+var file_repository_proto_msgTypes = make([]protoimpl.MessageInfo, 89)
var file_repository_proto_goTypes = []interface{}{
(GetArchiveRequest_Format)(0), // 0: gitaly.GetArchiveRequest.Format
(GetRawChangesResponse_RawChange_Operation)(0), // 1: gitaly.GetRawChangesResponse.RawChange.Operation
@@ -5913,152 +6078,159 @@ var file_repository_proto_goTypes = []interface{}{
(*FullPathResponse)(nil), // 83: gitaly.FullPathResponse
(*RemoveAllRequest)(nil), // 84: gitaly.RemoveAllRequest
(*RemoveAllResponse)(nil), // 85: gitaly.RemoveAllResponse
- (*RepositoryInfoResponse_ReferencesInfo)(nil), // 86: gitaly.RepositoryInfoResponse.ReferencesInfo
- (*RepositoryInfoResponse_ObjectsInfo)(nil), // 87: gitaly.RepositoryInfoResponse.ObjectsInfo
- (*GetRawChangesResponse_RawChange)(nil), // 88: gitaly.GetRawChangesResponse.RawChange
- (*Repository)(nil), // 89: gitaly.Repository
- (ObjectFormat)(0), // 90: gitaly.ObjectFormat
+ (*BackupRepositoryRequest)(nil), // 86: gitaly.BackupRepositoryRequest
+ (*BackupRepositoryResponse)(nil), // 87: gitaly.BackupRepositoryResponse
+ (*RepositoryInfoResponse_ReferencesInfo)(nil), // 88: gitaly.RepositoryInfoResponse.ReferencesInfo
+ (*RepositoryInfoResponse_ObjectsInfo)(nil), // 89: gitaly.RepositoryInfoResponse.ObjectsInfo
+ (*GetRawChangesResponse_RawChange)(nil), // 90: gitaly.GetRawChangesResponse.RawChange
+ (*BackupRepositoryResponse_SkippedError)(nil), // 91: gitaly.BackupRepositoryResponse.SkippedError
+ (*Repository)(nil), // 92: gitaly.Repository
+ (ObjectFormat)(0), // 93: gitaly.ObjectFormat
}
var file_repository_proto_depIdxs = []int32{
- 89, // 0: gitaly.RepositoryExistsRequest.repository:type_name -> gitaly.Repository
- 89, // 1: gitaly.RepositorySizeRequest.repository:type_name -> gitaly.Repository
- 89, // 2: gitaly.RepositoryInfoRequest.repository:type_name -> gitaly.Repository
- 86, // 3: gitaly.RepositoryInfoResponse.references:type_name -> gitaly.RepositoryInfoResponse.ReferencesInfo
- 87, // 4: gitaly.RepositoryInfoResponse.objects:type_name -> gitaly.RepositoryInfoResponse.ObjectsInfo
- 89, // 5: gitaly.ObjectFormatRequest.repository:type_name -> gitaly.Repository
- 90, // 6: gitaly.ObjectFormatResponse.format:type_name -> gitaly.ObjectFormat
- 89, // 7: gitaly.ApplyGitattributesRequest.repository:type_name -> gitaly.Repository
- 89, // 8: gitaly.FetchBundleRequest.repository:type_name -> gitaly.Repository
- 89, // 9: gitaly.FetchRemoteRequest.repository:type_name -> gitaly.Repository
+ 92, // 0: gitaly.RepositoryExistsRequest.repository:type_name -> gitaly.Repository
+ 92, // 1: gitaly.RepositorySizeRequest.repository:type_name -> gitaly.Repository
+ 92, // 2: gitaly.RepositoryInfoRequest.repository:type_name -> gitaly.Repository
+ 88, // 3: gitaly.RepositoryInfoResponse.references:type_name -> gitaly.RepositoryInfoResponse.ReferencesInfo
+ 89, // 4: gitaly.RepositoryInfoResponse.objects:type_name -> gitaly.RepositoryInfoResponse.ObjectsInfo
+ 92, // 5: gitaly.ObjectFormatRequest.repository:type_name -> gitaly.Repository
+ 93, // 6: gitaly.ObjectFormatResponse.format:type_name -> gitaly.ObjectFormat
+ 92, // 7: gitaly.ApplyGitattributesRequest.repository:type_name -> gitaly.Repository
+ 92, // 8: gitaly.FetchBundleRequest.repository:type_name -> gitaly.Repository
+ 92, // 9: gitaly.FetchRemoteRequest.repository:type_name -> gitaly.Repository
67, // 10: gitaly.FetchRemoteRequest.remote_params:type_name -> gitaly.Remote
- 89, // 11: gitaly.CreateRepositoryRequest.repository:type_name -> gitaly.Repository
- 90, // 12: gitaly.CreateRepositoryRequest.object_format:type_name -> gitaly.ObjectFormat
- 89, // 13: gitaly.GetArchiveRequest.repository:type_name -> gitaly.Repository
+ 92, // 11: gitaly.CreateRepositoryRequest.repository:type_name -> gitaly.Repository
+ 93, // 12: gitaly.CreateRepositoryRequest.object_format:type_name -> gitaly.ObjectFormat
+ 92, // 13: gitaly.GetArchiveRequest.repository:type_name -> gitaly.Repository
0, // 14: gitaly.GetArchiveRequest.format:type_name -> gitaly.GetArchiveRequest.Format
- 89, // 15: gitaly.HasLocalBranchesRequest.repository:type_name -> gitaly.Repository
- 89, // 16: gitaly.FetchSourceBranchRequest.repository:type_name -> gitaly.Repository
- 89, // 17: gitaly.FetchSourceBranchRequest.source_repository:type_name -> gitaly.Repository
- 89, // 18: gitaly.FsckRequest.repository:type_name -> gitaly.Repository
- 89, // 19: gitaly.WriteRefRequest.repository:type_name -> gitaly.Repository
- 89, // 20: gitaly.FindMergeBaseRequest.repository:type_name -> gitaly.Repository
- 89, // 21: gitaly.CreateForkRequest.repository:type_name -> gitaly.Repository
- 89, // 22: gitaly.CreateForkRequest.source_repository:type_name -> gitaly.Repository
- 89, // 23: gitaly.CreateRepositoryFromURLRequest.repository:type_name -> gitaly.Repository
- 89, // 24: gitaly.CreateBundleRequest.repository:type_name -> gitaly.Repository
- 89, // 25: gitaly.CreateBundleFromRefListRequest.repository:type_name -> gitaly.Repository
- 89, // 26: gitaly.GetConfigRequest.repository:type_name -> gitaly.Repository
- 89, // 27: gitaly.RestoreCustomHooksRequest.repository:type_name -> gitaly.Repository
- 89, // 28: gitaly.SetCustomHooksRequest.repository:type_name -> gitaly.Repository
- 89, // 29: gitaly.BackupCustomHooksRequest.repository:type_name -> gitaly.Repository
- 89, // 30: gitaly.GetCustomHooksRequest.repository:type_name -> gitaly.Repository
- 89, // 31: gitaly.CreateRepositoryFromBundleRequest.repository:type_name -> gitaly.Repository
- 89, // 32: gitaly.FindLicenseRequest.repository:type_name -> gitaly.Repository
- 89, // 33: gitaly.GetInfoAttributesRequest.repository:type_name -> gitaly.Repository
- 89, // 34: gitaly.CalculateChecksumRequest.repository:type_name -> gitaly.Repository
- 89, // 35: gitaly.GetSnapshotRequest.repository:type_name -> gitaly.Repository
- 89, // 36: gitaly.CreateRepositoryFromSnapshotRequest.repository:type_name -> gitaly.Repository
- 89, // 37: gitaly.GetRawChangesRequest.repository:type_name -> gitaly.Repository
- 88, // 38: gitaly.GetRawChangesResponse.raw_changes:type_name -> gitaly.GetRawChangesResponse.RawChange
- 89, // 39: gitaly.SearchFilesByNameRequest.repository:type_name -> gitaly.Repository
- 89, // 40: gitaly.SearchFilesByContentRequest.repository:type_name -> gitaly.Repository
- 89, // 41: gitaly.GetObjectDirectorySizeRequest.repository:type_name -> gitaly.Repository
- 89, // 42: gitaly.RemoveRepositoryRequest.repository:type_name -> gitaly.Repository
- 89, // 43: gitaly.RenameRepositoryRequest.repository:type_name -> gitaly.Repository
- 89, // 44: gitaly.ReplicateRepositoryRequest.repository:type_name -> gitaly.Repository
- 89, // 45: gitaly.ReplicateRepositoryRequest.source:type_name -> gitaly.Repository
- 89, // 46: gitaly.OptimizeRepositoryRequest.repository:type_name -> gitaly.Repository
+ 92, // 15: gitaly.HasLocalBranchesRequest.repository:type_name -> gitaly.Repository
+ 92, // 16: gitaly.FetchSourceBranchRequest.repository:type_name -> gitaly.Repository
+ 92, // 17: gitaly.FetchSourceBranchRequest.source_repository:type_name -> gitaly.Repository
+ 92, // 18: gitaly.FsckRequest.repository:type_name -> gitaly.Repository
+ 92, // 19: gitaly.WriteRefRequest.repository:type_name -> gitaly.Repository
+ 92, // 20: gitaly.FindMergeBaseRequest.repository:type_name -> gitaly.Repository
+ 92, // 21: gitaly.CreateForkRequest.repository:type_name -> gitaly.Repository
+ 92, // 22: gitaly.CreateForkRequest.source_repository:type_name -> gitaly.Repository
+ 92, // 23: gitaly.CreateRepositoryFromURLRequest.repository:type_name -> gitaly.Repository
+ 92, // 24: gitaly.CreateBundleRequest.repository:type_name -> gitaly.Repository
+ 92, // 25: gitaly.CreateBundleFromRefListRequest.repository:type_name -> gitaly.Repository
+ 92, // 26: gitaly.GetConfigRequest.repository:type_name -> gitaly.Repository
+ 92, // 27: gitaly.RestoreCustomHooksRequest.repository:type_name -> gitaly.Repository
+ 92, // 28: gitaly.SetCustomHooksRequest.repository:type_name -> gitaly.Repository
+ 92, // 29: gitaly.BackupCustomHooksRequest.repository:type_name -> gitaly.Repository
+ 92, // 30: gitaly.GetCustomHooksRequest.repository:type_name -> gitaly.Repository
+ 92, // 31: gitaly.CreateRepositoryFromBundleRequest.repository:type_name -> gitaly.Repository
+ 92, // 32: gitaly.FindLicenseRequest.repository:type_name -> gitaly.Repository
+ 92, // 33: gitaly.GetInfoAttributesRequest.repository:type_name -> gitaly.Repository
+ 92, // 34: gitaly.CalculateChecksumRequest.repository:type_name -> gitaly.Repository
+ 92, // 35: gitaly.GetSnapshotRequest.repository:type_name -> gitaly.Repository
+ 92, // 36: gitaly.CreateRepositoryFromSnapshotRequest.repository:type_name -> gitaly.Repository
+ 92, // 37: gitaly.GetRawChangesRequest.repository:type_name -> gitaly.Repository
+ 90, // 38: gitaly.GetRawChangesResponse.raw_changes:type_name -> gitaly.GetRawChangesResponse.RawChange
+ 92, // 39: gitaly.SearchFilesByNameRequest.repository:type_name -> gitaly.Repository
+ 92, // 40: gitaly.SearchFilesByContentRequest.repository:type_name -> gitaly.Repository
+ 92, // 41: gitaly.GetObjectDirectorySizeRequest.repository:type_name -> gitaly.Repository
+ 92, // 42: gitaly.RemoveRepositoryRequest.repository:type_name -> gitaly.Repository
+ 92, // 43: gitaly.RenameRepositoryRequest.repository:type_name -> gitaly.Repository
+ 92, // 44: gitaly.ReplicateRepositoryRequest.repository:type_name -> gitaly.Repository
+ 92, // 45: gitaly.ReplicateRepositoryRequest.source:type_name -> gitaly.Repository
+ 92, // 46: gitaly.OptimizeRepositoryRequest.repository:type_name -> gitaly.Repository
2, // 47: gitaly.OptimizeRepositoryRequest.strategy:type_name -> gitaly.OptimizeRepositoryRequest.Strategy
- 89, // 48: gitaly.PruneUnreachableObjectsRequest.repository:type_name -> gitaly.Repository
- 89, // 49: gitaly.SetFullPathRequest.repository:type_name -> gitaly.Repository
- 89, // 50: gitaly.FullPathRequest.repository:type_name -> gitaly.Repository
- 1, // 51: gitaly.GetRawChangesResponse.RawChange.operation:type_name -> gitaly.GetRawChangesResponse.RawChange.Operation
- 3, // 52: gitaly.RepositoryService.RepositoryExists:input_type -> gitaly.RepositoryExistsRequest
- 5, // 53: gitaly.RepositoryService.RepositorySize:input_type -> gitaly.RepositorySizeRequest
- 7, // 54: gitaly.RepositoryService.RepositoryInfo:input_type -> gitaly.RepositoryInfoRequest
- 9, // 55: gitaly.RepositoryService.ObjectFormat:input_type -> gitaly.ObjectFormatRequest
- 11, // 56: gitaly.RepositoryService.ApplyGitattributes:input_type -> gitaly.ApplyGitattributesRequest
- 15, // 57: gitaly.RepositoryService.FetchRemote:input_type -> gitaly.FetchRemoteRequest
- 17, // 58: gitaly.RepositoryService.CreateRepository:input_type -> gitaly.CreateRepositoryRequest
- 19, // 59: gitaly.RepositoryService.GetArchive:input_type -> gitaly.GetArchiveRequest
- 21, // 60: gitaly.RepositoryService.HasLocalBranches:input_type -> gitaly.HasLocalBranchesRequest
- 23, // 61: gitaly.RepositoryService.FetchSourceBranch:input_type -> gitaly.FetchSourceBranchRequest
- 25, // 62: gitaly.RepositoryService.Fsck:input_type -> gitaly.FsckRequest
- 27, // 63: gitaly.RepositoryService.WriteRef:input_type -> gitaly.WriteRefRequest
- 29, // 64: gitaly.RepositoryService.FindMergeBase:input_type -> gitaly.FindMergeBaseRequest
- 31, // 65: gitaly.RepositoryService.CreateFork:input_type -> gitaly.CreateForkRequest
- 33, // 66: gitaly.RepositoryService.CreateRepositoryFromURL:input_type -> gitaly.CreateRepositoryFromURLRequest
- 35, // 67: gitaly.RepositoryService.CreateBundle:input_type -> gitaly.CreateBundleRequest
- 37, // 68: gitaly.RepositoryService.CreateBundleFromRefList:input_type -> gitaly.CreateBundleFromRefListRequest
- 13, // 69: gitaly.RepositoryService.FetchBundle:input_type -> gitaly.FetchBundleRequest
- 49, // 70: gitaly.RepositoryService.CreateRepositoryFromBundle:input_type -> gitaly.CreateRepositoryFromBundleRequest
- 39, // 71: gitaly.RepositoryService.GetConfig:input_type -> gitaly.GetConfigRequest
- 51, // 72: gitaly.RepositoryService.FindLicense:input_type -> gitaly.FindLicenseRequest
- 53, // 73: gitaly.RepositoryService.GetInfoAttributes:input_type -> gitaly.GetInfoAttributesRequest
- 55, // 74: gitaly.RepositoryService.CalculateChecksum:input_type -> gitaly.CalculateChecksumRequest
- 57, // 75: gitaly.RepositoryService.GetSnapshot:input_type -> gitaly.GetSnapshotRequest
- 59, // 76: gitaly.RepositoryService.CreateRepositoryFromSnapshot:input_type -> gitaly.CreateRepositoryFromSnapshotRequest
- 61, // 77: gitaly.RepositoryService.GetRawChanges:input_type -> gitaly.GetRawChangesRequest
- 65, // 78: gitaly.RepositoryService.SearchFilesByContent:input_type -> gitaly.SearchFilesByContentRequest
- 63, // 79: gitaly.RepositoryService.SearchFilesByName:input_type -> gitaly.SearchFilesByNameRequest
- 41, // 80: gitaly.RepositoryService.RestoreCustomHooks:input_type -> gitaly.RestoreCustomHooksRequest
- 42, // 81: gitaly.RepositoryService.SetCustomHooks:input_type -> gitaly.SetCustomHooksRequest
- 45, // 82: gitaly.RepositoryService.BackupCustomHooks:input_type -> gitaly.BackupCustomHooksRequest
- 46, // 83: gitaly.RepositoryService.GetCustomHooks:input_type -> gitaly.GetCustomHooksRequest
- 68, // 84: gitaly.RepositoryService.GetObjectDirectorySize:input_type -> gitaly.GetObjectDirectorySizeRequest
- 70, // 85: gitaly.RepositoryService.RemoveRepository:input_type -> gitaly.RemoveRepositoryRequest
- 72, // 86: gitaly.RepositoryService.RenameRepository:input_type -> gitaly.RenameRepositoryRequest
- 74, // 87: gitaly.RepositoryService.ReplicateRepository:input_type -> gitaly.ReplicateRepositoryRequest
- 76, // 88: gitaly.RepositoryService.OptimizeRepository:input_type -> gitaly.OptimizeRepositoryRequest
- 78, // 89: gitaly.RepositoryService.PruneUnreachableObjects:input_type -> gitaly.PruneUnreachableObjectsRequest
- 80, // 90: gitaly.RepositoryService.SetFullPath:input_type -> gitaly.SetFullPathRequest
- 82, // 91: gitaly.RepositoryService.FullPath:input_type -> gitaly.FullPathRequest
- 84, // 92: gitaly.RepositoryService.RemoveAll:input_type -> gitaly.RemoveAllRequest
- 4, // 93: gitaly.RepositoryService.RepositoryExists:output_type -> gitaly.RepositoryExistsResponse
- 6, // 94: gitaly.RepositoryService.RepositorySize:output_type -> gitaly.RepositorySizeResponse
- 8, // 95: gitaly.RepositoryService.RepositoryInfo:output_type -> gitaly.RepositoryInfoResponse
- 10, // 96: gitaly.RepositoryService.ObjectFormat:output_type -> gitaly.ObjectFormatResponse
- 12, // 97: gitaly.RepositoryService.ApplyGitattributes:output_type -> gitaly.ApplyGitattributesResponse
- 16, // 98: gitaly.RepositoryService.FetchRemote:output_type -> gitaly.FetchRemoteResponse
- 18, // 99: gitaly.RepositoryService.CreateRepository:output_type -> gitaly.CreateRepositoryResponse
- 20, // 100: gitaly.RepositoryService.GetArchive:output_type -> gitaly.GetArchiveResponse
- 22, // 101: gitaly.RepositoryService.HasLocalBranches:output_type -> gitaly.HasLocalBranchesResponse
- 24, // 102: gitaly.RepositoryService.FetchSourceBranch:output_type -> gitaly.FetchSourceBranchResponse
- 26, // 103: gitaly.RepositoryService.Fsck:output_type -> gitaly.FsckResponse
- 28, // 104: gitaly.RepositoryService.WriteRef:output_type -> gitaly.WriteRefResponse
- 30, // 105: gitaly.RepositoryService.FindMergeBase:output_type -> gitaly.FindMergeBaseResponse
- 32, // 106: gitaly.RepositoryService.CreateFork:output_type -> gitaly.CreateForkResponse
- 34, // 107: gitaly.RepositoryService.CreateRepositoryFromURL:output_type -> gitaly.CreateRepositoryFromURLResponse
- 36, // 108: gitaly.RepositoryService.CreateBundle:output_type -> gitaly.CreateBundleResponse
- 38, // 109: gitaly.RepositoryService.CreateBundleFromRefList:output_type -> gitaly.CreateBundleFromRefListResponse
- 14, // 110: gitaly.RepositoryService.FetchBundle:output_type -> gitaly.FetchBundleResponse
- 50, // 111: gitaly.RepositoryService.CreateRepositoryFromBundle:output_type -> gitaly.CreateRepositoryFromBundleResponse
- 40, // 112: gitaly.RepositoryService.GetConfig:output_type -> gitaly.GetConfigResponse
- 52, // 113: gitaly.RepositoryService.FindLicense:output_type -> gitaly.FindLicenseResponse
- 54, // 114: gitaly.RepositoryService.GetInfoAttributes:output_type -> gitaly.GetInfoAttributesResponse
- 56, // 115: gitaly.RepositoryService.CalculateChecksum:output_type -> gitaly.CalculateChecksumResponse
- 58, // 116: gitaly.RepositoryService.GetSnapshot:output_type -> gitaly.GetSnapshotResponse
- 60, // 117: gitaly.RepositoryService.CreateRepositoryFromSnapshot:output_type -> gitaly.CreateRepositoryFromSnapshotResponse
- 62, // 118: gitaly.RepositoryService.GetRawChanges:output_type -> gitaly.GetRawChangesResponse
- 66, // 119: gitaly.RepositoryService.SearchFilesByContent:output_type -> gitaly.SearchFilesByContentResponse
- 64, // 120: gitaly.RepositoryService.SearchFilesByName:output_type -> gitaly.SearchFilesByNameResponse
- 43, // 121: gitaly.RepositoryService.RestoreCustomHooks:output_type -> gitaly.RestoreCustomHooksResponse
- 44, // 122: gitaly.RepositoryService.SetCustomHooks:output_type -> gitaly.SetCustomHooksResponse
- 47, // 123: gitaly.RepositoryService.BackupCustomHooks:output_type -> gitaly.BackupCustomHooksResponse
- 48, // 124: gitaly.RepositoryService.GetCustomHooks:output_type -> gitaly.GetCustomHooksResponse
- 69, // 125: gitaly.RepositoryService.GetObjectDirectorySize:output_type -> gitaly.GetObjectDirectorySizeResponse
- 71, // 126: gitaly.RepositoryService.RemoveRepository:output_type -> gitaly.RemoveRepositoryResponse
- 73, // 127: gitaly.RepositoryService.RenameRepository:output_type -> gitaly.RenameRepositoryResponse
- 75, // 128: gitaly.RepositoryService.ReplicateRepository:output_type -> gitaly.ReplicateRepositoryResponse
- 77, // 129: gitaly.RepositoryService.OptimizeRepository:output_type -> gitaly.OptimizeRepositoryResponse
- 79, // 130: gitaly.RepositoryService.PruneUnreachableObjects:output_type -> gitaly.PruneUnreachableObjectsResponse
- 81, // 131: gitaly.RepositoryService.SetFullPath:output_type -> gitaly.SetFullPathResponse
- 83, // 132: gitaly.RepositoryService.FullPath:output_type -> gitaly.FullPathResponse
- 85, // 133: gitaly.RepositoryService.RemoveAll:output_type -> gitaly.RemoveAllResponse
- 93, // [93:134] is the sub-list for method output_type
- 52, // [52:93] is the sub-list for method input_type
- 52, // [52:52] is the sub-list for extension type_name
- 52, // [52:52] is the sub-list for extension extendee
- 0, // [0:52] is the sub-list for field type_name
+ 92, // 48: gitaly.PruneUnreachableObjectsRequest.repository:type_name -> gitaly.Repository
+ 92, // 49: gitaly.SetFullPathRequest.repository:type_name -> gitaly.Repository
+ 92, // 50: gitaly.FullPathRequest.repository:type_name -> gitaly.Repository
+ 92, // 51: gitaly.BackupRepositoryRequest.repository:type_name -> gitaly.Repository
+ 92, // 52: gitaly.BackupRepositoryRequest.vanity_repository:type_name -> gitaly.Repository
+ 1, // 53: gitaly.GetRawChangesResponse.RawChange.operation:type_name -> gitaly.GetRawChangesResponse.RawChange.Operation
+ 3, // 54: gitaly.RepositoryService.RepositoryExists:input_type -> gitaly.RepositoryExistsRequest
+ 5, // 55: gitaly.RepositoryService.RepositorySize:input_type -> gitaly.RepositorySizeRequest
+ 7, // 56: gitaly.RepositoryService.RepositoryInfo:input_type -> gitaly.RepositoryInfoRequest
+ 9, // 57: gitaly.RepositoryService.ObjectFormat:input_type -> gitaly.ObjectFormatRequest
+ 11, // 58: gitaly.RepositoryService.ApplyGitattributes:input_type -> gitaly.ApplyGitattributesRequest
+ 15, // 59: gitaly.RepositoryService.FetchRemote:input_type -> gitaly.FetchRemoteRequest
+ 17, // 60: gitaly.RepositoryService.CreateRepository:input_type -> gitaly.CreateRepositoryRequest
+ 19, // 61: gitaly.RepositoryService.GetArchive:input_type -> gitaly.GetArchiveRequest
+ 21, // 62: gitaly.RepositoryService.HasLocalBranches:input_type -> gitaly.HasLocalBranchesRequest
+ 23, // 63: gitaly.RepositoryService.FetchSourceBranch:input_type -> gitaly.FetchSourceBranchRequest
+ 25, // 64: gitaly.RepositoryService.Fsck:input_type -> gitaly.FsckRequest
+ 27, // 65: gitaly.RepositoryService.WriteRef:input_type -> gitaly.WriteRefRequest
+ 29, // 66: gitaly.RepositoryService.FindMergeBase:input_type -> gitaly.FindMergeBaseRequest
+ 31, // 67: gitaly.RepositoryService.CreateFork:input_type -> gitaly.CreateForkRequest
+ 33, // 68: gitaly.RepositoryService.CreateRepositoryFromURL:input_type -> gitaly.CreateRepositoryFromURLRequest
+ 35, // 69: gitaly.RepositoryService.CreateBundle:input_type -> gitaly.CreateBundleRequest
+ 37, // 70: gitaly.RepositoryService.CreateBundleFromRefList:input_type -> gitaly.CreateBundleFromRefListRequest
+ 13, // 71: gitaly.RepositoryService.FetchBundle:input_type -> gitaly.FetchBundleRequest
+ 49, // 72: gitaly.RepositoryService.CreateRepositoryFromBundle:input_type -> gitaly.CreateRepositoryFromBundleRequest
+ 39, // 73: gitaly.RepositoryService.GetConfig:input_type -> gitaly.GetConfigRequest
+ 51, // 74: gitaly.RepositoryService.FindLicense:input_type -> gitaly.FindLicenseRequest
+ 53, // 75: gitaly.RepositoryService.GetInfoAttributes:input_type -> gitaly.GetInfoAttributesRequest
+ 55, // 76: gitaly.RepositoryService.CalculateChecksum:input_type -> gitaly.CalculateChecksumRequest
+ 57, // 77: gitaly.RepositoryService.GetSnapshot:input_type -> gitaly.GetSnapshotRequest
+ 59, // 78: gitaly.RepositoryService.CreateRepositoryFromSnapshot:input_type -> gitaly.CreateRepositoryFromSnapshotRequest
+ 61, // 79: gitaly.RepositoryService.GetRawChanges:input_type -> gitaly.GetRawChangesRequest
+ 65, // 80: gitaly.RepositoryService.SearchFilesByContent:input_type -> gitaly.SearchFilesByContentRequest
+ 63, // 81: gitaly.RepositoryService.SearchFilesByName:input_type -> gitaly.SearchFilesByNameRequest
+ 41, // 82: gitaly.RepositoryService.RestoreCustomHooks:input_type -> gitaly.RestoreCustomHooksRequest
+ 42, // 83: gitaly.RepositoryService.SetCustomHooks:input_type -> gitaly.SetCustomHooksRequest
+ 45, // 84: gitaly.RepositoryService.BackupCustomHooks:input_type -> gitaly.BackupCustomHooksRequest
+ 46, // 85: gitaly.RepositoryService.GetCustomHooks:input_type -> gitaly.GetCustomHooksRequest
+ 68, // 86: gitaly.RepositoryService.GetObjectDirectorySize:input_type -> gitaly.GetObjectDirectorySizeRequest
+ 70, // 87: gitaly.RepositoryService.RemoveRepository:input_type -> gitaly.RemoveRepositoryRequest
+ 72, // 88: gitaly.RepositoryService.RenameRepository:input_type -> gitaly.RenameRepositoryRequest
+ 74, // 89: gitaly.RepositoryService.ReplicateRepository:input_type -> gitaly.ReplicateRepositoryRequest
+ 76, // 90: gitaly.RepositoryService.OptimizeRepository:input_type -> gitaly.OptimizeRepositoryRequest
+ 78, // 91: gitaly.RepositoryService.PruneUnreachableObjects:input_type -> gitaly.PruneUnreachableObjectsRequest
+ 80, // 92: gitaly.RepositoryService.SetFullPath:input_type -> gitaly.SetFullPathRequest
+ 82, // 93: gitaly.RepositoryService.FullPath:input_type -> gitaly.FullPathRequest
+ 84, // 94: gitaly.RepositoryService.RemoveAll:input_type -> gitaly.RemoveAllRequest
+ 86, // 95: gitaly.RepositoryService.BackupRepository:input_type -> gitaly.BackupRepositoryRequest
+ 4, // 96: gitaly.RepositoryService.RepositoryExists:output_type -> gitaly.RepositoryExistsResponse
+ 6, // 97: gitaly.RepositoryService.RepositorySize:output_type -> gitaly.RepositorySizeResponse
+ 8, // 98: gitaly.RepositoryService.RepositoryInfo:output_type -> gitaly.RepositoryInfoResponse
+ 10, // 99: gitaly.RepositoryService.ObjectFormat:output_type -> gitaly.ObjectFormatResponse
+ 12, // 100: gitaly.RepositoryService.ApplyGitattributes:output_type -> gitaly.ApplyGitattributesResponse
+ 16, // 101: gitaly.RepositoryService.FetchRemote:output_type -> gitaly.FetchRemoteResponse
+ 18, // 102: gitaly.RepositoryService.CreateRepository:output_type -> gitaly.CreateRepositoryResponse
+ 20, // 103: gitaly.RepositoryService.GetArchive:output_type -> gitaly.GetArchiveResponse
+ 22, // 104: gitaly.RepositoryService.HasLocalBranches:output_type -> gitaly.HasLocalBranchesResponse
+ 24, // 105: gitaly.RepositoryService.FetchSourceBranch:output_type -> gitaly.FetchSourceBranchResponse
+ 26, // 106: gitaly.RepositoryService.Fsck:output_type -> gitaly.FsckResponse
+ 28, // 107: gitaly.RepositoryService.WriteRef:output_type -> gitaly.WriteRefResponse
+ 30, // 108: gitaly.RepositoryService.FindMergeBase:output_type -> gitaly.FindMergeBaseResponse
+ 32, // 109: gitaly.RepositoryService.CreateFork:output_type -> gitaly.CreateForkResponse
+ 34, // 110: gitaly.RepositoryService.CreateRepositoryFromURL:output_type -> gitaly.CreateRepositoryFromURLResponse
+ 36, // 111: gitaly.RepositoryService.CreateBundle:output_type -> gitaly.CreateBundleResponse
+ 38, // 112: gitaly.RepositoryService.CreateBundleFromRefList:output_type -> gitaly.CreateBundleFromRefListResponse
+ 14, // 113: gitaly.RepositoryService.FetchBundle:output_type -> gitaly.FetchBundleResponse
+ 50, // 114: gitaly.RepositoryService.CreateRepositoryFromBundle:output_type -> gitaly.CreateRepositoryFromBundleResponse
+ 40, // 115: gitaly.RepositoryService.GetConfig:output_type -> gitaly.GetConfigResponse
+ 52, // 116: gitaly.RepositoryService.FindLicense:output_type -> gitaly.FindLicenseResponse
+ 54, // 117: gitaly.RepositoryService.GetInfoAttributes:output_type -> gitaly.GetInfoAttributesResponse
+ 56, // 118: gitaly.RepositoryService.CalculateChecksum:output_type -> gitaly.CalculateChecksumResponse
+ 58, // 119: gitaly.RepositoryService.GetSnapshot:output_type -> gitaly.GetSnapshotResponse
+ 60, // 120: gitaly.RepositoryService.CreateRepositoryFromSnapshot:output_type -> gitaly.CreateRepositoryFromSnapshotResponse
+ 62, // 121: gitaly.RepositoryService.GetRawChanges:output_type -> gitaly.GetRawChangesResponse
+ 66, // 122: gitaly.RepositoryService.SearchFilesByContent:output_type -> gitaly.SearchFilesByContentResponse
+ 64, // 123: gitaly.RepositoryService.SearchFilesByName:output_type -> gitaly.SearchFilesByNameResponse
+ 43, // 124: gitaly.RepositoryService.RestoreCustomHooks:output_type -> gitaly.RestoreCustomHooksResponse
+ 44, // 125: gitaly.RepositoryService.SetCustomHooks:output_type -> gitaly.SetCustomHooksResponse
+ 47, // 126: gitaly.RepositoryService.BackupCustomHooks:output_type -> gitaly.BackupCustomHooksResponse
+ 48, // 127: gitaly.RepositoryService.GetCustomHooks:output_type -> gitaly.GetCustomHooksResponse
+ 69, // 128: gitaly.RepositoryService.GetObjectDirectorySize:output_type -> gitaly.GetObjectDirectorySizeResponse
+ 71, // 129: gitaly.RepositoryService.RemoveRepository:output_type -> gitaly.RemoveRepositoryResponse
+ 73, // 130: gitaly.RepositoryService.RenameRepository:output_type -> gitaly.RenameRepositoryResponse
+ 75, // 131: gitaly.RepositoryService.ReplicateRepository:output_type -> gitaly.ReplicateRepositoryResponse
+ 77, // 132: gitaly.RepositoryService.OptimizeRepository:output_type -> gitaly.OptimizeRepositoryResponse
+ 79, // 133: gitaly.RepositoryService.PruneUnreachableObjects:output_type -> gitaly.PruneUnreachableObjectsResponse
+ 81, // 134: gitaly.RepositoryService.SetFullPath:output_type -> gitaly.SetFullPathResponse
+ 83, // 135: gitaly.RepositoryService.FullPath:output_type -> gitaly.FullPathResponse
+ 85, // 136: gitaly.RepositoryService.RemoveAll:output_type -> gitaly.RemoveAllResponse
+ 87, // 137: gitaly.RepositoryService.BackupRepository:output_type -> gitaly.BackupRepositoryResponse
+ 96, // [96:138] is the sub-list for method output_type
+ 54, // [54:96] is the sub-list for method input_type
+ 54, // [54:54] is the sub-list for extension type_name
+ 54, // [54:54] is the sub-list for extension extendee
+ 0, // [0:54] is the sub-list for field type_name
}
func init() { file_repository_proto_init() }
@@ -7066,7 +7238,7 @@ func file_repository_proto_init() {
}
}
file_repository_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*RepositoryInfoResponse_ReferencesInfo); i {
+ switch v := v.(*BackupRepositoryRequest); i {
case 0:
return &v.state
case 1:
@@ -7078,7 +7250,7 @@ func file_repository_proto_init() {
}
}
file_repository_proto_msgTypes[84].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*RepositoryInfoResponse_ObjectsInfo); i {
+ switch v := v.(*BackupRepositoryResponse); i {
case 0:
return &v.state
case 1:
@@ -7090,6 +7262,30 @@ func file_repository_proto_init() {
}
}
file_repository_proto_msgTypes[85].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*RepositoryInfoResponse_ReferencesInfo); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_repository_proto_msgTypes[86].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*RepositoryInfoResponse_ObjectsInfo); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_repository_proto_msgTypes[87].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetRawChangesResponse_RawChange); i {
case 0:
return &v.state
@@ -7101,6 +7297,18 @@ func file_repository_proto_init() {
return nil
}
}
+ file_repository_proto_msgTypes[88].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*BackupRepositoryResponse_SkippedError); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -7108,7 +7316,7 @@ func file_repository_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_repository_proto_rawDesc,
NumEnums: 3,
- NumMessages: 86,
+ NumMessages: 89,
NumExtensions: 0,
NumServices: 1,
},
diff --git a/proto/go/gitalypb/repository_grpc.pb.go b/proto/go/gitalypb/repository_grpc.pb.go
index db0fd8f15..8c3c77544 100644
--- a/proto/go/gitalypb/repository_grpc.pb.go
+++ b/proto/go/gitalypb/repository_grpc.pb.go
@@ -153,6 +153,10 @@ type RepositoryServiceClient interface {
FullPath(ctx context.Context, in *FullPathRequest, opts ...grpc.CallOption) (*FullPathResponse, error)
// RemoveAll deletes all repositories on a specified storage.
RemoveAll(ctx context.Context, in *RemoveAllRequest, opts ...grpc.CallOption) (*RemoveAllResponse, error)
+ // BackupRepository creates a full backup streamed directly to
+ // object-storage. The backup is created synchronously. The destination must
+ // be configured in config.backup.go_cloud_url
+ BackupRepository(ctx context.Context, in *BackupRepositoryRequest, opts ...grpc.CallOption) (*BackupRepositoryResponse, error)
}
type repositoryServiceClient struct {
@@ -888,6 +892,15 @@ func (c *repositoryServiceClient) RemoveAll(ctx context.Context, in *RemoveAllRe
return out, nil
}
+func (c *repositoryServiceClient) BackupRepository(ctx context.Context, in *BackupRepositoryRequest, opts ...grpc.CallOption) (*BackupRepositoryResponse, error) {
+ out := new(BackupRepositoryResponse)
+ err := c.cc.Invoke(ctx, "/gitaly.RepositoryService/BackupRepository", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
// RepositoryServiceServer is the server API for RepositoryService service.
// All implementations must embed UnimplementedRepositoryServiceServer
// for forward compatibility
@@ -1023,6 +1036,10 @@ type RepositoryServiceServer interface {
FullPath(context.Context, *FullPathRequest) (*FullPathResponse, error)
// RemoveAll deletes all repositories on a specified storage.
RemoveAll(context.Context, *RemoveAllRequest) (*RemoveAllResponse, error)
+ // BackupRepository creates a full backup streamed directly to
+ // object-storage. The backup is created synchronously. The destination must
+ // be configured in config.backup.go_cloud_url
+ BackupRepository(context.Context, *BackupRepositoryRequest) (*BackupRepositoryResponse, error)
mustEmbedUnimplementedRepositoryServiceServer()
}
@@ -1153,6 +1170,9 @@ func (UnimplementedRepositoryServiceServer) FullPath(context.Context, *FullPathR
func (UnimplementedRepositoryServiceServer) RemoveAll(context.Context, *RemoveAllRequest) (*RemoveAllResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method RemoveAll not implemented")
}
+func (UnimplementedRepositoryServiceServer) BackupRepository(context.Context, *BackupRepositoryRequest) (*BackupRepositoryResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method BackupRepository not implemented")
+}
func (UnimplementedRepositoryServiceServer) mustEmbedUnimplementedRepositoryServiceServer() {}
// UnsafeRepositoryServiceServer may be embedded to opt out of forward compatibility for this service.
@@ -1974,6 +1994,24 @@ func _RepositoryService_RemoveAll_Handler(srv interface{}, ctx context.Context,
return interceptor(ctx, in, info, handler)
}
+func _RepositoryService_BackupRepository_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(BackupRepositoryRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(RepositoryServiceServer).BackupRepository(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/gitaly.RepositoryService/BackupRepository",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(RepositoryServiceServer).BackupRepository(ctx, req.(*BackupRepositoryRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
// RepositoryService_ServiceDesc is the grpc.ServiceDesc for RepositoryService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -2085,6 +2123,10 @@ var RepositoryService_ServiceDesc = grpc.ServiceDesc{
MethodName: "RemoveAll",
Handler: _RepositoryService_RemoveAll_Handler,
},
+ {
+ MethodName: "BackupRepository",
+ Handler: _RepositoryService_BackupRepository_Handler,
+ },
},
Streams: []grpc.StreamDesc{
{
diff --git a/proto/repository.proto b/proto/repository.proto
index 93a96e19a..48f949bc0 100644
--- a/proto/repository.proto
+++ b/proto/repository.proto
@@ -343,6 +343,15 @@ service RepositoryService {
rpc RemoveAll(RemoveAllRequest) returns (RemoveAllResponse) {
option (intercepted_method) = true;
}
+
+ // BackupRepository creates a full backup streamed directly to
+ // object-storage. The backup is created synchronously. The destination must
+ // be configured in config.backup.go_cloud_url
+ rpc BackupRepository(BackupRepositoryRequest) returns (BackupRepositoryResponse) {
+ option (op_type) = {
+ op: ACCESSOR
+ };
+ }
}
// This comment is left unintentionally blank.
@@ -1167,3 +1176,20 @@ message RemoveAllRequest {
// RemoveAllResponse is a response for the RemoveAll RPC.
message RemoveAllResponse {
}
+
+// BackupRepository is a request for the BackupRepository RPC.
+message BackupRepositoryRequest {
+ // Repository is the repository to be backed up.
+ Repository repository = 1 [(target_repository)=true];
+ // VanityRepository is used to determine the backup path.
+ Repository vanity_repository = 2;
+ // BackupId is the label used to identify this backup when restoring.
+ string backup_id = 3;
+}
+
+// BackupRepositoryResponse is a response for the BackupRepository RPC.
+message BackupRepositoryResponse {
+ // SkippedError is returned when the repository backup has been skipped.
+ message SkippedError {
+ }
+}