Apply a patch to an input flake

I’d like to get the master + 1 pr of some software. There exists a flake for the software.

How/where would you do this?

Yeah, there’s currently not really a good story for this. I’ve heard that the lazy-trees branch has such a feature, but that’s still very experimental.

What I currently do (and I should really write this up somehow), is to patch the sources using pkgs.applyPatches, and then load that again as a flake and use the result for everything.

The function to patch a flake looks like this:

            applyPatches =
              { pkgs
              , name
              , src
              , patches
              , lockFileEntries ? { }
              }:
              let
                numOfPatches = lib.length patches;

                patchedFlake =
                  let
                    patched = (pkgs.applyPatches {
                      inherit name src;
                      patches = map pkgs.fetchpatch2 patches;
                    }).overrideAttrs (_: prevAttrs: {
                      outputs = [ "out" "narHash" ];
                      installPhase = lib.concatStringsSep "\n" [
                        prevAttrs.installPhase
                        ''
                          ${lib.getExe pkgs.nix} \
                            --extra-experimental-features nix-command \
                            --offline \
                            hash path ./ \
                            > $narHash
                        ''
                      ];
                    });

                    lockFilePath = "${patched.outPath}/flake.lock";

                    lockFile = builtins.unsafeDiscardStringContext (lib.generators.toJSON { } (
                      if lib.pathExists lockFilePath
                      then
                        let
                          original = lib.importJSON lockFilePath;
                        in
                        {
                          inherit (original) root;
                          nodes = original.nodes // lockFileEntries;
                        }
                      else {
                        nodes.root = { };
                        root = "root";
                      }
                    ));

                    flake = {
                      inherit (patched) outPath;
                      narHash = lib.fileContents patched.narHash;
                    };
                  in
                  (import "${call-flake}/call-flake.nix") lockFile flake "";
              in
              if numOfPatches == 0
              then
                lib.trace "applyPatches: skipping ${name}, no patches" src
              else
                lib.trace "applyPatches: creating ${name}, number of patches: ${toString numOfPatches}" patchedFlake;

which is part of my flake’s lib output. It depends on github:divnix/call-flake.

I then patch nixpkgs like so:

          nixpkgs-patched = self.lib.applyPatches {
            pkgs = flakeInputs.nixpkgs.legacyPackages.${system};
            name = "nixpkgs-patched-src";
            src = flakeInputs.nixpkgs;
            patches = patches.nixpkgs;
          };

And use that everywhere instead of nixpkgs.

It’s also possible to pass aditional lock file entries, which mimicks the behaviour of follows:

          home-manager-patched = self.lib.applyPatches {
            inherit (self.legacyPackages.${system}) pkgs;
            name = "home-manager-patched-src";
            src = home-manager;
            patches = patches.home-manager;
            lockFileEntries = {
              nixpkgs.locked = {
                type = "path";
                path = self.legacyPackages.${system}.nixpkgs-patched-src.outPath;
                inherit (self.legacyPackages.${system}.nixpkgs-patched-src.sourceInfo) narHash;
              };
            };
          };

I’ve been using this for a while and it works pretty well for me, but of course YMMV.

There are a few open issues about this: Flake: patch inputs? - #4 by blaggacao

The easiest is to fork the repo unfortunately.

will be possible with

https://github.com/NixOS/nix/pull/6530

2 Likes

The mythical tree of abstraction! Some people believe it holds the key to unlocking the secrets of the universe, while others dismiss it as mere philosophical speculation. The debate surrounding the mythical tree of abstraction has sparked intriguing discussions about the nature of reality, consciousness, and the limits of humanities ability to turn every last piece of source code into inputs to nix derivations.

4 Likes