[RFC 0192] version pins for the pkgs/by-name structure#192
[RFC 0192] version pins for the pkgs/by-name structure#192quantenzitrone wants to merge 5 commits intoNixOS:masterfrom
pkgs/by-name structure#192Conversation
Co-authored-by: Michael Daniels <mdaniels5757@gmail.com>
|
Related: NixOS/nixpkgs#421201 |
| - 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`. |
There was a problem hiding this comment.
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:
{
darwin,
stdenv,
}@args:
{
stdenv = if args.stdenv.hostPlatform.isDarwin then darwin.bootstrapStdenv else args.stdenv;
}{
luajit,
}@args:
{
luajit = args.luajit.override { enable52Compat = true; };
}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.
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 in
There was a problem hiding this comment.
Yes, let in handles 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:
# file: pkgs/all-packages.nix
{
aegisub = callPackage ../by-name/ae/aegisub/package.nix {
luajit = luajit.override { enable52Compat = false; };
};
# ...
}# file: pkgs/by-name/ae/aegisub/package.nix
{
stdenv,
luajit,
# ...
}:
stdenv.mkDerivation {
buildInputs = [ luajit ];
# ...
}# file: configuration.nix
{ pkgs, ... }:
{
environment.systemPackages = [
(pkgs.aegisub.override { luajit = luajit_2_0.override { enable52Compat = true; })
]
}The above code builds fine, luajit_2_0.override { enable52Compat = true; will be in buildInputs.
package is only in by name using let in, breaks override compatibility
Now let's move the override from all-packages to the by-name package:
# file: pkgs/all-packages.nix
{
# no override for aegisub
}# file: pkgs/by-name/ae/aegisub/package.nix
{
stdenv,
luajit,
# ...
}:
let
luajit' = luajit.override { enable52Compat = true; };
in
stdenv.mkDerivation {
buildInputs = [ luajit' ];
# ...
}# file: configuration.nix
{ pkgs, ... }:
{
environment.systemPackages = [
(pkgs.aegisub.override { luajit = luajit_2_0.override { enable52Compat = true; })
]
}The above code fails to build, (luajit_2_0.override { enable52Compat = true; }).override { enable52Compat = false; } will be in buildInputs. 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:
# file: pkgs/all-packages.nix
{
# no override for aegisub
}# file: pkgs/by-name/ae/aegisub/package.nix
{
stdenv,
luajit
# ...
}:
stdenv.mkDerivation {
buildInputs = [ luajit ];
# ...
}# file: pkgs/by-name/ae/aegisub/pins.nix
{
luajit
}:
{
luajit = luajit.override { enable52Compat = false; };
}# file: configuration.nix
{ pkgs, ... }:
{
environment.systemPackages = [
(pkgs.aegisub.override { luajit = luajit_2_0.override { enable52Compat = true; })
]
}The above code should build and should produce the same derivation as the first, all-packages example.
(The details in this example is unrealistic: enable52Compat is set to true in 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.
I think this falls under
- Some more generalized
overrides.nixwithout the strict requirements.
While I get the problem this is trying to solve, in my opinion it overcomplicates things.
Especially the resulting need to have overrideOverrides/overridePins is too confusing for people I think.
There was a problem hiding this comment.
Why would you need overridePins? This would be rare enough that «just copy the override and tune it, still better than let-in» should be sufficient.
The current attempts in minimising all-packages.nix are pure regressions for overriding interface quality, this would be an improvement.
| lists the problem this RFC is trying to solve under "Future work". | ||
|
|
||
| # Unresolved questions | ||
| [unresolved]: #unresolved-questions |
There was a problem hiding this comment.
When overriding a package, will it override the the arguments of pins.nix or the arguments of package.nix?
Perhaps it could override package.nix and we could have an overridePins function.
There was a problem hiding this comment.
.override {} overrides the package.nix
why would someone need to override the pins?
package.overridePins {
dependency_3 = my-dependency_3;
}would be the same as
package.override {
dependency = my-dependency_3;
}There was a problem hiding this comment.
I think there is an ambiguity here. Overrides relative to callPackage path/to/package.nix {} are not provided at all, because this would break more than help (and also override works relative to a package that is defined, and the package defined does use pins). You can just override all the pinned stuff one-by-one, though, if for some specific package it makes sense.
There was a problem hiding this comment.
sorry, i don't understand what you are trying to say
There was a problem hiding this comment.
why would someone need to override the pins?
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; };
}# file: pkgs/by-name/ae/aegisub/package.nix
{
stdenv,
luajit
# ...
}:
stdenv.mkDerivation {
buildInputs = [ luajit ];
# ...
}
The package.nix override that turns on enable52Compat could be written as:
aegisub.override {
luajit = luajit.override { enable52Compat = true; };
}And a pins.nix override that uses luajit_2_0 instead of luajit could be written as:
aegisub.overridePins {
luajit = luajit_2_0;
}The latter will result in luajit_2_0.override { enable52Compat = false; } getting into buildInputs, because it replace's the pin's input, the pin adds the override { enable52Compat = false; } and passes this to the package's input.
Rendered
Sorry if the RFC text is short, i don't know what else to write. The feature is quite simple.