Skip to content

v1.108.276 — A Windows drive-root child can prove it is a repository

Choose a tag to compare

@jgravelle jgravelle released this 13 Aug 12:31
· 312 commits to main since this release

Four merged fixes, two of them from community reports.

Exact Git working trees no longer trip the broad-root guard (#438, @JayceeB1)

On Windows, an explicit repository at X:\repo has only two logical path components, so index_folder rejected it alongside genuinely broad paths. The guard now accepts that narrow case only when .git exists at the selected root. Drive roots, shallow non-Git directories, POSIX paths and UNC depth handling are unchanged.

Review note, recorded because the wrong version of this nearly shipped on maintainer advice. The first review asked for the UNC scope predicate to be dropped as redundant with the shared depth helper. It is not: _path_safety_part_count measures depth, the UNC clause bounds scope, and a UNC share root computes to exactly two — the same as C:\repo. With the predicate gone, a share root holding a .git would have been admitted, handing a whole file server to the indexer through the guard that exists to prevent exactly that.

A path-safety test that let the network decide its verdict (#453)

Test-only, no behaviour change. TestWindowsUNCPathSafety was not fully isolated from the real filesystem, so its result depended on the runner's network. It failed two releases in one day, both times passing on re-run of the identical SHA.

One unpatched probe explains the intermittency: Path.is_file() swallows ENOENT-class errors (what a box with no such share returns, so it passes everywhere locally) but propagates WinError 64 (what a runner with live-but-failing networking returns). Same code, same test, opposite outcomes, decided by whose network answered.

Fixed by isolation, deliberately not by a retry or a flaky marker — a retry would have hidden the false red while leaving the false green fully intact, and the false green is what let a real regression through.

A stored list of 50 could mean 50 or 500 (#441, @rknighton)

ranking_events.returned_ids keeps the first 50 ids and the row carried nothing saying how many there really were, so a complete result set and a truncated one were byte-identical in every stored field. Rows now carry returned_count, recorded before the cap.

⚠ Pre-existing rows keep NULL, which means unknown and must never be read as "the count equals len(returned_ids)". That inference is the defect, not the fix; nothing backfills it.

Analysis-only blast radius, checked rather than assumed. Filed by @rknighton against his own earlier claim, caught on re-verification.

~79% of a telemetry write was reopening the database (#442, @rknighton)

With perf_telemetry_enabled on — off by default, so this reaches opt-in installs only — every event opened a fresh connection and replayed eight IF NOT EXISTS statements before inserting one row. Connections are now cached per resolved path for the process. Measured 3.455ms against 16.615ms.

Measuring the safe fix first is what chose the risky one. The obvious low-risk change — skip the DDL, keep the per-write open/close, no connection lifetime to manage — captures 2% of the available saving. The open/close is the other 98%. Had that not been measured, the cheap fix would have shipped, looked principled and delivered nothing.

Caching a connection introduces two failure modes the report did not name: a stray close() poisons the cache so every later caller gets a dead handle, and a deleted database gets written into an unlinked inode forever. A liveness probe catches only the first; the exists() check is what catches the second. Together they cost 2.1% of the pre-fix write.

Windows cannot produce the orphaned-inode case at all — it refuses to unlink a file with an open handle — so that end-to-end test is POSIX-only, with a portable unit test for the predicate. Do not read that skip as cross-platform coverage.


Gates: 7763 passed / 9 skipped / 0 failed on 3.10; 7757 / 15 / 0 on the 3.13 CI-environment reproduce (same 7772 total, different skip split); ruff check src/ clean; CI green on all 9 jobs for afe82fd, first attempt.

Count reconciled by same-tree collect rather than arithmetic: 7772 total, 7753 without test_v1_108_276.py (= its 19), and the +5 over 1.108.275's 7748 is five new test functions in test_tools.py from the drive-root work, counted in the diff.

Install: pip install --upgrade jcodemunch-mcp