Problems w/ applying a patch in a flake's devshell

Hi, I’m trying to apply a patch in a devshell defintion of a flake to the nixos-rebuild script defined in nixpkgs. The patch was generated via git diff >PATCHNAME.patch from a checked-out nixpkgs repository. The devshell definition is the following:

    devShells = with flake-utils.lib; nixpkgs.lib.genAttrs [ system.x86_64-linux system.aarch64-linux ] (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
      in {
        default = pkgs.mkShell {
          packages = [
            (pkgs.nixos-rebuild.overrideAttrs (prevAttrs: {
              patches = (prevAttrs.patches or []) ++ [ ./PATCHNAME.patch ];
            }))
            ...
          ];
        };
      }
    );

and the patch header looks like:

diff --git a/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.sh b/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.sh
index bc0b6507ecb..584298b9cb9 100755
--- a/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.sh
+++ b/pkgs/os-specific/linux/nixos-rebuild/nixos-rebuild.sh
...

However, when entering the shell with nix develop the patch isn’t applied to nixos-rebuild and no error message is shown. I end up with a vanilla version of the script in the shell, but the patch itself is added to the nix store (but no patched version of the script is present in the store).

(I tried to modify the paths in the header because I couldn’t find any information about to which directory the paths should be relative too, but it didn’t help.)

I probably misunderstood how patching works (I was following this article) and would be glad to get some hints what I’m doing wrong. Thanks!

Note: I only want to apply this patch in the devshell for now as it’s intended to be usable on a non-nixos system. I tried to apply it with an overlay on a NixOS system but to no avail.

patches only work if you are using something based on stdenv.mkDerivation. nixos-rebuild is built with substituteAll, which uses a different builder that doesn’t respect patches, so overriding it doesn’t do anything. To work around that, you can use applyPatches instead:

applyPatches {
  src = nixos-rebuild;
  patches = [ ./PATCHNAME.patch ];
}

The only difference is that you would be patching bin/nixos-rebuild instead, so the patch should start with something like

--- a/bin/nixos-rebuild
+++ b/bin/nixos-rebuild

Thanks for the help, that worked perfectly :+1:

I’m a bit surprised though because the Nixpkgs manual for overrideAttrs states:

This function is available on all derivations produced by the stdenv.mkDerivation function

So I assumed that the function has an effect (ok, it doesn’t say that the function is not available on other derivations). Triggering an error or at least printing a warning when overriding a non-existing attribute would probably help when trying to figure out what’s going on.

I couldn’t find any info that the applyPatches function exists in the Nixpkgs manual though. How would I go about finding this information myself?

Something I wasn’t clear about was that substituteAll is also based on stdenv.mkDerivation, but it overrides the default builder. That’s why it has overrideAttrs but doesn’t respect patches.

This is fair and an issue with the current approach of mkDerivation. This situation might get better once module system for packages is implemented: Working group member search: Module system for packages

This is currently only documented in the source code. I opened an issue to add it to the manual as well.

You can find same the documentation with noogle, though it doesn’t show up in the first few pages if you search patch.