mirror of
https://github.com/nix-community/home-manager
synced 2024-11-26 21:19:45 +01:00
types: improve dagOf and listOrDagOf
In particular, improve the behavior of these types if the element type is a submodule.
This commit is contained in:
parent
9f223e98b7
commit
8ad4bd6c1b
3 changed files with 67 additions and 18 deletions
|
@ -7,16 +7,25 @@ let
|
|||
isDagEntry = e: isAttrs e && (e ? data) && (e ? after) && (e ? before);
|
||||
|
||||
dagContentType = elemType:
|
||||
types.submodule {
|
||||
types.submodule ({ name, ... }: {
|
||||
options = {
|
||||
data = mkOption { type = elemType; };
|
||||
after = mkOption { type = with types; uniq (listOf str); };
|
||||
before = mkOption { type = with types; uniq (listOf str); };
|
||||
};
|
||||
};
|
||||
config = mkIf (elemType.name == "submodule") {
|
||||
data._module.args.dagName = name;
|
||||
};
|
||||
});
|
||||
|
||||
in {
|
||||
in rec {
|
||||
# A directed acyclic graph of some inner type.
|
||||
#
|
||||
# Note, if the element type is a submodule then the `name` argument
|
||||
# will always be set to the string "data" since it picks up the
|
||||
# internal structure of the DAG values. To give access to the
|
||||
# "actual" attribute name a new submodule argument is provided with
|
||||
# the name `dagName`.
|
||||
dagOf = elemType:
|
||||
let
|
||||
convertAllToDags = let
|
||||
|
@ -51,34 +60,30 @@ in {
|
|||
let padWidth = stringLength (toString (length list));
|
||||
in fixedWidthNumber padWidth i;
|
||||
|
||||
convertAllToDags = defs:
|
||||
convertAll = defs:
|
||||
let
|
||||
convertAttrValue = n: v:
|
||||
if isDagEntry v then v else dag.entryAnywhere v;
|
||||
|
||||
convertListValue = namePrefix: vs:
|
||||
let
|
||||
pad = paddedIndexStr vs;
|
||||
makeEntry = i: v:
|
||||
nameValuePair "${namePrefix}.${pad i}" (dag.entryAnywhere v);
|
||||
makeEntry = i: v: nameValuePair "${namePrefix}.${pad i}" v;
|
||||
in listToAttrs (imap1 makeEntry vs);
|
||||
|
||||
convertValue = i: value:
|
||||
if isList value then
|
||||
convertListValue "unnamed-${paddedIndexStr defs i}" value
|
||||
else
|
||||
mapAttrs convertAttrValue value;
|
||||
value;
|
||||
in imap1 (i: def: def // { value = convertValue i def.value; }) defs;
|
||||
|
||||
attrEquivalent = types.attrsOf (dagContentType elemType);
|
||||
dagType = dagOf elemType;
|
||||
in mkOptionType rec {
|
||||
name = "dagOf";
|
||||
description = "DAG of ${elemType.description}s";
|
||||
check = x: isAttrs x || isList x;
|
||||
merge = loc: defs: attrEquivalent.merge loc (convertAllToDags defs);
|
||||
getSubOptions = prefix: elemType.getSubOptions (prefix ++ [ "<name>" ]);
|
||||
getSubModules = elemType.getSubModules;
|
||||
substSubModules = m: dagOf (elemType.substSubModules m);
|
||||
name = "listOrDagOf";
|
||||
description = "list or DAG of ${elemType.description}s";
|
||||
check = x: isList x || dagType.check x;
|
||||
merge = loc: defs: dagType.merge loc (convertAll defs);
|
||||
getSubOptions = dagType.getSubOptions;
|
||||
getSubModules = dagType.getSubModules;
|
||||
substSubModules = m: listOrDagOf (elemType.substSubModules m);
|
||||
functor = (defaultFunctor name) // { wrapped = elemType; };
|
||||
};
|
||||
}
|
||||
|
|
43
tests/lib/types/dag-submodule.nix
Normal file
43
tests/lib/types/dag-submodule.nix
Normal file
|
@ -0,0 +1,43 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
|
||||
dag = config.lib.dag;
|
||||
|
||||
result = let
|
||||
sorted = dag.topoSort config.tested.dag;
|
||||
data = map (e: "${e.name}:${e.data.name}") sorted.result;
|
||||
in concatStringsSep "\n" data + "\n";
|
||||
|
||||
in {
|
||||
options.tested.dag = mkOption {
|
||||
type = hm.types.dagOf (types.submodule ({ dagName, ... }: {
|
||||
options.name = mkOption { type = types.str; };
|
||||
config.name = "dn-${dagName}";
|
||||
}));
|
||||
};
|
||||
|
||||
config = {
|
||||
tested.dag = {
|
||||
after = { };
|
||||
before = dag.entryBefore [ "after" ] { };
|
||||
between = dag.entryBetween [ "after" ] [ "before" ] { };
|
||||
};
|
||||
|
||||
home.file."result.txt".text = result;
|
||||
|
||||
nmt.script = ''
|
||||
assertFileContent \
|
||||
home-files/result.txt \
|
||||
${
|
||||
pkgs.writeText "result.txt" ''
|
||||
before:dn-before
|
||||
between:dn-between
|
||||
after:dn-after
|
||||
''
|
||||
}
|
||||
'';
|
||||
};
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
lib-types-dag-submodule = ./dag-submodule.nix;
|
||||
lib-types-dag-merge = ./dag-merge.nix;
|
||||
lib-types-list-or-dag-merge = ./list-or-dag-merge.nix;
|
||||
|
||||
|
|
Loading…
Reference in a new issue