apply backup

This commit is contained in:
2025-07-30 17:20:43 +02:00
parent 30b76e1887
commit 58c6bc56cf
7 changed files with 390 additions and 11 deletions

View File

@@ -16,6 +16,7 @@ import (
"time"
"github.com/google/subcommands"
"github.com/schollz/progressbar/v3"
)
type (
@@ -51,13 +52,21 @@ func (p *SyncCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
fmt.Fprintln(os.Stderr, "error: failed to load datastore:", err)
return subcommands.ExitFailure
}
cli, err := connect(remoteCred, r)
if err != nil {
fmt.Fprintln(os.Stderr, "error: failed to connect to the remote:", err)
return subcommands.ExitFailure
}
pg := progressbar.New(-1)
destroyPg := func() {
pg.Finish()
pg.Clear()
pg.Close()
}
pg.Describe(fmt.Sprintf("[%s] Checking status...", g.Name))
exists, err := cli.Exists(r.GameID)
if err != nil {
slog.Error(err.Error())
@@ -65,45 +74,61 @@ func (p *SyncCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
}
if !exists {
pg.Describe(fmt.Sprintf("[%s] Pushing data...", g.Name))
if err := push(g, cli); err != nil {
destroyPg()
fmt.Fprintln(os.Stderr, "failed to push:", err)
return subcommands.ExitFailure
}
pg.Describe(fmt.Sprintf("[%s] Pushing backup...", g.Name))
if err := pushBackup(g, cli); err != nil {
destroyPg()
slog.Warn("failed to push backup files", "err", err)
}
continue
}
pg.Describe(fmt.Sprintf("[%s] Fetching metadata...", g.Name))
hlocal, err := repository.Hash(r.GameID)
if err != nil {
destroyPg()
slog.Error(err.Error())
continue
}
hremote, err := cli.Hash(r.GameID)
if err != nil {
destroyPg()
fmt.Fprintln(os.Stderr, "error: failed to get the file hash from the remote:", err)
continue
}
vlocal, err := repository.Version(r.GameID)
if err != nil {
destroyPg()
slog.Error(err.Error())
continue
}
remoteMetadata, err := cli.Metadata(r.GameID)
if err != nil {
destroyPg()
fmt.Fprintln(os.Stderr, "error: failed to get the game metadata from the remote:", err)
continue
}
pg.Describe(fmt.Sprintf("[%s] Pulling backup...", g.Name))
if err := pullBackup(g, cli); err != nil {
slog.Warn("failed to pull backup files", "err", err)
}
pg.Describe(fmt.Sprintf("[%s] Pushing backup...", g.Name))
if err := pushBackup(g, cli); err != nil {
slog.Warn("failed to push backup files", "err", err)
}
if hlocal == hremote {
destroyPg()
if vlocal != remoteMetadata.Version {
slog.Debug("version is not the same, but the hash is equal. Updating local database")
if err := repository.SetVersion(r.GameID, remoteMetadata.Version); err != nil {
@@ -116,29 +141,38 @@ func (p *SyncCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
}
if vlocal > remoteMetadata.Version {
pg.Describe(fmt.Sprintf("[%s] Pushing data...", g.Name))
if err := push(g, cli); err != nil {
destroyPg()
fmt.Fprintln(os.Stderr, "failed to push:", err)
return subcommands.ExitFailure
}
destroyPg()
continue
}
if vlocal < remoteMetadata.Version {
destroyPg()
if err := pull(r.GameID, cli); err != nil {
destroyPg()
fmt.Fprintln(os.Stderr, "failed to push:", err)
return subcommands.ExitFailure
}
if err := repository.SetVersion(r.GameID, remoteMetadata.Version); err != nil {
destroyPg()
fmt.Fprintln(os.Stderr, "error: failed to synchronize version number:", err)
continue
}
if err := repository.SetDate(r.GameID, remoteMetadata.Date); err != nil {
destroyPg()
fmt.Fprintln(os.Stderr, "error: failed to synchronize date:", err)
continue
}
continue
}
destroyPg()
if vlocal == remoteMetadata.Version {
if err := conflict(r.GameID, g, remoteMetadata, cli); err != nil {
fmt.Fprintln(os.Stderr, "error: failed to resolve conflict:", err)
@@ -148,6 +182,7 @@ func (p *SyncCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{})
}
}
fmt.Println("done.")
return subcommands.ExitSuccess
}
@@ -222,6 +257,39 @@ func pushBackup(m repository.Metadata, cli *client.Client) error {
return nil
}
func pullBackup(m repository.Metadata, cli *client.Client) error {
bs, err := cli.ListArchives(m.ID)
if err != nil {
return err
}
for _, uuid := range bs {
rinfo, err := cli.ArchiveInfo(m.ID, uuid)
if err != nil {
return err
}
linfo, err := repository.Archive(m.ID, uuid)
if err != nil {
if !errors.Is(err, os.ErrNotExist) {
return err
}
}
path := filepath.Join(repository.DatastorePath(), m.ID, "hist", uuid)
if err := os.MkdirAll(path, 0740); err != nil {
return err
}
if rinfo.MD5 != linfo.MD5 {
if err := cli.PullBackup(m.ID, uuid, filepath.Join(path, "data.tar.gz")); err != nil {
return err
}
}
}
return nil
}
func pull(gameID string, cli *client.Client) error {
archivePath := filepath.Join(repository.DatastorePath(), gameID, "data.tar.gz")