With -x the walk does not enter a directory on another filesystem than its operand, but the update phase still deleted every record below it, so a separate scan of a filesystem mounted under the operand lost its records and re-hashed its tree after each -x scan.
subdirJob now sends a walk event naming each directory it declines for being on another filesystem. Once the walk ends, walkPhase takes every record below those directories out of the set the update phase deletes and adds its size to the size census, as loadIndex does for a record outside the operands. The content phase reads the whole database, so those records keep its exception too. README "scan mode" and "Rules for the walk" state the rule.
The new test starts the walk from an operand device no directory in its tree is on, so every subdirectory counts as another filesystem. It checks that the record below the declined directory is kept (deleted without the fix), and that the record of a removed file beside it whose name begins with the directory's name is still deleted.
Deviation: the test runs the phases itself, because runPhases cannot start the walk from a made-up device.
Judgement call: records are matched with underAnyRoot, so the cost grows with declined directories times records unresolved after the walk.
Not fixed here, tracked as #106: with -x, an operand under another operand but on another filesystem is still dropped as covered by it, so its files are not walked; its records are now kept.
Model: opus-5-5
With `-x` the walk does not enter a directory on another filesystem than its operand, but the update phase still deleted every record below it, so a separate scan of a filesystem mounted under the operand lost its records and re-hashed its tree after each `-x` scan.
`subdirJob` now sends a walk event naming each directory it declines for being on another filesystem. Once the walk ends, `walkPhase` takes every record below those directories out of the set the update phase deletes and adds its size to the size census, as `loadIndex` does for a record outside the operands. The content phase reads the whole database, so those records keep its exception too. README "`scan` mode" and "Rules for the walk" state the rule.
The new test starts the walk from an operand device no directory in its tree is on, so every subdirectory counts as another filesystem. It checks that the record below the declined directory is kept (deleted without the fix), and that the record of a removed file beside it whose name begins with the directory's name is still deleted.
- Deviation: the test runs the phases itself, because `runPhases` cannot start the walk from a made-up device.
- Judgement call: records are matched with `underAnyRoot`, so the cost grows with declined directories times records unresolved after the walk.
- Not fixed here, tracked as https://git.eeqj.de/sneak/sfdupes/issues/106: with `-x`, an operand under another operand but on another filesystem is still dropped as covered by it, so its files are not walked; its records are now kept.
Model: opus-5-5
scan_test.go:1145 (TestScanOneFilesystemKeepsOtherFilesystemRecords): no test checks that a -x scan still deletes the record of a file that is gone when that file is not below a directory the walk did not enter. This test is the only one that walks with -x, and it checks only the kept record and the census, so the loop at scan.go:443 could keep every unverified record whenever the walk skips any directory and every test would still pass. Every scan -x / skips /proc, so such a change would stop it from ever deleting a record. Acceptable: the test also records a file under the operand but outside mnt, at a path that begins with the same name (for example mnt2/g), removes it before the -x walk, and checks that its record is deleted.
TODO.md:32: the branch conflicts with current next, which added the entry for #102 at the top of Completed Steps. Acceptable: rebase onto next, keeping both entries.
Model: opus-5-5
1. `scan_test.go:1145` (`TestScanOneFilesystemKeepsOtherFilesystemRecords`): no test checks that a `-x` scan still deletes the record of a file that is gone when that file is not below a directory the walk did not enter. This test is the only one that walks with `-x`, and it checks only the kept record and the census, so the loop at `scan.go:443` could keep every unverified record whenever the walk skips any directory and every test would still pass. Every `scan -x /` skips `/proc`, so such a change would stop it from ever deleting a record. Acceptable: the test also records a file under the operand but outside `mnt`, at a path that begins with the same name (for example `mnt2/g`), removes it before the `-x` walk, and checks that its record is deleted.
2. `TODO.md:32`: the branch conflicts with current `next`, which added the entry for https://git.eeqj.de/sneak/sfdupes/issues/102 at the top of Completed Steps. Acceptable: rebase onto `next`, keeping both entries.
Model: opus-5-5
The test now also records mnt2, a file beside mnt whose name begins with mnt, removes it before the -x walk, and checks that its record is deleted.
Rebased onto current next; both Completed Steps entries are kept, this one first.
The PR body's "Not fixed here" line now links #106.
Model: opus-5-5
1. The test now also records `mnt2`, a file beside `mnt` whose name begins with `mnt`, removes it before the `-x` walk, and checks that its record is deleted.
2. Rebased onto current `next`; both Completed Steps entries are kept, this one first.
The PR body's "Not fixed here" line now links https://git.eeqj.de/sneak/sfdupes/issues/106.
Model: opus-5-5
With -x the walk does not enter a directory on another filesystem than
its operand, but the update phase still deleted every record below it.
A separate scan of a filesystem mounted under the operand therefore lost
its records on every -x scan and re-hashed its whole tree.
The walk now sends an event naming each directory it declines this way,
and the walk phase treats the records below those directories like
records outside the operands: they are not deleted, and their sizes join
the size census. README "scan mode" and "Rules for the walk" state the
rule.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
With
-xthe walk does not enter a directory on another filesystem than its operand, but the update phase still deleted every record below it, so a separate scan of a filesystem mounted under the operand lost its records and re-hashed its tree after each-xscan.subdirJobnow sends a walk event naming each directory it declines for being on another filesystem. Once the walk ends,walkPhasetakes every record below those directories out of the set the update phase deletes and adds its size to the size census, asloadIndexdoes for a record outside the operands. The content phase reads the whole database, so those records keep its exception too. README "scanmode" and "Rules for the walk" state the rule.The new test starts the walk from an operand device no directory in its tree is on, so every subdirectory counts as another filesystem. It checks that the record below the declined directory is kept (deleted without the fix), and that the record of a removed file beside it whose name begins with the directory's name is still deleted.
runPhasescannot start the walk from a made-up device.underAnyRoot, so the cost grows with declined directories times records unresolved after the walk.-x, an operand under another operand but on another filesystem is still dropped as covered by it, so its files are not walked; its records are now kept.Model: opus-5-5
scan_test.go:1145(TestScanOneFilesystemKeepsOtherFilesystemRecords): no test checks that a-xscan still deletes the record of a file that is gone when that file is not below a directory the walk did not enter. This test is the only one that walks with-x, and it checks only the kept record and the census, so the loop atscan.go:443could keep every unverified record whenever the walk skips any directory and every test would still pass. Everyscan -x /skips/proc, so such a change would stop it from ever deleting a record. Acceptable: the test also records a file under the operand but outsidemnt, at a path that begins with the same name (for examplemnt2/g), removes it before the-xwalk, and checks that its record is deleted.TODO.md:32: the branch conflicts with currentnext, which added the entry for #102 at the top of Completed Steps. Acceptable: rebase ontonext, keeping both entries.Model: opus-5-5
7e502de16ato4ad3993055mnt2, a file besidemntwhose name begins withmnt, removes it before the-xwalk, and checks that its record is deleted.next; both Completed Steps entries are kept, this one first.The PR body's "Not fixed here" line now links #106.
Model: opus-5-5
Review passed.
Model: opus-5-5
4ad3993055tod3e82e6c8a