Skip to content

Commit

Permalink
nix: make review-shell.nix code static
Browse files Browse the repository at this point in the history
Previously, the whole shell.nix was created at runtime using string substitution
and other crimes that made it hard to work on the expression itself.

This patch turns the string substitutions into Nix function arguments to an
otherwise static Nix expression and only generates the list of attrs to be built
dynamically.
  • Loading branch information
Atemu authored and mergify[bot] committed Jan 2, 2024
1 parent d364838 commit d758033
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 44 deletions.
99 changes: 55 additions & 44 deletions nixpkgs_review/nix.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from pathlib import Path
from sys import platform
from tempfile import NamedTemporaryFile
from typing import Any
from typing import Any, Final

from .allow import AllowedFeatures
from .errors import NixpkgsReviewError
Expand Down Expand Up @@ -42,6 +42,9 @@ def is_test(self) -> bool:
return self.name.startswith("nixosTests")


REVIEW_SHELL: Final[str] = str(ROOT.joinpath("nix/review-shell.nix"))


def nix_shell(
attrs: list[str],
cache_directory: Path,
Expand All @@ -57,22 +60,29 @@ def nix_shell(
if not nix_shell:
raise RuntimeError(f"{build_graph} not found in PATH")

shell = cache_directory.joinpath("shell.nix")
write_shell_expression(shell, attrs, system, nixpkgs_config)
shell_file_args = build_shell_file_args(
cache_directory, attrs, system, nixpkgs_config
)
if sandbox:
args = _nix_shell_sandbox(
nix_shell, shell, nix_path, nixpkgs_config, nixpkgs_overlay
nix_shell,
shell_file_args,
cache_directory,
nix_path,
nixpkgs_config,
nixpkgs_overlay,
)
else:
args = [nix_shell, str(shell), "--nix-path", nix_path]
args = [nix_shell, *shell_file_args, "--nix-path", nix_path, REVIEW_SHELL]
if run:
args.extend(["--run", run])
sh(args, cwd=cache_directory)


def _nix_shell_sandbox(
nix_shell: str,
shell: Path,
shell_file_args: list[str],
cache_directory: Path,
nix_path: str,
nixpkgs_config: Path,
nixpkgs_overlay: Path,
Expand Down Expand Up @@ -112,7 +122,7 @@ def tmpfs(path: Path | str, dir: bool = True) -> list[str]:

return [*dir_cmd, "--tmpfs", str(path)]

nixpkgs_review_pr = shell.parent
nixpkgs_review_pr = cache_directory
home = Path.home()
current_dir = Path().absolute()
xdg_config_home = Path(os.environ.get("XDG_CONFIG_HOME", home.joinpath(".config")))
Expand Down Expand Up @@ -149,7 +159,16 @@ def tmpfs(path: Path | str, dir: bool = True) -> list[str]:
*bind(hub_config, try_=True),
*bind(gh_config, try_=True),
]
return [bwrap, *bwrap_args, "--", nix_shell, str(shell), "--nix-path", nix_path]
return [
bwrap,
*bwrap_args,
"--",
nix_shell,
*shell_file_args,
REVIEW_SHELL,
"--nix-path",
nix_path,
]


def _nix_eval_filter(json: dict[str, Any]) -> list[Attr]:
Expand Down Expand Up @@ -260,12 +279,11 @@ def nix_build(
if len(filtered) == 0:
return attrs

build = cache_directory.joinpath("build.nix")
write_shell_expression(build, filtered, system, nixpkgs_config)

command = [
build_graph,
"build",
"--file",
REVIEW_SHELL,
"--nix-path",
nix_path,
"--extra-experimental-features",
Expand All @@ -285,41 +303,34 @@ def nix_build(
"relaxed",
]

command += [
"-f",
str(build),
] + shlex.split(args)
command += build_shell_file_args(
cache_directory, filtered, system, nixpkgs_config
) + shlex.split(args)

sh(command)
return attrs


def write_shell_expression(
filename: Path, attrs: list[str], system: str, nixpkgs_config: Path
) -> None:
with open(filename, "w+", encoding="utf-8") as f:
f.write(
f"""{{ pkgs ? import ./nixpkgs {{ system = \"{system}\"; config = import {nixpkgs_config}; }} }}:
with pkgs;
let
paths = [
"""
)
f.write("\n".join(f" {escape_attr(a)}" for a in attrs))
f.write(
"""
];
env = buildEnv {
name = "env";
inherit paths;
ignoreCollisions = true;
};
in (import ./nixpkgs { }).mkShell {
name = "review-shell";
preferLocalBuild = true;
allowSubstitutes = false;
dontWrapQtApps = true;
packages = if builtins.length paths > 50 then [ env ] else paths;
}
"""
)
def build_shell_file_args(
cache_dir: Path, attrs: list[str], system: str, nixpkgs_config: Path
) -> list[str]:
attrs_file = cache_dir.joinpath("attrs.nix")
with open(attrs_file, "w+", encoding="utf-8") as f:
f.write("pkgs: with pkgs; [\n")
f.write("\n".join(f" {escape_attr(a)}" for a in attrs))
f.write("\n]")

return [
"--argstr",
"system",
system,
"--argstr",
"nixpkgs-path",
str(cache_dir.joinpath("nixpkgs/")),
"--argstr",
"nixpkgs-config-path",
str(nixpkgs_config),
"--argstr",
"attrs-path",
str(attrs_file),
]
23 changes: 23 additions & 0 deletions nixpkgs_review/nix/review-shell.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{ system
, nixpkgs-config-path # Path to Nix file containing the Nixpkgs config
, attrs-path # Path to Nix file containing a list of attributes to build
, nixpkgs-path # Path to this review's nixpkgs
, pkgs ? import nixpkgs-path { inherit system; config = import nixpkgs-config-path; }
, lib ? pkgs.lib
}:

let
attrs = import attrs-path pkgs;
env = pkgs.buildEnv {
name = "env";
paths = attrs;
ignoreCollisions = true;
};
in
(import nixpkgs-path { }).mkShell {
name = "review-shell";
preferLocalBuild = true;
allowSubstitutes = false;
dontWrapQtApps = true;
packages = if builtins.length attrs > 50 then [ env ] else attrs;
}

0 comments on commit d758033

Please sign in to comment.