@@ -3,7 +3,45 @@
33# It adds a subDir argument in a way that allows descending into a subdirectory
44# to compose with cleaning the source with a filter.
55{ lib }: rec {
6− cleanSourceWith = { filter ? path: type: true, src, subDir ? "" }:
6+
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.
10+ #
11+ # lib.cleanSourceWith {
12+ # filter = f;
13+ # src = lib.cleanSourceWith {
14+ # filter = g;
15+ # src = ./.;
16+ # };
17+ # }
18+ # # Succeeds!
19+ #
20+ # builtins.filterSource f (builtins.filterSource g ./.)
21+ # # Fails!
22+ #
23+ # Parameters:
24+ #
25+ # src: A path or cleanSourceWith result to filter and/or rename.
26+ #
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
33+ #
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.
37+ #
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.
43+ #
44+ cleanSourceWith = { filter ? _path: _type: true, src, subDir ? "", name ? null }:
745 let
846 subDir' = if subDir == "" then "" else "/" + subDir;
947 # In case this is mixed with older versions of cleanSourceWith
@@ -22,14 +60,21 @@
2260 # Children only if both filters return true
2361 || (lib.strings.hasPrefix (origSrcSubDir + "/") path
2462 && (filter path type && parentFilter path type));
63+ name' = if name != null
64+ then name
65+ else (if isFiltered && src ? name
66+ then src.name
67+ else baseNameOf src)
68+ + (lib.optionalString (origSubDir != "") ("--" + baseNameOf origSubDir));
2569 in {
2670 inherit origSrc origSubDir origSrcSubDir;
2771 filter = filter';
28− outPath = (builtins.filterSource filter' origSrc) + origSubDir;
72+ outPath = (builtins.path { filter = filter'; path = origSrc; name = name'; }) + origSubDir;
2973 _isLibCleanSourceWithEx = true;
3074 # It is only safe for older cleanSourceWith to filter this one
3175 # if the we are still looking at the root of origSrc
3276 _isLibCleanSourceWith = origSubDir == "";
77+ name = name';
3378 };
3479
3580 pathHasContext = builtins.hasContext or (lib.hasPrefix builtins.storeDir);