From 1db8650fb4671b1495064d3fb2e99ca3457c1ff8 Mon Sep 17 00:00:00 2001 From: nicoo Date: Tue, 3 Dec 2024 11:12:11 +0000 Subject: [PATCH 1/2] lib.packagesFromDirectoryRecursive: refactor, again This is a second take on #359941, which was reverted by 940db5766a966b5586b53359bb785badac6c5662. Co-authored-by: Silvan Mosberger --- lib/filesystem.nix | 72 +++++++++++++++++----------------------------- 1 file changed, 26 insertions(+), 46 deletions(-) diff --git a/lib/filesystem.nix b/lib/filesystem.nix index 5a78bcca4ebd..753088f7542d 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -18,7 +18,10 @@ let ; inherit (lib.filesystem) + pathIsDirectory + pathIsRegularFile pathType + packagesFromDirectoryRecursive ; inherit (lib.strings) @@ -361,51 +364,28 @@ in ... }: 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}"; - 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); + inherit (lib.path) append; + defaultPath = append directory "package.nix"; in - packagesFromDirectory directory; + if pathExists 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); } From 065b48084f27798c8500a3c78582318eae25849d Mon Sep 17 00:00:00 2001 From: nicoo Date: Thu, 12 Dec 2024 18:02:21 +0000 Subject: [PATCH 2/2] lib.packagesFromDirectoryRecursive: let-bind functions called from `lib` I was told it is better for eval performance: https://github.com/NixOS/nixpkgs/pull/361424#discussion_r1879975642 --- lib/filesystem.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/filesystem.nix b/lib/filesystem.nix index 753088f7542d..e54776ba908d 100644 --- a/lib/filesystem.nix +++ b/lib/filesystem.nix @@ -364,13 +364,14 @@ in ... }: let + inherit (lib) concatMapAttrs removeSuffix; inherit (lib.path) append; defaultPath = append directory "package.nix"; in if pathExists defaultPath then # if `${directory}/package.nix` exists, call it directly callPackage defaultPath {} - else lib.concatMapAttrs (name: type: + else concatMapAttrs (name: type: # otherwise, for each directory entry let path = append directory name; in if type == "directory" then { @@ -381,7 +382,7 @@ in }; } else if type == "regular" && hasSuffix ".nix" name then { # call .nix files - "${lib.removeSuffix ".nix" name}" = callPackage path {}; + "${removeSuffix ".nix" name}" = callPackage path {}; } else if type == "regular" then { # ignore non-nix files } else throw ''