refactor(nix): order let bindings #103

Merged
alexion merged 1 commits from natu-let-order-nix into main 2026-09-26 23:43:54 -04:00
16 changed files with 245 additions and 249 deletions

View File

@@ -8,8 +8,8 @@
# Firefox as the desktop browser: stock mainline, hardened and de-monetized by policy. # Firefox as the desktop browser: stock mainline, hardened and de-monetized by policy.
let let
cfg = config.modules.desktop.apps.firefox; # NOLINT(let_order) cfg = config.modules.desktop.apps.firefox; # NOLINT(let_order)
user = config.user.name;
firefoxAddons = inputs.firefox-addons.packages.${pkgs.stdenv.hostPlatform.system}; firefoxAddons = inputs.firefox-addons.packages.${pkgs.stdenv.hostPlatform.system};
user = config.user.name;
in in
{ {
options.modules.desktop.apps.firefox = { options.modules.desktop.apps.firefox = {

View File

@@ -7,7 +7,6 @@
# The Hyprland compositor. # The Hyprland compositor.
let let
cfg = config.modules.desktop.session.hyprland; # NOLINT(let_order) cfg = config.modules.desktop.session.hyprland; # NOLINT(let_order)
user = config.user.name;
cursor = config.stylix.cursor; cursor = config.stylix.cursor;
# Numbered-workspace switch and move for 1..9, the operator's i3 muscle memory. # Numbered-workspace switch and move for 1..9, the operator's i3 muscle memory.
@@ -16,6 +15,8 @@ let
"$mod SHIFT, ${toString n}, movetoworkspace, ${toString n}" "$mod SHIFT, ${toString n}, movetoworkspace, ${toString n}"
]) (lib.range 1 9); ]) (lib.range 1 9);
user = config.user.name;
# Flip the tiling strategy between the two built-in layouts, since neither a # Flip the tiling strategy between the two built-in layouts, since neither a
# dispatcher nor a keyword toggles it on its own. # dispatcher nor a keyword toggles it on its own.
toggleLayout = pkgs.writeShellScript "hypr-toggle-layout" '' toggleLayout = pkgs.writeShellScript "hypr-toggle-layout" ''

View File

@@ -7,14 +7,15 @@
# hypridle: idle-triggered locking and display power management. # hypridle: idle-triggered locking and display power management.
let let
cfg = config.modules.desktop.session.hyprland.hypridle; # NOLINT(let_order) cfg = config.modules.desktop.session.hyprland.hypridle; # NOLINT(let_order)
# The guard drops the call when a locker is already up, so no idle trigger
# stacks a second hyprlock over the first.
lockCmd = "${pkgs.procps}/bin/pidof hyprlock || ${hyprlock}";
user = config.user.name; user = config.user.name;
hyprctl = "${config.programs.hyprland.package}/bin/hyprctl"; hyprctl = "${config.programs.hyprland.package}/bin/hyprctl";
hyprlock = "${config.home-manager.users.${user}.programs.hyprlock.package}/bin/hyprlock"; hyprlock = "${config.home-manager.users.${user}.programs.hyprlock.package}/bin/hyprlock";
# The guard drops the call when a locker is already up, so no idle trigger
# stacks a second hyprlock over the first.
lockCmd = "${pkgs.procps}/bin/pidof hyprlock || ${hyprlock}";
in in
{ {
options.modules.desktop.session.hyprland.hypridle = { options.modules.desktop.session.hyprland.hypridle = {

View File

@@ -8,11 +8,12 @@
let let
cfg = config.modules.desktop.session.waybar; # NOLINT(let_order) cfg = config.modules.desktop.session.waybar; # NOLINT(let_order)
vpnClient = config.modules.network.vpn-client; vpnClient = config.modules.network.vpn-client;
user = config.user.name;
# A Nerd Font Private-Use-Area codepoint as a literal character, decoded # A Nerd Font Private-Use-Area codepoint as a literal character, decoded
# through JSON so the glyph survives as bytes rather than an editor paste. # through JSON so the glyph survives as bytes rather than an editor paste.
g = code: builtins.fromJSON ''"\u${code}"''; g = code: builtins.fromJSON ''"\u${code}"'';
user = config.user.name;
sleepOffIcon = builtins.fromJSON ''"\udb81\udcb3"''; sleepOffIcon = builtins.fromJSON ''"\udb81\udcb3"'';
# Renders and toggles mako's do-not-disturb mode. # Renders and toggles mako's do-not-disturb mode.

View File

@@ -7,7 +7,6 @@
# Nord theming for the graphical layer, driven from one base16 scheme by Stylix. # Nord theming for the graphical layer, driven from one base16 scheme by Stylix.
let let
cfg = config.modules.desktop.utilities.theming; # NOLINT(let_order) cfg = config.modules.desktop.utilities.theming; # NOLINT(let_order)
user = config.user.name;
# A single static Nord wallpaper, drawn as a vertical gradient across the # A single static Nord wallpaper, drawn as a vertical gradient across the
# Polar Night shades so it needs no committed binary and no network fetch. # Polar Night shades so it needs no committed binary and no network fetch.
@@ -16,6 +15,7 @@ let
-size 2560x1440 gradient:'#2E3440'-'#3B4252' \ -size 2560x1440 gradient:'#2E3440'-'#3B4252' \
"$out" "$out"
''; '';
user = config.user.name;
in in
{ {
options.modules.desktop.utilities.theming.enable = options.modules.desktop.utilities.theming.enable =

View File

@@ -7,32 +7,6 @@
# SSH on this machine, in both directions. # SSH on this machine, in both directions.
let let
cfg = config.modules.network.ssh; # NOLINT(let_order) cfg = config.modules.network.ssh; # NOLINT(let_order)
user = config.user.name;
inherit (lib)
concatLists
concatStringsSep
elem
filter
genAttrs
hasAttr
imap0
listToAttrs
mapAttrs
mapAttrsToList
mkIf
mkMerge
mkOption
nameValuePair
optional
optionalAttrs
types
unique
;
hostKeySecret = type: "ssh-host-${type}-key";
userKeySecret = "ssh-user-ed25519-key";
targetType = types.submodule ( targetType = types.submodule (
{ name, ... }: { name, ... }:
{ {
@@ -90,54 +64,18 @@ let
} }
); );
keyWithoutComment = key: concatStringsSep " " (lib.take 2 (lib.splitString " " key));
targetNamesIn = names: filter (name: hasAttr name cfg.targets) names;
workstationNames = targetNamesIn cfg.hosts.workstations;
serverNames = targetNamesIn cfg.hosts.servers;
clientKeysFor = names: filter (key: key != null) (map (name: cfg.targets.${name}.clientKey) names);
currentHost = config.networking.hostName;
isServer = elem currentHost cfg.hosts.servers;
isWorkstation = elem currentHost cfg.hosts.workstations;
defaultAuthorizedKeys = lib.flatten ( defaultAuthorizedKeys = lib.flatten (
clientKeysFor workstationNames ++ optional isServer (clientKeysFor serverNames) clientKeysFor workstationNames ++ optional isServer (clientKeysFor serverNames)
); );
outboundTargetNames = clientKeysFor = names: filter (key: key != null) (map (name: cfg.targets.${name}.clientKey) names);
let
groupTargets =
if isServer then
[ "gitea" ] ++ cfg.hosts.servers
else if isWorkstation then
[ "gitea" ] ++ cfg.hosts.servers ++ cfg.hosts.workstations
else
[ "gitea" ];
in
filter (name: name != currentHost) (targetNamesIn groupTargets);
sshSettingsFor = workstationNames = targetNamesIn cfg.hosts.workstations;
name: targetNamesIn = names: filter (name: hasAttr name cfg.targets) names;
let
target = cfg.targets.${name};
in
{
header = "Host ${concatStringsSep " " target.aliases}";
HostName = target.hostName;
User = target.user;
}
// optionalAttrs (target.port != 22) { Port = target.port; };
knownHostNamesFor = isServer = elem currentHost cfg.hosts.servers;
target: currentHost = config.networking.hostName;
let serverNames = targetNamesIn cfg.hosts.servers;
names = unique (target.aliases ++ [ target.hostName ]);
withPort = name: if target.port == 22 then name else "[${name}]:${toString target.port}";
in
map withPort names;
knownHosts = listToAttrs ( knownHosts = listToAttrs (
concatLists ( concatLists (
@@ -153,6 +91,68 @@ let
) cfg.targets ) cfg.targets
) )
); );
knownHostNamesFor =
target:
let
withPort = name: if target.port == 22 then name else "[${name}]:${toString target.port}";
names = unique (target.aliases ++ [ target.hostName ]);
in
map withPort names;
keyWithoutComment = key: concatStringsSep " " (lib.take 2 (lib.splitString " " key));
sshSettingsFor =
name:
let
target = cfg.targets.${name};
in
{
header = "Host ${concatStringsSep " " target.aliases}";
HostName = target.hostName;
User = target.user;
}
// optionalAttrs (target.port != 22) { Port = target.port; };
outboundTargetNames =
let
groupTargets =
if isServer then
[ "gitea" ] ++ cfg.hosts.servers
else if isWorkstation then
[ "gitea" ] ++ cfg.hosts.servers ++ cfg.hosts.workstations
else
[ "gitea" ];
in
filter (name: name != currentHost) (targetNamesIn groupTargets);
isWorkstation = elem currentHost cfg.hosts.workstations;
hostKeySecret = type: "ssh-host-${type}-key";
user = config.user.name;
inherit (lib)
concatLists
concatStringsSep
elem
filter
genAttrs
hasAttr
imap0
listToAttrs
mapAttrs
mapAttrsToList
mkIf
mkMerge
mkOption
nameValuePair
optional
optionalAttrs
types
unique
;
userKeySecret = "ssh-user-ed25519-key";
in in
{ {
options.modules.network.ssh = { options.modules.network.ssh = {

View File

@@ -38,6 +38,31 @@ let
}; };
}; };
configScript = pkgs.writeShellScript "copyparty-config" ''
set -eu
umask 077
password="$(${pkgs.coreutils}/bin/tr -d '\n' < "$CREDENTIALS_DIRECTORY/password")"
cat > /run/copyparty/copyparty.conf <<EOF
[global]
p: ${toString cfg.port}
usernames
http-only
no-crt
no-thumb
no-snap
no-rescan
ses-db: ${cfg.stateDir}/sessions.db
chpw-db: ${cfg.stateDir}/chpw.json
shr-db: ${cfg.stateDir}/shares.db
${renderedReverseProxy}
[accounts]
${cfg.accountName}: $password
${renderedVolumes}
EOF
'';
renderAccess = permission: accounts: " ${permission}: ${lib.concatStringsSep ", " accounts}"; renderAccess = permission: accounts: " ${permission}: ${lib.concatStringsSep ", " accounts}";
hasFlag = hasFlag =
@@ -72,31 +97,6 @@ let
renderedVolumes = lib.concatStringsSep "\n" (lib.mapAttrsToList renderVolume cfg.volumes); renderedVolumes = lib.concatStringsSep "\n" (lib.mapAttrsToList renderVolume cfg.volumes);
configScript = pkgs.writeShellScript "copyparty-config" ''
set -eu
umask 077
password="$(${pkgs.coreutils}/bin/tr -d '\n' < "$CREDENTIALS_DIRECTORY/password")"
cat > /run/copyparty/copyparty.conf <<EOF
[global]
p: ${toString cfg.port}
usernames
http-only
no-crt
no-thumb
no-snap
no-rescan
ses-db: ${cfg.stateDir}/sessions.db
chpw-db: ${cfg.stateDir}/chpw.json
shr-db: ${cfg.stateDir}/shares.db
${renderedReverseProxy}
[accounts]
${cfg.accountName}: $password
${renderedVolumes}
EOF
'';
in in
{ {
options.modules.services.copyparty = { options.modules.services.copyparty = {

View File

@@ -7,9 +7,42 @@
let let
cfg = config.modules.services.homepage; # NOLINT(let_order) cfg = config.modules.services.homepage; # NOLINT(let_order)
mkRegistryPath = derivedAllowedHosts = lib.unique (
registryName: host: entry: lib.optional (selfRoute != null) selfRoute.domain
"registry.${registryName}.${host}.${entry}"; ++ lib.optionals (selfAddress != null) [
selfAddress
"${selfAddress}:${toString cfg.listenPort}"
]
);
selfRoute = selfEntry.route or null;
selfEntry = registry.join cfg.hostName cfg.entryName;
selfAddress = selfEntry.address or null;
homepageServices = map mkTab (lib.filter (tab: lib.hasAttr tab entriesByTab) orderedTabs);
mkTab =
tab:
let
sections = entriesByTab.${tab};
in
{
${tab} = map (section: { ${section} = sections.${section}; }) (orderedSections tab sections);
};
entriesByTab = lib.foldl' insertEntry { } sortedEntries;
insertEntry =
acc: item:
acc
// {
${item.homepage.tab} = (acc.${item.homepage.tab} or { }) // {
${item.homepage.section} = (acc.${item.homepage.tab}.${item.homepage.section} or [ ]) ++ [
{ ${item.homepage.name} = mkServiceAttrs item; }
];
};
};
sortedEntries = lib.sort (left: right: left.homepage.name < right.homepage.name) homepageEntries;
homepageEntries = lib.concatLists ( homepageEntries = lib.concatLists (
lib.mapAttrsToList ( lib.mapAttrsToList (
@@ -21,6 +54,18 @@ let
) registry.homepage ) registry.homepage
); );
orderedTabs = tabOrder ++ lib.filter (tab: !lib.elem tab tabOrder) (lib.attrNames entriesByTab);
tabOrder = [
"Apps"
"Download"
"System"
];
mkRegistryPath =
registryName: host: entry:
"registry.${registryName}.${host}.${entry}";
mkHref = mkHref =
item: item:
if item.homepage.href != null then if item.homepage.href != null then
@@ -42,29 +87,6 @@ let
inherit (item.homepage) description icon; inherit (item.homepage) description icon;
}; };
sortedEntries = lib.sort (left: right: left.homepage.name < right.homepage.name) homepageEntries;
insertEntry =
acc: item:
acc
// {
${item.homepage.tab} = (acc.${item.homepage.tab} or { }) // {
${item.homepage.section} = (acc.${item.homepage.tab}.${item.homepage.section} or [ ]) ++ [
{ ${item.homepage.name} = mkServiceAttrs item; }
];
};
};
entriesByTab = lib.foldl' insertEntry { } sortedEntries;
tabOrder = [
"Apps"
"Download"
"System"
];
orderedTabs = tabOrder ++ lib.filter (tab: !lib.elem tab tabOrder) (lib.attrNames entriesByTab);
sectionOrderByTab = { sectionOrderByTab = {
Apps = [ Apps = [
"Media" "Media"
@@ -91,28 +113,6 @@ let
in in
sectionOrder ++ lib.filter (section: !lib.elem section sectionOrder) (lib.attrNames sections); sectionOrder ++ lib.filter (section: !lib.elem section sectionOrder) (lib.attrNames sections);
mkTab =
tab:
let
sections = entriesByTab.${tab};
in
{
${tab} = map (section: { ${section} = sections.${section}; }) (orderedSections tab sections);
};
homepageServices = map mkTab (lib.filter (tab: lib.hasAttr tab entriesByTab) orderedTabs);
selfEntry = registry.join cfg.hostName cfg.entryName;
selfAddress = selfEntry.address or null;
selfRoute = selfEntry.route or null;
derivedAllowedHosts = lib.unique (
lib.optional (selfRoute != null) selfRoute.domain
++ lib.optionals (selfAddress != null) [
selfAddress
"${selfAddress}:${toString cfg.listenPort}"
]
);
in in
{ {
options.modules.services.homepage = { options.modules.services.homepage = {

View File

@@ -7,61 +7,43 @@
let let
cfg = config.modules.services.reverse-proxy; # NOLINT(let_order) cfg = config.modules.services.reverse-proxy; # NOLINT(let_order)
mkRegistryPath = generatedUdpStreams = lib.concatLists (
registryName: host: entry: lib.mapAttrsToList (
"registry.${registryName}.${host}.${entry}"; host: routes:
lib.concatLists (
lib.mapAttrsToList (entry: route: map (mkUdpStream host entry) route.udp.ports) routes
)
) registry.route
);
mkBackend = address: port: "http://${address}:${toString port}"; mkUdpStream =
host: entry: port:
mkVirtualHost =
host: entry: mode:
let let
compositeEntry = registry.join host entry;
inherit (compositeEntry) route;
address = address =
compositeEntry.address compositeEntry.address
or (throw "no matching entry in registry.address for ${mkRegistryPath "route" host entry}"); or (throw "no matching entry in registry.address for ${mkRegistryPath "route" host entry}");
isHttp = mode == "http"; compositeEntry = registry.join host entry;
port = if isHttp then route.http.port else route.port;
in in
{ {
inherit host entry; inherit
registryName = "route"; host
name = route.domain; entry
value = { port
forceSSL = !isHttp; address
enableACME = !isHttp; ;
locations."/".proxyPass = mkBackend address port;
};
}; };
generatedHttpsVirtualHostList = lib.concatLists ( generatedStreamConfig = lib.concatMapStringsSep "\n" (stream: ''
lib.mapAttrsToList ( server {
host: routes: listen ${toString stream.port} udp;
lib.mapAttrsToList (entry: _route: mkVirtualHost host entry "https") ( proxy_pass ${stream.address}:${toString stream.port};
lib.filterAttrs (_entry: route: route.port != null) routes
)
) registry.route
);
generatedHttpVirtualHostList = lib.concatLists (
lib.mapAttrsToList (
host: routes:
lib.mapAttrsToList (entry: _route: mkVirtualHost host entry "http") (
lib.filterAttrs (_entry: route: route.http.port != null) routes
)
) registry.route
);
generatedVirtualHostList = generatedHttpsVirtualHostList ++ generatedHttpVirtualHostList;
virtualHostsByDomain = lib.foldl' (
acc: virtualHost:
acc
// {
${virtualHost.name} = (acc.${virtualHost.name} or [ ]) ++ [ virtualHost ];
} }
) { } generatedVirtualHostList; '') generatedUdpStreams;
generatedVirtualHosts =
if duplicateDomainMessages != [ ] then
throw (builtins.head duplicateDomainMessages)
else
lib.listToAttrs generatedVirtualHostList;
duplicateDomainMessages = lib.concatLists ( duplicateDomainMessages = lib.concatLists (
lib.mapAttrsToList ( lib.mapAttrsToList (
@@ -79,44 +61,62 @@ let
) virtualHostsByDomain ) virtualHostsByDomain
); );
generatedVirtualHosts = virtualHostsByDomain = lib.foldl' (
if duplicateDomainMessages != [ ] then acc: virtualHost:
throw (builtins.head duplicateDomainMessages) acc
else // {
lib.listToAttrs generatedVirtualHostList; ${virtualHost.name} = (acc.${virtualHost.name} or [ ]) ++ [ virtualHost ];
}
) { } generatedVirtualHostList;
mkUdpStream = generatedVirtualHostList = generatedHttpsVirtualHostList ++ generatedHttpVirtualHostList;
host: entry: port:
let
compositeEntry = registry.join host entry;
address =
compositeEntry.address
or (throw "no matching entry in registry.address for ${mkRegistryPath "route" host entry}");
in
{
inherit
host
entry
port
address
;
};
generatedUdpStreams = lib.concatLists ( generatedHttpsVirtualHostList = lib.concatLists (
lib.mapAttrsToList ( lib.mapAttrsToList (
host: routes: host: routes:
lib.concatLists ( lib.mapAttrsToList (entry: _route: mkVirtualHost host entry "https") (
lib.mapAttrsToList (entry: route: map (mkUdpStream host entry) route.udp.ports) routes lib.filterAttrs (_entry: route: route.port != null) routes
) )
) registry.route ) registry.route
); );
generatedStreamConfig = lib.concatMapStringsSep "\n" (stream: '' mkVirtualHost =
server { host: entry: mode:
listen ${toString stream.port} udp; let
proxy_pass ${stream.address}:${toString stream.port}; isHttp = mode == "http";
} address =
'') generatedUdpStreams; compositeEntry.address
or (throw "no matching entry in registry.address for ${mkRegistryPath "route" host entry}");
compositeEntry = registry.join host entry;
inherit (compositeEntry) route;
port = if isHttp then route.http.port else route.port;
in
{
inherit host entry;
registryName = "route";
name = route.domain;
value = {
forceSSL = !isHttp;
enableACME = !isHttp;
locations."/".proxyPass = mkBackend address port;
};
};
mkBackend = address: port: "http://${address}:${toString port}";
generatedHttpVirtualHostList = lib.concatLists (
lib.mapAttrsToList (
host: routes:
lib.mapAttrsToList (entry: _route: mkVirtualHost host entry "http") (
lib.filterAttrs (_entry: route: route.http.port != null) routes
)
) registry.route
);
mkRegistryPath =
registryName: host: entry:
"registry.${registryName}.${host}.${entry}";
in in
{ {
options.modules.services.reverse-proxy = { options.modules.services.reverse-proxy = {

View File

@@ -80,10 +80,10 @@
(lib.mkIf config.modules.services.steamcmd.enable ( (lib.mkIf config.modules.services.steamcmd.enable (
let let
service = config.modules.services.steamcmd;
user = "steamcmd";
group = "storage"; group = "storage";
service = config.modules.services.steamcmd;
user = "steamcmd";
prepareScript = pkgs.writeShellScript "steamcmd-${service.serviceName}-prepare" '' prepareScript = pkgs.writeShellScript "steamcmd-${service.serviceName}-prepare" ''
set -eu set -eu

View File

@@ -7,13 +7,13 @@
# fish for the primary user, configured through home-manager. # fish for the primary user, configured through home-manager.
let let
cfg = config.modules.shell.fish; # NOLINT(let_order) cfg = config.modules.shell.fish; # NOLINT(let_order)
user = config.user.name;
shortcuts = lib.attrByPath [ config.networking.hostName ] { } config.registry.shell-shortcut;
envVars = lib.attrByPath [ config.networking.hostName ] { } config.registry.env-var;
commandsOf = shortcuts: lib.mapAttrs (_name: shortcut: shortcut.command) shortcuts; commandsOf = shortcuts: lib.mapAttrs (_name: shortcut: shortcut.command) shortcuts;
shortcuts = lib.attrByPath [ config.networking.hostName ] { } config.registry.shell-shortcut;
exportEnvVar = name: value: '' exportEnvVar = name: value: ''
set -gx ${name} ${lib.escapeShellArg value} set -gx ${name} ${lib.escapeShellArg value}
''; '';
envVars = lib.attrByPath [ config.networking.hostName ] { } config.registry.env-var;
user = config.user.name;
in in
{ {
options.modules.shell.fish = { options.modules.shell.fish = {

View File

@@ -9,12 +9,12 @@
# The login credential is left unmanaged, so it survives rebuilds. # The login credential is left unmanaged, so it survives rebuilds.
let let
cfg = config.modules.shell.pi; # NOLINT(let_order) cfg = config.modules.shell.pi; # NOLINT(let_order)
user = config.user.name;
piDir = "${config.users.users.${user}.home}/.pi/agent";
vendoredPi = pkgs.pi-coding-agent.overrideAttrs { vendoredPi = pkgs.pi-coding-agent.overrideAttrs {
src = ../../../../../third_party/pi; src = ../../../../../third_party/pi;
patches = [ ]; patches = [ ];
}; };
user = config.user.name;
piDir = "${config.users.users.${user}.home}/.pi/agent";
in in
{ {
options.modules.shell.pi = { options.modules.shell.pi = {

View File

@@ -7,7 +7,6 @@
# Rust tools for the primary user's shell environment. # Rust tools for the primary user's shell environment.
let let
cfg = config.modules.shell.rust; # NOLINT(let_order) cfg = config.modules.shell.rust; # NOLINT(let_order)
user = config.user.name;
toolchain = pkgs.symlinkJoin { toolchain = pkgs.symlinkJoin {
name = "rust-toolchain"; name = "rust-toolchain";
paths = with pkgs; [ paths = with pkgs; [
@@ -18,6 +17,7 @@ let
rustfmt rustfmt
]; ];
}; };
user = config.user.name;
in in
{ {
options.modules.shell.rust.enable = options.modules.shell.rust.enable =

View File

@@ -1,11 +1,8 @@
{ lib, ... }: { lib, ... }:
let let
inherit (lib) duplicateUids =
filterAttrs entries:
groupBy filterAttrs (_uid: serviceNames: builtins.length serviceNames > 1) (serviceNamesByUid entries);
mapAttrs
unique
;
serviceNamesByUid = serviceNamesByUid =
entries: entries:
@@ -13,10 +10,6 @@ let
groupBy (entry: toString entry.value) entries groupBy (entry: toString entry.value) entries
); );
duplicateUids =
entries:
filterAttrs (_uid: serviceNames: builtins.length serviceNames > 1) (serviceNamesByUid entries);
in in
{ {
# Next stable UID: 20005 # Next stable UID: 20005

View File

@@ -8,6 +8,7 @@
util, util,
}: }:
let let
files = util.collectNixFiles root;
mkGuest = mkGuest =
name: name:
{ config, lib, ... }: { config, lib, ... }:
@@ -167,22 +168,22 @@ let
config = lib.mkIf cfg.enable { config = lib.mkIf cfg.enable {
assertions = assertions =
let let
hasDirectorySettings = mount: mount.owner != null || mount.group != null || mount.mode != null;
hasCompleteDirectorySettings =
mount: mount.owner != null && mount.group != null && mount.mode != null;
hasOneSource = mount: (mount.directory != null) != (mount.file != null);
mountsWithInvalidSource = lib.attrNames ( mountsWithInvalidSource = lib.attrNames (
lib.filterAttrs (_: mount: !hasOneSource mount) cfg.mounts lib.filterAttrs (_: mount: !hasOneSource mount) cfg.mounts
); );
hasOneSource = mount: (mount.directory != null) != (mount.file != null);
fileMountsWithHostSettings = lib.attrNames ( fileMountsWithHostSettings = lib.attrNames (
lib.filterAttrs (_: mount: mount.file != null && hasDirectorySettings mount) cfg.mounts lib.filterAttrs (_: mount: mount.file != null && hasDirectorySettings mount) cfg.mounts
); );
hasDirectorySettings = mount: mount.owner != null || mount.group != null || mount.mode != null;
directoryMountsWithPartialHostSettings = lib.attrNames ( directoryMountsWithPartialHostSettings = lib.attrNames (
lib.filterAttrs ( lib.filterAttrs (
_: mount: _: mount:
mount.directory != null && hasDirectorySettings mount && !hasCompleteDirectorySettings mount mount.directory != null && hasDirectorySettings mount && !hasCompleteDirectorySettings mount
) cfg.mounts ) cfg.mounts
); );
hasCompleteDirectorySettings =
mount: mount.owner != null && mount.group != null && mount.mode != null;
in in
[ [
{ {
@@ -275,11 +276,10 @@ let
}; };
}; };
files = util.collectNixFiles root; names = map (file: lib.removeSuffix ".nix" file) (lib.attrNames guestFiles);
guestFiles = lib.filterAttrs (file: type: type == "regular" && lib.hasSuffix ".nix" file) ( guestFiles = lib.filterAttrs (file: type: type == "regular" && lib.hasSuffix ".nix" file) (
builtins.readDir root builtins.readDir root
); );
names = map (file: lib.removeSuffix ".nix" file) (lib.attrNames guestFiles);
in in
{ {
imports = files ++ map mkGuest names; imports = files ++ map mkGuest names;

View File

@@ -9,6 +9,8 @@
registryModule, registryModule,
}: }:
let let
names = lib.attrNames directories;
directories = lib.filterAttrs (_name: type: type == "directory") (builtins.readDir root);
mkHost = mkHost =
{ {
root, root,
@@ -36,7 +38,5 @@ let
]; ];
}; };
directories = lib.filterAttrs (_name: type: type == "directory") (builtins.readDir root);
names = lib.attrNames directories;
in in
lib.genAttrs names (name: mkHost { inherit root name; }) lib.genAttrs names (name: mkHost { inherit root name; })