Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add filterFiles to lib and lib.sources #188301

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ let
inherit (self.sources) pathType pathIsDirectory cleanSourceFilter
cleanSource sourceByRegex sourceFilesBySuffices
commitIdFromGitRepo cleanSourceWith pathHasContext
canCleanSource pathIsRegularFile pathIsGitRepo;
canCleanSource pathIsRegularFile pathIsGitRepo filterFiles;
inherit (self.modules) evalModules setDefaultModuleLocation
unifyModuleSyntax applyModuleArgsIfFunction mergeModules
mergeModules' mergeOptionDecls evalOptionValue mergeDefinitions
Expand Down
53 changes: 53 additions & 0 deletions lib/sources.nix
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,57 @@ let

canCleanSource = src: src ? _isLibCleanSourceWith || !(pathHasContext (toString src));

/*
Get all files and symlinks that pass a filter function, by scanning
directories recursively, unconditionally. Unlike other source filtering
functions, this will not include empty directories in the final derivation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This function always scans the entire directory tree. In large code bases, you can improve performance by filtering the second argument.

(assuming you're flipping the parameters as suggested below, and we fix sourceLike support)

Type: (String -> Bool) -> sourceLike -> Source

Example:
filterFiles ./. (lib.hasSuffix ".html")
*/
filterFiles = filter: src:
let
pathToList = path: lib.splitString "/" (builtins.toString path);
dirDepth = builtins.length (pathToList src);
dropCommon = path: lib.drop dirDepth (pathToList path);

includedPaths =
builtins.filter
filter
(lib.filesystem.listFilesRecursive src);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not actually support all sourceLike values, such as the result of cleanSource. Types are a bit vague in Nix documentation, so I really can't blame you for not picking up on this subtlety.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tried

lib.filesystem.listFilesRecursive (lib.cleanSource ./.)

in nixpkgs and it worked.


dirs =
let
f = dir: filter':
builtins.foldl'
(acc: { name, value }:
if value == "directory" then
let recurse = f (dir + "/${name}") filter'; in
if recurse == {}
then acc
else acc // { ${name} = recurse; }
else if filter' name then
acc // { ${name} = value; }
else
acc
)
{}
(lib.mapAttrsToList lib.nameValuePair (builtins.readDir dir));
in
f src filter;
in
cleanSourceWith {
inherit src;
name = "source";

filter = path: type:
if type == "directory"
then lib.hasAttrByPath (dropCommon path) dirs
else filter path;
};

# -------------------------------------------------------------------------- #
# Internal functions
#
Expand Down Expand Up @@ -279,6 +330,8 @@ in {
sourceByRegex
sourceFilesBySuffices

filterFiles

trace
;
}