discover: a symlink must not abort a bounded count (any repo with a symlink can never auto-index) - #1803
Conversation
safe_stat reports a symlink as CBM_NOT_FOUND by policy, and walk_dir_process_entry turns any CBM_NOT_FOUND into out->failed when count_only is set. One symlink anywhere in a tree therefore aborts the whole count. cbm_discover_count_bounded is what auto-index admission calls, so any repository containing any symlink could never auto-index: maybe_auto_index logs reason=unsafe_or_unavailable_path files=-1 and returns. The label is misleading too — nothing is unsafe, and the walk is not slow; the count simply refused at the first symlink it met. Explicit index_repository is unaffected, because count_only is false there and the same entry is skipped rather than fatal. safe_stat now reports whether the entry was a symlink. A count skips symlinks and still aborts on an entry it genuinely cannot observe, which is what the admission guard wants. Reproduced before fixing: a scratch git repository auto-indexed successfully, then failed with the identical log line after one symlink was added and nothing else changed. The regression test fails without this change (113 passed, 1 failed) and passes with it (114 passed). It is guarded for Windows because it calls symlink().
|
Thanks for opening this — it has been seen, and it is queued. This note is automated, but it is not a brush-off: it exists so you know where your PR stands instead of having to guess from silence. Current review status: working through a backlog. What that means for this PR, concretely:
Things that will genuinely speed it up whenever review does happen:
If this fixes a bug, a reproduction we can run is worth more than a description of the symptom. Thanks for contributing, and sorry in advance for the wait. |
|
Thank you for the minimal reproduction and for documenting the explicit-index versus auto-index asymmetry. I checked current I have labeled this as a high-priority stability bug and routed it for review. The focused test shape is useful. The current DCO check is red, so the commit will need a valid |
The bug
safe_statreports a symlink asCBM_NOT_FOUNDby policy (src/discover/discover.c, theS_ISLNKbranch and the Windows reparse-point branch).walk_dir_process_entrythen turns anyCBM_NOT_FOUNDintoout->failedwhencount_onlyis set, which aborts the entire walk.cbm_discover_count_boundedis what auto-index admission calls, so any repository containing any symlink can never auto-index.maybe_auto_indexlogsreason=unsafe_or_unavailable_path files=-1and returns.The label misleads in two directions, which is what cost me the time: nothing is unsafe, and the 5,000 ms count deadline is not involved either — a full
findover the repository I hit this on takes 26 ms. The count simply refused at the first symlink it met.Explicit
index_repositoryis unaffected:count_onlyis false there, so the same entry is skipped rather than fatal. That asymmetry is what makes it confusing in practice — the repository indexes perfectly when you ask for it by hand, and silently never indexes itself.Reproduction
git inita scratch repo with one.jsfile, start an MCP session in it → auto-indexes, project appears inlist_projects.delete_project, addln -s sub linkdir, commit, start a session again →daemon.autoindex.skipped ... reason=unsafe_or_unavailable_path files=-1, no project.Nothing else changed between the two runs.
The fix
safe_statgains anis_linkout-parameter so the caller can tell "skipped by policy" from "could not observe". A count skips symlinks and still aborts on an entry it genuinely cannot observe, which preserves the conservative behaviour the admission guard wants.Test
discover_count_bounded_survives_a_symlinkintests/test_discover.c: a repo with two files and one symlink must giveCBM_DISCOVER_OKand count 2. Guarded with#ifndef _WIN32because it callssymlink().Verified in this tree with
HOME=$(mktemp -d) scripts/test.sh --suites discover:113 passed, 1 failed(tests/test_discover.c:1473)114 passedFound while vendoring this project — a
Formula -> pkg/homebrew/Formulasymlink in the tree was enough to trip it.