diff --git a/lib/filesystem.nix b/lib/filesystem.nix index f9fd4a981b2d6..5a78bcca4ebd6 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -18,10 +18,7 @@ let ; inherit (lib.filesystem) - pathIsDirectory - pathIsRegularFile pathType - packagesFromDirectoryRecursive ; inherit (lib.strings) @@ -363,30 +360,52 @@ in directory, ... }: - assert pathIsDirectory directory; let - inherit (lib.path) append; - defaultPath = append directory "package.nix"; + # Determine if a directory entry from `readDir` indicates a package or + # directory of packages. + directoryEntryIsPackage = basename: type: + type == "directory" || hasSuffix ".nix" basename; + + # List directory entries that indicate packages in the given `path`. + packageDirectoryEntries = path: + filterAttrs directoryEntryIsPackage (readDir path); + + # Transform a directory entry (a `basename` and `type` pair) into a + # package. + directoryEntryToAttrPair = subdirectory: basename: type: + let + path = subdirectory + "/${basename}"; + in + if type == "regular" + then + { + name = removeSuffix ".nix" basename; + value = callPackage path { }; + } + else + if type == "directory" + then + { + name = basename; + value = packagesFromDirectory path; + } + else + throw + '' + lib.filesystem.packagesFromDirectoryRecursive: Unsupported file type ${type} at path ${toString subdirectory} + ''; + + # Transform a directory into a package (if there's a `package.nix`) or + # set of packages (otherwise). + packagesFromDirectory = path: + let + defaultPackagePath = path + "/package.nix"; + in + if pathExists defaultPackagePath + then callPackage defaultPackagePath { } + else mapAttrs' + (directoryEntryToAttrPair path) + (packageDirectoryEntries path); in - if pathIsRegularFile defaultPath then - # if `${directory}/package.nix` exists, call it directly - callPackage defaultPath {} - else lib.concatMapAttrs (name: type: - # otherwise, for each directory entry - let path = append directory name; in - if type == "directory" then { - # recurse into directories - "${name}" = packagesFromDirectoryRecursive { - inherit callPackage; - directory = path; - }; - } else if type == "regular" && hasSuffix ".nix" name then { - # call .nix files - "${lib.removeSuffix ".nix" name}" = callPackage path {}; - } else if type == "regular" then { - # ignore non-nix files - } else throw '' - lib.filesystem.packagesFromDirectoryRecursive: Unsupported file type ${type} at path ${toString path} - '' - ) (builtins.readDir directory); + packagesFromDirectory directory; }