nixos-rebuild-ng: do not parse the path part from Flake as a Path (#445188)
This commit is contained in:
@@ -134,14 +134,17 @@ python3Packages.buildPythonApplication rec {
|
||||
# NOTE: this is a passthru test rather than a build-time test because we
|
||||
# want to keep the build closures small
|
||||
linters = runCommand "${pname}-linters" { nativeBuildInputs = [ python-with-pkgs ]; } ''
|
||||
export MYPY_CACHE_DIR="$(mktemp -d)"
|
||||
export RUFF_CACHE_DIR="$(mktemp -d)"
|
||||
|
||||
pushd ${src}
|
||||
echo -e "\x1b[32m## run mypy\x1b[0m"
|
||||
mypy ${src}
|
||||
mypy .
|
||||
echo -e "\x1b[32m## run ruff\x1b[0m"
|
||||
ruff check ${src}
|
||||
ruff check .
|
||||
echo -e "\x1b[32m## run ruff format\x1b[0m"
|
||||
ruff format --check ${src}
|
||||
ruff format --check .
|
||||
popd
|
||||
|
||||
touch $out
|
||||
'';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# mypy: disable-error-code=comparison-overlap
|
||||
from typing import Final
|
||||
|
||||
# Build-time flags
|
||||
|
||||
@@ -8,7 +8,7 @@ from typing import Any, ClassVar, Self, TypedDict, override
|
||||
|
||||
from .process import Remote, run_wrapper
|
||||
|
||||
type ImageVariants = list[str]
|
||||
type ImageVariants = dict[str, str]
|
||||
|
||||
|
||||
class NixOSRebuildError(Exception):
|
||||
@@ -77,7 +77,7 @@ def _get_hostname(target_host: Remote | None) -> str | None:
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Flake:
|
||||
path: Path | str
|
||||
path: str
|
||||
attr: str
|
||||
_re: ClassVar = re.compile(r"^(?P<path>[^\#]*)\#?(?P<attr>[^\#\"]*)$")
|
||||
|
||||
@@ -86,11 +86,7 @@ class Flake:
|
||||
|
||||
@override
|
||||
def __str__(self) -> str:
|
||||
if isinstance(self.path, Path):
|
||||
# https://github.com/NixOS/nixpkgs/issues/433726
|
||||
return f"{self.path.absolute()}#{self.attr}"
|
||||
else:
|
||||
return f"{self.path}#{self.attr}"
|
||||
return f"{self.path}#{self.attr}"
|
||||
|
||||
@classmethod
|
||||
def parse(cls, flake_str: str, target_host: Remote | None = None) -> Self:
|
||||
@@ -101,10 +97,7 @@ class Flake:
|
||||
f'nixosConfigurations."{attr or _get_hostname(target_host) or "default"}"'
|
||||
)
|
||||
path = m.group("path")
|
||||
if ":" in path:
|
||||
return cls(path, nixos_attr)
|
||||
else:
|
||||
return cls(Path(path), nixos_attr)
|
||||
return cls(path, nixos_attr)
|
||||
|
||||
@classmethod
|
||||
def from_arg(cls, flake_arg: Any, target_host: Remote | None) -> Self | None: # noqa: ANN401
|
||||
@@ -125,6 +118,12 @@ class Flake:
|
||||
else:
|
||||
return None
|
||||
|
||||
def resolve_path_if_exists(self) -> str:
|
||||
try:
|
||||
return str(Path(self.path).resolve(strict=True))
|
||||
except FileNotFoundError:
|
||||
return self.path
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Generation:
|
||||
|
||||
@@ -545,7 +545,7 @@ def repl_flake(flake: Flake, flake_flags: Args | None = None) -> None:
|
||||
files(__package__).joinpath(FLAKE_REPL_TEMPLATE).read_text()
|
||||
).substitute(
|
||||
flake=flake,
|
||||
flake_path=flake.path.resolve() if isinstance(flake.path, Path) else flake.path,
|
||||
flake_path=flake.resolve_path_if_exists(),
|
||||
flake_attr=flake.attr,
|
||||
bold="\033[1m",
|
||||
blue="\033[34;1m",
|
||||
|
||||
@@ -14,7 +14,7 @@ class LogFormatter(logging.Formatter):
|
||||
}
|
||||
|
||||
@override
|
||||
def format(self, record: logging.LogRecord) -> str:
|
||||
def format(self, record: logging.LogRecord) -> Any:
|
||||
record.levelname = record.levelname.lower()
|
||||
formatter = self.formatters.get(record.levelno, self.formatters["DEFAULT"])
|
||||
return formatter.format(record)
|
||||
|
||||
@@ -33,10 +33,10 @@ def test_build_attr_to_attr() -> None:
|
||||
@patch("platform.node", autospec=True, return_value=None)
|
||||
def test_flake_parse(mock_node: Mock, tmpdir: Path, monkeypatch: MonkeyPatch) -> None:
|
||||
assert m.Flake.parse("/path/to/flake#attr") == m.Flake(
|
||||
Path("/path/to/flake"), 'nixosConfigurations."attr"'
|
||||
"/path/to/flake", 'nixosConfigurations."attr"'
|
||||
)
|
||||
assert m.Flake.parse("/path/ to /flake") == m.Flake(
|
||||
Path("/path/ to /flake"), 'nixosConfigurations."default"'
|
||||
"/path/ to /flake", 'nixosConfigurations."default"'
|
||||
)
|
||||
with patch(
|
||||
get_qualified_name(m.run_wrapper, m),
|
||||
@@ -45,11 +45,11 @@ def test_flake_parse(mock_node: Mock, tmpdir: Path, monkeypatch: MonkeyPatch) ->
|
||||
):
|
||||
target_host = m.Remote("target@remote", [], None)
|
||||
assert m.Flake.parse("/path/to/flake", target_host) == m.Flake(
|
||||
Path("/path/to/flake"), 'nixosConfigurations."remote"'
|
||||
"/path/to/flake", 'nixosConfigurations."remote"'
|
||||
)
|
||||
assert m.Flake.parse(".#attr") == m.Flake(Path("."), 'nixosConfigurations."attr"')
|
||||
assert m.Flake.parse("#attr") == m.Flake(Path("."), 'nixosConfigurations."attr"')
|
||||
assert m.Flake.parse(".") == m.Flake(Path("."), 'nixosConfigurations."default"')
|
||||
assert m.Flake.parse(".#attr") == m.Flake(".", 'nixosConfigurations."attr"')
|
||||
assert m.Flake.parse("#attr") == m.Flake("", 'nixosConfigurations."attr"')
|
||||
assert m.Flake.parse(".") == m.Flake(".", 'nixosConfigurations."default"')
|
||||
assert m.Flake.parse("path:/to/flake#attr") == m.Flake(
|
||||
"path:/to/flake", 'nixosConfigurations."attr"'
|
||||
)
|
||||
@@ -64,19 +64,33 @@ def test_flake_parse(mock_node: Mock, tmpdir: Path, monkeypatch: MonkeyPatch) ->
|
||||
|
||||
def test_flake_to_attr() -> None:
|
||||
assert (
|
||||
m.Flake(Path("/path/to/flake"), "nixosConfigurations.preAttr").to_attr(
|
||||
m.Flake("/path/to/flake", "nixosConfigurations.preAttr").to_attr(
|
||||
"attr1", "attr2"
|
||||
)
|
||||
== "/path/to/flake#nixosConfigurations.preAttr.attr1.attr2"
|
||||
)
|
||||
|
||||
|
||||
def test_flake__str__(monkeypatch: MonkeyPatch, tmpdir: Path) -> None:
|
||||
def test_flake__str__() -> None:
|
||||
assert str(m.Flake("github:nixos/nixpkgs", "attr")) == "github:nixos/nixpkgs#attr"
|
||||
assert str(m.Flake(Path("/etc/nixos"), "attr")) == "/etc/nixos#attr"
|
||||
assert str(m.Flake("/etc/nixos", "attr")) == "/etc/nixos#attr"
|
||||
assert str(m.Flake(".", "attr")) == ".#attr"
|
||||
assert str(m.Flake("", "attr")) == "#attr"
|
||||
|
||||
|
||||
def test_flake_resolve_path_if_exists(monkeypatch: MonkeyPatch, tmpdir: Path) -> None:
|
||||
assert (
|
||||
m.Flake("github:nixos/nixpkgs", "attr").resolve_path_if_exists()
|
||||
== "github:nixos/nixpkgs"
|
||||
)
|
||||
assert (
|
||||
m.Flake("/an/inexistent/path", "attr").resolve_path_if_exists()
|
||||
== "/an/inexistent/path"
|
||||
)
|
||||
with monkeypatch.context() as patch_context:
|
||||
patch_context.chdir(tmpdir)
|
||||
assert str(m.Flake(Path("."), "attr")) == f"{tmpdir}#attr"
|
||||
assert m.Flake(str(tmpdir), "attr").resolve_path_if_exists() == str(tmpdir)
|
||||
assert m.Flake(".", "attr").resolve_path_if_exists() == str(tmpdir)
|
||||
|
||||
|
||||
@patch("platform.node", autospec=True)
|
||||
@@ -87,7 +101,7 @@ def test_flake_from_arg(
|
||||
|
||||
# Flake string
|
||||
assert m.Flake.from_arg("/path/to/flake#attr", None) == m.Flake(
|
||||
Path("/path/to/flake"), 'nixosConfigurations."attr"'
|
||||
"/path/to/flake", 'nixosConfigurations."attr"'
|
||||
)
|
||||
|
||||
# False
|
||||
@@ -97,7 +111,7 @@ def test_flake_from_arg(
|
||||
with monkeypatch.context() as patch_context:
|
||||
patch_context.chdir(tmpdir)
|
||||
assert m.Flake.from_arg(True, None) == m.Flake(
|
||||
Path("."), 'nixosConfigurations."hostname"'
|
||||
".", 'nixosConfigurations."hostname"'
|
||||
)
|
||||
|
||||
# None when we do not have /etc/nixos/flake.nix
|
||||
@@ -122,7 +136,7 @@ def test_flake_from_arg(
|
||||
),
|
||||
):
|
||||
assert m.Flake.from_arg(None, None) == m.Flake(
|
||||
Path("/etc/nixos"), 'nixosConfigurations."hostname"'
|
||||
"/etc/nixos", 'nixosConfigurations."hostname"'
|
||||
)
|
||||
|
||||
with (
|
||||
@@ -138,7 +152,7 @@ def test_flake_from_arg(
|
||||
),
|
||||
):
|
||||
assert m.Flake.from_arg(None, None) == m.Flake(
|
||||
Path("/path/to"), 'nixosConfigurations."hostname"'
|
||||
"/path/to", 'nixosConfigurations."hostname"'
|
||||
)
|
||||
|
||||
with (
|
||||
@@ -149,7 +163,7 @@ def test_flake_from_arg(
|
||||
),
|
||||
):
|
||||
assert m.Flake.from_arg("/path/to", m.Remote("user@host", [], None)) == m.Flake(
|
||||
Path("/path/to"), 'nixosConfigurations."remote-hostname"'
|
||||
"/path/to", 'nixosConfigurations."remote-hostname"'
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -385,7 +385,7 @@ def test_get_build_image_variants(mock_run: Mock, tmp_path: Path) -> None:
|
||||
),
|
||||
)
|
||||
def test_get_build_image_variants_flake(mock_run: Mock) -> None:
|
||||
flake = m.Flake(Path("/flake.nix"), "myAttr")
|
||||
flake = m.Flake("/flake.nix", "myAttr")
|
||||
assert n.get_build_image_variants_flake(flake, {"eval_flag": True}) == {
|
||||
"azure": "nixos-image-azure-25.05.20250102.6df2492-x86_64-linux.vhd",
|
||||
"vmware": "nixos-image-vmware-25.05.20250102.6df2492-x86_64-linux.vmdk",
|
||||
@@ -574,7 +574,7 @@ def test_repl(mock_run: Mock) -> None:
|
||||
|
||||
@patch(get_qualified_name(n.run_wrapper, n), autospec=True)
|
||||
def test_repl_flake(mock_run: Mock) -> None:
|
||||
n.repl_flake(m.Flake(Path("flake.nix"), "myAttr"), {"nix_flag": True})
|
||||
n.repl_flake(m.Flake("flake.nix", "myAttr"), {"nix_flag": True})
|
||||
# See nixos-rebuild-ng.tests.repl for a better test,
|
||||
# this is mostly for sanity check
|
||||
assert mock_run.call_count == 1
|
||||
|
||||
Reference in New Issue
Block a user