From 851ff898869641e51e715194799ad238dcc08c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lie=20DELHAIE?= Date: Sun, 17 Aug 2025 00:30:02 +0200 Subject: [PATCH] implement applu --- cmd/cli/commands/apply/apply.go | 23 ++++++++++++++----- cmd/cli/main.go | 3 +++ pkg/constants/constants.go | 2 +- pkg/data/data.go | 39 +++++++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 6 deletions(-) diff --git a/cmd/cli/commands/apply/apply.go b/cmd/cli/commands/apply/apply.go index 041b805..c0c3de9 100644 --- a/cmd/cli/commands/apply/apply.go +++ b/cmd/cli/commands/apply/apply.go @@ -1,6 +1,7 @@ package apply import ( + "cloudsave/pkg/data" "context" "flag" "fmt" @@ -11,13 +12,14 @@ import ( type ( ListCmd struct { + Service *data.Service } ) func (*ListCmd) Name() string { return "apply" } func (*ListCmd) Synopsis() string { return "apply a backup" } func (*ListCmd) Usage() string { - return `Usage: cloudsave apply + return `Usage: cloudsave apply [BACKUP_ID] Apply a backup ` @@ -27,15 +29,26 @@ func (p *ListCmd) SetFlags(f *flag.FlagSet) { } func (p *ListCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus { - if f.NArg() != 2 { + if f.NArg() < 1 { fmt.Fprintln(os.Stderr, "error: missing game ID and/or backup uuid") return subcommands.ExitUsageError } - //gameID := f.Arg(0) - //uuid := f.Arg(1) + gameID := f.Arg(0) + uuid := f.Arg(1) - panic("not implemented") + if len(uuid) == 0 { + if err := p.Service.ApplyCurrent(gameID); err != nil { + fmt.Fprintf(os.Stderr, "error: failed to apply: %s", err) + return subcommands.ExitFailure + } + return subcommands.ExitSuccess + } + + if err := p.Service.ApplyBackup(gameID, uuid); err != nil { + fmt.Fprintf(os.Stderr, "error: failed to apply: %s", err) + return subcommands.ExitFailure + } return subcommands.ExitSuccess } diff --git a/cmd/cli/main.go b/cmd/cli/main.go index 2b43b79..8ec7531 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -2,6 +2,7 @@ package main import ( "cloudsave/cmd/cli/commands/add" + "cloudsave/cmd/cli/commands/apply" "cloudsave/cmd/cli/commands/list" "cloudsave/cmd/cli/commands/pull" "cloudsave/cmd/cli/commands/remote" @@ -48,6 +49,8 @@ func main() { subcommands.Register(&list.ListCmd{Service: s}, "management") subcommands.Register(&remove.RemoveCmd{Service: s}, "management") + subcommands.Register(&apply.ListCmd{Service: s}, "restore") + subcommands.Register(&remote.RemoteCmd{Service: s}, "remote") subcommands.Register(&sync.SyncCmd{Service: s}, "remote") subcommands.Register(&pull.PullCmd{Service: s}, "remote") diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index b9ec354..cd821e8 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -1,5 +1,5 @@ package constants -const Version = "0.0.4" +const Version = "0.0.5" const ApiVersion = 1 diff --git a/pkg/data/data.go b/pkg/data/data.go index 525ffbe..8a6c9b3 100644 --- a/pkg/data/data.go +++ b/pkg/data/data.go @@ -344,3 +344,42 @@ func (l Service) CopyBackup(gameID, backupID string, src io.Reader) error { return nil } + +func (l Service) ApplyCurrent(gameID string) error { + id := repository.NewGameIdentifier(gameID) + path := l.repo.DataPath(id) + + g, err := l.repo.Metadata(id) + if err != nil { + return err + } + + return l.apply(path, g.Path) +} + +func (l Service) ApplyBackup(gameID, backupID string) error { + id := repository.NewGameIdentifier(gameID) + fullID := repository.NewBackupIdentifier(gameID, backupID) + path := l.repo.DataPath(fullID) + + g, err := l.repo.Metadata(id) + if err != nil { + return err + } + + return l.apply(path, g.Path) +} + +func (l Service) apply(src, dst string) error { + if err := os.RemoveAll(dst); err != nil { + return fmt.Errorf("failed to remove old save: %w", err) + } + + f, err := os.OpenFile(src, os.O_RDONLY, 0) + if err != nil { + return fmt.Errorf("failed to open archive: %w", err) + } + defer f.Close() + + return archive.Untar(f, dst) +}