Skip to content

Commit

Permalink
Merge pull request restic#4682 from konidev20/feat-add-target-for-dum…
Browse files Browse the repository at this point in the history
…p-command

feat: set --target for dump command
  • Loading branch information
MichaelEischer authored Feb 5, 2024
2 parents 0f09a88 + f5ffa40 commit 0cffdb7
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 6 deletions.
7 changes: 7 additions & 0 deletions changelog/unreleased/issue-4678
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Enhancement: Add --target flag to the dump command

Restic `dump` always printed to the standard output. It now permits to select a
`--target` file to write the output to.

https://github.com/restic/restic/issues/4678
https://github.com/restic/restic/pull/4682
30 changes: 24 additions & 6 deletions cmd/restic/cmd_dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Exit status is 0 if the command was successful, and non-zero if there was any er
type DumpOptions struct {
restic.SnapshotFilter
Archive string
Target string
}

var dumpOptions DumpOptions
Expand All @@ -56,6 +57,7 @@ func init() {
flags := cmdDump.Flags()
initSingleSnapshotFilter(flags, &dumpOptions.SnapshotFilter)
flags.StringVarP(&dumpOptions.Archive, "archive", "a", "tar", "set archive `format` as \"tar\" or \"zip\"")
flags.StringVarP(&dumpOptions.Target, "target", "t", "", "write the output to target `path`")
}

func splitPath(p string) []string {
Expand All @@ -67,11 +69,11 @@ func splitPath(p string) []string {
return append(s, f)
}

func printFromTree(ctx context.Context, tree *restic.Tree, repo restic.BlobLoader, prefix string, pathComponents []string, d *dump.Dumper) error {
func printFromTree(ctx context.Context, tree *restic.Tree, repo restic.BlobLoader, prefix string, pathComponents []string, d *dump.Dumper, canWriteArchiveFunc func() error) error {
// If we print / we need to assume that there are multiple nodes at that
// level in the tree.
if pathComponents[0] == "" {
if err := checkStdoutArchive(); err != nil {
if err := canWriteArchiveFunc(); err != nil {
return err
}
return d.DumpTree(ctx, tree, "/")
Expand All @@ -91,9 +93,9 @@ func printFromTree(ctx context.Context, tree *restic.Tree, repo restic.BlobLoade
if err != nil {
return errors.Wrapf(err, "cannot load subtree for %q", item)
}
return printFromTree(ctx, subtree, repo, item, pathComponents[1:], d)
return printFromTree(ctx, subtree, repo, item, pathComponents[1:], d, canWriteArchiveFunc)
case dump.IsDir(node):
if err := checkStdoutArchive(); err != nil {
if err := canWriteArchiveFunc(); err != nil {
return err
}
subtree, err := restic.LoadTree(ctx, repo, *node.Subtree)
Expand Down Expand Up @@ -168,8 +170,24 @@ func runDump(ctx context.Context, opts DumpOptions, gopts GlobalOptions, args []
return errors.Fatalf("loading tree for snapshot %q failed: %v", snapshotIDString, err)
}

d := dump.New(opts.Archive, repo, os.Stdout)
err = printFromTree(ctx, tree, repo, "/", splittedPath, d)
outputFileWriter := os.Stdout
canWriteArchiveFunc := checkStdoutArchive

if opts.Target != "" {
file, err := os.OpenFile(opts.Target, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o666)
if err != nil {
return fmt.Errorf("cannot dump to file: %w", err)
}
defer func() {
_ = file.Close()
}()

outputFileWriter = file
canWriteArchiveFunc = func() error { return nil }
}

d := dump.New(opts.Archive, repo, outputFileWriter)
err = printFromTree(ctx, tree, repo, "/", splittedPath, d, canWriteArchiveFunc)
if err != nil {
return errors.Fatalf("cannot dump file: %v", err)
}
Expand Down
7 changes: 7 additions & 0 deletions doc/050_restore.rst
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,10 @@ To include the folder content at the root of the archive, you can use the ``<sna
.. code-block:: console
$ restic -r /srv/restic-repo dump latest:/home/other/work / > restore.tar
It is also possible to ``dump`` the contents of a selected snapshot and folder
structure to a file using the ``--target`` flag. The ``dump`` command will fail
if the already file exists.

.. code-block:: console
$ restic -r /srv/restic-repo dump latest / --target /home/linux.user/output.tar -a tar

0 comments on commit 0cffdb7

Please sign in to comment.