{warn}: # Adapted from this: https://github.com/NixOS/nixpkgs/blob/1814b56453c91192f6d5a6276079948f9fe96c18/pkgs/top-level/by-name-overlay.nix # This file should not depend on `pkgs` and thus not use `lib`. { baseDirectory, fileName, finalizeFunction, coImportsNameFunction ? null, coImportsWarnMessageObject ? null, }: let # Takes a list of attrs as input and returns one merged attr set. flattenAttrs = list: if builtins.isList list then builtins.foldl' (acc: elem: if builtins.isList elem # Merging them with `//` is okay here, as we can be sure that the attr names are # unique (they were separate dictionary after all) then acc // (flattenAttrs elem) else acc // elem) {} list else list; # From nixpkgs/lib {{{ # These functions are taken straight out of the `nixpkgs/lib`. # We can't depended on `pkgs` (and thus on `lib`), because the `pkgs` module argument # is only defined in the `nixpkgs` module (which is imported through this function). mapAttrsToList = f: attrs: builtins.map (name: f name attrs.${name}) (builtins.attrNames attrs); nameValuePair = name: value: {inherit name value;}; filterAttrs = pred: set: builtins.listToAttrs (builtins.concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (builtins.attrNames set)); # }}} # Module files for a single shard # Type: String -> String -> ListOf Path namesForShard = shard: type: if type != "directory" then warn "Ignored non-directory, whilst importing by-name directory (${fileName}): '${shard}'" {} else let mkPath = name: _type: let path = baseDirectory + "/${shard}/${name}" + "/${fileName}"; coImportPath = if coImportsNameFunction != null then coImportsNameFunction {inherit shard name;} else path; in if builtins.pathExists path then if builtins.pathExists coImportPath then path else warn "'${builtins.toString coImportPath}' does not exist. Should include ${coImportsWarnMessageObject} for '${shard}/${name}'" path else warn "'${builtins.toString path}' does not exist. Skipped" null; in filterAttrs (name: value: value != null) (builtins.mapAttrs mkPath (builtins.readDir (baseDirectory + "/${shard}"))); # A list of all module paths. # These can the be simply injected into `import` files = flattenAttrs (mapAttrsToList namesForShard (builtins.readDir baseDirectory)); output = builtins.mapAttrs finalizeFunction files; in output