Skip to content

Potential breaking change in Repo.head() for annotated tags #1443

@abn

Description

@abn

@jelmer following up from python-poetry/poetry#9849 (comment) and python-poetry/poetry#9748 (comment) raising this issue to triage if this is in-fact a dulwich issue or a usage issue on our end.

A simplified reproducer that matches steps we use.

reproducer.py

import tempfile
from pathlib import Path

from dulwich import porcelain
from dulwich.client import get_transport_and_path
from dulwich.refs import ANNOTATED_TAG_SUFFIX
from dulwich.repo import Repo


def main() -> None:
    with tempfile.TemporaryDirectory(delete=True) as tmpdir:
        target = Path(tmpdir).joinpath("test-fixture-vcs-repository").as_posix()
        url = "https://github.com/python-poetry/test-fixture-vcs-repository.git"
        tag = "refs/tags/v0.1.0".encode()
        repo = Repo.init(target, mkdir=True)
        porcelain.remote_add(repo, "origin", url)

        config = repo.get_config_stack()
        client, path = get_transport_and_path(url, config=config)
        remote_refs = client.fetch(
            path,
            repo,
            determine_wants=repo.object_store.determine_wants_all,
        )

        annotated = tag + ANNOTATED_TAG_SUFFIX
        ref = annotated if annotated in remote_refs.refs else remote_refs.symrefs[b"HEAD"]
        head = remote_refs.refs[ref]
        remote_refs.refs[ref] = remote_refs.refs[b"HEAD"] = head

        repo.refs[b"HEAD"] = remote_refs.refs[b"HEAD"]

        with repo:
            repo.reset_index()

        print(repo.head(), repo.get_peeled(b"HEAD"))


if __name__ == '__main__':
    main()

container-one-line-reproducer.sh

podman run --rm -i --entrypoint bash docker.io/python:3.13 <<EOF
set -xe
cat > main.py <<PY
import tempfile
from pathlib import Path

from dulwich import porcelain
from dulwich.client import get_transport_and_path
from dulwich.refs import ANNOTATED_TAG_SUFFIX
from dulwich.repo import Repo


def main() -> None:
    with tempfile.TemporaryDirectory(delete=True) as tmpdir:
        target = Path(tmpdir).joinpath("test-fixture-vcs-repository").as_posix()
        url = "https://github.com/python-poetry/test-fixture-vcs-repository.git"
        tag = "refs/tags/v0.1.0".encode()
        repo = Repo.init(target, mkdir=True)
        porcelain.remote_add(repo, "origin", url)

        config = repo.get_config_stack()
        client, path = get_transport_and_path(url, config=config)
        remote_refs = client.fetch(
            path,
            repo,
            determine_wants=repo.object_store.determine_wants_all,
        )

        annotated = tag + ANNOTATED_TAG_SUFFIX
        ref = annotated if annotated in remote_refs.refs else remote_refs.symrefs[b"HEAD"]
        head = remote_refs.refs[ref]
        remote_refs.refs[ref] = remote_refs.refs[b"HEAD"] = head

        repo.refs[b"HEAD"] = remote_refs.refs[b"HEAD"]

        with repo:
            repo.reset_index()

        print(repo.head(), repo.get_peeled(b"HEAD"))


if __name__ == '__main__':
    main()

PY

python -m pip install --root-user-action=ignore --disable-pip-version-check -q 'dulwich==0.22.1'
python main.py
python -m pip install --root-user-action=ignore --disable-pip-version-check -q 'dulwich==0.22.3'
python main.py
python -m pip install --root-user-action=ignore --disable-pip-version-check -q 'dulwich==0.22.4'
python main.py
python -m pip install --root-user-action=ignore --disable-pip-version-check -q 'dulwich==0.22.5'
python main.py
python -m pip install --root-user-action=ignore --disable-pip-version-check -q 'dulwich==0.22.6'
python main.py
EOF

From the output of the above shell command, you can see that the change happened between 0.22.1 and 0.22.3.

+ python -m pip install --root-user-action=ignore --disable-pip-version-check -q dulwich==0.22.1
+ python main.py
b'b6204750a763268e941cec1f05f8986b6c66913e' b'b6204750a763268e941cec1f05f8986b6c66913e'
+ python -m pip install --root-user-action=ignore --disable-pip-version-check -q dulwich==0.22.3
+ python main.py
b'0be1215c90fffe37c5629cf2764615e9d9530e67' b'0be1215c90fffe37c5629cf2764615e9d9530e67'
+ python -m pip install --root-user-action=ignore --disable-pip-version-check -q dulwich==0.22.4
+ python main.py
b'0be1215c90fffe37c5629cf2764615e9d9530e67' b'0be1215c90fffe37c5629cf2764615e9d9530e67'
+ python -m pip install --root-user-action=ignore --disable-pip-version-check -q dulwich==0.22.5
+ python main.py
b'0be1215c90fffe37c5629cf2764615e9d9530e67' b'0be1215c90fffe37c5629cf2764615e9d9530e67'
+ python -m pip install --root-user-action=ignore --disable-pip-version-check -q dulwich==0.22.6
+ python main.py
b'0be1215c90fffe37c5629cf2764615e9d9530e67' b'0be1215c90fffe37c5629cf2764615e9d9530e67'

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions