Conversation
CONTRIBUTING.md told people to branch from main. main only moves at releases, so it sits well behind experimental, and a contributor following that instruction can rebuild work that already exists — which is what happened in #24. Adds a "Which branch to work from" section, switches the pull-request steps to experimental, says to change the PR base branch GitHub defaults to main, asks for an issue before anything substantial, and documents the backend test suite that now gates the CI build. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CONTRIBUTING.md told people to branch from main. main only moves at releases, so it sits well behind experimental, and a contributor following that instruction can rebuild work that already exists — which is what happened in #24. Adds a "Which branch to work from" section, switches the pull-request steps to experimental, says to change the PR base branch GitHub defaults to main, asks for an issue before anything substantial, and documents the backend test suite that now gates the CI build. Identical to the experimental copy, so the eventual merge is clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Thank you for this, the testing especially (running the script with no Python on PATH, injecting ln/mv/cmp failures, SIGKILL mid-rename) is better than I'd have asked for. Apologies but I do development work on the The bug you found is real - Because we both rewrote _build_dup_groups and the script generator from different premises where mine has no canonical copy at all, the script picks what to keep at runtime there's no clean merge path. I'll leave this open rather than close it. Please feel free to work from experimental, just note it's a working branch and can be mid-refactor on any given commit. auditorr itself never touches your files, but the scripts it generates do, so read one before you run it, especially while dedupe is in flux. Let me know if the dedupe script is missing anything and I'll incorporate your work as soon as I can. |
The duplicate map kept only one representative path per inode. If duplicate B had multiple hardlinks (for example, Luminarr and Darkpeers), replacing only Luminarr with a link to A left B's data alive through Darkpeers while the script still reported reclaimed space.
This change retains all known hardlink paths for each physical copy, merges overlapping groups, and groups copies by device and inode. The generated script compares content once per separate copy, creates a replacement hardlink before atomically replacing each included target, and counts each old copy's logical size only when its last hardlink is gone. Failed operations are reported, and partial or completed runs can be safely repeated.
Excluded paths remain untouched, and excluded or unscanned hardlinks prevent a reclamation claim. Filesystem boundaries are respected. The script runs directly on the Unraid host using Bash and standard system tools, with no Python dependency on the host.
Validation:
git diff --checkpassed.Limitations:
.auditorr-dedupe-*temporary directories, although target paths remain present and the script can be rerun.