Should `version` and `sha256` attributes of packages be easily overridable?

Problem: as a user of nixpkgs, I want to be able to install newly released versions of applications easily.

For example, if I read that vscode 1.25.2 is released, I’d like to be able to try it out using a (made up) invocations like

$  nix-env -iA nixos.vscode --override --version "1.25.2" --sha256 "..."

In theory, override and overrideAttrs should allow me to do something similar, but I want to argue that in practice they are not quite there yet, and I wonder if we can improve things?

Let’s look at the vscode derivation, for example:

There, the version and sha256 bindings are both local variables, so you can’t use .override to change them.

You can use .overrideAttrs to change every aspect of derivation, as usual, but that severely leaks implementation details of the derivation. With overrideAttrs, I’ll need to override src with fetchUrl, so I’ll need to replicate the logic for constructing the url. I’ll also need to update the name attr, or it’ll use the wrong version.

I think that the situation might be improved with the following guideline:

For binary application packages, make version and sha256 overridable with .override by making them default parameters of derivations, instead of local variables or hard-coded values.

Does this sound at all reasonable? Note: I’m more of a casual Nix user rather then developer, I might be misunderstanding something or making false assumptions.

Previous discussion: 1, 2.

4 Likes

Thank you for writing this up. Just chiming in to echo my sentiment in the original pull request.

Whatever is decided, I think it’s important that the process of overriding package versions is uniform across (almost) all packages. In this case it means that if this method is adopted, I think every package should do so.

I also think that this is a symptom of us not being able to have overridden name, version, sha256, arbitraryAttribute be propagated into src at “override time.” If that were possible, I think this would be a non-issue.

Wholeheartedly agree that uniformity would be really useful. It even seems that today’s split between override and overrideAttrs is sub optimal? I would naively expect a single API which would look like this:

# override version and all attributes depending on it, including src
pkgs.foo.overrideDwim { version = "92"; } 
# override the resulting src directly
pkgs.foo.overrideDwim { src = fetchUrl { ... }; } 
# override version, and, in addition override src 
pkgs.foo.overrideDwim { version = "92"; src = fetchUrl { ... }; } 

I think that being able to override the src is the correct level of granularity.

In order to make using new versions convenient if there is a consistent release scheme then a function vsCodeSrc can be provided which will construct the correct source for a specific version.

newSrc = vsCodeSrc "1.25.1" <SHA>

This can then be used internally by default in the vscode derivation as well as by users overriding.

1 Like

Do you happen to know why that is the case? Fixing that would really be the best solution.

I am thinking more and more that the mkDerivation { name } should be derived from the src attribute. The source knows the package version and name usually and has all sorts of other interesting information. Then you could just inject whatever src and it becomes the new version (as long as the build instructions haven’t changed).

I don’t think there’s a deep reason for this other than “that’s not how mkDerivation and overrideAttrs work” – one could imagine all sorts of methods where src is actually a function that finally picks up name, version etc., or something like that, but we’d need to make some deep changes for that to happen.

I’ve made a highly related feature request recently: https://github.com/NixOS/nixpkgs/issues/43510

Though it looks like Nix 2.0 performs rebuilds when fetchurl url has changed, this is proposed way

to move src to derivation function args.

{ stdenv, fetchurl ,         src ? fetchurl rec { meta.version = "1.2.0"; url = "[https://github.com/graknlabs/grakn/releases/download/v${meta.version}/grakn-dist-${meta.version}.tar.gz](https://github.com/graknlabs/grakn/releases/download/v${meta.version}/grakn-dist-${meta.version}.tar.gz)        "; sha256 = "0hjsfj0m80nhd6mdj2m3razamqhqavpvjx80v1nsgfrypp4lr88f"; }

}: stdenv.mkDerivation {
    name = "grakn-${src.meta.version}"; inherit src; inherit (src.meta) version; meta.version = src.meta.version;
...

Now you can .override{} package with correct source instead of .overrideDerivation{}.

Sources database can also be externalized and distributed separately of nixpkgs channels.

self: super: {
  grakn = super.grakn.override { src = (import <freshSrcs> { }).grakn.v1_3_0; };
}
1 Like

As a sort-of negative update, I ended up just specifying the overrides in my configuration.nix:

This works ok-enough in practice: if you put stuff in a file, it doesn’t really matter that you need copy-paste non-trivial chunks for nixpkgs. Though I still would prefer this to be convenient for nix-env.