Repository navigation
python3Packages.dunamai fails if Git has withBreakingChanges = true #571330
Copy link
Copy link
Closed
Labels
6.topic: fetchFetchers (e.g. fetchgit, fetchsvn, ...)Fetchers (e.g. fetchgit, fetchsvn, ...)6.topic: pythonPython is a high-level, general-purpose programming language.Python is a high-level, general-purpose programming language.
Description
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.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
6.topic: fetchFetchers (e.g. fetchgit, fetchsvn, ...)Fetchers (e.g. fetchgit, fetchsvn, ...)6.topic: pythonPython is a high-level, general-purpose programming language.Python is a high-level, general-purpose programming language.
Activity
me-and commentedon Oct 7, 2026
Tagging @jmgilman as the package owner.
me-and commentedon Oct 13, 2026
Reported upstream: mtkennerly/dunamai#117