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
Added composable version of filterSource
to lib
#33312
Conversation
@shlevy, how does this look? |
@GrahamcOfBorg what constitutes EDIT: Oh that's a bot. |
filterSource
to lib
filterSource
to lib
It'd be nice if we could transparently use |
78ecca2
to
d46e7d8
Compare
I suppose it's not actually possible to apply |
f85e792
to
a60642a
Compare
filterSource
to lib
filterSource
to lib
@ElvishJerricco The OfBorg tags say there are 0 linux rebuilds and 0 darwin rebuilds. |
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.
A few small changes. Have you tested with callCabal2nix?
lib/sources.nix
Outdated
# intermediate copies being put in the nix store. | ||
filterSource = f: src: | ||
let isPath = builtins.typeOf src == "path"; | ||
in assert isLocalSource src; rec { |
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.
Instead of asserting here, why don't we just do builtins.storePath src
if it's in the store already? You can't filter in that case but it's already in the store so there's no need anyway.
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.
Or maybe not even do storePath
, just pass src
as-is.
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 don't think it's a good idea to allow filterSource to accept inputs that it won't filter. That would be very misleading
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.
Filtering is an optimization, though...
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 don't think so. Filtering can be semantically relevant. e.g. If they want to filter out a particular source file.
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.
Hmm, OK. Better to fail now and be permissive later if we need it I suppose.
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.
Maybe this should take its arguments in an attrset so that we can extend it with new arguments (like, fallBackNoFilter
) in the future?
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.
👍
lib/sources.nix
Outdated
# allowing you to chain multiple calls together without any | ||
# intermediate copies being put in the nix store. | ||
filterSource = f: src: | ||
let isPath = builtins.typeOf src == "path"; |
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.
Seems like it would be better to switch on src ? __is-lib-filterSource
than isPath
. E.g. hydra will pass in paths as { outPath = the-actual-path; etc. }
so this will spuriously fail here.
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.
Wouldn't builtins.filterSource fail on such inputs as well? AFAIK, this will succeed on anything builtins.filterSource succeeds on
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.
filterSource
calls coerceToPath
, which respects outPath
etc.
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.
Just pushed a change. Is that better?
lib/sources.nix
Outdated
filter = if isPath then f else name: type: f name type && src.filter name type; | ||
origSrc = if isPath then src else src.origSrc; | ||
outPath = builtins.filterSource filter origSrc; | ||
__is-lib-filterSource = true; |
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.
There's nothing standardized here but IMO double underscore should be reserved by nix itself.
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.
Single underscore then?
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.
Yeah.
a60642a
to
2a83537
Compare
lib/sources.nix
Outdated
# intermediate copies being put in the nix store. | ||
filterSource = f: src: | ||
let isFiltered = src ? _is-lib-filterSource; | ||
in assert isLocalSource src; rec { |
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.
Hmm what does this assertion actually gain us? builtins.filterSource
itself will throw here. And note that typeOf src == "path"
is not quite exhaustive, as you can call builtins.filterSource
on, say toString ./.
(though I'm not sure if there are actual cases where that matters)
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.
Hm. Yea I suppose the only way to exhaustively check that builtins.filterSource
can take the argument would be to actually try it and catch any thrown error; but that would defeat the point since it would evaluate the intermediate filtered sources.
I was using the assertion to avoid an error message that's difficult to debug, but you're right; I don't think it will work. But the question remains: How do we have callCabal2nix
determine when it's appropriate to try to filter?
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.
callCabal2nix
can do something like check (src.type or "") != "derivation"
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.
That's not exhaustive though... I think either you have to do something like check if src is a string and if so if it's in the nix store, or just take an arg to callCabal2nix.
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.
@edolstra Would you object to a hasContext
primop? That would solve this...
2a83537
to
89d7af0
Compare
@shlevy Alright I think I've addressed all your points. Is this what you had in mind? |
lib/sources.nix
Outdated
# intermediate copies being put in the nix store. | ||
filterSource = { filter, src }: | ||
let isFiltered = src ? _is-lib-filterSource; | ||
in assert isLocalSource src; rec { |
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.
Does isLocalSource
exist any more?
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.
Derp. Fixed
89d7af0
to
af5eea1
Compare
lib/sources.nix
Outdated
filter = if isFiltered then name: type: filter name type && src.filter name type else filter; | ||
origSrc = if isFiltered then src.origSrc else src; | ||
outPath = builtins.filterSource filter origSrc; | ||
_is-lib-filterSource = true; |
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.
Please don't use dashes in variable names.
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.
Fixed
@shlevy One other thing we should probably think about is how |
lib/sources.nix
Outdated
# Like `builtins.filterSource`, except it will compose with itself, | ||
# allowing you to chain multiple calls together without any | ||
# intermediate copies being put in the nix store. | ||
filterSource = { filter, 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.
Please don't use the same name as a builtin function. Call it composableFilterSource
or something like that.
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.
EDIT: Wrong thread
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 was doing as fetchTarball
/fetchurl
do. I'm hesitant to call it something like composableFilterSource
, since I think that this should be the recommended way to filter sources instead of the builtin function.
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.
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.
cleanSourceWith
sounds good to me.
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.
Done
af5eea1
to
96894ec
Compare
@ElvishJerricco IMO we shouldn't hold ourselves to especially strong compatability guarantees across NixOS releases, but I'll defer to @peti on that one. |
@ElvishJerricco I think NixOS/nix#1772 would be a general solution though. |
96894ec
to
a35ccbc
Compare
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.
please address https://github.com/NixOS/nixpkgs/pull/33312/files#r159273889
@shlevy Forgive me; I don't know much about Nix internals. Would NixOS/nix#1772 require evaluating |
4db2546
to
9048189
Compare
@peti Do you think it's ok to break existing uses of |
filter = filter'; | ||
outPath = builtins.filterSource filter' origSrc; | ||
_isLibCleanSourceWith = true; | ||
}; | ||
|
||
# Filter sources by a list of regular expressions. | ||
# | ||
# E.g. `src = sourceByRegex ./my-subproject [".*\.py$" "^database.sql$"]` |
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.
IIRC this is actually a misleading example. I believe this will not recurse into directories unless they match these regexes. So in many cases this example would actually filter out everything and leave you with an empty folder. I need to double-check that this is the case but that's how it has appeared in my experience.
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 realize this is tangential to your actual change. Feel free to ignore while I look into opening a separate PR.
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've confirmed this. I'll open a separate PR.
|
||
# Like `builtins.filterSource`, except it will compose with itself, | ||
# allowing you to chain multiple calls together without any | ||
# intermediate copies being put in the nix store. |
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.
An example would be nice.
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.
Done
lib/sources.nix
Outdated
# Like `builtins.filterSource`, except it will compose with itself, | ||
# allowing you to chain multiple calls together without any | ||
# intermediate copies being put in the nix store. | ||
cleanSourceWith = { filter, 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.
An additional/alternative design that I've used is to write composeFilter
and just use that to build up bigger filters.
I don't know ... I have no idea how many people are actually using this idiom and would therefore be affected by this change. Personally, I think that it's okay'ish to break backwards-compatibility if there is a sufficiently self-explanatory error message. |
9048189
to
7e5f37d
Compare
Can this be merged? |
Addresses NixOS/nix#1767