about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/doc/manual/release-notes/rl-2405.section.md5
-rw-r--r--nixos/lib/systemd-unit-options.nix10
-rw-r--r--pkgs/test/default.nix2
-rw-r--r--pkgs/test/systemd/default.nix5
-rw-r--r--pkgs/test/systemd/nixos/default.nix37
5 files changed, 51 insertions, 8 deletions
diff --git a/nixos/doc/manual/release-notes/rl-2405.section.md b/nixos/doc/manual/release-notes/rl-2405.section.md
index e0162372d2153..204d08751b87a 100644
--- a/nixos/doc/manual/release-notes/rl-2405.section.md
+++ b/nixos/doc/manual/release-notes/rl-2405.section.md
@@ -388,6 +388,11 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
 
 - The `mpich` package expression now requires `withPm` to be a list, e.g. `"hydra:gforker"` becomes `[ "hydra" "gforker" ]`.
 
+- When merging systemd unit options (of type `unitOption`),
+  if at least one definition is a list, all those which aren't are now lifted into a list,
+  making it possible to accumulate definitions without resorting to `mkForce`,
+  hence to retain the definitions not anticipating that need.
+
 - YouTrack is bumped to 2023.3. The update is not performed automatically, it requires manual interaction. See the YouTrack section in the manual for details.
 
 - QtMultimedia has changed its default backend to `QT_MEDIA_BACKEND=ffmpeg` (previously `gstreamer` on Linux or `darwin` on MacOS).
diff --git a/nixos/lib/systemd-unit-options.nix b/nixos/lib/systemd-unit-options.nix
index bc7880da9fe0e..e4953ba72dd92 100644
--- a/nixos/lib/systemd-unit-options.nix
+++ b/nixos/lib/systemd-unit-options.nix
@@ -21,14 +21,8 @@ in rec {
       let
         defs' = filterOverrides defs;
       in
-        if isList (head defs').value
-        then concatMap (def:
-          if builtins.typeOf def.value == "list"
-          then def.value
-          else
-            throw "The definitions for systemd unit options should be either all lists, representing repeatable options, or all non-lists, but for the option ${showOption loc}, the definitions are a mix of list and non-list ${lib.options.showDefs defs'}"
-        ) defs'
-
+        if any (def: isList def.value) defs'
+        then concatMap (def: toList def.value) defs'
         else mergeEqualOption loc defs';
   };
 
diff --git a/pkgs/test/default.nix b/pkgs/test/default.nix
index 5382cae6159f4..f66b05b9f6f1b 100644
--- a/pkgs/test/default.nix
+++ b/pkgs/test/default.nix
@@ -175,4 +175,6 @@ with pkgs;
   nixpkgs-check-by-name = callPackage ./nixpkgs-check-by-name { };
 
   auto-patchelf-hook = callPackage ./auto-patchelf-hook { };
+
+  systemd = callPackage ./systemd { };
 }
diff --git a/pkgs/test/systemd/default.nix b/pkgs/test/systemd/default.nix
new file mode 100644
index 0000000000000..2208bf794481f
--- /dev/null
+++ b/pkgs/test/systemd/default.nix
@@ -0,0 +1,5 @@
+{ lib, callPackage }:
+
+lib.recurseIntoAttrs {
+  nixos = callPackage ./nixos { };
+}
diff --git a/pkgs/test/systemd/nixos/default.nix b/pkgs/test/systemd/nixos/default.nix
new file mode 100644
index 0000000000000..e45399b635167
--- /dev/null
+++ b/pkgs/test/systemd/nixos/default.nix
@@ -0,0 +1,37 @@
+{ pkgs, lib, stdenv, ... }:
+
+lib.runTests {
+  # Merging two non-list definitions must still result in an error
+  # about a conflicting definition.
+  test-unitOption-merging-non-lists-conflict =
+    let nixos = pkgs.nixos {
+        system.stateVersion = lib.trivial.release;
+        systemd.services.systemd-test-nixos = {
+          serviceConfig = lib.mkMerge [
+            { StateDirectory = "foo"; }
+            { StateDirectory = "bar"; }
+          ];
+        };
+      };
+    in {
+    expr = (builtins.tryEval (nixos.config.systemd.services.systemd-test-nixos.serviceConfig.StateDirectory)).success;
+    expected = false;
+  };
+
+  # Merging must lift non-list definitions to a list
+  # if at least one of them is a list.
+  test-unitOption-merging-list-non-list-append =
+    let nixos = pkgs.nixos {
+        system.stateVersion = lib.trivial.release;
+        systemd.services.systemd-test-nixos = {
+          serviceConfig = lib.mkMerge [
+            { StateDirectory = "foo"; }
+            { StateDirectory = ["bar"]; }
+          ];
+        };
+      };
+    in {
+    expr = nixos.config.systemd.services.systemd-test-nixos.serviceConfig.StateDirectory;
+    expected = [ "foo" "bar" ];
+  };
+}