mirror git: soportar pines que son objetos tag anotados
diffutils, findutils-xargs y kustomize pinean el SHA de un tag, no de un commit. Rompía las dos
puntas por la misma suposición: el poblador apuntaba una rama al tag (imposible) y hammer escribía
ese SHA en el fichero shallow (que sólo admite commits).
El poblador pela con ^{commit} y manda el objeto tag aparte en refs/tags/hammer-objeto; sin él el
cat-file -e del otro lado no encuentra lo que la receta pide. hammer lee la frontera del bundle con
git bundle list-heads, que no necesita los objetos, y trae refs/*:refs/*.
Los 339 bundles del formato viejo siguen sirviendo: comprobado con una receta de cada forma contra
un repo que no resuelve por DNS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016v9ozVm44p6DB7EMXeZK4o
This commit is contained in:
@@ -61,15 +61,32 @@ def bundle(e, tmpdir):
|
||||
|
||||
out = os.path.join(tmpdir, f'{e["commit"]}.bundle')
|
||||
for etiqueta, args, kw in (
|
||||
("init", ("init", "-q"), {}),
|
||||
("remote", ("remote", "add", "origin", e["repo"]), {}),
|
||||
("init", ("init", "-q"), {}),
|
||||
("remote", ("remote", "add", "origin", e["repo"]), {}),
|
||||
# --depth 1 del SHA exacto: el servidor debe permitir fetch por sha (uploadpack.allowReachableSHA1).
|
||||
("fetch", ("fetch", "-q", "--depth", "1", "origin", e["commit"]), {"t": 1800}),
|
||||
("update-ref",("update-ref", "refs/heads/hammer", e["commit"]), {}),
|
||||
("bundle", ("bundle", "create", out, "refs/heads/hammer"), {"t": 1800}),
|
||||
("fetch", ("fetch", "-q", "--depth", "1", "origin", e["commit"]), {"t": 1800}),
|
||||
):
|
||||
motivo = paso(etiqueta, *args, **kw)
|
||||
if motivo: return None, motivo
|
||||
|
||||
# El campo `commit` de una receta NO siempre es un commit: puede pinear un objeto TAG anotado.
|
||||
# Un SHA de tag es una identidad igual de buena (`git archive` lo acepta) y por eso hash_inputs
|
||||
# no lo distingue, pero `refs/heads/*` sólo apunta a commits. Se pela para la rama y, si hubo
|
||||
# que pelar, el objeto tag viaja aparte: sin él, el `cat-file -e <commit>` del lado de hammer
|
||||
# falla y el mirror queda correcto-pero-inútil justo para estas recetas.
|
||||
r = git("rev-parse", e["commit"] + "^{commit}")
|
||||
if r.returncode != 0:
|
||||
return None, f"rev-parse: {(r.stderr or '').strip().splitlines()[-1][:160]}"
|
||||
pelado = r.stdout.strip()
|
||||
refs = ["refs/heads/hammer"]
|
||||
pasos = [("update-ref", ("update-ref", "refs/heads/hammer", pelado), {})]
|
||||
if pelado != e["commit"]:
|
||||
refs.append("refs/tags/hammer-objeto")
|
||||
pasos.append(("update-ref-tag", ("update-ref", "refs/tags/hammer-objeto", e["commit"]), {}))
|
||||
pasos.append(("bundle", tuple(["bundle", "create", out] + refs), {"t": 1800}))
|
||||
for etiqueta, args, kw in pasos:
|
||||
motivo = paso(etiqueta, *args, **kw)
|
||||
if motivo: return None, motivo
|
||||
return (out, None) if os.path.exists(out) else (None, "bundle: git dijo OK pero no hay fichero")
|
||||
|
||||
def main():
|
||||
|
||||
Reference in New Issue
Block a user