Cloning with remote callback results in HEAD pointing to user's `init.defaultBranch`
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- Python
- Sterne
- 1.7k
- Forks
- 408
- Ø Merge
- 2 T. 57 Min.
- Gemergte PRs (30 T.)
- 7
Beschreibung
Cloning with a remote callback results in HEAD pointing to the user's init.defaultBranch instead of the default branch of the cloned repository. See repro below.
Looks like an upstream bug to me, just confirming with you... thanks :)
I'll also note that HEAD already contains the wrong reference before the callback is executed. (Reproduce this e.g. by placing a breakpoint() in remote_cb below, and inspecting HEAD from the debugger prompt.) Still, the issue does not reproduce without the callback.
Repro
❯ docker run --rm -ti python bash
root@e747d803b7f3:/# pip install pygit2
Collecting pygit2
Downloading pygit2-1.5.0-cp39-cp39-manylinux2014_x86_64.whl (3.1 MB)
|████████████████████████████████| 3.1 MB 2.4 MB/s
Collecting cffi>=1.4.0
Downloading cffi-1.14.5-cp39-cp39-manylinux1_x86_64.whl (406 kB)
|████████████████████████████████| 406 kB 15.7 MB/s
Collecting cached-property
Downloading cached_property-1.5.2-py2.py3-none-any.whl (7.6 kB)
Collecting pycparser
Downloading pycparser-2.20-py2.py3-none-any.whl (112 kB)
|████████████████████████████████| 112 kB 17.0 MB/s
Installing collected packages: pycparser, cffi, cached-property, pygit2
Successfully installed cached-property-1.5.2 cffi-1.14.5 pycparser-2.20 pygit2-1.5.0
root@e747d803b7f3:/# cat >> ~/.gitconfig
[init]
defaultBranch = teapot
root@e747d803b7f3:/# python
Python 3.9.4 (default, Apr 10 2021, 15:31:19)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pygit2
>>> def remote_cb(repo, name, url):
... n = name.decode()
... repo.config[f"remote.{n}.mirror"] = True
... return repo.remotes.create(name, url, "+refs/*:refs/*")
...
>>> repo = pygit2.clone_repository("https://github.com/libgit2/pygit2", "/tmp/pygit2", remote=remote_cb)
>>> repo.head
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
_pygit2.GitError: reference 'refs/heads/teapot' not found
>>> print(open("/tmp/pygit2/.git/HEAD").read())
ref: refs/heads/teapot
Workaround
import contextlib
import pygit2
def _fix_repository_head(repository: pygit2.Repository) -> pygit2.Reference:
"""Work around a bug in libgit2 resulting in a bogus HEAD reference.
Cloning with a remote callback results in HEAD pointing to the user's
`init.defaultBranch` instead of the default branch of the cloned repository.
"""
head = repository.references["HEAD"]
with contextlib.suppress(KeyError):
return head.resolve()
for branch in ["main", "master"]:
ref = f"refs/heads/{branch}"
if head.target != ref and ref in repository.references:
head.set_target(ref, message="repair broken HEAD after clone")
return head.resolve()
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Beginne mit dem bereitgestellten pygit2.clone_repository-Aufruf und seinem remote_cb-Callback und reproduziere das Verhalten mit und ohne Callback. Untersuche /tmp/pygit2/.git/HEAD, bevor der Callback ausgeführt wird, und vergleiche es mit dem Standardbranch des geklonten Repositorys. Als erledigt gilt die Aufgabe, wenn das Klonen mit dem Callback HEAD auf den Standardbranch des geklonten Repositorys verweisen lässt und nicht auf init.defaultBranch, und wenn überall dort, wo das Klonverhalten getestet wird, Abdeckung hinzugefügt wurde.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- git, python
- Bereich
- api, tooling
- Issue-Typ
- Bug
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Aktivitätsstatus
- Veraltet
- Klarheit
- Größtenteils klar
- Anfängerfreundlichkeit
- 45/100