If a package I want to use is missing from nixpkgs, the options to get around this include:
Create an overlay which adds the package locally.
Add the package to a local clone of nxipkgs (… and submit a PR for its inclusion).
I would like to understand how to make the two as compatible as possible, or how to write code that is as reusable-in-both-contexts as possible.
For example, here is a contribution to nixpkgs that was accepted a while ago:
{ buildPythonPackage
, fetchPypi
, lib
, pytestCheckHook
}:
buildPythonPackage rec {
pname = "pytest-instafail";
version = "0.4.2";
src = fetchPypi {
inherit pname version;
sha256 = "10lpr6mjcinabqynj6v85bvb1xmapnhqmg50nys1r6hg7zgky9qr";
};
checkInputs = [ pytestCheckHook ];
pythonImportsCheck = [ "pytest_instafail" ];
meta = {
description = "pytest plugin that shows failures and errors instantly instead of waiting until the end of test session";
homepage = "https://github.com/pytest-dev/pytest-instafail";
license = lib.licenses.bsd3;
maintainers = [ lib.maintainers.jacg ];
};
}
What is the minimal modification to this which would allow it to be used as a local overlay?
Most obviously, the nixpkgs version (BTW, what is a short and correct name for 'the expression which defines a/the package in nixpgs’ ?) receives everything it uses as an arbitrary set of arguments (in this case: buildPythonPackage, fetchPypi, lib, pytestCheckHook), while overlays are restricted to exactly self: super:. So it seems that I would need to prepend each occurrence of the nixpkgs-style parameters in the body of the expression, with self. or super., in order to make it usable in an overlay, which is a right royal PITA, whose cost grows with the complexity of the expression.
More generally, I find that there’s a tension between how things should look inside nixpkgs and elsewhere, and I find code reuse in different contexts in Nix to be quite challenging.
If you want to use the selected version in the overlay, you can make overlay.nix contain a function that takes py argument and returns an overlay, instead of just overlay. Then you will be able to import it as import ./nix/overlay.nix { inherit py; }.
Of course, this will no longer allow you to use the overlay.nix as an overlay directly so if you want that, you will need real-overlay.nix containing import ./overlay.nix { py = "something"; }.
These days flakes are filling in a similar role in providing a standard and I’d recommend using them as they are better in many ways. Flakes - NixOS Wiki
Which is essentially what I was doing, but I was unsatisfied with it precisely because, as you point out, it’s not usable as a genuine overlay any more.
Yes, I see … I’ll have to think through it carefully to see how it fits in with everything else, when I next have some time to spend on Nix. Thanks for the suggestion!
Yes, I had come across it in the past, and my attempts were, indeed, influenced by it.
Sigh. Flakes.
Yes, I’ve been wanting to use them for some time, but I’ve been holding off because their unstable status and my limited time available for all things Nix, didn’t seem like a good fit.