Skip to content

Stop git discovery at the mirror directory [patch] - #108

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/104-pin-git-to-mirror
Oct 30, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/104-pin-git-to-mirror

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #104

What changed

GitRunner.BuildEnvironment stripped inherited GIT_* variables but did not stop git's upward repository discovery. A mirror directory can stop being a repository, for example after a partial delete or the reaper/MarkUsed race (#58). When that happened, git walked up to the first enclosing repository and answered from it. That could be a checkout holding the mirror root, or an outer bare mirror. The result: /branches and 409 bodies served repository Y's branches to a caller admitted only for repository X.

Every invocation with a WorkingDirectory now sets GIT_CEILING_DIRECTORIES to that directory's parent:

  • git still finds the repository the directory itself holds, bare or not.
  • A directory that is not a repository now fails with not a git repository instead of reading a neighbour.
  • I chose the ceiling over GIT_DIR because clone (run from the mirror's parent) and the staging git config also go through this path. The ceiling is safe for all of them.
  • Runs without a working directory get no ceiling, and an inherited GIT_CEILING_DIRECTORIES is still dropped like any other GIT_* variable.

Tests

  • BuildEnvironment_WithAWorkingDirectory_StopsDiscoveryAtIt and BuildEnvironment_WithoutAWorkingDirectory_SetsNoCeiling (unit).
  • RefResolver_ABrokenMirrorInsideAnotherRepository_ReadsNothing (real git): a mirror directory holding only .last-used inside the fixture's work tree. ListAsync returns null. On main it returned the work tree's branches.
  • Both new behaviour tests fail with GitRunner.cs reverted. Full suite: 283/283 passed.
  • Also checked by hand with git 2.43: a bare mirror is still read under the ceiling, and the nested broken case fails with exit 128.

Generated by Claude Code

A mirror directory that is no longer a repository (a partial delete, the
reaper racing MarkUsed) did not fail: git walked up to the first enclosing
repository and answered from it, serving another repository's branches.
Every run with a working directory now sets GIT_CEILING_DIRECTORIES to that
directory's parent, so the directory's own repository is still found but
discovery never leaves it.

Fixes #104

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW3f2Szc4ZLoCTbPhuX
@sonarqubecloud

Copy link
Copy Markdown

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.

A broken mirror directory serves another repository's branches: git commands aren't pinned to the mirror, so git walks up to an enclosing repository

2 participants