libgit2 / libgit2/pygit2

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

Aperta
#1,073 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Lingua principale
Python
Stelle
1.7k
Fork
408
Merge medio
2g 57m
PR unite (30g)
7

Descrizione

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()

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia con la chiamata fornita a pygit2.clone_repository e il relativo callback remote_cb, riproducendo il comportamento con e senza il callback. Ispeziona /tmp/pygit2/.git/HEAD prima dell'esecuzione del callback e confrontalo con il branch predefinito del repository clonato. Il lavoro è completato quando il clone con il callback lascia HEAD puntare al branch predefinito del repository clonato invece che a init.defaultBranch, con la copertura aggiunta ovunque venga testato il comportamento del clone.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
git, python
Ambito
api, tooling
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
45/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.