How to use input arguments inside overrideAttrs

Say I have this package expression:

{ stdenv, fetchurl, surName ? "bar" }:

stdenv.mkDerivation rec {
  name = "foo-${surName}";
  src = { … };  
}

And that it is added to Nixpkgs like this:

foo = callPackage ../applications/misc/foo { };

baz = foo.override { surName = "baz"; };

I want to make an overlay so that the resulting names for foo and baz are bar-foo and baz-foo, respectively. Something like this:

(self: super:
  {
    foo = super.foo.overrideAttrs (_: rec {
      name = "${surName}-foo";
    }); 
  }
)

This results in an error: undefined variable 'surName' because surName is not in the scope of overrideAttrs, which is understandable. How can I, inside of overrideAttrs in an overlay for a given package expression, get a hold of the input arguments that is passed to that package expression?

1 Like

Intriguing question… I think you can’t do it that way because of how overrideAttrs works. You simply don’t have access to that function’s arguments defined in ../applications/misc/foo if it doesn’t pass them to mkDerivation.

You could try wrapping the definition of foo in another function which takes the same arguments, such that you have access to the argument of interest and then do overrideAttrs on the result of foo.override in the scope of the wrapper:

foo = super.callPackage ({ surName, ... }@args:
  (super.foo.override args).overrideAttrs (_: {
    name = "${surName}-foo";
}));

Not sure about it, though. Using ellipses may be super inefficient or even nonsensical with callPackage, haven’t checked implementation details. I also don’t know for sure if the resulting derivation’s override attribute belongs to the outer function as we would like to have. If so, I guess it would also cover bar after applying the overlay. Would be interested in the result.

1 Like

Nice, that seems to do the trick. I did need to specify the default value again for this to be callable without specifying surName, but that’s fine:

foo = super.callPackage ({ surName = "bar", ... }@args:
  (super.foo.override args).overrideAttrs (_: {
    name = "${surName}-foo";
}));

I can’t attest to how the extra function wrapper and the ellipsis perform, but the resulting override does belong to the outer function, i.e. building baz works as intended.

1 Like

Cool, I’m glad it worked!