Merge pull request #4334 from MichaelEischer/snapshot-subtree-syntax

Add support for snapshot:path syntax
This commit is contained in:
Michael Eischer
2023-07-22 23:59:26 +02:00
committed by GitHub
21 changed files with 291 additions and 102 deletions

View File

@@ -453,7 +453,7 @@ func findParentSnapshot(ctx context.Context, repo restic.Repository, opts Backup
f.Tags = []restic.TagList{opts.Tags.Flatten()}
}
sn, err := f.FindLatest(ctx, repo.Backend(), repo, snName)
sn, _, err := f.FindLatest(ctx, repo.Backend(), repo, snName)
// Snapshot not found is ok if no explicit parent was set
if opts.Parent == "" && errors.Is(err, restic.ErrNoSnapshotFound) {
err = nil

View File

@@ -13,7 +13,7 @@ import (
)
var cmdCat = &cobra.Command{
Use: "cat [flags] [pack|blob|snapshot|index|key|masterkey|config|lock] ID",
Use: "cat [flags] [masterkey|config|pack ID|blob ID|snapshot ID|index ID|key ID|lock ID|tree snapshot:subfolder]",
Short: "Print internal objects to stdout",
Long: `
The "cat" command is used to print internal objects to stdout.
@@ -55,7 +55,7 @@ func runCat(ctx context.Context, gopts GlobalOptions, args []string) error {
tpe := args[0]
var id restic.ID
if tpe != "masterkey" && tpe != "config" && tpe != "snapshot" {
if tpe != "masterkey" && tpe != "config" && tpe != "snapshot" && tpe != "tree" {
id, err = restic.ParseID(args[1])
if err != nil {
return errors.Fatalf("unable to parse ID: %v\n", err)
@@ -80,7 +80,7 @@ func runCat(ctx context.Context, gopts GlobalOptions, args []string) error {
Println(string(buf))
return nil
case "snapshot":
sn, err := restic.FindSnapshot(ctx, repo.Backend(), repo, args[1])
sn, _, err := restic.FindSnapshot(ctx, repo.Backend(), repo, args[1])
if err != nil {
return errors.Fatalf("could not find snapshot: %v\n", err)
}
@@ -165,6 +165,29 @@ func runCat(ctx context.Context, gopts GlobalOptions, args []string) error {
return errors.Fatal("blob not found")
case "tree":
sn, subfolder, err := restic.FindSnapshot(ctx, repo.Backend(), repo, args[1])
if err != nil {
return errors.Fatalf("could not find snapshot: %v\n", err)
}
err = repo.LoadIndex(ctx)
if err != nil {
return err
}
sn.Tree, err = restic.FindTreeDirectory(ctx, repo, sn.Tree, subfolder)
if err != nil {
return err
}
buf, err := repo.LoadBlob(ctx, restic.TreeBlob, *sn.Tree, nil)
if err != nil {
return err
}
_, err = globalOptions.stdout.Write(buf)
return err
default:
return errors.Fatal("invalid type")
}

View File

@@ -54,12 +54,12 @@ func init() {
f.BoolVar(&diffOptions.ShowMetadata, "metadata", false, "print changes in metadata")
}
func loadSnapshot(ctx context.Context, be restic.Lister, repo restic.Repository, desc string) (*restic.Snapshot, error) {
sn, err := restic.FindSnapshot(ctx, be, repo, desc)
func loadSnapshot(ctx context.Context, be restic.Lister, repo restic.Repository, desc string) (*restic.Snapshot, string, error) {
sn, subfolder, err := restic.FindSnapshot(ctx, be, repo, desc)
if err != nil {
return nil, errors.Fatal(err.Error())
return nil, "", errors.Fatal(err.Error())
}
return sn, err
return sn, subfolder, err
}
// Comparer collects all things needed to compare two snapshots.
@@ -346,12 +346,12 @@ func runDiff(ctx context.Context, opts DiffOptions, gopts GlobalOptions, args []
if err != nil {
return err
}
sn1, err := loadSnapshot(ctx, be, repo, args[0])
sn1, subfolder1, err := loadSnapshot(ctx, be, repo, args[0])
if err != nil {
return err
}
sn2, err := loadSnapshot(ctx, be, repo, args[1])
sn2, subfolder2, err := loadSnapshot(ctx, be, repo, args[1])
if err != nil {
return err
}
@@ -372,6 +372,16 @@ func runDiff(ctx context.Context, opts DiffOptions, gopts GlobalOptions, args []
return errors.Errorf("snapshot %v has nil tree", sn2.ID().Str())
}
sn1.Tree, err = restic.FindTreeDirectory(ctx, repo, sn1.Tree, subfolder1)
if err != nil {
return err
}
sn2.Tree, err = restic.FindTreeDirectory(ctx, repo, sn2.Tree, subfolder2)
if err != nil {
return err
}
c := &Comparer{
repo: repo,
opts: diffOptions,

View File

@@ -139,7 +139,7 @@ func runDump(ctx context.Context, opts DumpOptions, gopts GlobalOptions, args []
}
}
sn, err := (&restic.SnapshotFilter{
sn, subfolder, err := (&restic.SnapshotFilter{
Hosts: opts.Hosts,
Paths: opts.Paths,
Tags: opts.Tags,
@@ -153,6 +153,11 @@ func runDump(ctx context.Context, opts DumpOptions, gopts GlobalOptions, args []
return err
}
sn.Tree, err = restic.FindTreeDirectory(ctx, repo, sn.Tree, subfolder)
if err != nil {
return err
}
tree, err := restic.LoadTree(ctx, repo, *sn.Tree)
if err != nil {
return errors.Fatalf("loading tree for snapshot %q failed: %v", snapshotIDString, err)

View File

@@ -212,7 +212,7 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
}
}
sn, err := (&restic.SnapshotFilter{
sn, subfolder, err := (&restic.SnapshotFilter{
Hosts: opts.Hosts,
Paths: opts.Paths,
Tags: opts.Tags,
@@ -221,6 +221,11 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
return err
}
sn.Tree, err = restic.FindTreeDirectory(ctx, repo, sn.Tree, subfolder)
if err != nil {
return err
}
printSnapshot(sn)
err = walker.Walk(ctx, repo, *sn.Tree, nil, func(_ restic.ID, nodepath string, node *restic.Node, err error) (bool, error) {

View File

@@ -161,7 +161,7 @@ func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions,
}
}
sn, err := (&restic.SnapshotFilter{
sn, subfolder, err := (&restic.SnapshotFilter{
Hosts: opts.Hosts,
Paths: opts.Paths,
Tags: opts.Tags,
@@ -175,6 +175,11 @@ func runRestore(ctx context.Context, opts RestoreOptions, gopts GlobalOptions,
return err
}
sn.Tree, err = restic.FindTreeDirectory(ctx, repo, sn.Tree, subfolder)
if err != nil {
return err
}
msg := ui.NewMessage(term, gopts.verbosity)
var printer restoreui.ProgressPrinter
if gopts.JSON {