| 
									
										
										
										
											2013-10-30 19:12:25 +01:00
										 |  |  |  | with import ./lists.nix; | 
					
						
							|  |  |  |  | with import ./trivial.nix; | 
					
						
							|  |  |  |  | with import ./attrsets.nix; | 
					
						
							|  |  |  |  | with import ./options.nix; | 
					
						
							|  |  |  |  | with import ./debug.nix; | 
					
						
							|  |  |  |  | with import ./types.nix; | 
					
						
							| 
									
										
										
										
											2009-07-13 16:18:52 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | rec { | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |   /* Evaluate a set of modules.  The result is a set of two
 | 
					
						
							|  |  |  |  |      attributes: ‘options’: the nested set of all option declarations, | 
					
						
							| 
									
										
										
										
											2014-05-05 16:30:51 -04:00
										 |  |  |  |      and ‘config’: the nested set of all option values. | 
					
						
							|  |  |  |  |      !!! Please think twice before adding to this argument list! The more | 
					
						
							|  |  |  |  |      that is specified here instead of in the modules themselves the harder | 
					
						
							|  |  |  |  |      it is to transparently move a set of modules to be a submodule of another | 
					
						
							|  |  |  |  |      config (as the proper arguments need to be replicated at each call to | 
					
						
							|  |  |  |  |      evalModules) and the less declarative the module set is. */ | 
					
						
							|  |  |  |  |   evalModules = { modules | 
					
						
							|  |  |  |  |                 , prefix ? [] | 
					
						
							| 
									
										
										
										
											2015-06-06 22:38:08 +00:00
										 |  |  |  |                 , # This should only be used for special arguments that need to be evaluated | 
					
						
							|  |  |  |  |                   # when resolving module structure (like in imports). For everything else, | 
					
						
							|  |  |  |  |                   # there's _module.args. | 
					
						
							|  |  |  |  |                   specialArgs ? {} | 
					
						
							| 
									
										
										
										
											2015-03-12 23:19:23 +01:00
										 |  |  |  |                 , # This would be remove in the future, Prefer _module.args option instead. | 
					
						
							| 
									
										
										
										
											2014-05-05 16:30:51 -04:00
										 |  |  |  |                   args ? {} | 
					
						
							| 
									
										
										
										
											2015-03-12 23:19:23 +01:00
										 |  |  |  |                 , # This would be remove in the future, Prefer _module.check option instead. | 
					
						
							| 
									
										
										
										
											2014-05-05 16:30:51 -04:00
										 |  |  |  |                   check ? true | 
					
						
							|  |  |  |  |                 }: | 
					
						
							| 
									
										
										
										
											2009-07-13 16:18:52 +00:00
										 |  |  |  |     let | 
					
						
							| 
									
										
										
										
											2015-03-12 23:19:23 +01:00
										 |  |  |  |       # This internal module declare internal options under the `_module' | 
					
						
							|  |  |  |  |       # attribute.  These options are fragile, as they are used by the | 
					
						
							|  |  |  |  |       # module system to change the interpretation of modules. | 
					
						
							| 
									
										
										
										
											2014-05-05 15:52:33 -04:00
										 |  |  |  |       internalModule = rec { | 
					
						
							| 
									
										
										
										
											2014-05-05 15:18:53 -04:00
										 |  |  |  |         _file = ./modules.nix; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-05 15:52:33 -04:00
										 |  |  |  |         key = _file; | 
					
						
							| 
									
										
										
										
											2014-05-05 15:18:53 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |         options = { | 
					
						
							| 
									
										
										
										
											2015-03-12 23:19:23 +01:00
										 |  |  |  |           _module.args = mkOption { | 
					
						
							| 
									
										
										
										
											2014-05-05 15:18:53 -04:00
										 |  |  |  |             type = types.attrsOf types.unspecified; | 
					
						
							|  |  |  |  |             internal = true; | 
					
						
							| 
									
										
										
										
											2015-03-12 23:19:23 +01:00
										 |  |  |  |             description = "Arguments passed to each module."; | 
					
						
							| 
									
										
										
										
											2014-05-05 15:18:53 -04:00
										 |  |  |  |           }; | 
					
						
							| 
									
										
										
										
											2014-05-05 16:23:57 -04:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-12 23:19:23 +01:00
										 |  |  |  |           _module.check = mkOption { | 
					
						
							| 
									
										
										
										
											2015-06-15 18:10:26 +02:00
										 |  |  |  |             type = types.bool; | 
					
						
							| 
									
										
										
										
											2014-05-05 16:23:57 -04:00
										 |  |  |  |             internal = true; | 
					
						
							|  |  |  |  |             default = check; | 
					
						
							| 
									
										
										
										
											2015-03-12 23:19:23 +01:00
										 |  |  |  |             description = "Whether to check whether all option definitions have matching declarations."; | 
					
						
							| 
									
										
										
										
											2014-05-05 16:23:57 -04:00
										 |  |  |  |           }; | 
					
						
							| 
									
										
										
										
											2014-05-05 15:18:53 -04:00
										 |  |  |  |         }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         config = { | 
					
						
							| 
									
										
										
										
											2015-03-12 23:19:23 +01:00
										 |  |  |  |           _module.args = args; | 
					
						
							| 
									
										
										
										
											2014-05-05 15:18:53 -04:00
										 |  |  |  |         }; | 
					
						
							|  |  |  |  |       }; | 
					
						
							| 
									
										
										
										
											2015-03-12 23:19:23 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-06 22:38:08 +00:00
										 |  |  |  |       closed = closeModules (modules ++ [ internalModule ]) (specialArgs // { inherit config options; lib = import ./.; }); | 
					
						
							| 
									
										
										
										
											2015-03-12 23:19:23 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |       # Note: the list of modules is reversed to maintain backward | 
					
						
							|  |  |  |  |       # compatibility with the old module system.  Not sure if this is | 
					
						
							|  |  |  |  |       # the most sensible policy. | 
					
						
							| 
									
										
										
										
											2013-10-29 16:14:58 +01:00
										 |  |  |  |       options = mergeModules prefix (reverseList closed); | 
					
						
							| 
									
										
										
										
											2015-03-12 23:19:23 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-29 16:14:58 +01:00
										 |  |  |  |       # Traverse options and extract the option values into the final | 
					
						
							|  |  |  |  |       # config set.  At the same time, check whether all option | 
					
						
							|  |  |  |  |       # definitions have matching declarations. | 
					
						
							| 
									
										
										
										
											2015-03-12 23:19:23 +01:00
										 |  |  |  |       # !!! _module.check's value can't depend on any other config values | 
					
						
							| 
									
										
										
										
											2014-05-07 16:43:18 -04:00
										 |  |  |  |       # without an infinite recursion. One way around this is to make the | 
					
						
							|  |  |  |  |       # 'config' passed around to the modules be unconditionally unchecked, | 
					
						
							|  |  |  |  |       # and only do the check in 'result'. | 
					
						
							| 
									
										
										
										
											2013-10-30 14:21:41 +01:00
										 |  |  |  |       config = yieldConfig prefix options; | 
					
						
							| 
									
										
										
										
											2013-10-29 16:14:58 +01:00
										 |  |  |  |       yieldConfig = prefix: set: | 
					
						
							|  |  |  |  |         let res = removeAttrs (mapAttrs (n: v: | 
					
						
							|  |  |  |  |           if isOption v then v.value | 
					
						
							|  |  |  |  |           else yieldConfig (prefix ++ [n]) v) set) ["_definedNames"]; | 
					
						
							|  |  |  |  |         in | 
					
						
							| 
									
										
										
										
											2015-03-12 23:19:23 +01:00
										 |  |  |  |         if options._module.check.value && set ? _definedNames then | 
					
						
							| 
									
										
										
										
											2013-10-29 16:14:58 +01:00
										 |  |  |  |           fold (m: res: | 
					
						
							|  |  |  |  |             fold (name: res: | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |  |               if set ? ${name} then res else throw "The option `${showOption (prefix ++ [name])}' defined in `${m.file}' does not exist.") | 
					
						
							| 
									
										
										
										
											2013-10-29 16:14:58 +01:00
										 |  |  |  |               res m.names) | 
					
						
							|  |  |  |  |             res set._definedNames | 
					
						
							|  |  |  |  |         else | 
					
						
							|  |  |  |  |           res; | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |       result = { inherit options config; }; | 
					
						
							|  |  |  |  |     in result; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Close a set of modules under the ‘imports’ relation. */ | 
					
						
							|  |  |  |  |   closeModules = modules: args: | 
					
						
							| 
									
										
										
										
											2013-06-07 03:42:46 -04:00
										 |  |  |  |     let | 
					
						
							| 
									
										
										
										
											2013-10-28 17:24:14 +01:00
										 |  |  |  |       toClosureList = file: parentKey: imap (n: x: | 
					
						
							| 
									
										
										
										
											2013-11-12 13:48:19 +01:00
										 |  |  |  |         if isAttrs x || isFunction x then | 
					
						
							| 
									
										
										
										
											2015-03-11 23:30:30 +01:00
										 |  |  |  |           unifyModuleSyntax file "${parentKey}:anon-${toString n}" (unpackSubmodule applyIfFunction x args) | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |         else | 
					
						
							| 
									
										
										
										
											2013-10-28 14:25:58 +01:00
										 |  |  |  |           unifyModuleSyntax (toString x) (toString x) (applyIfFunction (import x) args)); | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |     in | 
					
						
							|  |  |  |  |       builtins.genericClosure { | 
					
						
							| 
									
										
										
										
											2013-10-28 17:24:14 +01:00
										 |  |  |  |         startSet = toClosureList unknownModule "" modules; | 
					
						
							|  |  |  |  |         operator = m: toClosureList m.file m.key m.imports; | 
					
						
							| 
									
										
										
										
											2013-06-07 03:42:46 -04:00
										 |  |  |  |       }; | 
					
						
							| 
									
										
										
										
											2009-10-09 18:11:24 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |   /* Massage a module into canonical form, that is, a set consisting
 | 
					
						
							|  |  |  |  |      of ‘options’, ‘config’ and ‘imports’ attributes. */ | 
					
						
							| 
									
										
										
										
											2013-10-28 04:46:36 +01:00
										 |  |  |  |   unifyModuleSyntax = file: key: m: | 
					
						
							| 
									
										
										
										
											2013-10-28 17:40:36 +01:00
										 |  |  |  |     if m ? config || m ? options then | 
					
						
							| 
									
										
										
										
											2013-10-30 14:21:41 +01:00
										 |  |  |  |       let badAttrs = removeAttrs m ["imports" "options" "config" "key" "_file"]; in | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |       if badAttrs != {} then | 
					
						
							| 
									
										
										
										
											2014-11-01 23:29:38 +01:00
										 |  |  |  |         throw "Module `${key}' has an unsupported attribute `${head (attrNames badAttrs)}'. This is caused by assignments to the top-level attributes `config' or `options'." | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |       else | 
					
						
							| 
									
										
										
										
											2013-10-30 14:21:41 +01:00
										 |  |  |  |         { file = m._file or file; | 
					
						
							| 
									
										
										
										
											2013-10-29 14:15:33 +01:00
										 |  |  |  |           key = toString m.key or key; | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |           imports = m.imports or []; | 
					
						
							|  |  |  |  |           options = m.options or {}; | 
					
						
							|  |  |  |  |           config = m.config or {}; | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |     else | 
					
						
							| 
									
										
										
										
											2013-10-30 14:21:41 +01:00
										 |  |  |  |       { file = m._file or file; | 
					
						
							| 
									
										
										
										
											2013-10-29 14:15:33 +01:00
										 |  |  |  |         key = toString m.key or key; | 
					
						
							| 
									
										
										
										
											2013-10-28 17:40:36 +01:00
										 |  |  |  |         imports = m.require or [] ++ m.imports or []; | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |         options = {}; | 
					
						
							| 
									
										
										
										
											2013-10-30 14:21:41 +01:00
										 |  |  |  |         config = removeAttrs m ["key" "_file" "require" "imports"]; | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |       }; | 
					
						
							| 
									
										
										
										
											2009-10-09 18:11:24 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-06 22:38:08 +00:00
										 |  |  |  |   applyIfFunction = f: arg@{ config, options, lib, ... }: if isFunction f then | 
					
						
							| 
									
										
										
										
											2014-05-05 15:18:53 -04:00
										 |  |  |  |     let | 
					
						
							| 
									
										
										
										
											2015-03-11 23:30:30 +01:00
										 |  |  |  |       # Module arguments are resolved in a strict manner when attribute set | 
					
						
							|  |  |  |  |       # deconstruction is used.  As the arguments are now defined with the | 
					
						
							| 
									
										
										
										
											2015-03-12 23:19:23 +01:00
										 |  |  |  |       # config._module.args option, the strictness used on the attribute | 
					
						
							| 
									
										
										
										
											2015-03-11 23:30:30 +01:00
										 |  |  |  |       # set argument would cause an infinite loop, if the result of the | 
					
						
							|  |  |  |  |       # option is given as argument. | 
					
						
							|  |  |  |  |       # | 
					
						
							|  |  |  |  |       # To work-around the strictness issue on the deconstruction of the | 
					
						
							|  |  |  |  |       # attributes set argument, we create a new attribute set which is | 
					
						
							|  |  |  |  |       # constructed to satisfy the expected set of attributes.  Thus calling | 
					
						
							|  |  |  |  |       # a module will resolve strictly the attributes used as argument but | 
					
						
							|  |  |  |  |       # not their values.  The values are forwarding the result of the | 
					
						
							|  |  |  |  |       # evaluation of the option. | 
					
						
							| 
									
										
										
										
											2014-05-05 15:18:53 -04:00
										 |  |  |  |       requiredArgs = builtins.attrNames (builtins.functionArgs f); | 
					
						
							|  |  |  |  |       extraArgs = builtins.listToAttrs (map (name: { | 
					
						
							|  |  |  |  |         inherit name; | 
					
						
							| 
									
										
										
										
											2015-03-12 23:19:23 +01:00
										 |  |  |  |         value = config._module.args.${name}; | 
					
						
							| 
									
										
										
										
											2014-05-05 15:18:53 -04:00
										 |  |  |  |       }) requiredArgs); | 
					
						
							|  |  |  |  |     in f (extraArgs // arg) | 
					
						
							|  |  |  |  |   else | 
					
						
							|  |  |  |  |     f; | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-11 23:30:30 +01:00
										 |  |  |  |   /* We have to pack and unpack submodules. We cannot wrap the expected
 | 
					
						
							|  |  |  |  |      result of the function as we would no longer be able to list the arguments | 
					
						
							|  |  |  |  |      of the submodule. (see applyIfFunction) */ | 
					
						
							|  |  |  |  |   unpackSubmodule = unpack: m: args: | 
					
						
							|  |  |  |  |     if isType "submodule" m then | 
					
						
							|  |  |  |  |       { _file = m.file; } // (unpack m.submodule args) | 
					
						
							|  |  |  |  |     else unpack m args; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   packSubmodule = file: m: | 
					
						
							|  |  |  |  |     { _type = "submodule"; file = file; submodule = m; }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |   /* Merge a list of modules.  This will recurse over the option
 | 
					
						
							|  |  |  |  |      declarations in all modules, combining them into a single set. | 
					
						
							|  |  |  |  |      At the same time, for each option declaration, it will merge the | 
					
						
							|  |  |  |  |      corresponding option definitions in all machines, returning them | 
					
						
							|  |  |  |  |      in the ‘value’ attribute of each option. */ | 
					
						
							| 
									
										
										
										
											2013-10-29 16:14:58 +01:00
										 |  |  |  |   mergeModules = prefix: modules: | 
					
						
							|  |  |  |  |     mergeModules' prefix modules | 
					
						
							| 
									
										
										
										
											2013-10-28 04:46:36 +01:00
										 |  |  |  |       (concatMap (m: map (config: { inherit (m) file; inherit config; }) (pushDownProperties m.config)) modules); | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-29 16:14:58 +01:00
										 |  |  |  |   mergeModules' = prefix: options: configs: | 
					
						
							|  |  |  |  |     listToAttrs (map (name: { | 
					
						
							| 
									
										
										
										
											2013-10-28 04:46:36 +01:00
										 |  |  |  |       # We're descending into attribute ‘name’. | 
					
						
							|  |  |  |  |       inherit name; | 
					
						
							|  |  |  |  |       value = | 
					
						
							|  |  |  |  |         let | 
					
						
							| 
									
										
										
										
											2013-10-28 14:25:58 +01:00
										 |  |  |  |           loc = prefix ++ [name]; | 
					
						
							| 
									
										
										
										
											2013-10-28 04:46:36 +01:00
										 |  |  |  |           # Get all submodules that declare ‘name’. | 
					
						
							|  |  |  |  |           decls = concatLists (map (m: | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |  |             if m.options ? ${name} | 
					
						
							|  |  |  |  |               then [ { inherit (m) file; options = m.options.${name}; } ] | 
					
						
							| 
									
										
										
										
											2013-10-28 07:51:46 +01:00
										 |  |  |  |               else [] | 
					
						
							| 
									
										
										
										
											2013-10-28 04:46:36 +01:00
										 |  |  |  |             ) options); | 
					
						
							|  |  |  |  |           # Get all submodules that define ‘name’. | 
					
						
							|  |  |  |  |           defns = concatLists (map (m: | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |  |             if m.config ? ${name} | 
					
						
							| 
									
										
										
										
											2013-10-28 07:51:46 +01:00
										 |  |  |  |               then map (config: { inherit (m) file; inherit config; }) | 
					
						
							| 
									
										
										
										
											2014-10-05 00:03:52 +02:00
										 |  |  |  |                 (pushDownProperties m.config.${name}) | 
					
						
							| 
									
										
										
										
											2013-10-28 07:51:46 +01:00
										 |  |  |  |               else [] | 
					
						
							| 
									
										
										
										
											2013-10-28 04:46:36 +01:00
										 |  |  |  |             ) configs); | 
					
						
							|  |  |  |  |           nrOptions = count (m: isOption m.options) decls; | 
					
						
							| 
									
										
										
										
											2014-05-01 17:29:30 -04:00
										 |  |  |  |           # Extract the definitions for this loc | 
					
						
							|  |  |  |  |           defns' = map (m: { inherit (m) file; value = m.config.${name}; }) | 
					
						
							|  |  |  |  |             (filter (m: m.config ? ${name}) configs); | 
					
						
							| 
									
										
										
										
											2013-10-28 04:46:36 +01:00
										 |  |  |  |         in | 
					
						
							|  |  |  |  |           if nrOptions == length decls then | 
					
						
							| 
									
										
										
										
											2013-10-28 14:25:58 +01:00
										 |  |  |  |             let opt = fixupOptionType loc (mergeOptionDecls loc decls); | 
					
						
							|  |  |  |  |             in evalOptionValue loc opt defns' | 
					
						
							| 
									
										
										
										
											2013-10-28 04:46:36 +01:00
										 |  |  |  |           else if nrOptions != 0 then | 
					
						
							|  |  |  |  |             let | 
					
						
							|  |  |  |  |               firstOption = findFirst (m: isOption m.options) "" decls; | 
					
						
							|  |  |  |  |               firstNonOption = findFirst (m: !isOption m.options) "" decls; | 
					
						
							|  |  |  |  |             in | 
					
						
							| 
									
										
										
										
											2013-10-28 14:25:58 +01:00
										 |  |  |  |               throw "The option `${showOption loc}' in `${firstOption.file}' is a prefix of options in `${firstNonOption.file}'." | 
					
						
							| 
									
										
										
										
											2013-10-28 04:46:36 +01:00
										 |  |  |  |           else | 
					
						
							| 
									
										
										
										
											2013-10-29 16:14:58 +01:00
										 |  |  |  |             mergeModules' loc decls defns; | 
					
						
							|  |  |  |  |     }) (concatMap (m: attrNames m.options) options)) | 
					
						
							|  |  |  |  |     // { _definedNames = map (m: { inherit (m) file; names = attrNames m.config; }) configs; }; | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Merge multiple option declarations into a single declaration.  In
 | 
					
						
							|  |  |  |  |      general, there should be only one declaration of each option. | 
					
						
							|  |  |  |  |      The exception is the ‘options’ attribute, which specifies | 
					
						
							|  |  |  |  |      sub-options.  These can be specified multiple times to allow one | 
					
						
							|  |  |  |  |      module to add sub-options to an option declared somewhere else | 
					
						
							| 
									
										
										
										
											2014-08-29 14:38:19 +02:00
										 |  |  |  |      (e.g. multiple modules define sub-options for ‘fileSystems’). | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      'loc' is the list of attribute names where the option is located. | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      'opts' is a list of modules.  Each module has an options attribute which | 
					
						
							|  |  |  |  |      correspond to the definition of 'loc' in 'opt.file'. */ | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |   mergeOptionDecls = loc: opts: | 
					
						
							| 
									
										
										
										
											2013-10-28 04:46:36 +01:00
										 |  |  |  |     fold (opt: res: | 
					
						
							|  |  |  |  |       if opt.options ? default && res ? default || | 
					
						
							|  |  |  |  |          opt.options ? example && res ? example || | 
					
						
							|  |  |  |  |          opt.options ? description && res ? description || | 
					
						
							|  |  |  |  |          opt.options ? apply && res ? apply || | 
					
						
							| 
									
										
										
										
											2014-08-29 16:42:44 +02:00
										 |  |  |  |          # Accept to merge options which have identical types. | 
					
						
							|  |  |  |  |          opt.options ? type && res ? type && opt.options.type.name != res.type.name | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |       then | 
					
						
							| 
									
										
										
										
											2013-10-28 19:48:30 +01:00
										 |  |  |  |         throw "The option `${showOption loc}' in `${opt.file}' is already declared in ${showFiles res.declarations}." | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |       else | 
					
						
							| 
									
										
										
										
											2014-08-29 14:38:19 +02:00
										 |  |  |  |         let | 
					
						
							|  |  |  |  |           /* Add the modules of the current option to the list of modules
 | 
					
						
							|  |  |  |  |              already collected.  The options attribute except either a list of | 
					
						
							|  |  |  |  |              submodules or a submodule. For each submodule, we add the file of the | 
					
						
							|  |  |  |  |              current option declaration as the file use for the submodule.  If the | 
					
						
							|  |  |  |  |              submodule defines any filename, then we ignore the enclosing option file. */ | 
					
						
							|  |  |  |  |           options' = toList opt.options.options; | 
					
						
							|  |  |  |  |           coerceOption = file: opt: | 
					
						
							| 
									
										
										
										
											2015-03-11 23:30:30 +01:00
										 |  |  |  |             if isFunction opt then packSubmodule file opt | 
					
						
							|  |  |  |  |             else packSubmodule file { options = opt; }; | 
					
						
							| 
									
										
										
										
											2014-08-29 16:42:44 +02:00
										 |  |  |  |           getSubModules = opt.options.type.getSubModules or null; | 
					
						
							| 
									
										
										
										
											2014-08-29 14:38:19 +02:00
										 |  |  |  |           submodules = | 
					
						
							| 
									
										
										
										
											2015-03-11 23:30:30 +01:00
										 |  |  |  |             if getSubModules != null then map (packSubmodule opt.file) getSubModules ++ res.options | 
					
						
							| 
									
										
										
										
											2014-08-29 16:42:44 +02:00
										 |  |  |  |             else if opt.options ? options then map (coerceOption opt.file) options' ++ res.options | 
					
						
							| 
									
										
										
										
											2014-08-29 14:38:19 +02:00
										 |  |  |  |             else res.options; | 
					
						
							|  |  |  |  |         in opt.options // res // | 
					
						
							| 
									
										
										
										
											2013-10-28 04:46:36 +01:00
										 |  |  |  |           { declarations = [opt.file] ++ res.declarations; | 
					
						
							| 
									
										
										
										
											2014-08-29 14:38:19 +02:00
										 |  |  |  |             options = submodules; | 
					
						
							| 
									
										
										
										
											2013-10-28 04:46:36 +01:00
										 |  |  |  |           } | 
					
						
							| 
									
										
										
										
											2013-10-28 14:25:58 +01:00
										 |  |  |  |     ) { inherit loc; declarations = []; options = []; } opts; | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Merge all the definitions of an option to produce the final
 | 
					
						
							|  |  |  |  |      config value. */ | 
					
						
							| 
									
										
										
										
											2013-10-28 05:23:10 +01:00
										 |  |  |  |   evalOptionValue = loc: opt: defs: | 
					
						
							| 
									
										
										
										
											2009-09-14 13:19:00 +00:00
										 |  |  |  |     let | 
					
						
							| 
									
										
										
										
											2014-05-01 17:29:30 -04:00
										 |  |  |  |       # Add in the default value for this option, if any. | 
					
						
							|  |  |  |  |       defs' = (optional (opt ? default) | 
					
						
							|  |  |  |  |         { file = head opt.declarations; value = mkOptionDefault opt.default; }) ++ defs; | 
					
						
							| 
									
										
										
										
											2015-03-12 23:01:47 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-01 17:29:30 -04:00
										 |  |  |  |       # Handle properties, check types, and merge everything together | 
					
						
							| 
									
										
										
										
											2015-03-12 23:01:47 +01:00
										 |  |  |  |       inherit (mergeDefinitions loc opt.type defs') isDefined defsFinal mergedValue; | 
					
						
							| 
									
										
										
										
											2013-10-30 12:10:40 +01:00
										 |  |  |  |       files = map (def: def.file) defsFinal; | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |       merged = | 
					
						
							| 
									
										
										
										
											2015-03-12 23:01:47 +01:00
										 |  |  |  |         if isDefined then mergedValue | 
					
						
							|  |  |  |  |         else throw "The option `${showOption loc}' is used but not defined."; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |       # Finally, apply the ‘apply’ function to the merged | 
					
						
							|  |  |  |  |       # value.  This allows options to yield a value computed | 
					
						
							|  |  |  |  |       # from the definitions. | 
					
						
							|  |  |  |  |       value = (opt.apply or id) merged; | 
					
						
							|  |  |  |  |     in opt // | 
					
						
							| 
									
										
										
										
											2013-10-28 15:13:51 +01:00
										 |  |  |  |       { value = addErrorContext "while evaluating the option `${showOption loc}':" value; | 
					
						
							| 
									
										
										
										
											2013-10-28 16:24:48 +01:00
										 |  |  |  |         definitions = map (def: def.value) defsFinal; | 
					
						
							| 
									
										
										
										
											2015-03-12 23:01:47 +01:00
										 |  |  |  |         inherit isDefined files; | 
					
						
							| 
									
										
										
										
											2011-04-27 18:41:37 +00:00
										 |  |  |  |       }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-01 17:29:30 -04:00
										 |  |  |  |     # Merge definitions of a value of a given type | 
					
						
							|  |  |  |  |     mergeDefinitions = loc: type: defs: rec { | 
					
						
							|  |  |  |  |       defsFinal = | 
					
						
							|  |  |  |  |         let | 
					
						
							|  |  |  |  |           # Process mkMerge and mkIf properties | 
					
						
							| 
									
										
										
										
											2015-03-12 22:38:51 +01:00
										 |  |  |  |           processIfAndMerge = defs: concatMap (m: | 
					
						
							| 
									
										
										
										
											2014-05-01 17:29:30 -04:00
										 |  |  |  |             map (value: { inherit (m) file; inherit value; }) (dischargeProperties m.value) | 
					
						
							|  |  |  |  |           ) defs; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |           # Process mkOverride properties | 
					
						
							| 
									
										
										
										
											2015-03-12 22:38:51 +01:00
										 |  |  |  |           processOverride = defs: filterOverrides defs; | 
					
						
							| 
									
										
										
										
											2014-05-01 17:29:30 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |           # Sort mkOrder properties | 
					
						
							| 
									
										
										
										
											2015-03-12 22:38:51 +01:00
										 |  |  |  |           processOrder = defs: | 
					
						
							| 
									
										
										
										
											2014-05-01 17:29:30 -04:00
										 |  |  |  |             # Avoid sorting if we don't have to. | 
					
						
							| 
									
										
										
										
											2015-03-12 22:38:51 +01:00
										 |  |  |  |             if any (def: def.value._type or "" == "order") defs | 
					
						
							|  |  |  |  |             then sortProperties defs | 
					
						
							|  |  |  |  |             else defs; | 
					
						
							|  |  |  |  |         in | 
					
						
							|  |  |  |  |           processOrder (processOverride (processIfAndMerge defs)); | 
					
						
							| 
									
										
										
										
											2014-05-01 17:29:30 -04:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |         # Type-check the remaining definitions, and merge them | 
					
						
							|  |  |  |  |         mergedValue = fold (def: res: | 
					
						
							|  |  |  |  |           if type.check def.value then res | 
					
						
							|  |  |  |  |           else throw "The option value `${showOption loc}' in `${def.file}' is not a ${type.name}.") | 
					
						
							|  |  |  |  |           (type.merge loc defsFinal) defsFinal; | 
					
						
							| 
									
										
										
										
											2015-03-12 23:01:47 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |         isDefined = defsFinal != []; | 
					
						
							|  |  |  |  |         optionalValue = | 
					
						
							|  |  |  |  |           if isDefined then { value = mergedValue; } | 
					
						
							|  |  |  |  |           else {}; | 
					
						
							| 
									
										
										
										
											2014-05-01 17:29:30 -04:00
										 |  |  |  |     }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |   /* Given a config set, expand mkMerge properties, and push down the
 | 
					
						
							| 
									
										
										
										
											2014-03-30 20:35:25 +02:00
										 |  |  |  |      other properties into the children.  The result is a list of | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |      config sets that do not have properties at top-level.  For | 
					
						
							|  |  |  |  |      example, | 
					
						
							| 
									
										
										
										
											2009-07-13 16:18:52 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |        mkMerge [ { boot = set1; } (mkIf cond { boot = set2; services = set3; }) ] | 
					
						
							| 
									
										
										
										
											2009-09-15 13:36:30 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |      is transformed into | 
					
						
							| 
									
										
										
										
											2009-09-15 13:36:30 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-17 20:29:08 +00:00
										 |  |  |  |        [ { boot = set1; } { boot = mkIf cond set2; services = mkIf cond set3; } ]. | 
					
						
							| 
									
										
										
										
											2012-11-30 12:56:18 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |      This transform is the critical step that allows mkIf conditions | 
					
						
							|  |  |  |  |      to refer to the full configuration without creating an infinite | 
					
						
							|  |  |  |  |      recursion. | 
					
						
							|  |  |  |  |   */ | 
					
						
							|  |  |  |  |   pushDownProperties = cfg: | 
					
						
							|  |  |  |  |     if cfg._type or "" == "merge" then | 
					
						
							|  |  |  |  |       concatMap pushDownProperties cfg.contents | 
					
						
							|  |  |  |  |     else if cfg._type or "" == "if" then | 
					
						
							|  |  |  |  |       map (mapAttrs (n: v: mkIf cfg.condition v)) (pushDownProperties cfg.content) | 
					
						
							| 
									
										
										
										
											2013-10-28 17:46:45 +01:00
										 |  |  |  |     else if cfg._type or "" == "override" then | 
					
						
							|  |  |  |  |       map (mapAttrs (n: v: mkOverride cfg.priority v)) (pushDownProperties cfg.content) | 
					
						
							| 
									
										
										
										
											2014-03-30 20:35:25 +02:00
										 |  |  |  |     else # FIXME: handle mkOrder? | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |       [ cfg ]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Given a config value, expand mkMerge properties, and discharge
 | 
					
						
							|  |  |  |  |      any mkIf conditions.  That is, this is the place where mkIf | 
					
						
							|  |  |  |  |      conditions are actually evaluated.  The result is a list of | 
					
						
							|  |  |  |  |      config values.  For example, ‘mkIf false x’ yields ‘[]’, | 
					
						
							|  |  |  |  |      ‘mkIf true x’ yields ‘[x]’, and | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |        mkMerge [ 1 (mkIf true 2) (mkIf true (mkIf false 3)) ] | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      yields ‘[ 1 2 ]’. | 
					
						
							|  |  |  |  |   */ | 
					
						
							|  |  |  |  |   dischargeProperties = def: | 
					
						
							|  |  |  |  |     if def._type or "" == "merge" then | 
					
						
							|  |  |  |  |       concatMap dischargeProperties def.contents | 
					
						
							|  |  |  |  |     else if def._type or "" == "if" then | 
					
						
							|  |  |  |  |       if def.condition then | 
					
						
							|  |  |  |  |         dischargeProperties def.content | 
					
						
							|  |  |  |  |       else | 
					
						
							|  |  |  |  |         [ ] | 
					
						
							| 
									
										
										
										
											2009-10-09 23:03:24 +00:00
										 |  |  |  |     else | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |       [ def ]; | 
					
						
							| 
									
										
										
										
											2009-09-15 13:36:30 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 07:52:24 +01:00
										 |  |  |  |   /* Given a list of config values, process the mkOverride properties,
 | 
					
						
							|  |  |  |  |      that is, return the values that have the highest (that is, | 
					
						
							|  |  |  |  |      numerically lowest) priority, and strip the mkOverride | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |      properties.  For example, | 
					
						
							| 
									
										
										
										
											2012-11-30 12:56:18 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 07:52:24 +01:00
										 |  |  |  |        [ { file = "/1"; value = mkOverride 10 "a"; } | 
					
						
							|  |  |  |  |          { file = "/2"; value = mkOverride 20 "b"; } | 
					
						
							|  |  |  |  |          { file = "/3"; value = "z"; } | 
					
						
							|  |  |  |  |          { file = "/4"; value = mkOverride 10 "d"; } | 
					
						
							| 
									
										
										
										
											2013-10-28 04:46:36 +01:00
										 |  |  |  |        ] | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |      yields | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 07:52:24 +01:00
										 |  |  |  |        [ { file = "/1"; value = "a"; } | 
					
						
							|  |  |  |  |          { file = "/4"; value = "d"; } | 
					
						
							| 
									
										
										
										
											2013-10-28 04:46:36 +01:00
										 |  |  |  |        ] | 
					
						
							| 
									
										
										
										
											2009-09-15 13:36:30 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 04:46:36 +01:00
										 |  |  |  |      Note that "z" has the default priority 100. | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |   */ | 
					
						
							| 
									
										
										
										
											2013-10-30 14:21:41 +01:00
										 |  |  |  |   filterOverrides = defs: | 
					
						
							| 
									
										
										
										
											2009-09-15 13:36:30 +00:00
										 |  |  |  |     let | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |       defaultPrio = 100; | 
					
						
							| 
									
										
										
										
											2013-10-28 05:23:10 +01:00
										 |  |  |  |       getPrio = def: if def.value._type or "" == "override" then def.value.priority else defaultPrio; | 
					
						
							| 
									
										
										
										
											2014-10-04 17:02:29 +02:00
										 |  |  |  |       min = x: y: if x < y then x else y; | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |       highestPrio = fold (def: prio: min (getPrio def) prio) 9999 defs; | 
					
						
							| 
									
										
										
										
											2013-10-28 05:23:10 +01:00
										 |  |  |  |       strip = def: if def.value._type or "" == "override" then def // { value = def.value.content; } else def; | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |     in concatMap (def: if getPrio def == highestPrio then [(strip def)] else []) defs; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-30 20:35:25 +02:00
										 |  |  |  |   /* Sort a list of properties.  The sort priority of a property is
 | 
					
						
							|  |  |  |  |      1000 by default, but can be overriden by wrapping the property | 
					
						
							|  |  |  |  |      using mkOrder. */ | 
					
						
							|  |  |  |  |   sortProperties = defs: | 
					
						
							|  |  |  |  |     let | 
					
						
							|  |  |  |  |       strip = def: | 
					
						
							|  |  |  |  |         if def.value._type or "" == "order" | 
					
						
							|  |  |  |  |         then def // { value = def.value.content; inherit (def.value) priority; } | 
					
						
							|  |  |  |  |         else def; | 
					
						
							|  |  |  |  |       defs' = map strip defs; | 
					
						
							|  |  |  |  |       compare = a: b: (a.priority or 1000) < (b.priority or 1000); | 
					
						
							|  |  |  |  |     in sort compare defs'; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |   /* Hack for backward compatibility: convert options of type
 | 
					
						
							| 
									
										
										
										
											2014-08-29 16:42:44 +02:00
										 |  |  |  |      optionSet to options of type submodule.  FIXME: remove | 
					
						
							|  |  |  |  |      eventually. */ | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |   fixupOptionType = loc: opt: | 
					
						
							| 
									
										
										
										
											2009-11-07 01:59:50 +00:00
										 |  |  |  |     let | 
					
						
							| 
									
										
										
										
											2014-08-29 14:38:19 +02:00
										 |  |  |  |       options = opt.options or | 
					
						
							| 
									
										
										
										
											2014-08-29 18:52:31 +02:00
										 |  |  |  |         (throw "Option `${showOption loc'}' has type optionSet but has no option attribute, in ${showFiles opt.declarations}."); | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |       f = tp: | 
					
						
							| 
									
										
										
										
											2014-08-29 18:52:31 +02:00
										 |  |  |  |         if tp.name == "option set" || tp.name == "submodule" then | 
					
						
							|  |  |  |  |           throw "The option ${showOption loc} uses submodules without a wrapping type, in ${showFiles opt.declarations}." | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |         else if tp.name == "attribute set of option sets" then types.attrsOf (types.submodule options) | 
					
						
							|  |  |  |  |         else if tp.name == "list or attribute set of option sets" then types.loaOf (types.submodule options) | 
					
						
							|  |  |  |  |         else if tp.name == "list of option sets" then types.listOf (types.submodule options) | 
					
						
							|  |  |  |  |         else if tp.name == "null or option set" then types.nullOr (types.submodule options) | 
					
						
							|  |  |  |  |         else tp; | 
					
						
							| 
									
										
										
										
											2014-08-29 16:42:44 +02:00
										 |  |  |  |     in | 
					
						
							|  |  |  |  |       if opt.type.getSubModules or null == null | 
					
						
							|  |  |  |  |       then opt // { type = f (opt.type or types.unspecified); } | 
					
						
							|  |  |  |  |       else opt // { type = opt.type.substSubModules opt.options; options = []; }; | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Properties. */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   mkIf = condition: content: | 
					
						
							|  |  |  |  |     { _type = "if"; | 
					
						
							|  |  |  |  |       inherit condition content; | 
					
						
							|  |  |  |  |     }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   mkAssert = assertion: message: content: | 
					
						
							|  |  |  |  |     mkIf | 
					
						
							|  |  |  |  |       (if assertion then true else throw "\nFailed assertion: ${message}") | 
					
						
							|  |  |  |  |       content; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   mkMerge = contents: | 
					
						
							|  |  |  |  |     { _type = "merge"; | 
					
						
							|  |  |  |  |       inherit contents; | 
					
						
							|  |  |  |  |     }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   mkOverride = priority: content: | 
					
						
							|  |  |  |  |     { _type = "override"; | 
					
						
							|  |  |  |  |       inherit priority content; | 
					
						
							|  |  |  |  |     }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-29 13:04:52 +01:00
										 |  |  |  |   mkOptionDefault = mkOverride 1001; # priority of option defaults | 
					
						
							|  |  |  |  |   mkDefault = mkOverride 1000; # used in config sections of non-user modules to set a default | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |   mkForce = mkOverride 50; | 
					
						
							| 
									
										
										
										
											2013-10-29 13:04:52 +01:00
										 |  |  |  |   mkVMOverride = mkOverride 10; # used by ‘nixos-rebuild build-vm’ | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-05 12:29:38 +02:00
										 |  |  |  |   mkStrict = builtins.trace "`mkStrict' is obsolete; use `mkOverride 0' instead." (mkOverride 0); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 00:56:22 +01:00
										 |  |  |  |   mkFixStrictness = id; # obsolete, no-op | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-30 20:35:25 +02:00
										 |  |  |  |   mkOrder = priority: content: | 
					
						
							|  |  |  |  |     { _type = "order"; | 
					
						
							|  |  |  |  |       inherit priority content; | 
					
						
							|  |  |  |  |     }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |   mkBefore = mkOrder 500; | 
					
						
							|  |  |  |  |   mkAfter = mkOrder 1500; | 
					
						
							| 
									
										
										
										
											2009-11-07 01:59:50 +00:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-22 22:38:38 +01:00
										 |  |  |  |   # Convenient property used to transfer all definitions and their | 
					
						
							|  |  |  |  |   # properties from one option to another. This property is useful for | 
					
						
							|  |  |  |  |   # renaming options, and also for including properties from another module | 
					
						
							|  |  |  |  |   # system, including sub-modules. | 
					
						
							|  |  |  |  |   # | 
					
						
							|  |  |  |  |   #   { config, options, ... }: | 
					
						
							|  |  |  |  |   # | 
					
						
							|  |  |  |  |   #   { | 
					
						
							|  |  |  |  |   #     # 'bar' might not always be defined in the current module-set. | 
					
						
							|  |  |  |  |   #     config.foo.enable = mkAliasDefinitions (options.bar.enable or {}); | 
					
						
							|  |  |  |  |   # | 
					
						
							|  |  |  |  |   #     # 'barbaz' has to be defined in the current module-set. | 
					
						
							|  |  |  |  |   #     config.foobar.paths = mkAliasDefinitions options.barbaz.paths; | 
					
						
							|  |  |  |  |   #   } | 
					
						
							|  |  |  |  |   # | 
					
						
							|  |  |  |  |   # Note, this is different than taking the value of the option and using it | 
					
						
							|  |  |  |  |   # as a definition, as the new definition will not keep the mkOverride / | 
					
						
							|  |  |  |  |   # mkDefault properties of the previous option. | 
					
						
							|  |  |  |  |   # | 
					
						
							|  |  |  |  |   mkAliasDefinitions = mkAliasAndWrapDefinitions id; | 
					
						
							|  |  |  |  |   mkAliasAndWrapDefinitions = wrap: option: | 
					
						
							|  |  |  |  |     mkMerge | 
					
						
							|  |  |  |  |       (optional (isOption option && option.isDefined) | 
					
						
							|  |  |  |  |         (wrap (mkMerge option.definitions))); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-29 14:23:10 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   /* Compatibility. */ | 
					
						
							| 
									
										
										
										
											2013-10-29 14:34:39 +01:00
										 |  |  |  |   fixMergeModules = modules: args: evalModules { inherit modules args; check = false; }; | 
					
						
							| 
									
										
										
										
											2013-10-29 14:23:10 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-14 20:10:41 +00:00
										 |  |  |  | } |