next into main: the duplicate check, hash storage, display and .zfs fixes from the trial #137

Open
clawbot wants to merge 4 commits from next into main
Collaborator

next holds the fixes from your trial beyond main.

The duplicate check you specified in #132:

  • Every file gets the SHA-256 of its first and last 64 KiB.
  • A file under 100 MiB also gets the SHA-256 of its whole content.
  • A file of 100 MiB or more gets the per-gigabyte sampled hash instead, so it is never read in full.
  • A file whose size no other file shares is hashed too, and the separate content phase is gone. A scan now runs load, walk, hash and update.

Hash storage, from #134: each hash is stored as its raw 32 bytes in a BLOB column, half the size of the hex text.

The display, from #133:

  • A file or directory removed while the scan runs is skipped without a line.
  • Every phase's line starts with the spinner, the hash phase included.
  • The bar has a fixed length at the right edge. A line too wide for the terminal drops its rate before its bar, so on 80 columns a phase with a bar shows no rate.
  • The time left is labelled remain.

.zfs, on your ruling in #142: an operand at or inside a .zfs directory, by its path or through a symlink, is never scanned. It gets a warning and counts as skipped.

Model: opus-5-5

`next` holds the fixes from your trial beyond `main`. The duplicate check you specified in https://git.eeqj.de/sneak/sfdupes/issues/132: - Every file gets the SHA-256 of its first and last 64 KiB. - A file under 100 MiB also gets the SHA-256 of its whole content. - A file of 100 MiB or more gets the per-gigabyte sampled hash instead, so it is never read in full. - A file whose size no other file shares is hashed too, and the separate content phase is gone. A scan now runs load, walk, hash and update. Hash storage, from https://git.eeqj.de/sneak/sfdupes/issues/134: each hash is stored as its raw 32 bytes in a BLOB column, half the size of the hex text. The display, from https://git.eeqj.de/sneak/sfdupes/issues/133: - A file or directory removed while the scan runs is skipped without a line. - Every phase's line starts with the spinner, the hash phase included. - The bar has a fixed length at the right edge. A line too wide for the terminal drops its rate before its bar, so on 80 columns a phase with a bar shows no rate. - The time left is labelled `remain`. `.zfs`, on your ruling in https://git.eeqj.de/sneak/sfdupes/issues/142: an operand at or inside a `.zfs` directory, by its path or through a symlink, is never scanned. It gets a warning and counts as skipped. Model: opus-5-5
clawbot added the merge-ready label 2026-10-26 02:03:39 +01:00
sneak was assigned by clawbot 2026-10-26 02:03:39 +01:00
clawbot added 1 commit 2026-10-26 02:03:39 +01:00
Every file the walk records now gets three hashes: head and tail, of
its first and last 64 KiB, and content. The content hash covers the
whole file under 100 MiB, and 1 MiB at each gigabyte from 100 MiB up,
so a large file is never read in full. One 100 MiB constant replaces
the 10 MiB and 50 MiB thresholds. The size census, the records stored
without hashes and the content phase are gone, so a rescan reads only
new and changed files. report and trees no longer special-case a
missing content hash. README "Duplicate detection" and "Rationale" are
rewritten.

Judgement call: info drops its two hash-count lines, which now always
equal the record count.

Model: opus-5-5
clawbot added 1 commit 2026-10-26 03:15:41 +01:00
The head, tail and content columns of the files table are BLOB NOT
NULL and hold the raw 32-byte SHA-256, half the size of the hex text,
in the table and in the files_signature index. The hash phase, the
records, report and trees carry each hash as a [sha256.Size]byte and
compare it with ==; nothing is hex-encoded. Reading a record whose
hash column is not 32 bytes is an error naming its path.

In the tests, testHash is a stand-in hash: a string's bytes padded
with zeros, so fixtures keep the sort order their strings give.

Judgement call: a hash of the wrong length is refused on reading,
not copied silently.

Model: opus-5-5
clawbot changed title from next into main: the duplicate check from the trial to next into main: the duplicate check and hash storage from the trial 2026-10-26 03:16:29 +01:00
clawbot added 1 commit 2026-10-26 06:32:39 +01:00
A path removed while the scan runs gets no warning and no skipped
count, in the walk or the hash phase. If the first of several hard
links is gone, the next is read. Other errors are still warned about.

On a terminal every display is the library's spinner, then the line. A
phase with an exact total ends the padded line with its percent and a
bar at a fixed column, drawn by sfdupes, as the library shows no
spinner beside its own bar. A too-wide line loses its rate first.

The time remaining is labelled remain, not eta.

Judgement call: an operand removed mid-scan is skipped silently too.
Deviation: README's stalled-line example keeps its words on 100
columns, not 80.

Model: opus-5-5
clawbot changed title from next into main: the duplicate check and hash storage from the trial to next into main: the duplicate check, hash storage and display fixes from the trial 2026-10-26 06:33:34 +01:00
clawbot added 1 commit 2026-10-26 15:15:40 +01:00
An operand inside a directory named .zfs was walked, because the
operand check looked only at the operand's own name. The check now
also looks at every directory above the operand, both as given and
with its symlinks resolved. Such an operand gets a warning, counts as
skipped and is not walked, whether given alone or under another
operand. The check runs before overlapping operands are pruned, so an
operand under another one still gets its warning.

The test for an operand named .zfs now writes its record beneath .zfs
straight into the database, since no scan stores one there any more.

Judgement call: a path component named .zfs counts whatever it is, a
symlink included.

Model: opus-5-5
clawbot changed title from next into main: the duplicate check, hash storage and display fixes from the trial to next into main: the duplicate check, hash storage, display and .zfs fixes from the trial 2026-10-26 15:16:31 +01:00
Some checks are pending
check / check (push) Waiting to run
You are not authorized to merge this pull request.
This pull request can be merged automatically.
This branch is out-of-date with the base branch
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin next:next
git checkout next
Sign in to join this conversation.