@@ -32,18 +32,25 @@
32 # https://nixos.org/nix/manual/#builtin-filterSource
32 # https://nixos.org/nix/manual/#builtin-filterSource
34 # subDir: Descend into a subdirectory in a way that will compose.
34 # subDir: Descend into a subdirectory in a way that will compose.
35− # It will be ase if `src = src + "/${subDir}` and filters
35+ # It will be as if `src = src + "/${subDir}` and filters
36 # already applied to `src` will be respected.
36 # already applied to `src` will be respected.
38 # name: Optional name to use as part of the store path.
38 # name: Optional name to use as part of the store path.
39− # This defaults `src.name` or otherwise `baseNameOf src`.
39+ # If you do not provide a `name` it wil be derived
40− # We recommend setting `name` whenever `src` is syntactically `./.`.
40+ # from the `subDir`. You should provide `name` or
41− # Otherwise, you depend on `./.`'s name in the parent directory,
41+ # `subDir`. If you do not a warning will be displayed
42− # which can cause inconsistent names, defeating caching.
42+ # and the name used will be `source`.
44+ # caller: Name of the function used in warning message.
45+ # Functions that are implemented using `cleanSourceWith`
46+ # (and forward a `name` argument) can use this to make
47+ # the message to the use more meaningful.
44− cleanSourceWith = { filter ? _path: _type: true, src, subDir ? "", name ? null }:
49+ cleanSourceWith = { filter ? _path: _type: true, src, subDir ? "", name ? null
50+ , caller ? "cleanSourceWith" }:
46 subDir' = if subDir == "" then "" else "/" + subDir;
52 subDir' = if subDir == "" then "" else "/" + subDir;
53+ subDirName = __replaceStrings ["/"] ["-"] subDir;
47 # In case this is mixed with older versions of cleanSourceWith
54 # In case this is mixed with older versions of cleanSourceWith
48 isFiltered = src ? _isLibCleanSourceWith;
55 isFiltered = src ? _isLibCleanSourceWith;
49 isFilteredEx = src ? _isLibCleanSourceWithEx;
56 isFilteredEx = src ? _isLibCleanSourceWithEx;
@@ -62,10 +69,32 @@
62 && (filter path type && parentFilter path type));
69 && (filter path type && parentFilter path type));
63 name' = if name != null
70 name' = if name != null
65− else (if isFiltered && src ? name
72+ else
66− then src.name
73+ if subDirName != ""
67− else baseNameOf src)
74+ then if src ? name
68− + (lib.optionalString (origSubDir != "") ("--" + baseNameOf origSubDir));
75+ then src.name + "-" + subDirName
76+ else "source-" + subDirName
80+ # No name was provided and one could not be constructed from
83+ # We used to use `baseNameOf src` as a default here.
84+ # This was cute, but it lead to cache misses. For instance if
85+ # `x = cleanSourceWith { src = ./.; }` then `baseName src`
86+ # will be different when `src` resolves to "/nix/store/X"
87+ # than when it is in a local directory. If people use
88+ # git worktrees they also may wind up with different
89+ # values for `name`. Anything that depends on `x.name` will
90+ # propagate the issue.
92+ # Encourage adding a suitable `name` with:
93+ # * A warning message.
94+ # * A default name that gives a hint as to why there is no name.
96+ "WARNING: `${caller}` called on ${toString src} without a `name`. "
97+ + "Consider adding `name = \"${baseNameOf src};\"`") "source";
70 inherit origSrc origSubDir origSrcSubDir;
99 inherit origSrc origSubDir origSrcSubDir;
71 filter = filter';
100 filter = filter';