@@ -3,7 +3,45 @@
3# It adds a subDir argument in a way that allows descending into a subdirectory
3# It adds a subDir argument in a way that allows descending into a subdirectory
4# to compose with cleaning the source with a filter.
4# to compose with cleaning the source with a filter.
5{ lib }: rec {
5{ lib }: rec {
7+ # Like `builtins.filterSource`, except it will compose with itself,
8+ # allowing you to chain multiple calls together without any
9+ # intermediate copies being put in the nix store.
6− cleanSourceWith = { filter ? path: type: true, src, subDir ? "" }:
11+ # lib.cleanSourceWith {
13+ # src = lib.cleanSourceWith {
20+ # builtins.filterSource f (builtins.filterSource g ./.)
25+ # src: A path or cleanSourceWith result to filter and/or rename.
27+ # filter: A function (path -> type -> bool)
28+ # Optional with default value: constant true (include everything)
29+ # The function will be combined with the && operator such
30+ # that src.filter is called lazily.
31+ # For implementing a filter, see
32+ # https://nixos.org/nix/manual/#builtin-filterSource
34+ # subDir: Descend into a subdirectory in a way that will compose.
35+ # It will be ase if `src = src + "/${subDir}` and filters
36+ # already applied to `src` will be respected.
38+ # name: Optional name to use as part of the store path.
39+ # This defaults `src.name` or otherwise `baseNameOf src`.
40+ # We recommend setting `name` whenever `src` is syntactically `./.`.
41+ # Otherwise, you depend on `./.`'s name in the parent directory,
42+ # which can cause inconsistent names, defeating caching.
44+ cleanSourceWith = { filter ? _path: _type: true, src, subDir ? "", name ? null }:
8 subDir' = if subDir == "" then "" else "/" + subDir;
46 subDir' = if subDir == "" then "" else "/" + subDir;
9 # In case this is mixed with older versions of cleanSourceWith
47 # In case this is mixed with older versions of cleanSourceWith
@@ -22,14 +60,21 @@
22 # Children only if both filters return true
60 # Children only if both filters return true
23 || (lib.strings.hasPrefix (origSrcSubDir + "/") path
61 || (lib.strings.hasPrefix (origSrcSubDir + "/") path
24 && (filter path type && parentFilter path type));
62 && (filter path type && parentFilter path type));
63+ name' = if name != null
65+ else (if isFiltered && src ? name
68+ + (lib.optionalString (origSubDir != "") ("--" + baseNameOf origSubDir));
26 inherit origSrc origSubDir origSrcSubDir;
70 inherit origSrc origSubDir origSrcSubDir;
27 filter = filter';
71 filter = filter';
28− outPath = (builtins.filterSource filter' origSrc) + origSubDir;
72+ outPath = (builtins.path { filter = filter'; path = origSrc; name = name'; }) + origSubDir;
29 _isLibCleanSourceWithEx = true;
73 _isLibCleanSourceWithEx = true;
30 # It is only safe for older cleanSourceWith to filter this one
74 # It is only safe for older cleanSourceWith to filter this one
31 # if the we are still looking at the root of origSrc
75 # if the we are still looking at the root of origSrc
32 _isLibCleanSourceWith = origSubDir == "";
76 _isLibCleanSourceWith = origSubDir == "";
35 pathHasContext = builtins.hasContext or (lib.hasPrefix builtins.storeDir);
80 pathHasContext = builtins.hasContext or (lib.hasPrefix builtins.storeDir);