scan will maintain a persistent database of file signatures (default /var/lib/sfdupes/db.sqlite, overridable via SFDUPES_DATABASE) that survives between runs; rescans hash only new or changed files (mtime/size) and remove records for vanished files, so scan can be cronned daily. report and trees will read the database instead of a scan stream.
5.5 KiB
5.5 KiB
Workflow
- branch (from
main) - do the work in Next Step
- move Next Step to the top of Completed Steps
- move the top item of Future Steps into Next Step
- commit (
TODO.mdchanges in the same commit as the work) - merge to
mainif the branch is not protected, otherwise open a PR - push
Status
- pre-1.0
Next Step
- persistent scan database (branch
persistent-database):scanmaintains a SQLite database that survives between runs so it can be cronned daily;reportandtreesread the database instead of a scan stream. Database path defaults to/var/lib/sfdupes/db.sqlite, overridable viaSFDUPES_DATABASE. Plan:- update
README.md(the authoritative spec) for the database: new Database section, revisedscan/report/treesmodes, dependency list (modernc.org/sqlite, pure Go, cgo stays disabled), exit codes, smoke test with incremental steps - add
modernc.org/sqlite(hash-pinned viago.sum) db.go: path resolution (SFDUPES_DATABASEenv, default/var/lib/sfdupes/db.sqlite), open/create with WAL + busy-timeout pragmas andPRAGMA user_versionschema check,filestable (path BLOB primary key, size, mtime, head, tail), load-all-rows, and single-transaction apply of upserts/deletesscan.go: resolve operands to absolute paths; diff stat results against loaded rows (reuse hashes when size matches and mtime is not newer); hash only new/changed files; delete rows under the scanned operands not successfully processed; leave rows outside the operands untouched; new summary line (added/updated/removed/unchanged/skipped); "update" progress pass for the database writereport.go/trees.go: read records from the database (no positional args, no stream parsing); drop the NUL-stream parser and malformed-record handlingmain.go: updated usage strings;report/treestake no args (usage error otherwise)- tests: db open/env-override/schema tests; incremental scan tests (add, mtime update, delete, unchanged-hash-reuse, out-of-scope rows untouched, error paths); rework pipeline test to go through the database; keep walk/stat/hash/grouping unit tests
.gitignore: local*.sqliteartifactsmake check,make docker, and the README smoke test pass
- update
Completed Steps
- add the
originremote (git@git.eeqj.de:sneak/sfdupes.git), tagv0.0.1, and pushmainplus tags (2026-07-23) scanCLI rework (2026-07-23, branchscan-required-paths): requiredPATH...operands via cobra flags replacing the/srv-rootdefault; new-x/--one-file-systemflag (GNU convention) to stop at filesystem boundaries, which are crossed by default- bring the repo into full policy compliance (2026-07-23, branch
repo-policy-compliance; checklist below) git initwith README-only first commit; code baseline committed onmain(2026-07-22)- implement
scan,report, andtreessubcommands (pre-git history)
Future Steps
- convert Makefile targets to scripts-to-rule-them-all
script/entrypoints like the other managed repos - possible later features (explicitly out of scope per README): full-content verification of candidates, removal-script helpers
Repo Policy Compliance
Audited 2026-07-22 against REPO_POLICIES.md (2026-07-06), the existing
repo checklist, and the Go styleguide. Code is already gofmt-clean, so no
standalone formatting commit is needed.
.gitignoremissing — the compiledsfdupesbinary andfiles.datsit untracked in the tree; needs OS/editor/Go artifacts plus secrets patterns.editorconfigmissingLICENSEmissing and README has no License section (MIT assumed from house convention — user to confirm)REPO_POLICIES.mdmissing from repo root.golangci.ymlmissing (install canonical copy); code must then passmake lint(150 findings fixed;make lintis clean)Makefilelacks required targetstest,lint,fmt,fmt-check,docker,hooks;checkcurrently depends onbuild, which writes the binary (make checkmust not modify files)- no tests —
go test ./...has nothing to run; policy requires real tests with a 30-second timeout and the conditional-vrerun pattern (suite covers parsing, grouping, digests, suppression, hashing, and the scan pipeline; 64% coverage) Dockerfilemissing — Go multistage with hash-pinned images: fail-fast lint stage, build stage runningmake check.dockerignoremissing.gitea/workflows/check.ymlmissing (docker build .on push, checkout action pinned by commit SHA)- README lacks required sections: Description first line (name/purpose/category/license/author), Getting Started, Rationale, TODO, License, Author
- README non-goal "no git repository setup and no CI" is stale now that the repo is under git with CI
- pre-commit hook not installed (
make hooksonce the target exists)
Accepted divergences (no action):
- flat single-package layout with
.gofiles in the repo root — fine for a small single-binary tool per the Go styleguide; the tracker audit agrees go testruns without-race— the repo mandatesCGO_ENABLED=0(pure-Go builds) and the race detector requires cgo