diff --git a/nixos/doc/manual/release-notes/rl-2405.section.md b/nixos/doc/manual/release-notes/rl-2405.section.md index e0162372d215..204d08751b87 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 bc7880da9fe0..e4953ba72dd9 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 5382cae6159f..f66b05b9f6f1 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 000000000000..2208bf794481 --- /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 000000000000..e45399b63516 --- /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" ]; + }; +}