Unverified Commit 8a59b790 authored by nicoo's avatar nicoo Committed by GitHub
Browse files

lib.filesystem.packagesFromDirectoryRecursive: refactor (#359941)

No functional changes.

- Centralize the logic classifying files/directories of interest, instead of
  being spread between `directoryEntryIsPackage` and `directoryEntryToAttrPair`.
- Replace a composition of `mapAttrs'` and `filterAttrs` with `concatMapAttrs`.
- Simplify future improvements, such as creating nested scopes for subdirs,
  or ignoring unsupported files.
parent e30e3649
Loading
Loading
Loading
Loading
+27 −46
Original line number Diff line number Diff line
@@ -18,7 +18,10 @@ let
    ;

  inherit (lib.filesystem)
    pathIsDirectory
    pathIsRegularFile
    pathType
    packagesFromDirectoryRecursive
    ;

  inherit (lib.strings)
@@ -360,52 +363,30 @@ in
      directory,
      ...
    }:
    assert pathIsDirectory directory;
    let
      # 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}";
      inherit (lib.path) append;
      defaultPath = append directory "package.nix";
    in
        if type == "regular"
        then
        {
          name = removeSuffix ".nix" basename;
          value = callPackage path { };
        }
        else
        if type == "directory"
        then
        {
          name = basename;
          value = packagesFromDirectory path;
        }
        else
        throw
    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}
      ''
            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
    packagesFromDirectory directory;
    ) (builtins.readDir directory);
}