Skip to content

fix(extraction): keep the git-aware scan working on git older than 2.36 (#1549) - #1604

Open
maxmilian wants to merge 1 commit into
colbymchenry:mainfrom
maxmilian:fix/1549-git-lsfiles-fallback
Open

fix(extraction): keep the git-aware scan working on git older than 2.36 (#1549)#1604
maxmilian wants to merge 1 commit into
colbymchenry:mainfrom
maxmilian:fix/1549-git-lsfiles-fallback

Conversation

@maxmilian

Copy link
Copy Markdown
Contributor

Fixes #1549.

git ls-files -s --recurse-submodules is rejected outright before git 2.36. builtin/ls-files.c listed show_stage among the modes that trigger die("ls-files --recurse-submodules unsupported mode"), and it was only dropped in 2.36:

tag guard
v2.34.1 (:720) recurse_submodules && (show_stage || show_deleted || …) → dies
v2.35.0 (:728) recurse_submodules && (show_stage || show_deleted || …) → dies
v2.36.0 (:728) show_stage removed → passes

The die is unconditional — it never checks whether the repo actually has submodules — so on those versions every call fails. That is Ubuntu 22.04 LTS (git 2.34.1) and Debian 11 (2.30.2), not just the 20.04 the report mentions.

Why it cost more than submodule expansion

The call at collectGitFiles had no try/catch, so the throw escaped to getGitVisibleFiles' catch { return null }, and scanDirectory fell through to scanDirectoryWalk. That walk has no notion of includeIgnored — all 39 references sit above the fallback — and the same try also covers gitlink recursion and collectIncludedFilesForRoot, so the codegraph.json include allowlist went with it.

The net effect on those distros: CodeGraph indexes a different file set than the configuration asks for, with no error, no warning, and no symptom other than files quietly missing from query results.

The fix

Retry as git ls-files -z -s, dropping --recurse-submodules rather than -s. Keeping -s is the important half — gitlink detection reads the mode bits to spot 160000 entries — and embedded repos are reached through that gitlink recursion anyway, so the fallback loses very little on old git and nothing at all on new.

Both call sites now go through one helper. The second one (discoverEmbeddedRepoRoots) already had a try/catch so it degraded less noisily, but it was silently losing the same expansion.

Testing

__tests__/extraction.test.ts gains a regression test that installs a PATH shim: a git that exits 128 with the real fatal: ls-files --recurse-submodules unsupported mode whenever it sees -s together with --recurse-submodules, and delegates to the real binary otherwise. That makes this reproducible on any git version rather than only on a machine old enough to fail naturally.

Fixture is the one from the issue — root repo, dir_b/ in .gitignore, codegraph.json with {"includeIgnored": ["dir_b/"]}, dir_b carrying its own .git:

before, under the shim →  ["a.ts"]                     # dir_b/b.ts silently dropped
after,  under the shim →  ["a.ts", "dir_b/b.ts"]

The test asserts the real-git baseline first, so it fails loudly if the shim ever stops shimming rather than passing vacuously.

__tests__/extraction.test.ts is 613/613. The full suite is unchanged against main — same 57 pre-existing environment failures on both, with the one extra pass being this test.

Credit

@newshowardz777 wrote the root-cause analysis and the patch shape in the issue; the commit carries a Co-authored-by trailer for them. I only widened the version boundary and added the shim-based coverage.

One non-claim, since it looks tempting from the outside: #1567 (nested .gitignore, node_modules walked into) has the shape of this same fallback, but scanDirectoryWalk does apply buildDefaultIgnore, which covers node_modules — so I can't call it the same root cause and haven't touched it here.

Worth noting #1568 edits this exact catch block to add a logDebug. It doesn't change behaviour, but it would have made this failure visible, so the two are complementary — happy to rebase around whichever lands first.

`git ls-files -s --recurse-submodules` dies before git 2.36: builtin/ls-files.c listed show_stage among the modes it rejects, and the check never looks at whether the repo has submodules, so every call fails on Ubuntu 22.04 LTS (2.34.1), Debian 11 (2.30.2) and older.

The throw escaped to getGitVisibleFiles' catch, which returns null and drops the caller into the plain filesystem walk. That walk knows nothing of includeIgnored, gitlink recursion, or the codegraph.json include allowlist, so all three silently stopped applying and files vanished from the index with no error.

Retry without --recurse-submodules rather than without -s: the mode bits are what gitlink detection reads, and embedded repos are reached through that recursion anyway. A PATH shim makes the regression testable on any git version.

Co-authored-by: newshowardz777 <newshowardz777@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

includeIgnored silently bypassed on older git (<2.34): git ls-files -s --recurse-submodules fails, falls back to filesystem walk that ignores the opt-in

1 participant