Skip to content

Commit 524e049

Browse files
authored
nixos-rebuild-ng: fix repl behaving differently on git flakes than bu… (NixOS#375493)
2 parents af9e505 + 8e2bc8e commit 524e049

File tree

3 files changed

+64
-16
lines changed

3 files changed

+64
-16
lines changed

pkgs/by-name/ni/nixos-rebuild-ng/src/nixos_rebuild/models.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,25 @@ def from_arg(cls, attr: str | None, file: str | None) -> Self:
6161
return cls(Path(file or "default.nix"), attr)
6262

6363

64+
def discover_git(location: Path) -> str | None:
65+
current = location.resolve()
66+
previous = None
67+
68+
while current.is_dir() and current != previous:
69+
dotgit = current / ".git"
70+
if dotgit.is_dir():
71+
return str(current)
72+
elif dotgit.is_file(): # this is a worktree
73+
with dotgit.open() as f:
74+
dotgit_content = f.read().strip()
75+
if dotgit_content.startswith("gitdir: "):
76+
return dotgit_content.split("gitdir: ")[1]
77+
previous = current
78+
current = current.parent
79+
80+
return None
81+
82+
6483
@dataclass(frozen=True)
6584
class Flake:
6685
path: Path | str
@@ -84,11 +103,15 @@ def parse(
84103
assert m is not None, f"got no matches for {flake_str}"
85104
attr = m.group("attr")
86105
nixos_attr = f"nixosConfigurations.{attr or hostname_fn() or 'default'}"
87-
path = m.group("path")
88-
if ":" in path:
89-
return cls(path, nixos_attr)
106+
path_str = m.group("path")
107+
if ":" in path_str:
108+
return cls(path_str, nixos_attr)
90109
else:
91-
return cls(Path(path), nixos_attr)
110+
path = Path(path_str)
111+
git_repo = discover_git(path)
112+
if git_repo is not None:
113+
return cls(f"git+file://{git_repo}", nixos_attr)
114+
return cls(path, nixos_attr)
92115

93116
@classmethod
94117
def from_arg(cls, flake_arg: Any, target_host: Remote | None) -> Self | None:

pkgs/by-name/ni/nixos-rebuild-ng/src/tests/test_models.py

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from typing import Any
55
from unittest.mock import patch
66

7+
from pytest import MonkeyPatch
8+
79
import nixos_rebuild.models as m
810

911
from .helpers import get_qualified_name
@@ -30,7 +32,7 @@ def test_build_attr_to_attr() -> None:
3032
)
3133

3234

33-
def test_flake_parse() -> None:
35+
def test_flake_parse(tmpdir: Path, monkeypatch: MonkeyPatch) -> None:
3436
assert m.Flake.parse("/path/to/flake#attr") == m.Flake(
3537
Path("/path/to/flake"), "nixosConfigurations.attr"
3638
)
@@ -40,15 +42,31 @@ def test_flake_parse() -> None:
4042
assert m.Flake.parse("/path/to/flake", lambda: "hostname") == m.Flake(
4143
Path("/path/to/flake"), "nixosConfigurations.hostname"
4244
)
43-
assert m.Flake.parse(".#attr") == m.Flake(Path("."), "nixosConfigurations.attr")
44-
assert m.Flake.parse("#attr") == m.Flake(Path("."), "nixosConfigurations.attr")
45-
assert m.Flake.parse(".") == m.Flake(Path("."), "nixosConfigurations.default")
45+
# change directory to tmpdir
46+
with monkeypatch.context() as patch_context:
47+
patch_context.chdir(tmpdir)
48+
assert m.Flake.parse(".#attr") == m.Flake(Path("."), "nixosConfigurations.attr")
49+
assert m.Flake.parse("#attr") == m.Flake(Path("."), "nixosConfigurations.attr")
50+
assert m.Flake.parse(".") == m.Flake(Path("."), "nixosConfigurations.default")
4651
assert m.Flake.parse("path:/to/flake#attr") == m.Flake(
4752
"path:/to/flake", "nixosConfigurations.attr"
4853
)
4954
assert m.Flake.parse("github:user/repo/branch") == m.Flake(
5055
"github:user/repo/branch", "nixosConfigurations.default"
5156
)
57+
git_root = tmpdir / "git_root"
58+
git_root.mkdir()
59+
(git_root / ".git").mkdir()
60+
assert m.Flake.parse(str(git_root)) == m.Flake(
61+
f"git+file://{git_root}", "nixosConfigurations.default"
62+
)
63+
64+
work_tree = tmpdir / "work_tree"
65+
work_tree.mkdir()
66+
(work_tree / ".git").write_text("gitdir: /path/to/git", "utf-8")
67+
assert m.Flake.parse(str(work_tree)) == m.Flake(
68+
"git+file:///path/to/git", "nixosConfigurations.default"
69+
)
5270

5371

5472
def test_flake_to_attr() -> None:
@@ -61,7 +79,7 @@ def test_flake_to_attr() -> None:
6179

6280

6381
@patch(get_qualified_name(platform.node), autospec=True)
64-
def test_flake_from_arg(mock_node: Any) -> None:
82+
def test_flake_from_arg(mock_node: Any, monkeypatch: MonkeyPatch, tmpdir: Path) -> None:
6583
mock_node.return_value = "hostname"
6684

6785
# Flake string
@@ -73,9 +91,11 @@ def test_flake_from_arg(mock_node: Any) -> None:
7391
assert m.Flake.from_arg(False, None) is None
7492

7593
# True
76-
assert m.Flake.from_arg(True, None) == m.Flake(
77-
Path("."), "nixosConfigurations.hostname"
78-
)
94+
with monkeypatch.context() as patch_context:
95+
patch_context.chdir(tmpdir)
96+
assert m.Flake.from_arg(True, None) == m.Flake(
97+
Path("."), "nixosConfigurations.hostname"
98+
)
7999

80100
# None when we do not have /etc/nixos/flake.nix
81101
with patch(

pkgs/by-name/ni/nixos-rebuild-ng/src/tests/test_nix.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from unittest.mock import ANY, call, patch
77

88
import pytest
9+
from pytest import MonkeyPatch
910

1011
import nixos_rebuild.models as m
1112
import nixos_rebuild.nix as n
@@ -51,7 +52,8 @@ def test_build(mock_run: Any, monkeypatch: Any) -> None:
5152
autospec=True,
5253
return_value=CompletedProcess([], 0, stdout=" \n/path/to/file\n "),
5354
)
54-
def test_build_flake(mock_run: Any) -> None:
55+
def test_build_flake(mock_run: Any, monkeypatch: MonkeyPatch, tmpdir: Path) -> None:
56+
monkeypatch.chdir(tmpdir)
5557
flake = m.Flake.parse(".#hostname")
5658

5759
assert n.build_flake(
@@ -165,7 +167,10 @@ def run_wrapper_side_effect(
165167
autospec=True,
166168
return_value=CompletedProcess([], 0, stdout=" \n/path/to/file\n "),
167169
)
168-
def test_build_remote_flake(mock_run: Any, monkeypatch: Any) -> None:
170+
def test_build_remote_flake(
171+
mock_run: Any, monkeypatch: MonkeyPatch, tmpdir: Path
172+
) -> None:
173+
monkeypatch.chdir(tmpdir)
169174
flake = m.Flake.parse(".#hostname")
170175
build_host = m.Remote("user@host", [], None)
171176
monkeypatch.setenv("NIX_SSHOPTS", "--ssh opts")
@@ -287,7 +292,7 @@ def test_copy_closure(monkeypatch: Any) -> None:
287292
@patch(get_qualified_name(n.run_wrapper, n), autospec=True)
288293
def test_edit(mock_run: Any, monkeypatch: Any, tmpdir: Any) -> None:
289294
# Flake
290-
flake = m.Flake.parse(".#attr")
295+
flake = m.Flake.parse(f"{tmpdir}#attr")
291296
n.edit(flake, {"commit_lock_file": True})
292297
mock_run.assert_called_with(
293298
[
@@ -297,7 +302,7 @@ def test_edit(mock_run: Any, monkeypatch: Any, tmpdir: Any) -> None:
297302
"edit",
298303
"--commit-lock-file",
299304
"--",
300-
".#nixosConfigurations.attr",
305+
f"{tmpdir}#nixosConfigurations.attr",
301306
],
302307
check=False,
303308
)

0 commit comments

Comments
 (0)