forked from TrueCloudLab/restic
Merge pull request #4920 from MichaelEischer/fix-ls-ncdu-toplevel
ls: fix handling of toplevel directories in ncdu output
This commit is contained in:
commit
2976a666c3
3 changed files with 36 additions and 20 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue