summary refs log blame commit diff
path: root/pkgs/lib/modules.nix
blob: 61cf7624bc558950d24c659174d76bc4948be765 (plain) (tree)

































                                            


                                                                  
       








                                                                                


















                                                    

                                                                        
                                                                


                                                      

                                                  
 
      

                                                                
                                                      
                                                                    



                                       

                                          



              
 
# NixOS module handling.

let lib = import ./default.nix; in

with { inherit (builtins) head tail; };
with import ./trivial.nix;
with import ./lists.nix;
with import ./misc.nix;
with import ./attrsets.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;

  # Convert module to a set which has imports / options and config
  # attributes.
  unifyModuleSyntax = m:
    let
      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);

      getConfig = m:
        removeAttrs (delayProperties m) ["require"];
    in
      if m ? config || m ? options then
        m
      else
        {
          imports = getImportedPaths m;
          config = getConfig m;
        } // (
          if getImportedSets m != [] then
            assert tail (getImportedSets m) == [];
            { options = head (getImportedSets m); }
          else
            {}
        );

  moduleClosure = initModules: args:
    let
      moduleImport = m:
        (unifyModuleSyntax (applyIfFunction (importIfPath m) args)) // {
          # used by generic closure to avoid duplicated imports.
          key = if isPath m then m else
            /bad/developer/implies/bad/error/messages;
        };

      getImports = m: attrByPath ["imports"] [] m;

    in
      (lazyGenericClosure {
        startSet = map moduleImport (filter isPath initModules);
        operator = m: map moduleImport (getImports m);
      }) ++ (map moduleImport (filter (m: ! isPath m) initModules));

  selectDeclsAndDefs = modules:
    lib.concatMap (m:
      if m ? config || m ? options then
         [ (attrByPath ["options"] {} m) ]
      ++ [ (attrByPath ["config"] {} m) ]
      else
        [ m ]
    ) modules;

}