-
Notifications
You must be signed in to change notification settings - Fork 238
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
Use subDir
not src
to construct default names
#506
Conversation
When no name is provided to `cleanSourceWith` or `cleanGit` we currently use `baseNameOf src` as a default. This was cute, but it lead to cache misses. For instance if `x = cleanSourceWith { src = ./.; }` then `baseName src` will be different when `src` resolves to "/nix/store/X" than when it is in a local directory. If people use git worktrees they also may wind up with different values for `name`. Anything that depends on `x.name` will propagate the issue. This change uses `subDir` if present or if it is not it encourages adding a suitable `name` with: * A warning message. * A default name that gives a hint as to why there is no name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it! I think we should consider making a PR like this to upstream nixpkgs. It'll probably be controversial, but I think it would be a clear improvement - this is a real new-user trap.
lib/clean-source-with.nix
Outdated
if subDirName != "" | ||
then if src ? name | ||
then src.name + "-" + subDirName | ||
else "cleaned-" + subDirName |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit circuitous: we have a default value for name
(null), which we then test for in order to act as if it had a different value ("unnamed"), except sometimes when we use something else ("cleaned"). How about just changing the default value for name
? i.e.
, name ? warnHere "unnamed"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I felt if you pass in subDir
, but not name
it should not warn you since it can derive what is likely to be a reasonable name from the subDir
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Eh, I'd be happy to just make people name it. But I can see the argument both ways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it might soften the impact for people who liked the baseNameOf src
default and used it carefully. They can go from:
cleanSourceWith { src = ./myDir; }
to:
cleanSourceWith { src = ./.; subDir = "myDir"; }
I prefer this to:
cleanSourceWith { src = ./myDir; name = "myDir"; }
I know at some point I would have a typo in the name
or update the src
and forget to update name
as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, I take your argument. But I would go for using "unnamed" as the prefix always just for consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. I've changed it so the prefix is "unnamed-${caller}-"
(where caller will be "cleanSourceWith" or "cleanGit"). This matches the name given when we issue the warning. Now the only difference between:
cleanSourceWith { src = ./.; subDir = "myDir"; }
and
cleanSourceWith { src = cleanSourceWith { src = ./.; }; subDir = "myDir"; }
should be that the latter will issue a warning to the user about the lack of a name.
@@ -44,6 +44,7 @@ | |||
cleanSourceWith = { filter ? _path: _type: true, src, subDir ? "", name ? null }: | |||
let | |||
subDir' = if subDir == "" then "" else "/" + subDir; | |||
subDirName = __replaceStrings ["/"] ["-"] subDir; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit, but I find it confusing that we use ""
as the default value for subDir
, but null
as the default value for name
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haskell types I was thinking of subDir :: FilePath
and name :: Maybe String
.
I wanted to avoid the use of null
for subDir
and since directory names cannot be empty it seems like a natural default. Since subDir works more or less like src + "/" + subDir
I felt this was consistent with ls dir
and ls dir/
.
What I was going for with name
is:
-
null
: build a name from thesubDir
if it can (warning if it cannot). -
""
: Use no name regardless ofsubDir
and with no warning (might be useful if you always plan to filter sub directories out). For instance this should not produce a warning or include a"unnamed"
in the name:root = cleanSourceWith { src ./.; name = ""; filter = ... }; x = cleanSourceWith { src = root; subDir = "x"; }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd have thought subDir :: Maybe FilePath
too, since it's optional, no? But yes, I guess the empty path is a reasonable default for subDir
, I guess I'm just surprised that you then have a bunch of checks for subDir == ""
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we used null
as the default I think we would still need the subDir == ""
checks (or to transform ""
to null
). Otherwise passing ""
would result in extra '/'
characters in the path and the filter function would not work (we could canonicalise the path later, but I would prefer just to make it hard to have non canonical paths in the first place).
lib/clean-git.nix
Outdated
@@ -102,7 +103,7 @@ then | |||
gitModules = builtins.path { name = "gitmodules"; path = gitModulesStr; }; | |||
|
|||
gitSubmoduleFiles = cleanSourceWith { | |||
inherit src; | |||
inherit name src; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd have thought you want different names for these, otherwise they're going to look confusingly like the main src. e.g. name = name + "-gitSubmoduleFiles"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea.
I've opened an upstream PR for some of this: NixOS/nixpkgs#83201 |
Eelco points out that we should probably use "source" instead of "unnamed" in the case of a missing name. |
bors try |
tryBuild succeeded |
When no name is provided to
cleanSourceWith
orcleanGit
wecurrently use
baseNameOf src
as a default.This was cute, but it lead to cache misses. For instance if
x = cleanSourceWith { src = ./.; }
thenbaseName src
will be different when
src
resolves to "/nix/store/X"than when it is in a local directory. If people use
git worktrees they also may wind up with different
values for
name
. Anything that depends onx.name
willpropagate the issue.
This change uses
subDir
if present or if it is not it encouragesadding a suitable
name
with: