diff --git a/flake.lock b/flake.lock index a3a335d..8b80244 100644 Binary files a/flake.lock and b/flake.lock differ diff --git a/flake.nix b/flake.nix index f938638..b448040 100644 --- a/flake.nix +++ b/flake.nix @@ -11,17 +11,12 @@ in [ # Run »nix flake show --allow-import-from-derivation« to see what this merges to: ## Exports (things to reuse in other flakes): - repo # lib.* nixosModules.* overlays.* - { patches = (lib.fun.importWrapped inputs "${self}/patches").result; } # patches.* + (repo // { packages = lib.fun.packagesFromOverlay { inherit inputs; exclude = [ "libblockdev" ]; }; }) # lib.* nixosModules.* overlays.* packages.* ## Examples: # The example host definitions from ./hosts/, plus their installers (apps): - (lib.self.mkSystemsFlake { inherit inputs; }) # nixosConfigurations.* apps.*-linux.* devShells.*-linux.* packages.*-linux.all-systems + (lib.self.mkSystemsFlake { inherit inputs; asDefaultPackage = true; }) # nixosConfigurations.* apps.*-linux.* devShells.*-linux.* packages.*-linux.all-systems/default # The same cross-compiled from aarch64 (just to show how that works): (lib.self.mkSystemsFlake { inherit inputs; buildPlatform = "aarch64-linux"; renameOutputs = name: "arm:${name}"; }) # nixosConfigurations.arm:* apps.*-linux.arm:* devShells.*-linux.arm:* packages.*-linux.arm:all-systems - # Any packages touched by the ./overlays/: - (lib.fun.forEachSystem [ "aarch64-linux" "x86_64-linux" ] (localSystem: let # packages.*-linux.* - packages = builtins.removeAttrs (lib.fun.getModifiedPackages (lib.fun.importPkgs inputs { system = localSystem; }) overlays) [ "libblockdev" ]; - in { packages = packages // { default = self.packages.${localSystem}.all-systems; }; })) ]); } diff --git a/lib/nixos.nix b/lib/nixos.nix index f228e9c..1b685a3 100644 --- a/lib/nixos.nix +++ b/lib/nixos.nix @@ -121,9 +121,11 @@ in rec { setupPlatforms ? if inputs?systems then import inputs.systems else [ "aarch64-linux" "x86_64-linux" ], ## If provided, then change the name of each output attribute by passing it through this function. Allows exporting of multiple variants of a repo's hosts from a single flake (by then merging the results): renameOutputs ? false, + ## Whether to export the »all-systems« package as »packages.*.default« as well. + asDefaultPackage ? false, ... }: let getName = if renameOutputs == false then (name: name) else renameOutputs; - otherArgs = (builtins.removeAttrs args [ "systems" "moduleInputs" "overlayInputs" "renameOutputs" ]) // { + otherArgs = (builtins.removeAttrs args [ "systems" "moduleInputs" "overlayInputs" "renameOutputs" "asDefaultPackage" ]) // { inherit inputs modules overlays moduleArgs nixosSystem buildPlatform extraModules; nixosArgs = (args.nixosArgs or { }) // { modules = (args.nixosArgs.modules or [ ]) ++ [ { imports = [ (args: { ${installer}.outputName = getName args.config._module.args.name; @@ -140,7 +142,7 @@ in rec { apps = lib.mapAttrs (name: system: rec { type = "app"; derivation = writeSystemScripts { inherit name pkgs system; }; program = "${derivation}"; }) nixosConfigurations; # dummy that just pulls in all system builds - packages.all-systems = pkgs.runCommandLocal "all-systems" { } '' + packages = let all-systems = pkgs.runCommandLocal "all-systems" { } '' ${'' mkdir -p $out/systems ${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: system: "ln -sT ${system.config.system.build.toplevel} $out/systems/${getName name}") nixosConfigurations)} @@ -153,7 +155,7 @@ in rec { mkdir -p $out/inputs ${lib.concatStringsSep "\n" (lib.mapAttrsToList (name: { outPath, ... }: "ln -sT ${outPath} $out/inputs/${name}") inputs)} ''} - ''; + ''; in { inherit all-systems; } // (lib.optionalAttrs asDefaultPackage { default = all-systems ; }); checks.all-systems = packages.all-systems; })); in if renameOutputs == false then outputs else { diff --git a/lib/setup-scripts/disk.sh b/lib/setup-scripts/disk.sh index 202eb6a..1214974 100644 --- a/lib/setup-scripts/disk.sh +++ b/lib/setup-scripts/disk.sh @@ -105,18 +105,13 @@ function partition-disks { actual=$( @{native.systemd}/bin/udevadm info --query=property --name="$blockDev" | grep -oP 'ID_SERIAL_SHORT=\K.*' || echo '' ) if [[ ${disk[serial]} != "$actual" ]] ; then echo "Block device $blockDev's serial ($actual) does not match the serial (${disk[serial]}) declared for ${disk[name]}" 1>&2 ; \return 1 ; fi fi + @{native.util-linux}/bin/blkdiscard -f "${blockDevs[${disk[name]}]}" &>$beLoud || true # can (and probably should) restore the backup: ( PATH=@{native.gptfdisk}/bin ; ${_set_x:-:} ; sgdisk --zap-all --load-backup=@{config.setup.disks.partitioning}/"${disk[name]}".backup ${disk[allowLarger]:+--move-second-header} "${blockDevs[${disk[name]}]}" >$beLoud 2>$beSilent ) || return #partition-disk "${disk[name]}" "${blockDevs[${disk[name]}]}" || return done @{native.parted}/bin/partprobe "${blockDevs[@]}" &>$beLoud || return @{native.systemd}/bin/udevadm settle -t 15 || true # sometimes partitions aren't quite made available yet - - # ensure that filesystem creation does not complain about the devices already being occupied by a previous filesystem - local toWipe=( ) ; for part in "@{config.setup.disks.partitions!attrNames[@]/#/'/dev/disk/by-partlabel/'}" ; do [[ ! -e "$part" ]] || toWipe+=( "$part" ) ; done - @{native.util-linux}/bin/wipefs --all "${toWipe[@]}" >$beLoud 2>$beSilent || return - #/dev/null - #for part in "@{config.setup.disks.partitions!attrNames[@]/#/'/dev/disk/by-partlabel/'}" ; do @{native.util-linux}/bin/blkdiscard -f "$part" || return ; done } ## Given a declared disk device's »name« and a path to an actual »blockDev« (or image) file, partitions the device as declared in the config. @@ -194,16 +189,18 @@ function format-partitions { eval 'declare -A fs='"$fsDecl" if [[ ${fs[device]} == /dev/disk/by-partlabel/* ]] ; then if ! is-partition-on-disks "${fs[device]}" "${blockDevs[@]}" ; then echo "Partition alias ${fs[device]} used by mount ${fs[mountPoint]} does not point at one of the target disks ${blockDevs[@]}" 1>&2 ; \return 1 ; fi + @{native.util-linux}/bin/wipefs --all "${fs[device]}" >$beLoud 2>$beSilent || return # else mkfs might refuse to replace any previous filesystems elif [[ ${fs[device]} == /dev/mapper/* ]] ; then if [[ ! @{config.boot.initrd.luks.devices!catAttrSets.device[${fs[device]/'/dev/mapper/'/}]:-} ]] ; then echo "LUKS device ${fs[device]} used by mount ${fs[mountPoint]} does not point at one of the device mappings ${!config.boot.initrd.luks.devices!catAttrSets.device[@]}" 1>&2 ; \return 1 ; fi else continue ; fi eval 'declare -a formatArgs='"${fs[formatArgs]}" - ( PATH=@{native.e2fsprogs}/bin:@{native.f2fs-tools}/bin:@{native.xfsprogs}/bin:@{native.dosfstools}/bin:$PATH ; ${_set_x:-:} ; mkfs."${fs[fsType]}" "${formatArgs[@]}" "${fs[device]}" >$beLoud 2>$beSilent ) || return + ( PATH=@{native.e2fsprogs}/bin:@{native.f2fs-tools}/bin:@{native.xfsprogs}/bin:@{native.dosfstools}/bin:$PATH ; ${_set_x:-:} ; mkfs."${fs[fsType]}" "${formatArgs[@]}" "${fs[device]}" >$beLoud 2>$beSilent ) || [[ $options == *,nofail,* ]] || return @{native.parted}/bin/partprobe "${fs[device]}" || true done for swapDev in "@{config.swapDevices!catAttrs.device[@]}" ; do if [[ $swapDev == /dev/disk/by-partlabel/* ]] ; then if ! is-partition-on-disks "$swapDev" "${blockDevs[@]}" ; then echo "Partition alias $swapDev used for SWAP does not point at one of the target disks ${blockDevs[@]}" 1>&2 ; \return 1 ; fi + @{native.util-linux}/bin/wipefs --all "${fs[device]}" >$beLoud 2>$beSilent || return # else mkswap might refuse to replace any previous filesystems elif [[ $swapDev == /dev/mapper/* ]] ; then if [[ ! @{config.boot.initrd.luks.devices!catAttrSets.device[${swapDev/'/dev/mapper/'/}]:-} ]] ; then echo "LUKS device $swapDev used for SWAP does not point at one of the device mappings @{!config.boot.initrd.luks.devices!catAttrSets.device[@]}" 1>&2 ; \return 1 ; fi else continue ; fi @@ -233,10 +230,10 @@ function mount-system {( # 1: mnt, 2?: fstabPath, 3?: allowFail # While not generally required for fstab, nixos uses the dependency-sorted »config.system.build.fileSystems« list (instead of plain »builtins.attrValues config.fileSystems«) to generate »/etc/fstab« (provided »config.fileSystems.*.depends« is set correctly, e.g. for overlay mounts). # This function depends on the file at »fstabPath« to be sorted like that. - # The following is roughly equivalent to: mount --all --fstab @{config.system.build.toplevel}/etc/fstab --target-prefix "$1" -o X-mount.mkdir # (but »--target-prefix« is not supported with older versions on »mount«, e.g. on Ubuntu 20.04 (but can't we use mount from nixpkgs?)) mnt=$1 ; fstabPath=${2:-"@{config.system.build.toplevel}/etc/fstab"} ; allowFail=${3:-} PATH=@{native.e2fsprogs}/bin:@{native.f2fs-tools}/bin:@{native.xfsprogs}/bin:@{native.dosfstools}/bin:$PATH + # The following is roughly equivalent to: mount --all --fstab "$fstabPath" --target-prefix "$mnt" -o X-mount.mkdir # (but »--target-prefix« does not apply to bind/overlay sources) while read -u3 source target type options numbers ; do if [[ ! $target || $target == none ]] ; then continue ; fi options=,$options, ; options=${options//,ro,/,} diff --git a/modules/filesystems/format-args.nix.md b/modules/filesystems/format-args.nix.md index 44c6fbf..b41f6b7 100644 --- a/modules/filesystems/format-args.nix.md +++ b/modules/filesystems/format-args.nix.md @@ -12,7 +12,7 @@ in { options = { fileSystems = lib.mkOption { type = lib.types.attrsOf (lib.types.submodule [ ({ config, ...}@_: { options = { - formatArgs = lib.mkOption { description = "Arguments passed to mkfs for this filesystem during OS installation."; type = lib.types.listOf lib.types.str; default = if (lib.isString config.formatOptions or null) then lib.splitString config.formatOptions else [ ]; }; + formatArgs = lib.mkOption { description = "Arguments passed to mkfs for this filesystem during OS installation."; type = lib.types.listOf lib.types.str; default = if (lib.isString config.formatOptions or null) && config.formatOptions != "" then lib.splitString " " config.formatOptions else [ ]; }; }; }) ]); }; }; diff --git a/patches/default.nix b/patches/default.nix index 5eb6c89..277021b 100644 --- a/patches/default.nix +++ b/patches/default.nix @@ -1,8 +1 @@ -# Returns an attrset where the values are the paths to all ».patch« files in this directory, and the names the respective »basename -s .patch«s. -dirname: inputs: let - getNamedPatchFiles = dir: builtins.removeAttrs (builtins.listToAttrs (map (name: let - match = builtins.match ''^(.*)[.]patch$'' name; - in if (match != null) then { - name = builtins.head match; value = builtins.path { path = "${dir}/${name}"; inherit name; }; # »builtins.path« puts the file in a separate, content-addressed store path, ensuring it's path only changes when the content changes, thus avoiding unnecessary rebuilds. - } else { name = ""; value = null; }) (builtins.attrNames (builtins.readDir dir)))) [ "" ]; -in (getNamedPatchFiles dirname) +dirname: inputs@{ self, nixpkgs, ...}: self.lib.__internal__.fun.importPatches inputs dirname { }