Merge pull request #4920 from MichaelEischer/fix-ls-ncdu-toplevel

ls: fix handling of toplevel directories in ncdu output
This commit is contained in:
Michael Eischer 2024-07-14 11:09:57 +02:00 committed by GitHub
commit 2976a666c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 36 additions and 20 deletions

View file

@ -178,7 +178,7 @@ func (p *ncduLsPrinter) Snapshot(sn *restic.Snapshot) {
Warnf("JSON encode failed: %v\n", err) Warnf("JSON encode failed: %v\n", err)
} }
p.depth++ p.depth++
fmt.Fprintf(p.out, "[%d, %d, %s", NcduMajorVer, NcduMinorVer, string(snapshotBytes)) fmt.Fprintf(p.out, "[%d, %d, %s, [{\"name\":\"/\"}", NcduMajorVer, NcduMinorVer, string(snapshotBytes))
} }
func lsNcduNode(_ string, node *restic.Node) ([]byte, error) { func lsNcduNode(_ string, node *restic.Node) ([]byte, error) {
@ -222,6 +222,10 @@ func lsNcduNode(_ string, node *restic.Node) ([]byte, error) {
if node.Mode&os.ModeSticky != 0 { if node.Mode&os.ModeSticky != 0 {
outNode.Mode |= 0o1000 outNode.Mode |= 0o1000
} }
if outNode.Mtime < 0 {
// ncdu does not allow negative times
outNode.Mtime = 0
}
return json.Marshal(outNode) return json.Marshal(outNode)
} }
@ -246,7 +250,7 @@ func (p *ncduLsPrinter) LeaveDir(_ string) {
} }
func (p *ncduLsPrinter) Close() { func (p *ncduLsPrinter) Close() {
fmt.Fprint(p.out, "\n]\n") fmt.Fprint(p.out, "\n]\n]\n")
} }
type textLsPrinter struct { type textLsPrinter struct {

View file

@ -3,7 +3,6 @@ package main
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"path/filepath"
"strings" "strings"
"testing" "testing"
@ -26,9 +25,10 @@ func testRunLs(t testing.TB, gopts GlobalOptions, snapshotID string) []string {
func assertIsValidJSON(t *testing.T, data []byte) { func assertIsValidJSON(t *testing.T, data []byte) {
// Sanity check: output must be valid JSON. // Sanity check: output must be valid JSON.
var v interface{} var v []any
err := json.Unmarshal(data, &v) err := json.Unmarshal(data, &v)
rtest.OK(t, err) rtest.OK(t, err)
rtest.Assert(t, len(v) == 4, "invalid ncdu output, expected 4 array elements, got %v", len(v))
} }
func TestRunLsNcdu(t *testing.T) { func TestRunLsNcdu(t *testing.T) {
@ -37,12 +37,13 @@ func TestRunLsNcdu(t *testing.T) {
testSetupBackupData(t, env) testSetupBackupData(t, env)
opts := BackupOptions{} opts := BackupOptions{}
testRunBackup(t, filepath.Dir(env.testdata), []string{"testdata"}, opts, env.gopts) // backup such that there are multiple toplevel elements
testRunBackup(t, env.testdata+"/0", []string{"."}, opts, env.gopts)
for _, paths := range [][]string{ for _, paths := range [][]string{
{"latest"}, {"latest"},
{"latest", "/testdata"}, {"latest", "/0"},
{"latest", "/testdata/0", "/testdata/0/tests"}, {"latest", "/0", "/0/9"},
} { } {
ncdu := testRunLsWithOpts(t, env.gopts, LsOptions{Ncdu: true}, paths) ncdu := testRunLsWithOpts(t, env.gopts, LsOptions{Ncdu: true}, paths)
assertIsValidJSON(t, ncdu) assertIsValidJSON(t, ncdu)

View file

@ -109,11 +109,11 @@ func TestLsNodeJSON(t *testing.T) {
func TestLsNcduNode(t *testing.T) { func TestLsNcduNode(t *testing.T) {
for i, expect := range []string{ for i, expect := range []string{
`{"name":"baz","asize":12345,"dsize":12800,"dev":0,"ino":0,"nlink":1,"notreg":false,"uid":10000000,"gid":20000000,"mode":0,"mtime":-62135596800}`, `{"name":"baz","asize":12345,"dsize":12800,"dev":0,"ino":0,"nlink":1,"notreg":false,"uid":10000000,"gid":20000000,"mode":0,"mtime":0}`,
`{"name":"empty","asize":0,"dsize":0,"dev":0,"ino":0,"nlink":3840,"notreg":false,"uid":1001,"gid":1001,"mode":0,"mtime":-62135596800}`, `{"name":"empty","asize":0,"dsize":0,"dev":0,"ino":0,"nlink":3840,"notreg":false,"uid":1001,"gid":1001,"mode":0,"mtime":0}`,
`{"name":"link","asize":0,"dsize":0,"dev":0,"ino":0,"nlink":0,"notreg":true,"uid":0,"gid":0,"mode":511,"mtime":-62135596800}`, `{"name":"link","asize":0,"dsize":0,"dev":0,"ino":0,"nlink":0,"notreg":true,"uid":0,"gid":0,"mode":511,"mtime":0}`,
`{"name":"directory","asize":0,"dsize":0,"dev":0,"ino":0,"nlink":0,"notreg":false,"uid":0,"gid":0,"mode":493,"mtime":1577934245}`, `{"name":"directory","asize":0,"dsize":0,"dev":0,"ino":0,"nlink":0,"notreg":false,"uid":0,"gid":0,"mode":493,"mtime":1577934245}`,
`{"name":"sticky","asize":0,"dsize":0,"dev":0,"ino":0,"nlink":0,"notreg":false,"uid":0,"gid":0,"mode":4077,"mtime":-62135596800}`, `{"name":"sticky","asize":0,"dsize":0,"dev":0,"ino":0,"nlink":0,"notreg":false,"uid":0,"gid":0,"mode":4077,"mtime":0}`,
} { } {
c := lsTestNodes[i] c := lsTestNodes[i]
out, err := lsNcduNode(c.path, &c.Node) out, err := lsNcduNode(c.path, &c.Node)
@ -132,28 +132,39 @@ func TestLsNcdu(t *testing.T) {
printer := &ncduLsPrinter{ printer := &ncduLsPrinter{
out: &buf, out: &buf,
} }
modTime := time.Date(2020, 1, 2, 3, 4, 5, 0, time.UTC)
printer.Snapshot(&restic.Snapshot{ printer.Snapshot(&restic.Snapshot{
Hostname: "host", Hostname: "host",
Paths: []string{"/example"}, Paths: []string{"/example"},
}) })
printer.Node("/directory", &restic.Node{ printer.Node("/directory", &restic.Node{
Type: "dir", Type: "dir",
Name: "directory", Name: "directory",
ModTime: modTime,
}, false) }, false)
printer.Node("/directory/data", &restic.Node{ printer.Node("/directory/data", &restic.Node{
Type: "file", Type: "file",
Name: "data", Name: "data",
Size: 42, Size: 42,
ModTime: modTime,
}, false) }, false)
printer.LeaveDir("/directory") printer.LeaveDir("/directory")
printer.Node("/file", &restic.Node{
Type: "file",
Name: "file",
Size: 12345,
ModTime: modTime,
}, false)
printer.Close() printer.Close()
rtest.Equals(t, `[1, 2, {"time":"0001-01-01T00:00:00Z","tree":null,"paths":["/example"],"hostname":"host"}, rtest.Equals(t, `[1, 2, {"time":"0001-01-01T00:00:00Z","tree":null,"paths":["/example"],"hostname":"host"}, [{"name":"/"},
[ [
{"name":"directory","asize":0,"dsize":0,"dev":0,"ino":0,"nlink":0,"notreg":false,"uid":0,"gid":0,"mode":0,"mtime":-62135596800}, {"name":"directory","asize":0,"dsize":0,"dev":0,"ino":0,"nlink":0,"notreg":false,"uid":0,"gid":0,"mode":0,"mtime":1577934245},
{"name":"data","asize":42,"dsize":512,"dev":0,"ino":0,"nlink":0,"notreg":false,"uid":0,"gid":0,"mode":0,"mtime":-62135596800} {"name":"data","asize":42,"dsize":512,"dev":0,"ino":0,"nlink":0,"notreg":false,"uid":0,"gid":0,"mode":0,"mtime":1577934245}
] ],
{"name":"file","asize":12345,"dsize":12800,"dev":0,"ino":0,"nlink":0,"notreg":false,"uid":0,"gid":0,"mode":0,"mtime":1577934245}
]
] ]
`, buf.String()) `, buf.String())
} }