Preserve discovery failures for damaged checkouts

This commit is contained in:
2026-11-01 21:53:40 +00:00
parent 5d5653bfc3
commit 66f5884ab4
5 changed files with 176 additions and 12 deletions

View File

@@ -127,7 +127,7 @@ already suffice.
through `internal/process`. Apply `LC_ALL=C` to this child only so the known
no-repository diagnostics can be recognized without depending on operator
locale. Do not change process-global locale or configuration.
3. Git uses exit status 128 for both absence and other failures. Classify absence
3. Git uses exit status 128 for both absence and other failures. Consider absence
only when that status accompanies its recognized no-parent-repository
diagnostic: `fatal: not a git repository (or any of the parent directories): .git`,
or the form beginning `fatal: not a git repository (or any parent up to mount point `
@@ -137,6 +137,11 @@ already suffice.
classifier small, private, and covered by diagnostic samples. Do not accept
every message starting with `not a git repository` as standalone: an invalid
explicit `GIT_DIR` has a different diagnostic.
Confirm the absence of `.git` entries in the directories Git could search
before accepting standalone use: damaged directory metadata can produce the
same recognized diagnostic. Respect configured discovery ceilings and any
reported filesystem boundary. A relevant marker preserves the Git failure;
filesystem inspection errors also remain failures.
4. Treat cancellation, inaccessible working directories, broken Git metadata,
ownership errors, bare-repository worktree errors, and unrecognized
diagnostics as errors. Preserve `errors.Is`/`errors.As` causes and useful
@@ -161,8 +166,10 @@ filesystem aliases, and an independent worktree with a `.git` file; real
standalone directories for absence. Use controlled Git-process failures for
permission/ownership errors and cancellation, rather than relying on host user
privileges. Test both no-repository diagnostic forms and a status-128 failure
that must remain an error. A broken `.git` file must not trigger standalone
fallback. Existing strict-root tests continue to pass.
that must remain an error. A broken `.git` file or a `.git` directory missing
`HEAD` must not trigger standalone fallback. Cover discovery boundaries so an
excluded ancestor's marker does not change standalone selection. Existing
strict-root tests continue to pass.
Also cover a Go-only executable path in a marker-free standalone directory:
preparation can still run there. With that same executable path inside a
checkout, discovery fails with the missing-Git cause before Go runs.

View File

@@ -132,7 +132,15 @@ following findings require follow-up; the other planned corrections are present.
### 1. Damaged checkout metadata can silently select standalone preparation
**Priority:** medium. **Status:** open.
**Priority:** medium. **Status:** complete.
**Completion evidence:** `TestPrepareBuildDependenciesRejectsDamagedCheckout`
verifies healthy root selection, preservation of the damaged checkout's Git
failure with no Go invocation, and genuine standalone preparation. Git discovery
regressions cover ceiling directories, physical and literal aliases, and the
filesystem boundary. Focused preparation and discovery checks pass offline with
the race detector. The implementation plan now requires marker inspection before
accepting the recognized no-repository diagnostic.
**Code:** `DiscoverRepositoryRoot` in
[internal/git/source.go](../../internal/git/source.go), particularly the