Unverified Commit 80f60ad1 authored by nikstur's avatar nikstur Committed by GitHub
Browse files

Merge pull request #297224 from WilliButz/repart-image/mkDerivation

nixos/repart-image: refactor to use mkDerivation instead of runCommand
parents 0a01fb5e d9264d05
Loading
Loading
Loading
Loading
+59 −26
Original line number Diff line number Diff line
@@ -2,8 +2,8 @@
# NixOS module that can be imported.

{ lib
, stdenvNoCC
, runCommand
, runCommandLocal
, python3
, black
, ruff
@@ -26,15 +26,18 @@
, xz

  # arguments
, name
, version
, imageFileBasename
, compression
, fileSystems
, partitions
, partitionsJSON
, split
, seed
, definitionsDirectory
, sectorSize
, mkfsEnv ? {}
, createEmpty ? true
}:

let
@@ -52,11 +55,6 @@ let
    mypy --strict $out
  '';

  amendedRepartDefinitions = runCommandLocal "amended-repart.d" {} ''
    definitions=$(${amendRepartDefinitions} ${partitions} ${definitionsDirectory})
    cp -r $definitions $out
  '';

  fileSystemToolMapping = {
    "vfat" = [ dosfstools mtools ];
    "ext4" = [ e2fsprogs.bin ];
@@ -78,38 +76,56 @@ let
    "xz" = "xz --keep --verbose --threads=0 -${toString compression.level}";
  }."${compression.algorithm}";
in

runCommand imageFileBasename
{
  stdenvNoCC.mkDerivation (finalAttrs:
  (if (version != null)
  then { pname = name; inherit version; }
  else { inherit name;  }
  ) // {
  __structuredAttrs = true;

  nativeBuildInputs = [
    systemd
    fakeroot
    util-linux
  ] ++ lib.optionals (compression.enable) [
    compressionPkg
  ] ++ fileSystemTools;

  env = mkfsEnv;

  inherit partitionsJSON definitionsDirectory;

  # relative path to the repart definitions that are read by systemd-repart
  finalRepartDefinitions = "repart.d";

  systemdRepartFlags = [
    "--dry-run=no"
    "--empty=create"
    "--size=auto"
    "--seed=${seed}"
    "--definitions=${amendedRepartDefinitions}"
    "--definitions=${finalAttrs.finalRepartDefinitions}"
    "--split=${lib.boolToString split}"
    "--json=pretty"
  ] ++ lib.optionals createEmpty [
    "--empty=create"
  ] ++ lib.optionals (sectorSize != null) [
    "--sector-size=${toString sectorSize}"
  ];

  passthru = {
    inherit amendRepartDefinitions amendedRepartDefinitions;
  };
} ''
  mkdir -p $out
  cd $out
  dontUnpack = true;
  dontConfigure = true;
  doCheck = false;

  patchPhase = ''
    runHook prePatch

    amendedRepartDefinitionsDir=$(${amendRepartDefinitions} $partitionsJSON $definitionsDirectory)
    ln -vs $amendedRepartDefinitionsDir $finalRepartDefinitions

    runHook postPatch
  '';

  buildPhase = ''
    runHook preBuild

    echo "Building image with systemd-repart..."
    unshare --map-root-user fakeroot systemd-repart \
@@ -117,14 +133,31 @@ runCommand imageFileBasename
      ${imageFileBasename}.raw \
      | tee repart-output.json

    runHook postBuild
  '';

  installPhase = ''
    runHook preInstall

    mkdir -p $out
  ''
  # Compression is implemented in the same derivation as opposed to in a
  # separate derivation to allow users to save disk space. Disk images are
  # already very space intensive so we want to allow users to mitigate this.
  if ${lib.boolToString compression.enable}; then
  + lib.optionalString compression.enable
  ''
    for f in ${imageFileBasename}*; do
      echo "Compressing $f with ${compression.algorithm}..."
      # Keep the original file when compressing and only delete it afterwards
      ${compressionCommand} $f && rm $f
    done
  fi
''
  '' + ''
    mv -v repart-output.json ${imageFileBasename}* $out

    runHook postInstall
  '';

  passthru = {
    inherit amendRepartDefinitions;
  };
})
+26 −16
Original line number Diff line number Diff line
@@ -211,6 +211,15 @@ in
      '';
    };

    finalPartitions = lib.mkOption {
      type = lib.types.attrs;
      internal = true;
      readOnly = true;
      description = lib.mdDoc ''
        Convenience option to access partitions with added closures.
      '';
    };

  };

  config = {
@@ -224,6 +233,16 @@ in
            "zstd" = ".zst";
            "xz" = ".xz";
          }."${cfg.compression.algorithm}";

        makeClosure = paths: pkgs.closureInfo { rootPaths = paths; };

        # Add the closure of the provided Nix store paths to cfg.partitions so
        # that amend-repart-definitions.py can read it.
        addClosure = _name: partitionConfig: partitionConfig // (
          lib.optionalAttrs
            (partitionConfig.storePaths or [ ] != [ ])
            { closure = "${makeClosure partitionConfig.storePaths}/store-paths"; }
        );
      in
      {
        name = lib.mkIf (config.system.image.id != null) (lib.mkOptionDefault config.system.image.id);
@@ -239,6 +258,8 @@ in
            "xz" = 3;
          }."${cfg.compression.algorithm}";
        };

        finalPartitions = lib.mapAttrs addClosure cfg.partitions;
      };

    system.build.image =
@@ -247,36 +268,25 @@ in
          (f: f != null)
          (lib.mapAttrsToList (_n: v: v.repartConfig.Format or null) cfg.partitions);

        makeClosure = paths: pkgs.closureInfo { rootPaths = paths; };

        # Add the closure of the provided Nix store paths to cfg.partitions so
        # that amend-repart-definitions.py can read it.
        addClosure = _name: partitionConfig: partitionConfig // (
          lib.optionalAttrs
            (partitionConfig.storePaths or [ ] != [ ])
            { closure = "${makeClosure partitionConfig.storePaths}/store-paths"; }
        );

        finalPartitions = lib.mapAttrs addClosure cfg.partitions;

        format = pkgs.formats.ini { };

        definitionsDirectory = utils.systemdUtils.lib.definitions
          "repart.d"
          format
          (lib.mapAttrs (_n: v: { Partition = v.repartConfig; }) finalPartitions);
          (lib.mapAttrs (_n: v: { Partition = v.repartConfig; }) cfg.finalPartitions);

        partitions = pkgs.writeText "partitions.json" (builtins.toJSON finalPartitions);
        partitionsJSON = pkgs.writeText "partitions.json" (builtins.toJSON cfg.finalPartitions);

        mkfsEnv = mkfsOptionsToEnv cfg.mkfsOptions;
      in
      pkgs.callPackage ./repart-image.nix {
        systemd = cfg.package;
        inherit (cfg) imageFileBasename compression split seed sectorSize;
        inherit fileSystems definitionsDirectory partitions mkfsEnv;
        inherit (cfg) name version imageFileBasename compression split seed sectorSize;
        inherit fileSystems definitionsDirectory partitionsJSON mkfsEnv;
      };

    meta.maintainers = with lib.maintainers; [ nikstur ];
    meta.maintainers = with lib.maintainers; [ nikstur willibutz ];

  };
}