From 8eab0f1ceb67d4b25d34c1edf9aecf48ad437ce9 Mon Sep 17 00:00:00 2001 From: Christian Zangl Date: Thu, 22 Aug 2024 16:02:58 +0200 Subject: [PATCH] new --add-only mode --- README.md | 1 + cmd/chkbit/main.go | 8 +++-- context.go | 5 ++- index.go | 9 ++++-- scripts/run_test.go | 74 ++++++++++++++++++++++++++++++++++----------- 5 files changed, 74 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 0ed2e9b..5bc3aa6 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ Flags: -H, --tips Show tips. -c, --check check mode: chkbit will verify files in readonly mode (default mode) -u, --update update mode: add and update indices + -a, --add-only add mode: only add new files, do not check existing (quicker) -i, --show-ignored-only show-ignored mode: only show ignored files -m, --show-missing show missing files/directories --force force update of damaged items (advanced usage only) diff --git a/cmd/chkbit/main.go b/cmd/chkbit/main.go index 2011534..ee5ec4d 100644 --- a/cmd/chkbit/main.go +++ b/cmd/chkbit/main.go @@ -46,6 +46,7 @@ var cli struct { Tips bool `short:"H" help:"Show tips."` Check bool `short:"c" help:"check mode: chkbit will verify files in readonly mode (default mode)"` Update bool `short:"u" help:"update mode: add and update indices"` + AddOnly bool `short:"a" help:"add mode: only add new files, do not check existing (quicker)"` ShowIgnoredOnly bool `short:"i" help:"show-ignored mode: only show ignored files"` ShowMissing bool `short:"m" help:"show missing files/directories"` Force bool `help:"force update of damaged items (advanced usage only)"` @@ -158,9 +159,9 @@ func (m *Main) showStatus() { func (m *Main) process() bool { // verify mode var b01 = map[bool]int8{false: 0, true: 1} - if b01[cli.Check]+b01[cli.Update]+b01[cli.ShowIgnoredOnly] > 1 { + if b01[cli.Check]+b01[cli.Update]+b01[cli.AddOnly]+b01[cli.ShowIgnoredOnly] > 1 { fmt.Println("Error: can only run one mode at a time!") - return false + os.Exit(1) } var err error @@ -170,7 +171,8 @@ func (m *Main) process() bool { return false } m.context.ForceUpdateDmg = cli.Force - m.context.UpdateIndex = cli.Update + m.context.UpdateIndex = cli.Update || cli.AddOnly + m.context.AddOnly = cli.AddOnly m.context.ShowIgnoredOnly = cli.ShowIgnoredOnly m.context.ShowMissing = cli.ShowMissing m.context.SkipSymlinks = cli.SkipSymlinks diff --git a/context.go b/context.go index c9d05b5..b94ca08 100644 --- a/context.go +++ b/context.go @@ -10,6 +10,7 @@ import ( type Context struct { NumWorkers int UpdateIndex bool + AddOnly bool ShowIgnoredOnly bool ShowMissing bool ForceUpdateDmg bool @@ -71,7 +72,9 @@ func (context *Context) log(stat Status, message string) { context.NumTotal++ context.NumNew++ case STATUS_OK: - context.NumTotal++ + if !context.AddOnly { + context.NumTotal++ + } case STATUS_MISSING: context.NumDel++ //case STATUS_PANIC: diff --git a/index.go b/index.go index e4521d3..694d2d9 100644 --- a/index.go +++ b/index.go @@ -91,7 +91,7 @@ func (i *Index) calcHashes(ignore *Ignore) { var info *idxInfo algo := i.context.HashAlgo if val, ok := i.cur[name]; ok { - // existing + // existing file if val.LegacyHash != nil { // convert from py1 to new format val = idxInfo{ @@ -104,8 +104,13 @@ func (i *Index) calcHashes(ignore *Ignore) { if val.Algo != nil { algo = *val.Algo } - info, err = i.calcFile(name, algo) + if i.context.AddOnly { + info = &val + } else { + info, err = i.calcFile(name, algo) + } } else { + // new file if i.readonly { info = &idxInfo{Algo: &algo} } else { diff --git a/scripts/run_test.go b/scripts/run_test.go index 11c5366..bd378dd 100644 --- a/scripts/run_test.go +++ b/scripts/run_test.go @@ -67,7 +67,12 @@ func setDate(filename string, r int) { os.Chtimes(filename, date, date) } -func genFile(dir string, a int) { +func genFile(path string, size int) { + os.WriteFile(path, make([]byte, size), 0644) + setDate(path, size*size) +} + +func genFiles(dir string, a int) { os.MkdirAll(dir, 0755) for i := 1; i <= 5; i++ { size := a*i*wordIdx*100 + extIdx @@ -78,9 +83,7 @@ func genFile(dir string, a int) { } file += "." + nextExt() - path := filepath.Join(dir, file) - os.WriteFile(path, make([]byte, size), 0644) - setDate(path, size*size) + genFile(filepath.Join(dir, file), size) } } @@ -89,11 +92,11 @@ func genDir(root string) { for i := 1; i <= 5; i++ { dir := filepath.Join(root, start, nextWord()) - genFile(dir, 1) + genFiles(dir, 1) if wordIdx%3 == 0 { dir = filepath.Join(dir, nextWord()) - genFile(dir, 1) + genFiles(dir, 1) } } } @@ -140,7 +143,7 @@ func TestRoot(t *testing.T) { root := filepath.Join(testDir, "root") // update index, no recourse - t.Run("Step1", func(t *testing.T) { + t.Run("no-recourse", func(t *testing.T) { cmd := exec.Command(tool, "-umR", filepath.Join(root, "day/office")) out, err := cmd.Output() if err != nil { @@ -155,7 +158,7 @@ func TestRoot(t *testing.T) { }) // update remaining index from root - t.Run("Step2", func(t *testing.T) { + t.Run("update-remaining", func(t *testing.T) { cmd := exec.Command(tool, "-um", root) out, err := cmd.Output() if err != nil { @@ -170,7 +173,7 @@ func TestRoot(t *testing.T) { }) // delete files, check for missing - t.Run("Step3", func(t *testing.T) { + t.Run("delete", func(t *testing.T) { os.RemoveAll(filepath.Join(root, "thing/change")) os.Remove(filepath.Join(root, "time/hour/minute/body-information.csv")) @@ -185,7 +188,7 @@ func TestRoot(t *testing.T) { }) // do not report missing without -m - t.Run("Step4", func(t *testing.T) { + t.Run("no-missing", func(t *testing.T) { cmd := exec.Command(tool, root) out, err := cmd.Output() if err != nil { @@ -197,7 +200,7 @@ func TestRoot(t *testing.T) { }) // check for missing and update - t.Run("Step5", func(t *testing.T) { + t.Run("missing", func(t *testing.T) { cmd := exec.Command(tool, "-um", root) out, err := cmd.Output() if err != nil { @@ -209,16 +212,53 @@ func TestRoot(t *testing.T) { }) // check again - t.Run("Step6", func(t *testing.T) { + t.Run("repeat", func(t *testing.T) { for i := 0; i < 10; i++ { - cmd := exec.Command(tool, "-u", root) + cmd := exec.Command(tool, "-uv", root) out, err := cmd.Output() if err != nil { t.Fatalf("failed with '%s'\n", err) } sout := string(out) checkOut(t, sout, "Processed 289 files") + checkNotOut(t, sout, "removed") + checkNotOut(t, sout, "updated") + checkNotOut(t, sout, "added") + } + }) + + // add files only + t.Run("add-only", func(t *testing.T) { + + genFiles(filepath.Join(root, "way/add"), 99) + genFile(filepath.Join(root, "time/add-file.txt"), 500) + // modify existing, will not be reported: + genFile(filepath.Join(root, "way/job/word-business.mp3"), 500) + + cmd := exec.Command(tool, "-a", root) + out, err := cmd.Output() + if err != nil { + t.Fatalf("failed with '%s'\n", err) } + sout := string(out) + checkOut(t, sout, "Processed 6 files") + checkOut(t, sout, "- 3 directories were updated") + checkOut(t, sout, "- 6 file hashes were added") + checkOut(t, sout, "- 0 file hashes were updated") + }) + + // update remaining + t.Run("update-remaining-add", func(t *testing.T) { + cmd := exec.Command(tool, "-u", root) + out, err := cmd.Output() + if err != nil { + t.Fatalf("failed with '%s'\n", err) + } + sout := string(out) + checkOut(t, sout, "Processed 295 files") + checkOut(t, sout, "- 1 directory was updated") + checkOut(t, sout, "- 0 file hashes were added") + checkOut(t, sout, "- 1 file hash was updated") }) } @@ -246,7 +286,7 @@ func TestDMG(t *testing.T) { t3, _ := time.Parse(time.RFC3339, "2022-02-01T13:00:00Z") // create test and set the modified time" - t.Run("Step1", func(t *testing.T) { + t.Run("create", func(t *testing.T) { os.WriteFile(testFile, []byte("foo1"), 0644) os.Chtimes(testFile, t2, t2) @@ -259,7 +299,7 @@ func TestDMG(t *testing.T) { }) // update test with different content & old modified (expect 'old')" - t.Run("Step2", func(t *testing.T) { + t.Run("expect-old", func(t *testing.T) { os.WriteFile(testFile, []byte("foo2"), 0644) os.Chtimes(testFile, t1, t1) @@ -272,7 +312,7 @@ func TestDMG(t *testing.T) { }) // update test & new modified (expect 'upd')" - t.Run("Step3", func(t *testing.T) { + t.Run("expect-upd", func(t *testing.T) { os.WriteFile(testFile, []byte("foo3"), 0644) os.Chtimes(testFile, t3, t3) @@ -285,7 +325,7 @@ func TestDMG(t *testing.T) { }) // Now update test with the same modified to simulate damage (expect DMG)" - t.Run("Step4", func(t *testing.T) { + t.Run("expect-DMG", func(t *testing.T) { os.WriteFile(testFile, []byte("foo4"), 0644) os.Chtimes(testFile, t3, t3)