From 6311f4adc39fc8ce77f7b80212024fe4286280d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Na=C3=AFm=20Favier?= Date: Mon, 9 May 2022 19:50:15 +0200 Subject: [PATCH] lib/types: make DAG entries mergeable Removes the `uniq` constraint on `after` and `before` so that we can merge multiple definitions for the same DAG entry: { dag = mkMerge [ { foo = lib.hm.dag.entryBefore [ "bar" ] { # definition 1 }; } { foo = lib.hm.dag.entryBefore [ "qux" ] { # definition 2 }; } { foo = { # definition 3 }; } ]; } In this example `foo` will come before `bar` and `qux`. --- modules/lib/types-dag.nix | 25 +++++++++++++++++-------- tests/lib/types/dag-merge-result.txt | 1 + tests/lib/types/dag-merge.nix | 12 +++++++++--- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/modules/lib/types-dag.nix b/modules/lib/types-dag.nix index 366cc2bee..e793940e3 100644 --- a/modules/lib/types-dag.nix +++ b/modules/lib/types-dag.nix @@ -3,8 +3,8 @@ let inherit (lib) concatStringsSep defaultFunctor fixedWidthNumber imap1 isAttrs isList length - listToAttrs mapAttrs mkIf mkOption mkOptionType nameValuePair stringLength - types warn; + listToAttrs mapAttrs mkIf mkOrder mkOption mkOptionType nameValuePair + stringLength types warn; isDagEntry = e: isAttrs e && (e ? data) && (e ? after) && (e ? before); @@ -13,21 +13,30 @@ let submoduleType = types.submodule ({ name, ... }: { options = { data = mkOption { type = elemType; }; - after = mkOption { type = with types; uniq (listOf str); }; - before = mkOption { type = with types; uniq (listOf str); }; + after = mkOption { type = with types; listOf str; }; + before = mkOption { type = with types; listOf str; }; }; config = mkIf (elemType.name == "submodule") { data._module.args.dagName = name; }; }); - maybeConvert = v: if isDagEntry v then v else dag.entryAnywhere v; + maybeConvert = def: + if isDagEntry def.value then + def.value + else + dag.entryAnywhere (if def ? priority then + mkOrder def.priority def.value + else + def.value); in mkOptionType { name = "dagEntryOf"; description = "DAG entry of ${elemType.description}"; # leave the checking to the submodule type merge = loc: defs: - submoduleType.merge loc - (map (def: def // { value = maybeConvert def.value; }) defs); + submoduleType.merge loc (map (def: { + inherit (def) file; + value = maybeConvert def; + }) defs); }; in rec { @@ -42,7 +51,7 @@ in rec { let attrEquivalent = types.attrsOf (dagEntryOf elemType); in mkOptionType rec { name = "dagOf"; - description = "DAG of ${elemType.description}s"; + description = "DAG of ${elemType.description}"; inherit (attrEquivalent) check merge emptyValue; getSubOptions = prefix: elemType.getSubOptions (prefix ++ [ "" ]); getSubModules = elemType.getSubModules; diff --git a/tests/lib/types/dag-merge-result.txt b/tests/lib/types/dag-merge-result.txt index 9779ef13c..0330161e6 100644 --- a/tests/lib/types/dag-merge-result.txt +++ b/tests/lib/types/dag-merge-result.txt @@ -1,3 +1,4 @@ before:before +merged:left,middle,middle,right between:between after:after diff --git a/tests/lib/types/dag-merge.nix b/tests/lib/types/dag-merge.nix index 0b41ec8a0..5d502924a 100644 --- a/tests/lib/types/dag-merge.nix +++ b/tests/lib/types/dag-merge.nix @@ -1,7 +1,8 @@ { config, lib, pkgs, ... }: let - inherit (lib) concatStringsSep hm mkIf mkMerge mkOption types; + inherit (lib) + concatStringsSep hm mkIf mkMerge mkBefore mkAfter mkOption types; dag = lib.hm.dag; @@ -11,17 +12,22 @@ let in concatStringsSep "\n" data + "\n"; in { - options.tested.dag = mkOption { type = hm.types.dagOf types.str; }; + options.tested.dag = mkOption { type = hm.types.dagOf types.commas; }; config = { tested.dag = mkMerge [ - { never = mkIf false "never"; } + (mkIf false { never = "never"; }) + { never2 = mkIf false "never2"; } { after = mkMerge [ "after" (mkIf false "neither") ]; } { before = dag.entryBefore [ "after" ] (mkIf true "before"); } { between = mkIf true (dag.entryBetween [ "after" ] [ "before" ] "between"); } + { merged = dag.entryBefore [ "between" ] "middle"; } + { merged = mkBefore "left"; } + { merged = dag.entryBetween [ "after" ] [ "before" ] (mkAfter "right"); } + { merged = dag.entryBefore [ "between" ] "middle"; } ]; home.file."result.txt".text = result;