Skip to content

python3Packages.dunamai fails if Git has withBreakingChanges = true #571330

Closed

Description

@me-and

Git v3 breaking changes tracking issue: #567918

Git v3 (and Git v2 when compiled with breaking changes enabled) includes – as the name implies – several breaking changes. Building python3Packages.dunamai in this mode currently fails.

This is particularly relevant because this package is in the dependency chain for nix itself.

Building on commit 847c87d on x86_64-linux, with the following command:

nix-build --arg overlays '[ (final: prev: { git = prev.git.override { withBreakingChanges = true; }; }) ]' -A python3Packages.dunamai

the build fails during the pytestCheckPhase:

Nix build logs from the failing build stage
Running phase: pytestCheckPhase
Executing pytestCheckPhase
pytest flags: -m pytest -k not\ \(test__version__from_git__shallow\)
============================= test session starts ==============================
platform linux -- Python 3.14.7, pytest-9.1.1, pluggy-1.6.0
rootdir: /build/source
configfile: pyproject.toml
collected 63 items / 1 deselected / 62 selected

tests/integration/test_dunamai.py .FFFF....FF..s..sssss                  [ 33%]
tests/unit/test_dunamai.py ......................................        [ 95%]
tests/unit/test_main.py ...                                              [100%]

=================================== FAILURES ===================================
________________ test__version__from_git__with_lightweight_tags ________________

tmp_path = PosixPath('/build/pytest-of-nixbld/pytest-0/test__version__from_git__with_1')

    @pytest.mark.skipif(shutil.which("git") is None, reason="Requires Git")
    def test__version__from_git__with_lightweight_tags(tmp_path) -> None:
        run = make_run_callback(tmp_path)
        from_vcs = make_from_callback(Version.from_git)
        b = "master"
        legacy = is_git_legacy()

        with chdir(tmp_path):
            run("git init")
            (tmp_path / "foo.txt").write_text("hi")
            run("git add .")
            run('git commit --no-gpg-sign -m "Initial commit"')

            run("git tag v0.1.0")
>           assert from_vcs() == Version("0.1.0", dirty=False, branch=b)
E           AssertionError: assert Version(base='0.1.0', stage=None, revision=None, distance=0, commit=None, dirty=False, tagged_metadata=None, epoch=None, branch='main', timestamp=None) == Version(base='0.1.0', stage=None, revision=None, distance=0, commit=None, dirty=False, tagged_metadata=None, epoch=None, branch='master', timestamp=None)
E            +  where Version(base='0.1.0', stage=None, revision=None, distance=0, commit=None, dirty=False, tagged_metadata=None, epoch=None, branch='main', timestamp=None) = <function make_from_callback.<locals>.inner at 0x7ffff4d96140>()
E            +  and   Version(base='0.1.0', stage=None, revision=None, distance=0, commit=None, dirty=False, tagged_metadata=None, epoch=None, branch='master', timestamp=None) = Version('0.1.0', dirty=False, branch='master')

tests/integration/test_dunamai.py:241: AssertionError
___________________ test__version__from_git__with_mixed_tags ___________________

tmp_path = PosixPath('/build/pytest-of-nixbld/pytest-0/test__version__from_git__with_2')

    @pytest.mark.skipif(shutil.which("git") is None, reason="Requires Git")
    def test__version__from_git__with_mixed_tags(tmp_path) -> None:
        run = make_run_callback(tmp_path)
        from_vcs = make_from_callback(Version.from_git)
        b = "master"

        with chdir(tmp_path):
            run("git init")
            (tmp_path / "foo.txt").write_text("hi")
            run("git add .")
            run('git commit --no-gpg-sign -m "Initial commit"')

            run("git tag v0.1.0")
            (tmp_path / "foo.txt").write_text("hi 2")
            run("git add .")
            avoid_identical_ref_timestamps()
            run('git commit --no-gpg-sign -m "Second"')

            run('git tag v0.2.0 -m "Annotated"')
>           assert from_vcs() == Version("0.2.0", dirty=False, branch=b)
E           AssertionError: assert Version(base='0.2.0', stage=None, revision=None, distance=0, commit=None, dirty=False, tagged_metadata=None, epoch=None, branch='main', timestamp=None) == Version(base='0.2.0', stage=None, revision=None, distance=0, commit=None, dirty=False, tagged_metadata=None, epoch=None, branch='master', timestamp=None)
E            +  where Version(base='0.2.0', stage=None, revision=None, distance=0, commit=None, dirty=False, tagged_metadata=None, epoch=None, branch='main', timestamp=None) = <function make_from_callback.<locals>.inner at 0x7ffff4c1d7a0>()
E            +  and   Version(base='0.2.0', stage=None, revision=None, distance=0, commit=None, dirty=False, tagged_metadata=None, epoch=None, branch='master', timestamp=None) = Version('0.2.0', dirty=False, branch='master')

tests/integration/test_dunamai.py:290: AssertionError
____________ test__version__from_git__with_nonchronological_commits ____________

tmp_path = PosixPath('/build/pytest-of-nixbld/pytest-0/test__version__from_git__with_3')

    @pytest.mark.skipif(shutil.which("git") is None, reason="Requires Git")
    def test__version__from_git__with_nonchronological_commits(tmp_path) -> None:
        run = make_run_callback(tmp_path)
        from_vcs = make_from_callback(Version.from_git, chronological=False)
        b = "master"
        legacy = is_git_legacy()

        with chdir(tmp_path):
            run("git init")
            (tmp_path / "foo.txt").write_text("hi")
            run("git add .")
            run(
                'git commit --no-gpg-sign -m "Initial commit"',
                env={
                    "GIT_COMMITTER_DATE": "2000-01-02T01:00:00",
                    "GIT_AUTHOR_DATE": "2000-01-02T01:00:00",
                    **os.environ,
                },
            )

            run("git tag v0.1.0")
            (tmp_path / "foo.txt").write_text("hi 2")
            run("git add .")
            avoid_identical_ref_timestamps()
            run(
                'git commit --no-gpg-sign -m "Second"',
                env={
                    "GIT_COMMITTER_DATE": "2000-01-01T01:00:00",
                    "GIT_AUTHOR_DATE": "2000-01-01T01:00:00",
                    **os.environ,
                },
            )

            run("git tag v0.2.0")
            if legacy:
                assert from_vcs() == Version("0.1.0", distance=1, dirty=False, branch=b)
            else:
>               assert from_vcs() == Version("0.2.0", dirty=False, branch=b)
E               AssertionError: assert Version(base='0.2.0', stage=None, revision=None, distance=0, commit=None, dirty=False, tagged_metadata=None, epoch=None, branch='main', timestamp=None) == Version(base='0.2.0', stage=None, revision=None, distance=0, commit=None, dirty=False, tagged_metadata=None, epoch=None, branch='master', timestamp=None)
E                +  where Version(base='0.2.0', stage=None, revision=None, distance=0, commit=None, dirty=False, tagged_metadata=None, epoch=None, branch='main', timestamp=None) = <function make_from_callback.<locals>.inner at 0x7ffff4d81850>()
E                +  and   Version(base='0.2.0', stage=None, revision=None, distance=0, commit=None, dirty=False, tagged_metadata=None, epoch=None, branch='master', timestamp=None) = Version('0.2.0', dirty=False, branch='master')

tests/integration/test_dunamai.py:340: AssertionError
_______________________ test__version__from_git__gitflow _______________________

tmp_path = PosixPath('/build/pytest-of-nixbld/pytest-0/test__version__from_git__gitfl0')

    @pytest.mark.skipif(shutil.which("git") is None, reason="Requires Git")
    @pytest.mark.skipif(is_git_legacy(), reason="Requires non-legacy Git")
    def test__version__from_git__gitflow(tmp_path) -> None:
        run = make_run_callback(tmp_path)
        from_vcs = make_from_callback(Version.from_git)
        b = "master"
        b2 = "develop"

        with chdir(tmp_path):
            run("git init")
            (tmp_path / "foo.txt").write_text("hi")
            run("git add .")
            run("git commit --no-gpg-sign -m Initial")
            run("git tag v0.1.0 -m Release")

            run("git checkout -b develop")
            (tmp_path / "foo.txt").write_text("second")
            run("git add .")
            run("git commit --no-gpg-sign -m Second")

            run("git checkout -b release/v0.2.0")
            (tmp_path / "foo.txt").write_text("bugfix")
            run("git add .")
            run("git commit --no-gpg-sign -m Bugfix")

            run("git checkout develop")
            run("git merge --no-gpg-sign --no-ff release/v0.2.0")

>           run("git checkout master")

tests/integration/test_dunamai.py:371:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/integration/test_dunamai.py:56: in inner
    _, out = _run_cmd(command, where=where, codes=[expected_code], env=env)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

command = 'git checkout master'
where = PosixPath('/build/pytest-of-nixbld/pytest-0/test__version__from_git__gitfl0')
codes = [0], shell = False, env = None

    def _run_cmd(
        command: str,
        where: Optional[Path],
        codes: Sequence[int] = (0,),
        shell: bool = False,
        env: Optional[dict] = None,
    ) -> Tuple[int, str]:
        result = subprocess.run(
            shlex.split(command),
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            cwd=str(where) if where is not None else None,
            shell=shell,
            env=env,
        )
        output = result.stdout.decode().strip()
        if codes and result.returncode not in codes:
>           raise RuntimeError("The command '{}' returned code {}. Output:\n{}".format(command, result.returncode, output))
E           RuntimeError: The command 'git checkout master' returned code 1. Output:
E           error: pathspec 'master' did not match any file(s) known to git

dunamai/__init__.py:222: RuntimeError
_________________ test__version__from_git__exclude_decoration __________________

tmp_path = PosixPath('/build/pytest-of-nixbld/pytest-0/test__version__from_git__exclu0')

    @pytest.mark.skipif(lacks_git_version([2, 27]), reason="Requires Git 2.27+")
    def test__version__from_git__exclude_decoration(tmp_path) -> None:
        run = make_run_callback(tmp_path)
        from_vcs = make_from_callback(Version.from_git)
        b = "master"

        with chdir(tmp_path):
            run("git init")
            (tmp_path / "foo.txt").write_text("hi")
            run("git add .")
            run("git commit --no-gpg-sign -m Initial")
            run("git tag v0.1.0 -m Release")
            run("git config log.excludeDecoration refs/tags/")

>           assert from_vcs() == Version("0.1.0", dirty=False, branch=b)
E           AssertionError: assert Version(base='0.1.0', stage=None, revision=None, distance=0, commit=None, dirty=False, tagged_metadata=None, epoch=None, branch='main', timestamp=None) == Version(base='0.1.0', stage=None, revision=None, distance=0, commit=None, dirty=False, tagged_metadata=None, epoch=None, branch='master', timestamp=None)
E            +  where Version(base='0.1.0', stage=None, revision=None, distance=0, commit=None, dirty=False, tagged_metadata=None, epoch=None, branch='main', timestamp=None) = <function make_from_callback.<locals>.inner at 0x7ffff4d81c70>()
E            +  and   Version(base='0.1.0', stage=None, revision=None, distance=0, commit=None, dirty=False, tagged_metadata=None, epoch=None, branch='master', timestamp=None) = Version('0.1.0', dirty=False, branch='master')

tests/integration/test_dunamai.py:487: AssertionError
_____________________ test__version__from_git__broken_ref ______________________

tmp_path = PosixPath('/build/pytest-of-nixbld/pytest-0/test__version__from_git__broke0')

    @pytest.mark.skipif(lacks_git_version([2, 7]), reason="Requires Git 2.7+")
    def test__version__from_git__broken_ref(tmp_path) -> None:
        run = make_run_callback(tmp_path)
        from_vcs = make_from_callback(Version.from_git)
        b = "master"

        with chdir(tmp_path):
            run("git init")
            (tmp_path / "foo.txt").write_text("hi")
            run("git add .")
            run("git commit --no-gpg-sign -m Initial")
            run("git tag v0.1.0 -m Release")
>           (tmp_path / ".git/refs/tags/bad.txt").touch()

tests/integration/test_dunamai.py:504:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = PosixPath('/build/pytest-of-nixbld/pytest-0/test__version__from_git__broke0/.git/refs/tags/bad.txt')
mode = 438, exist_ok = True

    def touch(self, mode=0o666, exist_ok=True):
        """
        Create this file with the given access mode, if it doesn't exist.
        """

        if exist_ok:
            # First try to bump modification time
            # Implementation note: GNU touch uses the UTIME_NOW option of
            # the utimensat() / futimens() functions.
            try:
                os.utime(self, None)
            except OSError:
                # Avoid exception chaining
                pass
            else:
                return
        flags = os.O_CREAT | os.O_WRONLY
        if not exist_ok:
            flags |= os.O_EXCL
>       fd = os.open(self, flags, mode)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
E       FileNotFoundError: [Errno 2] No such file or directory: '/build/pytest-of-nixbld/pytest-0/test__version__from_git__broke0/.git/refs/tags/bad.txt'

/nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/pathlib/__init__.py:1003: FileNotFoundError
=============================== warnings summary ===============================
tests/integration/test_dunamai.py: 25 warnings
  /build/source/tests/integration/test_dunamai.py:74: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
    now = dt.datetime.utcnow().replace(tzinfo=dt.timezone.utc)

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================== short test summary info ============================
FAILED tests/integration/test_dunamai.py::test__version__from_git__with_lightweight_tags - AssertionError: assert Version(base='0.1.0', stage=None, revision=None, dis...
FAILED tests/integration/test_dunamai.py::test__version__from_git__with_mixed_tags - AssertionError: assert Version(base='0.2.0', stage=None, revision=None, dis...
FAILED tests/integration/test_dunamai.py::test__version__from_git__with_nonchronological_commits - AssertionError: assert Version(base='0.2.0', stage=None, revision=None, dis...
FAILED tests/integration/test_dunamai.py::test__version__from_git__gitflow - RuntimeError: The command 'git checkout master' returned code 1. Output:
FAILED tests/integration/test_dunamai.py::test__version__from_git__exclude_decoration - AssertionError: assert Version(base='0.1.0', stage=None, revision=None, dis...
FAILED tests/integration/test_dunamai.py::test__version__from_git__broken_ref - FileNotFoundError: [Errno 2] No such file or directory: '/build/pytest-of-n...
===== 6 failed, 50 passed, 6 skipped, 1 deselected, 25 warnings in 12.91s ======

This build failure will need to be resolved one way or another before we can make Git v3 the default in Nixpkgs. First step is probably working out whether this failure is specific to Nixpkgs or something that also affects upstream when using a version of Git compiled with breaking changes.

Activity

  1. added
    6.topic: pythonPython is a high-level, general-purpose programming language.
    6.topic: fetchFetchers (e.g. fetchgit, fetchsvn, ...)
    on Oct 7, 2026
  2. me-and commented on Oct 7, 2026

    @me-and
    MemberAuthor

    Tagging @jmgilman as the package owner.

  3. me-and commented on Oct 13, 2026

    @me-and
    MemberAuthor

    Reported upstream: mtkennerly/dunamai#117

  4. linked a pull request that will close this issuepython3Packages.dunamai: 1.26.2 -> 1.26.3 #574373on Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    6.topic: fetchFetchers (e.g. fetchgit, fetchsvn, ...)6.topic: pythonPython is a high-level, general-purpose programming language.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions