Cloning with remote callback results in HEAD pointing to user's `init.defaultBranch`
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Python
- Star
- 1.7k
- Fork
- 408
- Merge trung bình
- 2 ngày 57 phút
- Pull request đã merge (30 ngày)
- 7
Mô tả
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()
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu với lệnh gọi pygit2.clone_repository được cung cấp và callback remote_cb của nó, tái hiện hành vi khi có và không có callback. Kiểm tra /tmp/pygit2/.git/HEAD trước khi callback chạy và so sánh nó với branch mặc định của repository đã clone. Được xem là hoàn tất khi việc clone với callback khiến HEAD trỏ đến branch mặc định của repository đã clone thay vì init.defaultBranch, đồng thời bổ sung coverage ở mọi nơi kiểm thử hành vi clone.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- git, python
- Lĩnh vực
- api, tooling
- Loại issue
- Lỗi
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 45/100