add --no-recurse flag

This commit is contained in:
Christian Zangl 2024-08-21 21:14:13 +02:00
parent fb45c82625
commit 76c46c2cb4
No known key found for this signature in database
GPG Key ID: 6D468AC36E2A4B3D
4 changed files with 153 additions and 112 deletions

View File

@ -90,6 +90,7 @@ Flags:
--algo="blake3" hash algorithm: md5, sha512, blake3 (default: blake3)
-f, --force force update of damaged items
-s, --skip-symlinks do not follow symlinks
-R, --no-recurse do not recurse into subdirectories
-D, --no-dir-in-index do not track directories in the index
-l, --log-file=STRING write to a logfile if specified
--log-verbose verbose logging

View File

@ -50,6 +50,7 @@ var cli struct {
Algo string `default:"blake3" help:"hash algorithm: md5, sha512, blake3 (default: blake3)"`
Force bool `short:"f" help:"force update of damaged items"`
SkipSymlinks bool `short:"s" help:"do not follow symlinks"`
NoRecurse bool `short:"R" help:"do not recurse into subdirectories"`
NoDirInIndex bool `short:"D" help:"do not track directories in the index"`
LogFile string `short:"l" help:"write to a logfile if specified"`
LogVerbose bool `help:"verbose logging"`
@ -170,6 +171,7 @@ func (m *Main) process() bool {
m.context.ShowIgnoredOnly = cli.ShowIgnoredOnly
m.context.ShowMissing = cli.ShowMissing
m.context.SkipSymlinks = cli.SkipSymlinks
m.context.SkipSubdirectories = cli.NoRecurse
m.context.TrackDirectories = !cli.NoDirInIndex
var wg sync.WaitGroup

View File

@ -16,6 +16,7 @@ type Context struct {
HashAlgo string
TrackDirectories bool
SkipSymlinks bool
SkipSubdirectories bool
IndexFilename string
IgnoreFilename string
WorkQueue chan *WorkItem
@ -183,7 +184,9 @@ func (context *Context) scanDir(root string, parentIgnore *Ignore) {
context.addWork(root, filesToIndex, dirList, ignore)
if !context.SkipSubdirectories {
for _, name := range dirList {
context.scanDir(filepath.Join(root, name), ignore)
}
}
}

View File

@ -137,60 +137,87 @@ func TestRoot(t *testing.T) {
tool := getCmd()
root := filepath.Join(testDir, "root")
// step1: update index
// update index, no recourse
t.Run("Step1", func(t *testing.T) {
cmd := exec.Command(tool, "-umR", filepath.Join(root, "day/office"))
out, err := cmd.Output()
if err != nil {
t.Fatalf("failed with '%s'\n", err)
}
sout := string(out)
checkOut(t, sout, "Processed 5 files")
checkOut(t, sout, "- 1 directory was updated")
checkOut(t, sout, "- 5 file hashes were added")
checkOut(t, sout, "- 0 file hashes were updated")
checkNotOut(t, sout, "removed")
})
// update remaining index from root
t.Run("Step2", func(t *testing.T) {
cmd := exec.Command(tool, "-um", root)
out, err := cmd.Output()
if err != nil {
t.Fatalf("step1 failed with '%s'\n", err)
t.Fatalf("failed with '%s'\n", err)
}
sout := string(out)
checkOut(t, sout, "67 directories were updated")
checkOut(t, sout, "300 file hashes were added")
checkOut(t, sout, "Processed 300 files")
checkOut(t, sout, "- 66 directories were updated")
checkOut(t, sout, "- 295 file hashes were added")
checkOut(t, sout, "- 0 file hashes were updated")
checkNotOut(t, sout, "removed")
})
// step2: delete files, check for missing
// delete files, check for missing
t.Run("Step3", func(t *testing.T) {
os.RemoveAll(filepath.Join(root, "thing/change"))
os.Remove(filepath.Join(root, "time/hour/minute/body-information.csv"))
cmd = exec.Command(tool, "-m", root)
out, err = cmd.Output()
cmd := exec.Command(tool, "-m", root)
out, err := cmd.Output()
if err != nil {
t.Fatalf("step2 failed with '%s'\n", err)
t.Fatalf("failed with '%s'\n", err)
}
sout = string(out)
sout := string(out)
checkOut(t, sout, "del /tmp/chkbit/root/thing/change/")
checkOut(t, sout, "2 files/directories would have been removed")
})
// step2a: do not report missing without -m
cmd = exec.Command(tool, root)
out, err = cmd.Output()
// do not report missing without -m
t.Run("Step4", func(t *testing.T) {
cmd := exec.Command(tool, root)
out, err := cmd.Output()
if err != nil {
t.Fatalf("step2a failed with '%s'\n", err)
t.Fatalf("failed with '%s'\n", err)
}
sout = string(out)
sout := string(out)
checkNotOut(t, sout, "del ")
checkNotOut(t, sout, "removed")
})
// step3: check for missing and update
cmd = exec.Command(tool, "-um", root)
out, err = cmd.Output()
// check for missing and update
t.Run("Step5", func(t *testing.T) {
cmd := exec.Command(tool, "-um", root)
out, err := cmd.Output()
if err != nil {
t.Fatalf("step3 failed with '%s'\n", err)
t.Fatalf("failed with '%s'\n", err)
}
sout = string(out)
sout := string(out)
checkOut(t, sout, "del /tmp/chkbit/root/thing/change/")
checkOut(t, sout, "2 files/directories have been removed")
})
// step4: check again
// check again
t.Run("Step6", func(t *testing.T) {
for i := 0; i < 10; i++ {
cmd = exec.Command(tool, "-u", root)
out, err = cmd.Output()
cmd := exec.Command(tool, "-u", root)
out, err := cmd.Output()
if err != nil {
t.Fatalf("step4 failed with '%s'\n", err)
t.Fatalf("failed with '%s'\n", err)
}
sout = string(out)
sout := string(out)
checkOut(t, sout, "Processed 289 files")
}
})
}
func TestDMG(t *testing.T) {
@ -216,50 +243,58 @@ func TestDMG(t *testing.T) {
t2, _ := time.Parse(time.RFC3339, "2022-02-01T12:00:00Z")
t3, _ := time.Parse(time.RFC3339, "2022-02-01T13:00:00Z")
// step1: create test and set the modified time"
// create test and set the modified time"
t.Run("Step1", func(t *testing.T) {
os.WriteFile(testFile, []byte("foo1"), 0644)
os.Chtimes(testFile, t2, t2)
cmd := exec.Command(tool, "-u", ".")
if out, err := cmd.Output(); err != nil {
t.Fatalf("step1 failed with '%s'\n", err)
t.Fatalf("failed with '%s'\n", err)
} else {
checkOut(t, string(out), "new test.txt")
}
})
// step2: update test with different content & old modified (expect 'old')"
// update test with different content & old modified (expect 'old')"
t.Run("Step2", func(t *testing.T) {
os.WriteFile(testFile, []byte("foo2"), 0644)
os.Chtimes(testFile, t1, t1)
cmd = exec.Command(tool, "-u", ".")
cmd := exec.Command(tool, "-u", ".")
if out, err := cmd.Output(); err != nil {
t.Fatalf("step2 failed with '%s'\n", err)
t.Fatalf("failed with '%s'\n", err)
} else {
checkOut(t, string(out), "old test.txt")
}
})
// step3: update test & new modified (expect 'upd')"
// update test & new modified (expect 'upd')"
t.Run("Step3", func(t *testing.T) {
os.WriteFile(testFile, []byte("foo3"), 0644)
os.Chtimes(testFile, t3, t3)
cmd = exec.Command(tool, "-u", ".")
cmd := exec.Command(tool, "-u", ".")
if out, err := cmd.Output(); err != nil {
t.Fatalf("step3 failed with '%s'\n", err)
t.Fatalf("failed with '%s'\n", err)
} else {
checkOut(t, string(out), "upd test.txt")
}
})
// step4: Now update test with the same modified to simulate damage (expect DMG)"
// Now update test with the same modified to simulate damage (expect DMG)"
t.Run("Step4", func(t *testing.T) {
os.WriteFile(testFile, []byte("foo4"), 0644)
os.Chtimes(testFile, t3, t3)
cmd = exec.Command(tool, "-u", ".")
cmd := exec.Command(tool, "-u", ".")
if out, err := cmd.Output(); err != nil {
if cmd.ProcessState.ExitCode() != 1 {
t.Fatalf("step4 expected to fail with exit code 1 vs %d!", cmd.ProcessState.ExitCode())
t.Fatalf("expected to fail with exit code 1 vs %d!", cmd.ProcessState.ExitCode())
}
checkOut(t, string(out), "DMG test.txt")
} else {
t.Fatal("step4 expected to fail!")
t.Fatal("expected to fail!")
}
})
}