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:
Diffstat (limited to 'internal/backup/backup.go')
-rw-r--r--internal/backup/backup.go80
1 files changed, 34 insertions, 46 deletions
diff --git a/internal/backup/backup.go b/internal/backup/backup.go
index c59591b59..70a9b6d91 100644
--- a/internal/backup/backup.go
+++ b/internal/backup/backup.go
@@ -38,20 +38,10 @@ type Sink interface {
GetReader(ctx context.Context, relativePath string) (io.ReadCloser, error)
}
-// Backup represents all the information needed to restore a backup for a repository
-type Backup struct {
- // Steps are the ordered list of steps required to restore this backup
- Steps []Step
-}
-
-// Step represents an incremental step that makes up a complete backup for a repository
-type Step struct {
+// Full represents all paths required for a full backup
+type Full struct {
// BundlePath is the path of the bundle
BundlePath string
- // SkippableOnNotFound defines if the bundle can be skipped when it does
- // not exist. This allows us to maintain legacy behaviour where we always
- // check a specific location for a bundle without knowing if it exists.
- SkippableOnNotFound bool
// RefPath is the path of the ref file
RefPath string
// CustomHooksPath is the path of the custom hooks archive
@@ -60,14 +50,14 @@ type Step struct {
// Locator finds sink backup paths for repositories
type Locator interface {
- // BeginFull returns a tentative first step needed to create a new full backup.
- BeginFull(ctx context.Context, repo *gitalypb.Repository, backupID string) *Step
+ // BeginFull returns paths for a new full backup
+ BeginFull(ctx context.Context, repo *gitalypb.Repository, backupID string) *Full
- // CommitFull marks the step returned by `BeginFull` as the latest backup.
- CommitFull(ctx context.Context, step *Step) error
+ // CommitFull persists the paths for a new backup so that it can be looked up by FindLatestFull
+ CommitFull(ctx context.Context, full *Full) error
- // FindLatest returns the latest backup that was written by CommitFull
- FindLatest(ctx context.Context, repo *gitalypb.Repository) (*Backup, error)
+ // FindLatestFull returns the paths committed by the latest call to CommitFull
+ FindLatestFull(ctx context.Context, repo *gitalypb.Repository) (*Full, error)
}
// ResolveSink returns a sink implementation based on the provided path.
@@ -182,40 +172,38 @@ func (mgr *Manager) Restore(ctx context.Context, req *RestoreRequest) error {
return fmt.Errorf("manager: %w", err)
}
- backup, err := mgr.locator.FindLatest(ctx, req.Repository)
+ full, err := mgr.locator.FindLatestFull(ctx, req.Repository)
if err != nil {
- return fmt.Errorf("manager: %w", err)
+ return mgr.checkRestoreSkip(ctx, err, req)
}
- if err := mgr.createRepository(ctx, req.Server, req.Repository); err != nil {
+ if err := mgr.restoreBundle(ctx, full.BundlePath, req.Server, req.Repository); err != nil {
+ return mgr.checkRestoreSkip(ctx, err, req)
+ }
+ if err := mgr.restoreCustomHooks(ctx, full.CustomHooksPath, req.Server, req.Repository); err != nil {
return fmt.Errorf("manager: %w", err)
}
+ return nil
+}
- for _, step := range backup.Steps {
- if err := mgr.restoreBundle(ctx, step.BundlePath, req.Server, req.Repository); err != nil {
- if step.SkippableOnNotFound && errors.Is(err, ErrDoesntExist) {
- // For compatibility with existing backups we need to make sure the
- // repository exists even if there's no bundle for project
- // repositories (not wiki or snippet repositories). Gitaly does
- // not know which repository is which type so here we accept a
- // parameter to tell us to employ this behaviour. Since the
- // repository has already been created, we simply skip cleaning up.
- if req.AlwaysCreate {
- return nil
- }
-
- if err := mgr.removeRepository(ctx, req.Server, req.Repository); err != nil {
- return fmt.Errorf("manager: remove on skipped: %w", err)
- }
-
- return fmt.Errorf("manager: %w: %s", ErrSkipped, err.Error())
+func (mgr *Manager) checkRestoreSkip(ctx context.Context, err error, req *RestoreRequest) error {
+ if errors.Is(err, ErrDoesntExist) {
+ // For compatibility with existing backups we need to always create the
+ // repository even if there's no bundle for project repositories
+ // (not wiki or snippet repositories). Gitaly does not know which
+ // repository is which type so here we accept a parameter to tell us
+ // to employ this behaviour.
+ if req.AlwaysCreate {
+ if err := mgr.createRepository(ctx, req.Server, req.Repository); err != nil {
+ return fmt.Errorf("manager: %w", err)
}
+ return nil
}
- if err := mgr.restoreCustomHooks(ctx, step.CustomHooksPath, req.Server, req.Repository); err != nil {
- return fmt.Errorf("manager: %w", err)
- }
+
+ return fmt.Errorf("manager: %w: %s", ErrSkipped, err.Error())
}
- return nil
+
+ return fmt.Errorf("manager: %w", err)
}
func (mgr *Manager) isEmpty(ctx context.Context, server storage.ServerInfo, repo *gitalypb.Repository) (bool, error) {
@@ -329,11 +317,11 @@ func (mgr *Manager) restoreBundle(ctx context.Context, path string, server stora
if err != nil {
return fmt.Errorf("restore bundle: %q: %w", path, err)
}
- stream, err := repoClient.FetchBundle(ctx)
+ stream, err := repoClient.CreateRepositoryFromBundle(ctx)
if err != nil {
return fmt.Errorf("restore bundle: %q: %w", path, err)
}
- request := &gitalypb.FetchBundleRequest{Repository: repo}
+ request := &gitalypb.CreateRepositoryFromBundleRequest{Repository: repo}
bundle := streamio.NewWriter(func(p []byte) error {
request.Data = p
if err := stream.Send(request); err != nil {
@@ -341,7 +329,7 @@ func (mgr *Manager) restoreBundle(ctx context.Context, path string, server stora
}
// Only set `Repository` on the first `Send` of the stream
- request = &gitalypb.FetchBundleRequest{}
+ request = &gitalypb.CreateRepositoryFromBundleRequest{}
return nil
})