Skip to content

fix(relay/git): advertise empty refs so a new repo can take its first… - #7651

Open
brendio wants to merge 1 commit into
block:mainfrom
brendio:fix/receive-pack-advertise-empty
Open

brendio wants to merge 1 commit into
block:mainfrom
brendio:fix/receive-pack-advertise-empty

Conversation

@brendio

@brendio brendio commented Sep 14, 2026

Copy link
Copy Markdown

… push

info_refs_subprocess mapped hydrate_for_read's Ok(None) (pointer absent = no published content yet) to 404 for both services. Git performs the info/refs?service=git-receive-pack ref-discovery GET before it sends any pack, so that 404 aborts the push — which makes the first-push branch of hydrate_for_write in receive_pack unreachable. Every repo with no content is permanently unpushable over smart HTTP, so a relay-hosted repo can never be seeded at all.

scripts/e2e-git-perms.sh already asserts the correct behaviour ("Bot1 clones, creates index.html, pushes (should succeed)", with a git init fallback for the empty-repo case), but it is not wired into CI.

Answer the git-receive-pack advertisement for a content-less repo against an empty bare repo instead of 404ing. git-upload-pack still 404s — there is genuinely nothing to clone. The advertisement is produced by the real git receive-pack --advertise-refs subprocess, so the capability set stays byte-correct rather than hand-rolled.

Authorization is unchanged: info_refs runs authorize_git_read before any of this, and push policy is still enforced by the pre-receive hook. The new branch discloses an empty ref list to a caller who already passed the read gate.

Also extracts the empty-bare-repo construction shared by both call sites into hydrate::empty_bare_repo, and covers the advertisement shape (zero oid, capabilities^{}, report-status) with a unit test — that well-formedness is what makes git proceed to POST the pack.

Summary

Related issue

Testing

… push

`info_refs_subprocess` mapped `hydrate_for_read`'s `Ok(None)` (pointer
absent = no published content yet) to 404 for both services. Git performs
the `info/refs?service=git-receive-pack` ref-discovery GET *before* it
sends any pack, so that 404 aborts the push — which makes the first-push
branch of `hydrate_for_write` in `receive_pack` unreachable. Every repo
with no content is permanently unpushable over smart HTTP, so a
relay-hosted repo can never be seeded at all.

`scripts/e2e-git-perms.sh` already asserts the correct behaviour ("Bot1
clones, creates index.html, pushes (should succeed)", with a `git init`
fallback for the empty-repo case), but it is not wired into CI.

Answer the `git-receive-pack` advertisement for a content-less repo
against an empty bare repo instead of 404ing. `git-upload-pack` still
404s — there is genuinely nothing to clone. The advertisement is produced
by the real `git receive-pack --advertise-refs` subprocess, so the
capability set stays byte-correct rather than hand-rolled.

Authorization is unchanged: `info_refs` runs `authorize_git_read` before
any of this, and push policy is still enforced by the pre-receive hook.
The new branch discloses an empty ref list to a caller who already passed
the read gate.

Also extracts the empty-bare-repo construction shared by both call sites
into `hydrate::empty_bare_repo`, and covers the advertisement shape
(zero oid, `capabilities^{}`, `report-status`) with a unit test — that
well-formedness is what makes git proceed to POST the pack.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: brendio <brendan@brendio.com>
@brendio
brendio requested a review from a team as a code owner September 14, 2026 23:15
@github-actions

Copy link
Copy Markdown

🔐 Codex Security Review

Status: review required for the current range.

The current range is 7c789dee09d198469bded1cb5be902eaf5562ad9...097a7d66223db7d981ef98cbc4ae64269b977dc4.
A new review must complete for this exact range. When manual authorization
is required, a Block organization member must comment exactly
@buzz-security-review 097a7d66223db7d981ef98cbc4ae64269b977dc4 to authorize a new review.
Any previous review applies only to its recorded range.

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.

1 participant