You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Config exclude globs are matched against walked paths without exempting the scan roots themselves, so an exclude that covers a root silently empties it:
Nothing is listed and the exit code is 0, indistinguishable from a clean scan of an empty directory.
The contract is ambiguous
The README makes two statements that pull in opposite directions here:
"A path named on the command line is where the walk starts rather than something it found, so .gitignore does not apply to it... naming an ignored directory scans it in full." Root semantics: explicit intent beats ignore rules.
"The exclude config key covers whatever .gitignore does not." Readable as: excludes are deliberately stronger than .gitignore, a veto that root semantics do not pierce.
.gitignore honors the first statement (a gitignored directory named as a root is walked in full). Excludes follow neither statement cleanly: they do veto roots, but silently, with exit 0 and no notice, while the same "nothing usable was named" situation for version control metadata prints a stderr notice and a missing path exits 2.
Options
Root semantics win: excludes prune the walk below a root but never veto a named root. Consistent with .gitignore handling; todo-by docs always scans docs.
Excludes stay a hard veto, but loudly: a root eliminated by an exclude gets a stderr notice, and a scan where every root was excluded stops looking like a clean run (same principle as Fix: a scan that could not run could still exit 0 #23).
Either option also needs a sentence in the README saying which rule excludes follow.
Excludes matching walked spellings means two spellings of one directory can differ in coverage. #24 collapses exact-duplicate roots by canonical path, keeping the first spelling; when the kept spelling is the excluded one, the coverage the dropped spelling had is lost:
Under option 1 both spellings cover the same set again and the collapse in #24 is sound as shipped. Under option 2 the notice makes the loss visible. Special-casing aliases inside the collapse itself was prototyped during the #24 review and rejected: it reintroduces duplicate output for a plain absolute/relative root pair, and leaves the single-root case above unfixed either way.
Not a regression
Pre-existing on a single root with no overlap involved. Surfaced during the #24 review rather than introduced by it.
What happens
Config exclude globs are matched against walked paths without exempting the scan roots themselves, so an exclude that covers a root silently empties it:
Nothing is listed and the exit code is 0, indistinguishable from a clean scan of an empty directory.
The contract is ambiguous
The README makes two statements that pull in opposite directions here:
.gitignoredoes not apply to it... naming an ignored directory scans it in full." Root semantics: explicit intent beats ignore rules.excludeconfig key covers whatever.gitignoredoes not." Readable as: excludes are deliberately stronger than.gitignore, a veto that root semantics do not pierce..gitignorehonors the first statement (a gitignored directory named as a root is walked in full). Excludes follow neither statement cleanly: they do veto roots, but silently, with exit 0 and no notice, while the same "nothing usable was named" situation for version control metadata prints a stderr notice and a missing path exits 2.Options
.gitignorehandling;todo-by docsalways scansdocs.Either option also needs a sentence in the README saying which rule excludes follow.
Why this matters for #24
Excludes matching walked spellings means two spellings of one directory can differ in coverage. #24 collapses exact-duplicate roots by canonical path, keeping the first spelling; when the kept spelling is the excluded one, the coverage the dropped spelling had is lost:
Under option 1 both spellings cover the same set again and the collapse in #24 is sound as shipped. Under option 2 the notice makes the loss visible. Special-casing aliases inside the collapse itself was prototyped during the #24 review and rejected: it reintroduces duplicate output for a plain absolute/relative root pair, and leaves the single-root case above unfixed either way.
Not a regression
Pre-existing on a single root with no overlap involved. Surfaced during the #24 review rather than introduced by it.