Expand description
Tier two: the gitignore fallback, for the ecosystems nobody wrote a rule for.
This is the differentiator from kondo, whose coverage is exactly its ruleset and which is
therefore blind to anything outside it. Inside a git work tree a directory is reclaimable by
inference when all four of these hold:
- it is ignored, per the whole gitignore stack — nested files, negations,
info/exclude, global excludes — and not merely per the root.gitignore; - it contains no tracked file at any depth;
- it clears a size floor, 10 MiB by default;
- no tier-one rule already claimed it.
Condition two is the safety property, it is exactly the guarantee git clean enforces, and
it is the reason this tier can be on by default without being reckless. Condition four falls
out of evaluation order in crate::walk: tier one is asked first, and it prunes.
§A candidate may be a FILE, and then only conditions one, two and four apply
Conditions one, two and four are statements about a path and hold unchanged. Condition
three does not, and leaving it out is the design rather than an exemption: the floor is
about rows, not about safety. A gitignored directory under 10 MiB is not worth a row
because the list is sorted by size and it would be at the bottom of it. A 40-byte .env IS
worth a row, and the reason has nothing to do with its size.
A file is also always priced, where a tier-one directory lives in
crate::size::Size::Unmeasured until somebody asks for a breakdown. One lstat — which
the walk has already done — is the exact and complete answer in constant time, so the
unpriced machinery never has to grow a file branch. That is a simplification rather than a
special case.
Because this is a different job from the one the tier does for directories — clearing fifty
env files reclaims kilobytes, and the value is hygiene rather than space — it is asked for
separately: see crate::walk::Walker::ignored_files, which is off unless a caller says
otherwise.
§The fifth condition, which git clean also enforces
A directory holding a git checkout at any depth is not claimed either. This is not in the
four above and it is not optional: git clean -ndX in a repository whose ignored
.sandboxes/ holds live work trees prints Would skip repository … and then lists the
siblings one by one, rather than collapsing the directory into a single removal. Anything
that collapses it is offering to delete somebody’s uncommitted work, and that shape —
checkouts parked under an ignored directory — is common rather than exotic. So a candidate
holding a checkout is refused and descended into, which is exactly what git does with it,
and its subdirectories that hold no checkout are claimed on their own.
For the same reason a candidate with an unreadable corner is refused. “Holds no checkout” is a claim about the whole subtree, and a traversal that could not see all of it has not made that claim. Tier one survives an unreadable corner with a size that is a lower bound, because a rule vouched for the directory; here the traversal is the evidence.
§Outside a work tree this tier is inert
Deliberately, and it is reported rather than left to look like an empty result. With no
repository there is no ignore file that means anything, and the only signal left would be
the directory’s name — which is precisely how a cleaner deletes somebody’s source. build/
is a CMake project’s hand-written source as often as it is output, and no amount of wanting
a broader tier makes a name into evidence.
§Why a query matcher rather than a filtering walk
Tier one switches every ignore file off, because node_modules, target and .venv are
gitignored in every repository that has a .gitignore and a filtering walk would find
almost nothing. So tier two cannot ride on the walk’s own filtering and instead asks
IncrementalIgnore, which answers the same question for one path at a time and caches per
directory. One matcher per work tree per walker thread: the matchers hold mutable caches, so
sharing one would mean a lock on the hottest path in the scan.
Structs§
- Fallback
Report - What tier two was able to do, reported alongside what it found.
Constants§
- DEFAULT_
MIN_ SIZE - The default size floor: below this a directory is not worth a row, and tier two would otherwise report every scrap of ignored cache on the disk.