-
-
Notifications
You must be signed in to change notification settings - Fork 44
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
Allow patching dependency sources #151
Conversation
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 a few comments that I had while going through the first couple of changes.
internal.nix
Outdated
@@ -76,20 +76,42 @@ rec { | |||
inherit rev ref; | |||
allRefs = true; | |||
}; | |||
|
|||
# If sourceMods.${name} is set, call it with some information about this |
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.
Can we give strong gurantees what "some information" are going to be? It would be good to pick something that we can document somewhere. Having to guess or debug your way there wouldn't be the best 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.
In the API.md
I at documented it as only a version
attribute for now, leaving the possibility for more in the future open. The version
however is a bit ambiguous, because for github:
dependencies it could be a git hash or any other git reference. Maybe it would be better to let users distinguish between github:
and url sources, e.g. by setting sourceType = "github" / "url"
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 changed this a bit, now these attributes are passed:
version
for HTTP tarball sourcesgithub = { org, repo, rev, ref }
for GitHub sources
Considering that sources for a specific package should typically all be of the same source type, this should also work fairly well.
I also thought a lot about providing a proper version in the GitHub case:
- It's possible to get the version at build time via the
.version
field in thepackage.json
file. This would be a uniform way of getting a correct version - However we lose the ability to decide on which patches to include at eval time
- In order to still be able to limit patches to specific versions, it would be best to have some way of specifying NPM version ranges for each patch and calling runtime checks to figure out whether to include them.
- I deemed this approach too complicated though, because it would have to involve coming up with our own custom scheme of declaring patches and patch commands, entirely separately from the current nixpkgs way.
- The
version
andgithub
based version decisions should be good enough for most use cases for now.
internal.nix
Outdated
|
||
# If sourceMods.${name} is set, call it with some information about this | ||
# source for it to make a decision about when to do modifications | ||
mods = lib.optionalAttrs (sourceOptions ? sourceMods.${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.
Here you call it mods
(sourceMods
) but it actually is extra attributes (attrs
) in the packTgz
invocation. Can we agree on one way to call these?
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 called it sourceAttrs
now, also relating to the thoughts in #151 (comment)
inherit src; | ||
nativeBuildInputs = attrs.nativeBuildInputs or [ ] ++ [ | ||
# Allows patchShebangs in postPatch to patch shebangs to nodejs | ||
nodejs |
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 might not be required if patchShebangs
isn't called at all.
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.
It's a bit annoying to include the correct version of nodejs, and considering that it's always a dependency anyways, and that many scripts would use node
as an executable, I think it makes sense to provide this as a default
|
||
# Patching shebangs | ||
node-pre-gyp = _: { | ||
postPatch = "patchShebangs bin"; |
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.
The interface here is a very leaky abstraction. We just plug some additional variables into the runCommand
but only some will ever actually have an impact. I'd rather prefer an interface that isn't passing everything through from the user but defines a stricter interface.
The alternative is to provide an overrideAttrs
interface here instead.
I prefer the first approach as it comes with a more limited set of features that we have to take care of.
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.
Sounds good. I think we can limit this to only patches
and postPatch
for now, but it could be extended with support for other attributes in the future (for now other attributes should give an error)
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.
After another thought, I think it's probably better to just support all attributes, both to keep it simpler, but also because people might have different needs. Notably there's also prePatch
, you can add dependencies in buildInputs
as needed by patchShebangs
, you may want to set NIX_DEBUG
for debugging, you may want to set sourceRoot
to only get a subdirectory, you may want to set dontUnpack
to preserve the original .tgz
and patch that with tar
directly, you may want to set environment variables.
I pushed support for this in this PR now, along with documentation for it
4b3a198
to
a236825
Compare
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/tweag-nix-dev-update-26/18252/1 |
API.md
Outdated
@@ -114,3 +115,32 @@ npmlock2nix.build { | |||
}; | |||
} | |||
``` | |||
|
|||
### Source derivation attributes |
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 addition seems sound. I just worry a bit about supporting this as an interface. Users should/will experience breakage over time as this is a very broad interface that we can't by no means keep stable/guarantee.
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.
See #151 (comment), do you think it would be fine with to have it be like this considering the arguments there?
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 get the appeal and I can see why it might be used. I just don't want to advertise it as the go-to solution. We should do most if not all things for the users instead of exposing these broad interfaces...
I'll give it a bit of though.
internal.nix
Outdated
# of entries, where each entry contains a JSON object path of the | ||
# integrity field and the corresponding resolved file path, separated | ||
# by a tab, ready for shell consumption | ||
jqFindNullIntegrity = '' |
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.
Why do we have to do that during build time? Can't we have nix do this for us? I'd rather not depend on yet another DSL for this. Especially since I am not using jq very often and at some point changes to this will have to be made.
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.
Ah that's a good point, this part could be done by Nix at eval time, I'll give that a go
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.
Pushed a commit to do this with Nix instead. Also rebased this PR on top of master.
This allows more flexibility for the future, such as support for: - Source patches - Fetch authentication
Can be used to patchShebangs for specific packages, which with NPM version 7.0 can't be done globally for all packages anymore Could also be a replacement for preInstallLinks
Instead of jq
1a45e5b
to
bbb6fd4
Compare
Thank you for the updates you provided. I'll try to get through them some afternoon this week. |
API.md
Outdated
# sourceInfo either contains: | ||
# - A version attribute | ||
# - A github = { org, repo, rev, ref } attribute for GitHub sources | ||
package-name = sourceInfo: { |
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.
The more I think about this the interface should be:
sourceOverrides = {
package-name = sourceInfo: drv: drv.overrideAttrs (_:{ });
}
As that is the standard way of doing overrides within nixpkgs. This also doesn't expose some half-baked custom solution but rather whatever the typical nix developer is already familiar with. IIRC poetry2nix does it very similar.
Besides the override interface this looks fine and I'd accept it. @infinisil can you make that change? |
@andir Changed the interface according to your suggestion. While I think there's some redundancy to it (because it's probably always going to be a |
(ping, does this look good?) |
Adds support for patching dependency sources with
patches
andpostPatch
derivation attributes. This is a bit hacky, as patching any files requires recalculating theintegrity
value, which needs to be done at build-time. But it works, and I made sure to make the code resilient and commented.This is a solution for #110, as this allows doing
patchShebangs
on individual packages.npmlock2nix
could also provide a predefined list of patches for individual packages for convenience in the future.