Proposal from the acceptance test (#164). It needs your decision before anyone builds it.
What is missing
There is no way to tell sfdupes that a tree is gone. After a user deletes a duplicate tree that the report named, its records stay in the database, and report and trees keep listing it.
Example from the test:
sfdupes scan tree/elsewhere recorded 20 files, all duplicates of files in other directories.
The directory was deleted, as a user acting on the report would do.
sfdupes scan tree/elsewhere then failed with sfdupes: resolve .../tree/elsewhere: lstat .../tree/elsewhere: no such file or directory and exit 1. README.md specifies that: an operand that does not exist is a fatal error.
report still named the deleted directory in 40 rows, and trees in 2.
The two ways out today:
Scan a parent directory that still exists. That walks everything under the parent, which is all of /srv to forget /srv/old-backup.
Delete the database and hash everything again.
A cron line with several operands, sfdupes scan /srv/a /srv/b, has the same problem: once /srv/b is removed, every scan fails before it walks /srv/a.
Why a user expects it
Find, delete, look again is what a duplicate finder is used for. The step after deleting should be quick and should not need a walk of the whole disk.
Your choices
A subcommand that drops records: for example sfdupes forget PATH... deletes the records at or below each path. It reads no filesystem and takes the scan lock. The name is yours to choose.
scan drops a missing operand's records: a missing operand stops being a fatal error. Its records are deleted and the other operands are scanned. The catch: today the fatal error keeps the records safe when an operand is missing only because its disk is not mounted, and that protection would go.
Leave as is: the README says to scan the parent.
Recommended: A subcommand that drops records. It is explicit, and it leaves the fatal error, and the protection it gives, in place.
Model: fable-5-2
Proposal from the acceptance test (https://git.eeqj.de/sneak/sfdupes/issues/164). It needs your decision before anyone builds it.
## What is missing
There is no way to tell `sfdupes` that a tree is gone. After a user deletes a duplicate tree that the report named, its records stay in the database, and `report` and `trees` keep listing it.
Example from the test:
- `sfdupes scan tree/elsewhere` recorded 20 files, all duplicates of files in other directories.
- The directory was deleted, as a user acting on the report would do.
- `sfdupes scan tree/elsewhere` then failed with `sfdupes: resolve .../tree/elsewhere: lstat .../tree/elsewhere: no such file or directory` and exit 1. `README.md` specifies that: an operand that does not exist is a fatal error.
- `report` still named the deleted directory in 40 rows, and `trees` in 2.
The two ways out today:
- Scan a parent directory that still exists. That walks everything under the parent, which is all of `/srv` to forget `/srv/old-backup`.
- Delete the database and hash everything again.
A `cron` line with several operands, `sfdupes scan /srv/a /srv/b`, has the same problem: once `/srv/b` is removed, every scan fails before it walks `/srv/a`.
## Why a user expects it
Find, delete, look again is what a duplicate finder is used for. The step after deleting should be quick and should not need a walk of the whole disk.
## Your choices
- **A subcommand that drops records**: for example `sfdupes forget PATH...` deletes the records at or below each path. It reads no filesystem and takes the scan lock. The name is yours to choose.
- **`scan` drops a missing operand's records**: a missing operand stops being a fatal error. Its records are deleted and the other operands are scanned. The catch: today the fatal error keeps the records safe when an operand is missing only because its disk is not mounted, and that protection would go.
- **Leave as is**: the README says to scan the parent.
Recommended: **A subcommand that drops records**. It is explicit, and it leaves the fatal error, and the protection it gives, in place.
Model: fable-5-2
sneak
was assigned by clawbot2026-11-11 01:06:01 +01:00
only have 'report' do stat() on the top level duplicate, not on every file in the proposed tree. it's the user's fault if the report isn't fresh bc they didn't run scan recently enough.
only have 'report' do stat() on the top level duplicate, not on every file in the proposed tree. it's the user's fault if the report isn't fresh bc they didn't run scan recently enough.
sneak rejected the proposal and ruled instead (11 November, about 02:21 UTC), which is the definition of done:
A missing operand stays a fatal error for scan.
report and trees show only duplicates that still exist: for each duplicate group, stat() only its top-level entry (the file, or the root of a duplicate tree), never every file below it, and leave the group out if that entry is gone.
A stale report from an old scan is the user's to fix by scanning again; say so in the README.
Tests cover a removed top-level duplicate disappearing from the report.
Model: opus-5-5
sneak rejected the proposal and ruled instead (11 November, about 02:21 UTC), which is the definition of done:
- A missing operand stays a fatal error for `scan`.
- `report` and `trees` show only duplicates that still exist: for each duplicate group, `stat()` only its top-level entry (the file, or the root of a duplicate tree), never every file below it, and leave the group out if that entry is gone.
- A stale report from an old scan is the user's to fix by scanning again; say so in the README.
- Tests cover a removed top-level duplicate disappearing from the report.
Model: opus-5-5
sneak
was unassigned by clawbot2026-11-11 03:24:03 +01:00
Built in #184. report checks each path of a possible duplicate group with lstat. trees checks only the directory at the top of each copy. A copy that is gone is left out, and so is a group left with one copy. scan still fails on a missing operand. A permission error counts as present, so an unprivileged user's report stays whole.
Model: opus-5-5
Built in https://git.eeqj.de/sneak/sfdupes/pulls/184. `report` checks each path of a possible duplicate group with `lstat`. `trees` checks only the directory at the top of each copy. A copy that is gone is left out, and so is a group left with one copy. `scan` still fails on a missing operand. A permission error counts as present, so an unprivileged user's report stays whole.
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.
Proposal from the acceptance test (#164). It needs your decision before anyone builds it.
What is missing
There is no way to tell
sfdupesthat a tree is gone. After a user deletes a duplicate tree that the report named, its records stay in the database, andreportandtreeskeep listing it.Example from the test:
sfdupes scan tree/elsewhererecorded 20 files, all duplicates of files in other directories.sfdupes scan tree/elsewherethen failed withsfdupes: resolve .../tree/elsewhere: lstat .../tree/elsewhere: no such file or directoryand exit 1.README.mdspecifies that: an operand that does not exist is a fatal error.reportstill named the deleted directory in 40 rows, andtreesin 2.The two ways out today:
/srvto forget/srv/old-backup.A
cronline with several operands,sfdupes scan /srv/a /srv/b, has the same problem: once/srv/bis removed, every scan fails before it walks/srv/a.Why a user expects it
Find, delete, look again is what a duplicate finder is used for. The step after deleting should be quick and should not need a walk of the whole disk.
Your choices
sfdupes forget PATH...deletes the records at or below each path. It reads no filesystem and takes the scan lock. The name is yours to choose.scandrops a missing operand's records: a missing operand stops being a fatal error. Its records are deleted and the other operands are scanned. The catch: today the fatal error keeps the records safe when an operand is missing only because its disk is not mounted, and that protection would go.Recommended: A subcommand that drops records. It is explicit, and it leaves the fatal error, and the protection it gives, in place.
Model: fable-5-2
no, missing operands are still a fatal error. make the report filter on extant duplicates only when reporting.
only have 'report' do stat() on the top level duplicate, not on every file in the proposed tree. it's the user's fault if the report isn't fresh bc they didn't run scan recently enough.
sneak rejected the proposal and ruled instead (11 November, about 02:21 UTC), which is the definition of done:
scan.reportandtreesshow only duplicates that still exist: for each duplicate group,stat()only its top-level entry (the file, or the root of a duplicate tree), never every file below it, and leave the group out if that entry is gone.Model: opus-5-5
Built in #184.
reportchecks each path of a possible duplicate group withlstat.treeschecks only the directory at the top of each copy. A copy that is gone is left out, and so is a group left with one copy.scanstill fails on a missing operand. A permission error counts as present, so an unprivileged user's report stays whole.Model: opus-5-5