diff options
Diffstat (limited to 'pkgs/lib/modules.nix')
-rw-r--r-- | pkgs/lib/modules.nix | 380 |
1 files changed, 0 insertions, 380 deletions
diff --git a/pkgs/lib/modules.nix b/pkgs/lib/modules.nix deleted file mode 100644 index acd10e7bf576..000000000000 --- a/pkgs/lib/modules.nix +++ /dev/null @@ -1,380 +0,0 @@ -# NixOS module handling. - -let lib = import ./default.nix; in - -with { inherit (builtins) head; }; -with import ./trivial.nix; -with import ./lists.nix; -with import ./misc.nix; -with import ./attrsets.nix; -with import ./options.nix; -with import ./properties.nix; - -rec { - - # Unfortunately this can also be a string. - isPath = x: !( - builtins.isFunction x - || builtins.isAttrs x - || builtins.isInt x - || builtins.isBool x - || builtins.isList x - ); - - - importIfPath = path: - if isPath path then - import path - else - path; - - - applyIfFunction = f: arg: - if builtins.isFunction f then - f arg - else - f; - - - isModule = m: - (m ? config && isAttrs m.config && ! isOption m.config) - || (m ? options && isAttrs m.options && ! isOption m.options); - - - # Convert module to a set which has imports / options and config - # attributes. - unifyModuleSyntax = m: - let - delayedModule = delayProperties m; - - getImports = - toList (rmProperties (delayedModule.require or [])); - getImportedPaths = filter isPath getImports; - getImportedSets = filter (x: !isPath x) getImports; - - getConfig = - removeAttrs delayedModule ["require" "key" "imports"]; - - in - if isModule m then - { key = "<unknown location>"; } // m - else - { key = "<unknown location>"; - imports = (m.imports or []) ++ getImportedPaths; - config = getConfig; - } // ( - if getImportedSets != [] then - assert length getImportedSets == 1; - { options = head getImportedSets; } - else - {} - ); - - - unifyOptionModule = {key ? "<unknown location>"}: name: index: m: (args: - let - module = lib.applyIfFunction m args; - key_ = rec { - file = key; - option = name; - number = index; - outPath = key; - }; - in if lib.isModule module then - { key = key_; } // module - else - { key = key_; options = module; } - ); - - - moduleClosure = initModules: args: - let - moduleImport = origin: index: m: - let m' = applyIfFunction (importIfPath m) args; - in (unifyModuleSyntax m') // { - # used by generic closure to avoid duplicated imports. - key = - if isPath m then m - else m'.key or (newModuleName origin index); - }; - - getImports = m: m.imports or []; - - newModuleName = origin: index: - "${origin.key}:<import-${toString index}>"; - - topLevel = { - key = "<top-level>"; - }; - - in - (lazyGenericClosure { - startSet = imap (moduleImport topLevel) initModules; - operator = m: imap (moduleImport m) (getImports m); - }); - - - moduleApply = funs: module: - lib.mapAttrs (name: value: - if builtins.hasAttr name funs then - let fun = lib.getAttr name funs; in - fun value - else - value - ) module; - - - # Handle mkMerge function left behind after a delay property. - moduleFlattenMerge = module: - if module ? config && - isProperty module.config && - isMerge module.config.property - then - (map (cfg: { key = module.key; config = cfg; }) module.config.content) - ++ [ (module // { config = {}; }) ] - else - [ module ]; - - - # Handle mkMerge attributes which are left behind by previous delay - # properties and convert them into a list of modules. Delay properties - # inside the config attribute of a module and create a second module if a - # mkMerge attribute was left behind. - # - # Module -> [ Module ] - delayModule = module: - map (moduleApply { config = delayProperties; }) (moduleFlattenMerge module); - - - evalDefinitions = opt: values: - if opt.type.delayOnGlobalEval or false then - map (delayPropertiesWithIter opt.type.iter opt.name) - (evalLocalProperties values) - else - evalProperties values; - - - selectModule = name: m: - { inherit (m) key; - } // ( - if m ? options && builtins.hasAttr name m.options then - { options = lib.getAttr name m.options; } - else {} - ) // ( - if m ? config && builtins.hasAttr name m.config then - { config = lib.getAttr name m.config; } - else {} - ); - - filterModules = name: modules: - filter (m: m ? config || m ? options) ( - map (selectModule name) modules - ); - - - modulesNames = modules: - lib.concatMap (m: [] - ++ optionals (m ? options) (lib.attrNames m.options) - ++ optionals (m ? config) (lib.attrNames m.config) - ) modules; - - - moduleZip = funs: modules: - lib.mapAttrs (name: fun: - fun (catAttrs name modules) - ) funs; - - - moduleMerge = path: modules: - let modules_ = modules; in - let - addName = name: - if path == "" then name else path + "." + name; - - modules = concatLists (map delayModule modules_); - - modulesOf = name: filterModules name modules; - declarationsOf = name: filter (m: m ? options) (modulesOf name); - definitionsOf = name: filter (m: m ? config ) (modulesOf name); - - recurseInto = name: - moduleMerge (addName name) (modulesOf name); - - recurseForOption = name: modules: args: - moduleMerge name ( - moduleClosure modules args - ); - - errorSource = modules: - "The error may come from the following files:\n" + ( - lib.concatStringsSep "\n" ( - map (m: - if m ? key then toString m.key else "<unknown location>" - ) modules - ) - ); - - eol = "\n"; - - allNames = modulesNames modules; - - getResults = m: - let fetchResult = s: mapAttrs (n: v: v.result) s; in { - options = fetchResult m.options; - config = fetchResult m.config; - }; - - endRecursion = { options = {}; config = {}; }; - - in if modules == [] then endRecursion else - getResults (fix (crossResults: moduleZip { - options = lib.zipWithNames allNames (name: values: rec { - config = lib.getAttr name crossResults.config; - - declarations = declarationsOf name; - declarationSources = - map (m: { - source = m.key; - }) declarations; - - hasOptions = values != []; - isOption = any lib.isOption values; - - decls = # add location to sub-module options. - map (m: - mapSubOptions - (unifyOptionModule {inherit (m) key;} name) - m.options - ) declarations; - - decl = - lib.addErrorContext "${eol - }while enhancing option `${addName name}':${eol - }${errorSource declarations}${eol - }" ( - addOptionMakeUp - { name = addName name; recurseInto = recurseForOption; } - (mergeOptionDecls decls) - ); - - value = decl // (with config; { - inherit (config) isNotDefined; - isDefined = ! isNotDefined; - declarations = declarationSources; - definitions = definitionSources; - config = strictResult; - }); - - recurse = (recurseInto name).options; - - result = - if isOption then value - else if !hasOptions then {} - else if all isAttrs values then recurse - else - throw "${eol - }Unexpected type where option declarations are expected.${eol - }${errorSource declarations}${eol - }"; - - }); - - config = lib.zipWithNames allNames (name: values_: rec { - option = lib.getAttr name crossResults.options; - - definitions = definitionsOf name; - definitionSources = - map (m: { - source = m.key; - value = m.config; - }) definitions; - - values = values_ ++ - optionals (option.isOption && option.decl ? extraConfigs) - option.decl.extraConfigs; - - defs = evalDefinitions option.decl values; - - isNotDefined = defs == []; - - value = - lib.addErrorContext "${eol - }while evaluating the option `${addName name}':${eol - }${errorSource (modulesOf name)}${eol - }" ( - let opt = option.decl; in - opt.apply ( - if isNotDefined then - opt.default or (throw "Option `${addName name}' not defined and does not have a default value.") - else opt.merge defs - ) - ); - - strictResult = builtins.tryEval (builtins.toXML value); - - recurse = (recurseInto name).config; - - configIsAnOption = v: isOption (rmProperties v); - errConfigIsAnOption = - let badModules = filter (m: configIsAnOption m.config) definitions; in - "${eol - }Option ${addName name} is defined in the configuration section.${eol - }${errorSource badModules}${eol - }"; - - errDefinedWithoutDeclaration = - let badModules = definitions; in - "${eol - }Option '${addName name}' defined without option declaration.${eol - }${errorSource badModules}${eol - }"; - - result = - if option.isOption then value - else if !option.hasOptions then throw errDefinedWithoutDeclaration - else if any configIsAnOption values then throw errConfigIsAnOption - else if all isAttrs values then recurse - # plain value during the traversal - else throw errDefinedWithoutDeclaration; - - }); - } modules)); - - - fixMergeModules = initModules: {...}@args: - lib.fix (result: - # This trick avoids an infinite loop because names of attribute - # are know and it is not required to evaluate the result of - # moduleMerge to know which attributes are present as arguments. - let module = { inherit (result) options config; }; in - moduleMerge "" ( - moduleClosure initModules (module // args) - ) - ); - - - # Visit all definitions to raise errors related to undeclared options. - checkModule = path: {config, options, ...}@m: - let - eol = "\n"; - addName = name: - if path == "" then name else path + "." + name; - in - if lib.isOption options then - if options ? options then - options.type.fold - (cfg: res: res && checkModule (options.type.docPath path) cfg._args) - true config - else - true - else if isAttrs options && lib.attrNames m.options != [] then - all (name: - lib.addErrorContext "${eol - }while checking the attribute `${addName name}':${eol - }" (checkModule (addName name) (selectModule name m)) - ) (lib.attrNames m.config) - else - builtins.trace "try to evaluate config ${lib.showVal config}." - false; - -} |