From bb16a7f08d7798e7ca49900f2af32ae229835f02 Mon Sep 17 00:00:00 2001 From: Nicolas Pierron Date: Fri, 9 Oct 2009 18:11:30 +0000 Subject: [PATCH] Replace a counter intuitive behaviour of module evaluations. - types.nix: Introduce a new flag named "delayProperties" which define either that properties should be evaluated (when false) or that they should be delaied through the type structure. - properties.nix: Generalized the delayProperties function to make it work with the iter functions of option types. - modules.nix: Replace evalProperties by a condition based on the value of the "delayProperties" flag of the option type. If the flag does not exists or if it is false, then the system behaves as always. Otherwise it delays the properties from the current value to each values contained inside it. svn path=/nixpkgs/trunk/; revision=17736 --- pkgs/lib/modules.nix | 10 +++++++++- pkgs/lib/properties.nix | 9 ++++++--- pkgs/lib/types.nix | 14 +++++++++++--- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/pkgs/lib/modules.nix b/pkgs/lib/modules.nix index aeabf640cc2e..6f894cb98028 100644 --- a/pkgs/lib/modules.nix +++ b/pkgs/lib/modules.nix @@ -113,9 +113,17 @@ rec { value ) module; + delayModule = module: moduleApply { config = delayProperties; } module; + evalDefinitions = opt: values: + if opt ? type && opt.type.delayProperties then + map (delayPropertiesTemplate opt.type.iter opt.name) values + else + evalProperties values; + + selectModule = name: m: { inherit (m) key; } // ( @@ -243,7 +251,7 @@ rec { opt.extraConfigs; in if hasOpt && isOption opt then - let defs = evalProperties values; in + let defs = evalDefinitions opt values; in lib.addErrorContext "${eol }while evaluating the option '${addName name}'.${eol }${errorSource (modulesOf name)}${eol diff --git a/pkgs/lib/properties.nix b/pkgs/lib/properties.nix index f523e6067b72..5254292655ed 100644 --- a/pkgs/lib/properties.nix +++ b/pkgs/lib/properties.nix @@ -69,18 +69,21 @@ rec { # Move properties from the current attribute set to the attribute # contained in this attribute set. This trigger property handlers called # `onDelay' and `onGlobalDelay'. - delayProperties = attrs: + delayPropertiesWithIter = iter: path: attrs: let cleanAttrs = rmProperties attrs; in if isProperty attrs then - lib.mapAttrs (a: v: + iter (a: v: lib.addErrorContext "while moving properties on the attribute `${a}'." ( triggerPropertiesGlobalDelay a ( triggerPropertiesDelay a ( copyProperties attrs v - )))) cleanAttrs + )))) path cleanAttrs else attrs; + delayProperties = # implicit attrs argument. + delayPropertiesWithIter (f: p: v: lib.mapAttrs f v) ""; + # Call onDelay functions. triggerPropertiesDelay = name: attrs: let diff --git a/pkgs/lib/types.nix b/pkgs/lib/types.nix index 5e0393e9604b..723dd22e2f05 100644 --- a/pkgs/lib/types.nix +++ b/pkgs/lib/types.nix @@ -19,7 +19,8 @@ rec { # iter (iterate on all elements contained in this type) # fold (fold all elements contained in this type) # hasOptions (boolean: whatever this option contains an option set) - # path (path contatenated to the option name contained contained in the option set) + # delayProperties (boolean: should properties go through the evaluation of this option) + # docPath (path concatenated to the option name contained in the option set) isOptionType = attrs: typeOf attrs == "option-type"; mkOptionType = { name @@ -31,10 +32,11 @@ rec { , docPath ? lib.id # If the type can contains option sets. , hasOptions ? false + , delayProperties ? false }: { _type = "option-type"; - inherit name check merge iter fold docPath hasOptions; + inherit name check merge iter fold docPath hasOptions delayProperties; }; @@ -73,6 +75,7 @@ rec { check = lib.traceValIfNot isDerivation; }; + listOf = types.list; list = elemType: mkOptionType { name = "list of ${elemType.name}s"; check = value: lib.traceValIfNot isList value && all elemType.check value; @@ -81,6 +84,10 @@ rec { fold = op: nul: list: lib.fold (e: l: elemType.fold op l e) nul list; docPath = path: elemType.docPath (path + ".*"); inherit (elemType) hasOptions; + + # You cannot define multiple configurations of one entity, therefore + # no reason justify to delay properties inside list elements. + delayProperties = false; }; attrsOf = elemType: mkOptionType { @@ -91,7 +98,7 @@ rec { iter = f: path: set: lib.mapAttrs (name: elemType.iter f (path + "." + name)) set; fold = op: nul: set: fold (e: l: elemType.fold op l e) nul (lib.attrValues set); docPath = path: elemType.docPath (path + "."); - inherit (elemType) hasOptions; + inherit (elemType) hasOptions delayProperties; }; uniq = elemType: mkOptionType { @@ -118,6 +125,7 @@ rec { merge = lib.id; check = x: lib.traceValIfNot builtins.isAttrs x; hasOptions = true; + delayProperties = true; }; };