mirror of
https://github.com/nix-community/home-manager
synced 2024-11-27 05:29:46 +01:00
types: fix dagOf
behaviour with mkIf
This makes definitions like
home.activation.foo = mkIf false "bar"
work, where previously they would complain about
`home.activation.foobar.data` being used but not defined.
The crucial part is that we don't call `convertAllToDags` in
`dagOf.merge`, because we need to process `mkIf`/`mkMerge` properties
first. So we let `attrEquivalent.merge` do its job normally, but give
it a type `dagEntryOf` that does the conversion.
Ideally this shouldn't require so much boilerplate; I'd like to
implement something like
types.changeInto dagContentType elemType dagEntryAnywhere
in Nixpkgs.
(cherry picked from commit 8db712a6a2
)
This commit is contained in:
parent
236c6ec214
commit
834d863dd2
2 changed files with 33 additions and 24 deletions
|
@ -8,8 +8,9 @@ let
|
|||
|
||||
isDagEntry = e: isAttrs e && (e ? data) && (e ? after) && (e ? before);
|
||||
|
||||
dagContentType = elemType:
|
||||
types.submodule ({ name, ... }: {
|
||||
dagEntryOf = elemType:
|
||||
let
|
||||
submoduleType = types.submodule ({ name, ... }: {
|
||||
options = {
|
||||
data = mkOption { type = elemType; };
|
||||
after = mkOption { type = with types; uniq (listOf str); };
|
||||
|
@ -19,6 +20,15 @@ let
|
|||
data._module.args.dagName = name;
|
||||
};
|
||||
});
|
||||
maybeConvert = v: if isDagEntry v then v else dag.entryAnywhere v;
|
||||
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);
|
||||
};
|
||||
|
||||
in rec {
|
||||
# A directed acyclic graph of some inner type.
|
||||
|
@ -29,21 +39,16 @@ in rec {
|
|||
# "actual" attribute name a new submodule argument is provided with
|
||||
# the name `dagName`.
|
||||
dagOf = elemType:
|
||||
let
|
||||
convertAllToDags = let
|
||||
maybeConvert = n: v: if isDagEntry v then v else dag.entryAnywhere v;
|
||||
in map (def: def // { value = mapAttrs maybeConvert def.value; });
|
||||
|
||||
attrEquivalent = types.attrsOf (dagContentType elemType);
|
||||
let attrEquivalent = types.attrsOf (dagEntryOf elemType);
|
||||
in mkOptionType rec {
|
||||
name = "dagOf";
|
||||
description = "DAG of ${elemType.description}s";
|
||||
check = isAttrs;
|
||||
merge = loc: defs: attrEquivalent.merge loc (convertAllToDags defs);
|
||||
inherit (attrEquivalent) check merge emptyValue;
|
||||
getSubOptions = prefix: elemType.getSubOptions (prefix ++ [ "<name>" ]);
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: dagOf (elemType.substSubModules m);
|
||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
||||
nestedTypes.elemType = elemType;
|
||||
};
|
||||
|
||||
# A directed acyclic graph of some inner type OR a list of that
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
inherit (lib) concatStringsSep hm mkMerge mkOption types;
|
||||
inherit (lib) concatStringsSep hm mkIf mkMerge mkOption types;
|
||||
|
||||
dag = lib.hm.dag;
|
||||
|
||||
|
@ -14,10 +14,14 @@ in {
|
|||
options.tested.dag = mkOption { type = hm.types.dagOf types.str; };
|
||||
|
||||
config = {
|
||||
tested = mkMerge [
|
||||
{ dag.after = "after"; }
|
||||
{ dag.before = dag.entryBefore [ "after" ] "before"; }
|
||||
{ dag.between = dag.entryBetween [ "after" ] [ "before" ] "between"; }
|
||||
tested.dag = mkMerge [
|
||||
{ never = mkIf false "never"; }
|
||||
{ after = mkMerge [ "after" (mkIf false "neither") ]; }
|
||||
{ before = dag.entryBefore [ "after" ] (mkIf true "before"); }
|
||||
{
|
||||
between =
|
||||
mkIf true (dag.entryBetween [ "after" ] [ "before" ] "between");
|
||||
}
|
||||
];
|
||||
|
||||
home.file."result.txt".text = result;
|
||||
|
|
Loading…
Reference in a new issue