-
-
Notifications
You must be signed in to change notification settings - Fork 159
[RFC 0192] version pins for the pkgs/by-name structure
#192
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
base: master
Are you sure you want to change the base?
Changes from all commits
6733241
dd79622
f6d34a7
b0c2009
8add3b0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| --- | ||
| feature: by-name-version-pins | ||
| start-date: 2025-11-25 | ||
| author: Quantenzitrone | ||
| co-authors: (find a buddy later to help out with the RFC) | ||
| shepherd-team: (names, to be nominated and accepted by RFC steering committee) | ||
| shepherd-leader: (name to be appointed by RFC steering committee) | ||
| related-issues: https://github.com/NixOS/nixpkgs/pull/464396 | ||
| --- | ||
|
|
||
| # Summary | ||
| [summary]: #summary | ||
|
|
||
| Add an additional file `pins.nix` to the `pkgs/by-name` structure that allows | ||
| overriding/pinning versions of package dependencies. | ||
|
|
||
| # Motivation | ||
| [motivation]: #motivation | ||
|
|
||
| > Why are we doing this? | ||
|
|
||
| - The `pkgs/by-name` structure doesn't have support for overriding packages yet | ||
| leading to a lot of remaining entries in `pkgs/top-level/all-packages.nix`. | ||
| - Packages with dependency version pins often get neglected and stay on the old | ||
| version for a long time, even though it already supports the new version. By | ||
| having dependency version pins in a defined location with a defined structure, | ||
| package update bots or scripts could check if the package works without the | ||
| pin and remove it automatically on update. | ||
|
|
||
| > What use cases does it support? | ||
|
|
||
| - Pinning dependency versions of packages. | ||
|
|
||
| > What is the expected outcome? | ||
|
|
||
| - Less confusion if dependency pins should go into `all-packages.nix` or be | ||
| inlined in the `package.nix`. | ||
| - Less maintenance burden due to possible automation of pin removal. | ||
|
|
||
| # Detailed design | ||
| [design]: #detailed-design | ||
|
|
||
| In addition to `pkgs/by-name/{shard}/{pname}/package.nix` there can also be | ||
| `pkgs/by-name/{shard}/{pname}/pins.nix`. This file will have the following structure: | ||
|
|
||
| ```nix | ||
| { | ||
| package-a_version, | ||
| package-b_version, | ||
| # ... | ||
| }: | ||
| { | ||
| package-a = package-a_version; | ||
| package-b = package-b_version; | ||
| # ... | ||
| } | ||
| ``` | ||
|
|
||
| - Every attrName in the resulting attribute set has to be a valid package | ||
| attribute name. | ||
| - Every attrValue should be the pinned version of the respectice attrName | ||
| package, this is however hard to check I think. | ||
| - Every attrName has to be a functionArg of the `package.nix`. | ||
|
|
||
| I think you know where this is going. | ||
|
|
||
| Packages with a `pin.nix` will have the versions of dependencies pinned | ||
| accordingly. This can be easily achieved with: | ||
|
|
||
| ```nix | ||
| if lib.pathExists (packageDirectory + "/pins.nix") then | ||
| let | ||
| pins = lib.removeAttrs (callPackage (packageDirectory + "/pins.nix") { }) [ | ||
| "override" | ||
| "overrideDerivation" | ||
| ]; | ||
| in | ||
| callPackage (packageDirectory + "/package.nix") pins | ||
| else | ||
| callPackage (packageDirectory + "/package.nix") { } | ||
| ``` | ||
|
|
||
| # Examples and Interactions | ||
| [examples-and-interactions]: #examples-and-interactions | ||
|
|
||
| # Drawbacks | ||
| [drawbacks]: #drawbacks | ||
|
|
||
| Probably longer eval time, this has to be tested however. | ||
|
|
||
| # Alternatives | ||
kevincox marked this conversation as resolved.
Show resolved
Hide resolved
quantenzitrone marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| [alternatives]: #alternatives | ||
|
|
||
| - Keep the current situation: version pins are either in `all-packages.nix` or | ||
| directly in the `package.nix`. | ||
|
|
||
| - Some more generalized `overrides.nix` without the strict requirements. | ||
| - This would be less useful for automation of dependency pin removal. | ||
|
|
||
| - Inline dependency pins in `package.nix` as default values in the function arguments. | ||
| ```nix | ||
| { | ||
| package-a_version, | ||
| package-a ? package-a_version, | ||
| # ... | ||
| }: | ||
| # ... | ||
| ``` | ||
| This would require a custom `callPackage` for `pkgs/by-name` that prefers default values over | ||
| values from the `pkgs`. | ||
| - Confusing for contributors if something works differently through the normal `callPackage`. | ||
|
|
||
| - Inline dependency pins in `package.nix` with `let in` syntax. | ||
| ```nix | ||
| { | ||
| package-a_version, | ||
| # ... | ||
| }: | ||
| let | ||
| package-a = package-a_version; | ||
| in | ||
| # ... | ||
| ``` | ||
| - Possibly harder to automate dependency pin removal. | ||
|
|
||
| - Your suggestion here. | ||
|
|
||
| # Prior art | ||
| [prior-art]: #prior-art | ||
|
|
||
| - [RFC 140](https://github.com/NixOS/rfcs/blob/master/rfcs/0140-simple-package-paths.md) | ||
| lists the problem this RFC is trying to solve under "Future work". | ||
|
|
||
| # Unresolved questions | ||
| [unresolved]: #unresolved-questions | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When overriding a package, will it override the the arguments of
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
package.overridePins {
dependency_3 = my-dependency_3;
}would be the same as package.override {
dependency = my-dependency_3;
}
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there is an ambiguity here. Overrides relative to
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry, i don't understand what you are trying to say There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I forgot to mention it's heavily related to my other comment, so it's only useful if we also want to pin non-versioned packages. Following the last example in that thread, we have: # file: pkgs/by-name/ae/aegisub/pins.nix
{
luajit
}:
{
luajit = luajit.override { enable52Compat = false; };
}The aegisub.override {
luajit = luajit.override { enable52Compat = true; };
}And a aegisub.overridePins {
luajit = luajit_2_0;
}The latter will result in |
||
|
|
||
| # Future work | ||
| [future]: #future-work | ||
|
|
||
| - pinning versions of packages, e.g. having ffmpeg_7 as a subattribute of ffmpeg | ||
| (not dependency pinning, what this rfc is about) | ||
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 is out of scope, but can we also pin dependencies that not just differ in their semantic versions like
nodejs = nodejs_22, but have other overrides or logic?Some example
pins.nix:This would be useful to keep compatibility with previous overrides of a package when removing by-name overrides.
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 we lose some of the usefulness if we allow that
also like with version pins we can already do that just in the package.nix with
let inUh oh!
There was an error while loading. Please reload this page.
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.
Yes,
let inhandles most of the cases, but there are a few edge cases when it breaks override compatibility.package called in all-package.nix
Consider this package and it's possible usage before it being fully self contained in
by-name:The above code builds fine,
luajit_2_0.override { enable52Compat = true;will be inbuildInputs.package is only in by name using
let in, breaks override compatibilityNow let's move the override from all-packages to the by-name package:
The above code fails to build,
(luajit_2_0.override { enable52Compat = true; }).override { enable52Compat = false; }will be inbuildInputs. There is no way to override a variable in a let binding.package using pins, override compatible and doesn't touch all-packages
To solve this, we may use versions pins:
The above code should build and should produce the same derivation as the first, all-packages example.
(The details in this example is unrealistic:
enable52Compatis set totruein nixpkgs and it's unlikely for someone to override it. The PR I linked in my previous comment talked about overriding platforms, but I didn't want to complicate this example by introducing platforms.)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 this falls under
While I get the problem this is trying to solve, in my opinion it overcomplicates things.
Especially the resulting need to have
overrideOverrides/overridePinsis too confusing for people I think.