From 15419d603dbfa0159963331ad1a7168d35ba5871 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sun, 7 Jul 2024 13:28:56 +0200 Subject: [PATCH] ls: add missing intermediate directories to --ncdu output --- cmd/restic/cmd_ls.go | 26 ++++++++++++++++++-------- cmd/restic/cmd_ls_integration_test.go | 15 +++++++++------ cmd/restic/cmd_ls_test.go | 4 ++-- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/cmd/restic/cmd_ls.go b/cmd/restic/cmd_ls.go index 7499da68f..8dd2af2d6 100644 --- a/cmd/restic/cmd_ls.go +++ b/cmd/restic/cmd_ls.go @@ -71,7 +71,7 @@ func init() { type lsPrinter interface { Snapshot(sn *restic.Snapshot) - Node(path string, node *restic.Node) + Node(path string, node *restic.Node, isPrefixDirectory bool) LeaveDir(path string) Close() } @@ -102,7 +102,10 @@ func (p *jsonLsPrinter) Snapshot(sn *restic.Snapshot) { } // Print node in our custom JSON format, followed by a newline. -func (p *jsonLsPrinter) Node(path string, node *restic.Node) { +func (p *jsonLsPrinter) Node(path string, node *restic.Node, isPrefixDirectory bool) { + if isPrefixDirectory { + return + } err := lsNodeJSON(p.enc, path, node) if err != nil { Warnf("JSON encode failed: %v\n", err) @@ -217,7 +220,7 @@ func lsNcduNode(_ string, node *restic.Node) ([]byte, error) { return json.Marshal(outNode) } -func (p *ncduLsPrinter) Node(path string, node *restic.Node) { +func (p *ncduLsPrinter) Node(path string, node *restic.Node, _ bool) { out, err := lsNcduNode(path, node) if err != nil { Warnf("JSON encode failed: %v\n", err) @@ -249,8 +252,10 @@ type textLsPrinter struct { func (p *textLsPrinter) Snapshot(sn *restic.Snapshot) { Verbosef("%v filtered by %v:\n", sn, p.dirs) } -func (p *textLsPrinter) Node(path string, node *restic.Node) { - Printf("%s\n", formatNode(path, node, p.ListLong, p.HumanReadable)) +func (p *textLsPrinter) Node(path string, node *restic.Node, isPrefixDirectory bool) { + if !isPrefixDirectory { + Printf("%s\n", formatNode(path, node, p.ListLong, p.HumanReadable)) + } } func (p *textLsPrinter) LeaveDir(_ string) {} @@ -369,8 +374,8 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri printedDir := false if withinDir(nodepath) { - // if we're within a dir, print the node - printer.Node(nodepath, node) + // if we're within a target path, print the node + printer.Node(nodepath, node, false) printedDir = true // if recursive listing is requested, signal the walker that it @@ -383,12 +388,17 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri // if there's an upcoming match deeper in the tree (but we're not // there yet), signal the walker to descend into any subdirs if approachingMatchingTree(nodepath) { + // print node leading up to the target paths + if !printedDir { + printer.Node(nodepath, node, true) + } return nil } // otherwise, signal the walker to not walk recursively into any // subdirs if node.Type == "dir" { + // immediately generate leaveDir if the directory is skipped if printedDir { printer.LeaveDir(nodepath) } @@ -401,7 +411,7 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri ProcessNode: processNode, LeaveDir: func(path string) { // the root path `/` has no corresponding node and is thus also skipped by processNode - if withinDir(path) && path != "/" { + if path != "/" { printer.LeaveDir(path) } }, diff --git a/cmd/restic/cmd_ls_integration_test.go b/cmd/restic/cmd_ls_integration_test.go index 1b3c964e4..2b742d1b2 100644 --- a/cmd/restic/cmd_ls_integration_test.go +++ b/cmd/restic/cmd_ls_integration_test.go @@ -35,13 +35,16 @@ func TestRunLsNcdu(t *testing.T) { env, cleanup := withTestEnvironment(t) defer cleanup() - testRunInit(t, env.gopts) + testSetupBackupData(t, env) opts := BackupOptions{} testRunBackup(t, filepath.Dir(env.testdata), []string{"testdata"}, opts, env.gopts) - ncdu := testRunLsWithOpts(t, env.gopts, LsOptions{Ncdu: true}, []string{"latest"}) - assertIsValidJSON(t, ncdu) - - ncdu = testRunLsWithOpts(t, env.gopts, LsOptions{Ncdu: true}, []string{"latest", "/testdata"}) - assertIsValidJSON(t, ncdu) + for _, paths := range [][]string{ + {"latest"}, + {"latest", "/testdata"}, + {"latest", "/testdata/0", "/testdata/0/tests"}, + } { + ncdu := testRunLsWithOpts(t, env.gopts, LsOptions{Ncdu: true}, paths) + assertIsValidJSON(t, ncdu) + } } diff --git a/cmd/restic/cmd_ls_test.go b/cmd/restic/cmd_ls_test.go index 828b2920e..a59b5f81b 100644 --- a/cmd/restic/cmd_ls_test.go +++ b/cmd/restic/cmd_ls_test.go @@ -140,12 +140,12 @@ func TestLsNcdu(t *testing.T) { printer.Node("/directory", &restic.Node{ Type: "dir", Name: "directory", - }) + }, false) printer.Node("/directory/data", &restic.Node{ Type: "file", Name: "data", Size: 42, - }) + }, false) printer.LeaveDir("/directory") printer.Close()