Warn about and skip non-regular and .zfs operands, keeping their records (closes #9)
check / check (push) Successful in 1m11s

A symlink, socket, FIFO or device-node operand, or a directory operand
named .zfs, was ignored without a word and stayed in the scanned
operands, so the update phase deleted every record stored beneath it.
Such an operand now gets a one-line warning naming the path and what it
is, counts as skipped in the summary, and is dropped before the
database index is loaded, so the records beneath it count as outside
the scanned operands and are not deleted, unless it lies under another
operand. The exit status stays 0. An operand that turns into one of
these between that check and the walk is warned about and skipped by
the walk instead. README "scan mode" and "Rules for the walk" say so.

Model: opus-5-5
This commit is contained in:
2026-10-03 15:02:56 +00:00
parent d63d3cc7fc
commit cf34b59632
5 changed files with 215 additions and 42 deletions
+22 -5
View File
@@ -263,6 +263,18 @@ duplicates another or lies under another is dropped before walking,
so every file is reached exactly once and produces one database
record.
An operand that is a symlink (never followed, not even as an operand),
socket, FIFO, or device node, or a directory named `.zfs`, is not
scanned. `scan` prints a one-line warning naming the path and what it
is, counts it as skipped, and drops it from the scanned operands before
reading the database. The records stored beneath it are not deleted:
they are treated like any other record outside the scanned operands,
including the content-phase exception below. If it lies under another
operand, they are under that operand instead, and are deleted like any
other record there that this scan did not verify. This is not an
error: a scan whose every operand is dropped walks nothing and
exits 0.
`scan` synchronizes the database with the filesystem state under the
scanned operands:
@@ -368,9 +380,12 @@ during the hash phase:
Rules for the walk:
- Only regular files. Skip directories, symlinks (do not follow,
including symlink operands), sockets, FIFOs, and device nodes.
including symlink operands), sockets, FIFOs, and device nodes. An
operand that is a symlink, socket, FIFO, or device node is dropped
as described in "`scan` mode" above.
- Never descend into a directory named `.zfs` (ZFS snapshot pseudo-dirs;
walking them would list every file once per snapshot).
walking them would list every file once per snapshot), not even
when it is an operand; such an operand is dropped the same way.
- Filesystem boundaries are crossed by default. With `-x`
(long form `--one-file-system`, following the GNU `du`/`rsync`
convention), never descend into a directory on a different
@@ -381,9 +396,11 @@ Rules for the walk:
path, and continue. Per-file errors never abort the run; the final
summary reports how many were skipped. As specified above, a
skipped path that has a database record from an earlier scan loses
that record, unless it failed only in the content phase; an
unreadable directory subtree likewise loses its records (accepted:
the database mirrors what the latest scan could actually verify).
that record, unless it failed only in the content phase, or is an
operand dropped before the database was read that lies under no
other operand; an unreadable directory subtree likewise loses its
records (accepted: the database mirrors what the latest scan could
actually verify).
Concurrency: the walk phase (which also stats files), the hash phase,
and the content phase each use a worker pool of `--workers` workers