pkgs.writeErofsLayers,profiles/ch-runner: MVE

$ nix-build -A examples.dummy.config.debug.closure.erofs.list | xargs
cat | xargs du -h
749M    /nix/store/bzfv5x6lycq6hzhjv6d6vlk1q8fdg9di-base0.erofs
24M     /nix/store/hp41jfq36y0mmjrzqilyh3jfsvqic3kb-nixos.erofs

$ nix run -f . examples.dummy.config.uvms.cloud-hypervisor.runner
...
<<< Welcome to NixOS 25.11pre-git (x86_64) - ttyS0 >>>

nixos login:

The definition of the `pkgs` fixpoint was moved to pkgs/default.nix.
For that, dirToAttrs was moved to lib/, imported ad hoc
This commit is contained in:
Else, Someone 2025-09-19 16:28:48 +03:00
parent 1828835a1d
commit 28d3f89ad4
12 changed files with 428 additions and 77 deletions

23
pkgs/default.nix Normal file
View file

@ -0,0 +1,23 @@
{ lib, newScope }:
let
dirToAttrs = import ../lib/dirToAttrs.nix { inherit lib; };
in
lib.makeScope newScope (
self:
dirToAttrs ./.
[
(
path: fname: _:
if fname == "default.nix" then null else lib.strings.removeSuffix ".nix" fname
)
]
(
name: fpath: typ:
if typ == "regular" then
self.callPackage fpath { }
else if typ == "directory" && builtins.pathExists (fpath + "/package.nix") then
self.callPackage (fpath + "/package.nix") { }
else
null
)
)

View file

@ -0,0 +1,84 @@
{
lib,
erofs-utils,
runCommand,
python3Minimal,
bubblewrap,
writeClosure,
}:
{
name ? "${label}.erofs",
label ? "image",
roots ? [ ],
rootsExclude ? [ ],
erofsArgs ? [
"--mount-point=/nix/store"
"-z"
"lz4hc,level=3"
"-T0"
"-L"
label
"--all-root"
],
...
}@attrs:
let
old = writeClosure rootsExclude;
new = writeClosure roots;
attrs' = lib.removeAttrs [ "name" "roots" "rootsExclude" "erofsArgs" ] attrs;
in
runCommand name
(
attrs
// {
__structuredAttrs = true;
inherit name label;
unsafeDiscardReferences.out = true;
nativeBuildInputs = [
erofs-utils
bubblewrap
python3Minimal
]
++ attrs.nativeBuildInputs or [ ];
inherit old new erofsArgs;
}
)
''
mkdir -p store
python3 << EOF
import hashlib, json, os, subprocess
from uuid import UUID
def uuid_from_node(node: int = 0) -> UUID:
return UUID(fields=(*((0,) * 5), node))
out_path = os.environ.get("out")
default_uuid = uuid_from_node((2**48 - 1) & int.from_bytes(hashlib.sha256(out_path.encode("ascii")).digest()))
with open(os.environ.get("NIX_ATTRS_JSON_FILE"), mode="r") as f:
attrs = json.load(f)
name = attrs["name"]
with open(attrs["old"], mode="r") as f:
old_paths = set(ln.rstrip() for ln in f)
with open(attrs["new"], mode="r") as f:
new_paths = [ln.rstrip() for ln in f]
new_paths = [p for p in new_paths if p not in old_paths]
erofs_args = attrs.get("erofsArgs", [])
if not any(a.startswith("-U") for a in erofs_args):
erofs_args.extend(["-U", str(default_uuid)])
subprocess.run(
check=True,
env=os.environ,
args=[
"bwrap",
"--dev-bind", "/", "/",
"--chdir", os.getcwd(),
*[a for p in new_paths for a in [f"--ro-bind", p, f"{os.getcwd()}/store/{os.path.basename(p)}"]],
"--",
"mkfs.erofs", *attrs.get("erofsArgs", []), out_path, "store",
],
)
EOF
''

View file

@ -0,0 +1,35 @@
{ lib, writeErofs }:
{
layers,
labelLower ? "base",
labelUpper ? "image",
}:
let
inherit (lib.lists) toList;
nLayers = builtins.length layers;
mkLabel = seq: if seq + 1 < nLayers then labelLower + toString seq else labelUpper;
f =
{
roots ? [ ],
layers ? [ ],
seq ? 0,
}:
newRoots: {
seq = seq + 1;
roots = roots ++ (toList newRoots);
layers = layers ++ [
(writeErofs ({
roots = toList newRoots;
rootsExclude = roots;
passthru = {
inherit seq;
label = mkLabel seq;
};
label = mkLabel seq;
}))
];
};
acc = lib.foldl f { } layers;
in
acc.layers