Substitute fixOptionSetsFun by multiple functions which are:

- well named,
- capable to handle the proposal of Eelco Dolstra { imports= [..]; options = {}; config = {}; } in addition to the current { require = [..]; .. } syntax.

svn path=/nixpkgs/trunk/; revision=16192
This commit is contained in:
Nicolas Pierron 2009-07-06 16:20:05 +00:00
parent a89f3bca50
commit c49dddb1ab
2 changed files with 78 additions and 87 deletions

View file

@ -208,20 +208,24 @@ rec {
(filter (__hasAttr name) sets)); (filter (__hasAttr name) sets));
}) (concatMap builtins.attrNames sets)); }) (concatMap builtins.attrNames sets));
# flatten a list of elements by following the properties of the elements.
# next : return the list of following elements. lazyGenericClosure = {startSet, operator}:
# seen : lists of elements already visited. let
# default: result if 'x' is empty. work = list: doneKeys: result:
# x : list of values that have to be processed. if list == [] then
uniqFlatten = next: seen: default: x: result
if x == [] else
then default let x = head list; key = x.key; in
else if elem key doneKeys then
let h = head x; t = tail x; n = next h; in work (tail list) doneKeys result
if elem h seen else
then uniqFlatten next seen default t work (tail list ++ operator x) ([key] ++ doneKeys) ([x] ++ result);
else uniqFlatten next (seen ++ [h]) (default ++ [h]) (n ++ t) in
; work startSet [] [];
genericClosure =
if builtins ? genericClosure then builtins.genericClosure
else lazyGenericClosure;
innerModifySumArgs = f: x: a: b: if b == null then (f a b) // x else innerModifySumArgs = f: x: a: b: if b == null then (f a b) // x else
innerModifySumArgs f x (a // b); innerModifySumArgs f x (a // b);

View file

@ -78,7 +78,7 @@ rec {
merge = list: merge = list:
decl.type.iter decl.type.iter
(path: opts: (path: opts:
fixMergeFun (recurseInto path) (optionConfig opts) lib.fix (fixableMergeFun (recurseInto path) (optionConfig opts))
) )
opt.name opt.name
(opt.merge list); (opt.merge list);
@ -262,6 +262,12 @@ rec {
|| builtins.isList x || builtins.isList x
); );
importIfPath = path:
if isPath path then
import path
else
path;
applyIfFunction = f: arg: applyIfFunction = f: arg:
if builtins.isFunction f then if builtins.isFunction f then
f arg f arg
@ -270,106 +276,87 @@ rec {
moduleClosure = initModules: args: moduleClosure = initModules: args:
let let
moduleImport = path: moduleImport = m:
(applyIfFunction (import path) args) // { (applyIfFunction (importIfPath m) args) // {
# used by generic closure to avoid duplicated imports. # used by generic closure to avoid duplicated imports.
key = path; key = m;
}; };
removeKeys = list: map (m: removeAttrs m ["key"]) list;
getImports = m:
if m ? config || m ? options then
attrByPath ["imports"] [] m
else
toList (rmProperties (attrByPath ["require"] [] (delayProperties m)));
getImportedPaths = m: filter isPath (getImports m);
getImportedSets = m: filter (x: !isPath x) (getImports m);
inlineImportedSets = list:
lib.concatMap (m:[m] ++ map moduleImport (getImportedSets m)) list;
in in
builtins.genericClosure { inlineImportedSets (removeKeys (lazyGenericClosure {
startSet = map moduleImport initModules; startSet = map moduleImport initModules;
operator = m: operator = m: map moduleImport (getImportedPaths m);
map moduleImport (attrByPath ["imports"] [] m); }));
};
selectDeclsAndDefs = modules: selectDeclsAndDefs = modules:
lib.concatMap (m: lib.concatMap (m:
attrByPath ["options"] [] m if m ? config || m ? options then
++ attrByPath ["config"] [] m attrByPath ["options"] [] m
++ attrByPath ["config"] [] m
else
[ m ]
) modules; ) modules;
fixMergeFun = merge: optFun:
lib.fix (config: fixableMergeFun = merge: f: config:
merge ( merge (
# remove require because this is not an option.
map (m: removeAttrs m ["require"]) (
# Delay top-level properties like mkIf # Delay top-level properties like mkIf
map delayProperties ( map delayProperties (
# generate the list of option sets. # generate the list of option sets.
optFun config f config
) )
) )
); );
fixMergeModules = merge: initModules: {...}@args: fixableMergeModules = merge: initModules: {...}@args: config:
fixMergeFun (config: fixableMergeFun merge (config:
# filter the list of option sets.
selectDeclsAndDefs ( selectDeclsAndDefs (
# generate the list of modules from a closure of imports/require
# attribtues.
moduleClosure initModules (args // { inherit config; }) moduleClosure initModules (args // { inherit config; })
) )
); ) config;
fixModulesConfig = initModules: {...}@args:
fixMergeModules (mergeOptionSets "") initModules args;
fixOptionsConfig = initModules: {...}@args:
fixMergeModules (filterOptionSets "") initModules args;
# Evaluate a list of option sets that would be merged with the fixableDefinitionsOf = initModules: {...}@args:
# function "merge" which expects two arguments. The attribute named fixableMergeModules (mergeOptionSets "") initModules args;
# "require" is used to imports option declarations and bindings.
#
# * cfg[0-9]: configuration
# * cfgSet[0-9]: configuration set
#
# merge: the function used to merge options sets.
# args: is the set of packages available. (nixpkgs)
# opts: list of option sets or option set functions.
# config: result of this evaluation.
fixOptionSetsFun = merge: args: opts: config:
let
# remove possible mkIf to access the require attribute.
noImportConditions = cfgSet0:
let cfgSet1 = delayProperties cfgSet0; in
if cfgSet1 ? require then
cfgSet1 // { require = rmProperties cfgSet1.require; }
else
cfgSet1;
filenameHandler = cfg: fixableDeclarationsOf = initModules: {...}@args:
if isPath cfg then import cfg else cfg; fixableMergeModules (filterOptionSets "") initModules args;
argumentHandler = cfg: definitionsOf = initModules: {...}@args:
applyIfFunction cfg (args // { inherit config; }); lib.fix (fixableDefinitionsOf initModules args);
preprocess = cfg0: declarationsOf = initModules: {...}@args:
let cfg1 = filenameHandler cfg0; lib.fix (fixableDeclarationsOf initModules args);
cfg2 = argumentHandler cfg1;
cfg3 = noImportConditions cfg2;
in cfg3;
getRequire = x: toList (attrByPath ["require"] [] (preprocess x));
getRecursiveRequire = x:
fold (cfg: l:
if isPath cfg then
[ cfg ] ++ l
else
[ cfg ] ++ (getRecursiveRequire cfg) ++ l
) [] (getRequire x);
getRequireSets = x: filter (x: ! isPath x) (getRecursiveRequire x); fixMergeModules = merge: initModules: {...}@args:
getRequirePaths = x: filter isPath (getRecursiveRequire x); lib.fix (fixableMergeModules merge initModules args);
rmRequire = x: removeAttrs (preprocess x) ["require"];
inlineRequiredSets = cfgs:
fold (cfg: l: [ cfg ] ++ (getRequireSets cfg) ++ l) [] cfgs;
in
merge "" (
map rmRequire (
inlineRequiredSets ((toList opts) ++ lib.uniqFlatten getRequirePaths [] [] (lib.concatMap getRequirePaths (toList opts)))
)
);
fixOptionSets = merge: args: opts: # old interface.
lib.fix (fixOptionSetsFun merge args opts); fixOptionSetsFun = merge: {...}@args: initModules: config:
fixableMergeModules (merge "") initModules args config;
fixOptionSets = merge: args: initModules:
fixMergeModules (merge "") initModules args;
# Generate documentation template from the list of option declaration like # Generate documentation template from the list of option declaration like