summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukas@labunix.xyz>2026-09-15 00:41:00 +0200
committerLukasz Kasprzak <lukas@labunix.xyz>2026-09-15 00:41:00 +0200
commit2e812847572839e6c8097a7ecf5c4a469222087a (patch)
treef2c8908d235469dbdb4091984231d2ddb3beb3c8 /cmd
parent2a7452c3fd83000f239755825f38246f8537b6cc (diff)
downloadkrino-2e812847572839e6c8097a7ecf5c4a469222087a.tar.gz
krino-2e812847572839e6c8097a7ecf5c4a469222087a.zip
only where an earlier directory's files ended up stays claimed
Diffstat (limited to 'cmd')
-rw-r--r--cmd/krino/sort.go16
-rw-r--r--cmd/krino/sort_test.go29
2 files changed, 44 insertions, 1 deletions
diff --git a/cmd/krino/sort.go b/cmd/krino/sort.go
index b516629..aeeb1d4 100644
--- a/cmd/krino/sort.go
+++ b/cmd/krino/sort.go
@@ -264,12 +264,26 @@ func cmdSort(g *globals, names []string, stdout, stderr io.Writer) int {
}
res, aerr := e.Apply(ctx, toApply, approved, j, run)
if res != nil {
+ // Where files ended up: each copy, and the last place a
+ // move or rename put the file - not a path it passed
+ // through and left.
for _, fr := range res.Files {
+ final := ""
for _, sr := range fr.Steps {
- if sr.Status == "ok" && sr.Dst != "" {
+ switch {
+ case sr.Status != "ok":
+ case sr.Step.Kind == plan.DeletePermanent:
+ final = "" // gone: nothing is left anywhere
+ case sr.Dst == "":
+ case sr.Step.Kind == plan.Copy:
applied = append(applied, sr.Dst)
+ default:
+ final = sr.Dst
}
}
+ if final != "" {
+ applied = append(applied, final)
+ }
}
}
if aerr != nil {
diff --git a/cmd/krino/sort_test.go b/cmd/krino/sort_test.go
index 071a64d..4f3e29f 100644
--- a/cmd/krino/sort_test.go
+++ b/cmd/krino/sort_test.go
@@ -366,3 +366,32 @@ func TestLaterDirectoryNeverOverwritesAnEarlierOnesResult(t *testing.T) {
t.Errorf("the Trash holds %d entries; nothing should have been displaced", len(entries))
}
}
+
+// TestOnlyWhereFilesEndedUpStaysClaimed: a path an earlier directory's file
+// passed through and left - renamed, then moved on - is free for a later
+// directory; only where files ended up stays claimed (plan 11 re-check).
+func TestOnlyWhereFilesEndedUpStaysClaimed(t *testing.T) {
+ h := home(t)
+ old := time.Date(2026, 1, 1, 0, 0, 0, 0, time.UTC)
+ if code, _, errOut := runCLI(t, "init"); code != 0 {
+ t.Fatal(errOut)
+ }
+ for _, n := range []string{"a", "b"} {
+ p := filepath.Join(h, n, "x.pdf")
+ os.MkdirAll(filepath.Dir(p), 0o755)
+ os.WriteFile(p, []byte("from "+n), 0o644)
+ os.Chtimes(p, old, old)
+ if code, _, errOut := runCLI(t, "new", n, filepath.Join(h, n)); code != 0 {
+ t.Fatal(errOut)
+ }
+ }
+ dirs := filepath.Join(h, ".config", "krino", "dirs")
+ os.WriteFile(filepath.Join(dirs, "a.conf"), []byte("(path \"~/a\")\n(rule \"r\" (rename \"x-r.pdf\") (move \"~/Out\"))\n"), 0o644)
+ os.WriteFile(filepath.Join(dirs, "b.conf"), []byte("(path \"~/b\")\n(rule \"r\" (rename \"x-r.pdf\") (move \"~/a\"))\n"), 0o644)
+ if code, out, errOut := runCLI(t, "-y", "a", "b"); code != 0 {
+ t.Fatalf("exit %d\n%s\n%s", code, out, errOut)
+ }
+ if b, err := os.ReadFile(filepath.Join(h, "a", "x-r.pdf")); err != nil || string(b) != "from b" {
+ t.Errorf("a/x-r.pdf: %q, %v; want b's file under its planned name", b, err)
+ }
+}