libgit2 / libgit2/pygit2

Cloning with remote callback results in HEAD pointing to user's `init.defaultBranch`

Offen
#1,073 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

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

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Ö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

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.