Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support flake references to patches #3920

Open
worldofpeace opened this issue Aug 11, 2020 · 44 comments · May be fixed by #6530
Open

Support flake references to patches #3920

worldofpeace opened this issue Aug 11, 2020 · 44 comments · May be fixed by #6530
Labels
feature Feature request or proposal flakes UX The way in which users interact with Nix. Higher level than UI.

Comments

@worldofpeace
Copy link
Contributor

Describe the bug

There is a patch in nixpkgs NixOS/nixpkgs#59990 "Support patching nixpkgs" which is meant to support users who track a specific branch of nixpkgs (like nixpkgs-unstable or some release branch) but you would like to apply some unmerged pull requests or some other patches to that revision. This is really common flow for linux users in general. What people currently do is fork nixpkgs, create a branch based on your desired upstream branch and cherry-pick the commits you need on top of that branch. Then everytime you need to upgrade nixpkgs you rebase your branch on the latest upstream branch that you're tracking. IMHO a kinda consuming process if you just want a few patches.

Overall, this patch was a 👎 from @edolstra who commented the following as the most early retort:

I'm -1 on this. It seems very ad hoc and hacky to make Nixpkgs rewrite its own source tree. That's the job of the version management tool (e.g. Git), which can do a much better job of managing sources and patches.

Maybe flakes could provide this functionality (e.g. by having a flake reference like github:NixOS/nixpkgs?patch=./foo.patch) but I'm convinced it's a good idea.

This idea with flakes piqued my interest as possible, though.

@edolstra did eventually see the usefulness of such a functionality after the following comments NixOS/nixpkgs#59990 (comment) NixOS/nixpkgs#59990 (comment)

I've opened this issue, as I'm not entirely sure how this should look like with flakes, but it is certainly something I'd like to have and would be an instant user of (and judging from the thumbs up on the PR in nixpkgs it would be welcome to many others).

Pinging people from NixOS/nixpkgs#59990
@basvandijk @volth @edolstra

@worldofpeace
Copy link
Contributor Author

I seemed to have used the wrong template for a feature request 😬

@zimbatm zimbatm added feature Feature request or proposal flakes and removed bug labels Aug 11, 2020
@Ma27
Copy link
Member

Ma27 commented Aug 12, 2020

@edolstra already suggested to add a patches-argument to fetchTarball[1]. As this is basically part of the new fetchTree-API, it could look like this with flakes:

{
  inputs.nixpkgs = {
    url = github:NixOS/nixpkgs/nixos-20.03;
    patches = [
      ./foo.patch
      ./bar.patch
    ];
  };
}

Not sure (yet) how this can use fetchpatch then as this is part of nixpkgs.

[1] NixOS/nixpkgs#59990 (comment)

@bqv
Copy link
Contributor

bqv commented Aug 12, 2020

I'm not sure I'm a fan of this idea. It's simple enough to do that patching outside the context of flake setup, not to mention nixpkgs itself supports disabledModules etc. anyway. I think this would overcomplicate the mechanics of flakes

@Ma27
Copy link
Member

Ma27 commented Aug 12, 2020

It's simple enough to do that patching outside the context of flake setup

I'm currently doing this for my personal machines and my infra and I don't really think it is.

Also, when people ask me how I deal with my patches (that aren't on NixOS master/stable) I explain my approach (with those tracking branches) to them and we usually agree pretty fast that this is not really suitable for someone who's new to NixOS or not a poweruser (which I think I am). So we should either add a feature as suggested above or document those approaches pretty well.

Additionally, I'd like to quote @worldofpeace's original comment here:

@edolstra did eventually see the usefulness of such a functionality after the following comments NixOS/nixpkgs#59990 (comment) NixOS/nixpkgs#59990 (comment)

not to mention nixpkgs itself supports disabledModules etc. anyway

I don't like this kind of monkey-patching approach (and I think I've heard similar opinions from a few more NixOS users) for the following reasons:

  • When I have e.g. a small bugfix that is in a pending PR (or not backported yet), I don't want to maintain a full copy of a module, a small patch applied on top would be way easier.
  • You rely on implementation details like the file-structure of nixpkgs/nixos.
  • Modules tend to go through many changes during e.g. a release-cycle. If you only want to use a specific feature on your stable NixOS from the master-version of a module, it's IMHO way easier to use the patch rather than disabledModules. This will eventually lead to even more patching of the module-system since modules can affect each other and you'll probably have to "replace" even more modules.

I think this would overcomplicate the mechanics of flakes

This is not necessarily related to flakes. I suggested to simply pass this argument to the underlying code which uses the libfetchers-API that is also used for builtins.fetchTree/builtins.fetchTarball/etc and it was already suggested to add a patches-functionality to those primops, so this is something that can be implemented on the libfetchers-level (in Nix's source) and thus also used for flake-inputs.

@ju1m
Copy link

ju1m commented Aug 27, 2020

If that may help, here's the workaround I'm currently using to cherry-pick patches against Nixpkgs (not sure at all that everything is correct wrt. using flakes, but at least it's not breaking obviously to me):

{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/a332da8588aeea4feb9359d23f58d95520899e3c";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = flakes: let
  remoteNixpkgsPatches = [
    { meta.description = "sanoid: fix sanoid.conf generation";
      url = "https://github.com/NixOS/nixpkgs/pull/83904.diff";
      sha256 = "Sy9wPmL+Lfl7hMEeXYOEMk3KlfdL21aL92v6MiGajds=";
    }
    { meta.description = "nixos/public-inbox: init";
      url = "https://github.com/NixOS/nixpkgs/pull/77450.diff";
      sha256 = "13ikg7chpbf6rrg5sngbdb95q3awhdgl4g8vci42xmqyf208hzzd";
    }
    { meta.description = "apparmor: fix and improve the service";
      url = "https://github.com/NixOS/nixpkgs/pull/93457.diff";
      sha256 = "8QNOKDWNJiZujAvmDtZPZI5VRc+oh40IqjTYn/RCUi4=";
    }
    { meta.description = "nixos/security.gnupg: provisioning GnuPG-protected secrets through the Nix store";
      url = "https://github.com/NixOS/nixpkgs/pull/93659.diff";
      sha256 = "8prVG0VYXsTPwnGyAv7FlMh2M5MENX1NxkX/ql1lmHs=";
    }
  ];
  localNixpkgsPatches = [
    #nixpkgs/patches/fix-ld-nix.diff
    #nixpkgs/patches/fix-ld-nix-apparmor.diff
  ];
  originPkgs = flakes.nixpkgs.legacyPackages."x86_64-linux";
  nixpkgs = originPkgs.applyPatches {
    name = "nixpkgs-patched";
    src = flakes.nixpkgs;
    patches = map originPkgs.fetchpatch remoteNixpkgsPatches ++ localNixpkgsPatches;
    postPatch = ''
      patch=$(printf '%s\n' ${builtins.concatStringsSep " "
         (map (p: p.sha256) remoteNixpkgsPatches ++ localNixpkgsPatches)} |
        sort | sha256sum | cut -c -7)
      echo "+patch-$patch" >.version-suffix
    '';
  };
  lib = originPkgs.lib;
  machines = builtins.mapAttrs (machineName: machineConfig:
    let cfg = import machineConfig { inherit flakes; }; in
    import (nixpkgs + "/nixos/lib/eval-config.nix") (cfg // {
      extraArgs = {
        inherit machineName flakes;
        machines = flakes.self.nixosConfigurations;
      } // (cfg.extraArgs or {});
      modules = cfg.modules ++ [({pkgs, ...}: {
        system.nixos.versionSuffix = ".${
          lib.substring 0 8 (flakes.self.lastModifiedDate or flakes.self.lastModified)}.${
          flakes.self.shortRev or "dirty"}";
        system.nixos.revision = lib.mkIf (flakes.self ? rev) flakes.self.rev;
        nix.registry.nixpkgs.flake = nixpkgs;
        nix.package = pkgs.nixFlakes;
        nix.extraOptions = "experimental-features = nix-command flakes";
        nixpkgs.config = {};
        nixpkgs.overlays = import nixpkgs/overlays.nix;
        # Let 'nixos-version --json' know about the Git revision of this flake.
        system.configurationRevision = lib.mkIf (flakes.self ? rev) flakes.self.rev;
      })];
    }));
  in
  {
    nixosConfigurations = machines {
      losurdo = machines/losurdo.nix;
      mermet  = machines/mermet.nix;
    };
  }
  // flakes.flake-utils.lib.eachDefaultSystem (system:
    #let pkgs = flakes.nixpkgs.legacyPackages.${system}; in
    let
      pkgs = import nixpkgs {
        inherit system;
        config = {};
        overlays = import nixpkgs/overlays.nix;
      };
    in {
    devShell = import ./shell.nix { inherit flakes pkgs; };
    }
  );
}

If possible, I would prefer to have a more builtin way, like the proposed patches= attribute to inputs: it would feel less hacky and could maybe avoid to slow down builds by having to load originPkgs to get a NixOS configuration or pkgs in devShell.

@bqv
Copy link
Contributor

bqv commented Sep 27, 2020

After several frustrating experiences with nixpkgs PRs, I've come around to this idea. I remove my apprehension

@worldofpeace
Copy link
Contributor Author

After several frustrating experiences with nixpkgs PRs, I've come around to this idea. I remove my apprehension

That's great to hear 👍

@bqv
Copy link
Contributor

bqv commented Oct 15, 2020

It seems sensible to me that the patches themselves would also be flake references, to support being urls that can be updated like any other input, rather than having to manually download and keep the files up to date

Edit: nevermind, it seems flake references can't be files... (?)

@blaggacao
Copy link
Contributor

blaggacao commented Jan 7, 2021

While this proposal is not immediately clear to me, I strongly endorse the following:

(for sake of conciseness I opened another issue with my user story)

{
  inputs.foo.patches = [ # in order merged
     "abgc6h" # same remote
     "ref/pr/123" # same remote pull request
    { # long form (just like normal inputs)
       type = "github";
       org = "foo";
       repo = "bar";
       rev = "abgckh";
    }
  ];
}

@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/flake-patch-inputs/10854/4

@FRidh
Copy link
Member

FRidh commented Jan 7, 2021

I wonder then whether we need a new primop for applying a patch (a content-addressable path) to a content-addressable path producing a new content-addressable path. That could be used with non-flake code as well.

@blaggacao
Copy link
Contributor

blaggacao commented Jan 7, 2021

If "primop" means avoid bin/patch and possibly (in the far [nickel-]future) support semantic merges (so that potential merge conflicts for nickel-type source artifacts are reduced), then this represents an enticing through to me.

@FRidh
Copy link
Member

FRidh commented Jan 7, 2021

It would mean there is a Nix builtin you call to apply one or more patches. How this is implemented, I don't know. Maybe it invokes patch impurely just as fetchGit invokes git. The important part is that this way you can apply patches anywhere in Nix code on any content addressable path. If we look at flakes, it would make it possible to not patch an input directly, but to conditionally apply it later on (which means a reimport) because, while you sometimes need a patch, the patch may not always be appropriate under all conditions.

@blaggacao
Copy link
Contributor

blaggacao commented Jan 7, 2021

If we look at flakes, it would make it possible to not patch an input directly, but to conditionally apply it later on (which means a reimport) because, while you sometimes need a patch, the patch may not always be appropriate under all conditions.

(At least remote) patches still ought to be inputs of a flake's encapsulation, so at any rate we need a input semantic for (at least fetching) them.

What would be the practical merits of conditional patch application? That rather seems like violating flake's encapsulation: any given input produces exactly one output and flake commands (afaik) to not provide arguments. Should variants be needed based on some exogenous conditions, those ought to be provided by git references. Their accessor is the fqdn of the flake's derivation itself, and hence the exogenous condition needs to be factored in by the user.

@bqv
Copy link
Contributor

bqv commented Jan 7, 2021

@blaggacao Hence #3785. If patches are also flake inputs, half the battle is won

@eadwu
Copy link
Member

eadwu commented Jan 8, 2021

I do see how it can be useful, but I'm not sure if it's actually needed or if it should be even added since I don't think it'll be useful to anyone who isn't a "power-user".

For the direct use-case of patching nixpkgs here, I'm not too sure about any real advantages other than increased locality for a project configuration. Haphazardly monkey-patching nixpkgs can cause more problems (i.e. in the case where a new person to Nix just pulls random PRs that bump versions on master while using a stable channel and ends up missing dependencies bumps from other PRs and failing builds because of it) than just using the specific branch as a flake input (though we do have to consider API limits if we're pinging GitHub a lot). In the case of modules, the patching flow may be more convenient (to a certain extent) since without it'll probably require some disabledModules and import combinations otherwise. I guess my point is that when someone generally makes a PR, it'll probably (or it at least have a better chance of) work on the tree it's currently on (which probably isn't the commit your nixpkgs input is on) than your own tree (though this has the disadvantage of ballooning the closure size from derivations from different trees).

As for patching source trees (flake = false), I'm not sure if there's any real difference to just doing it in a derivation, though I guess it can be considered to be overkill somewhat if a derivation is created exclusively for patching, doubling the space usage of the input (though I suppose we can probably reduce by symlinks to everything that isn't patched).

@gytis-ivaskevicius
Copy link
Contributor

gytis-ivaskevicius commented Mar 24, 2021

It is possible to patch channels using something like this:

    patchChannel = channel: patches:
      if patches == [ ] then channel else
      (import channel { inherit system; }).pkgs.applyPatches {
        name = "nixpkgs-patched-${channel.shortRev}";
        src = channel;
        patches = patches;
      };

I used this technique for loading a couple of PR's and during development of nixpkgs (this allowed me to easily test changes without updating my channel or anything)

I'd love to see such change implemented properly.

@worldofpeace
Copy link
Contributor Author

Exactly, I feel like it would be a greater joy to use nix if things didn't have to be done soo manually all the time.

@blaggacao
Copy link
Contributor

blaggacao commented Mar 25, 2021

Are we actually +- concludently agreeing on a spec for this already?

The use cases are:
  • generating patches from the tip of remote branches, prominently: pull requests, but also forks (non-power-users)
  • applying individual commits or a splice thereof (power user / tricky requirements)
  • prototype and apply local patches (power-user)
Tentative UX
{
  inputs.nixpkgs = {
    url = github:NixOS/nixpkgs/nixos-20.03;
    patches = [
      ./foo.patch
      ./bar.patch
     "abctgf657" # commit-ish
     "ref/pr/123" # same remote pull request
    { # long form (just like normal inputs)
       type = "github";
       org = "foo";
       repo = "bar";
       rev = "abgckh";
      }
    ];
  };
}

EDIT

There is another one from the sister issue #3785

{
  inputs.nixpkgs = {
    url = github:NixOS/nixpkgs/nixos-20.03;
    patches = [
      "https://url.example.com/some.patch"
      {
        type ="​file​";
        urL ="​https://url.example.com/some.patch​";
        flake = false;
      }
    ];
  };
}

@bqv
Copy link
Contributor

bqv commented Mar 25, 2021

I don't understand how long form would sensibly interact there.

@blaggacao
Copy link
Contributor

blaggacao commented Mar 25, 2021

I don't understand how long form would sensibly interact there.

Currently, you always need an escape hatch:

{ 
   org = "different";
   ref = "​my/branch/with/slashes​";
}

This is not parseable by the short form url.


To be consistent with current URL formatting, implementation might choose to omit the "special purpose" short forms

{
  patches = [
    "​abctgf657​" # cocommit-is
    "​ref/pr/123​" # same remote pull
  ];
}

which could also be fully qualified as

{
  patches = [
    "github:NixOS/nixpkgs/nixos-20.03/abctgf657​"{
        type = "​github​";
        org = "​NixOS​";
        repo = "​nixpkgs​";
        ref = "​ref/pr/123​";
    }
  ];
}

If something resides on the same repo, maybe this can be shortened instead to:

{
  patches = [
    { rev = "​abctgf657​"; }
    { ref = "​ref/pr/123​"; }
  ];
}

That might be overall a saner implementation versus brittely extracting type from the shape of a string.

@blaggacao
Copy link
Contributor

blaggacao commented Mar 26, 2021

An extended / derivated use case: we might want to recommend this as a "blessed" community collaboration model to prototype library additions "as a (draft) PR", cutting out plumbing workflows for potential contributors.

For somebody with dedicated domain knowledge, but insufficient plumbing knowledge, burden the design those workflows onto the contributor has prevented valuable contributions in the past.

@edolstra
Copy link
Member

I implemented patch support for fetchTree, which could be extended to flake inputs (edolstra@ffd2622). Since this is part of the lazy trees branch, it doesn't require writing a complete copy of e.g. nixpkgs to disk just to apply the patch.

@thufschmitt thufschmitt added the UX The way in which users interact with Nix. Higher level than UI. label Feb 24, 2022
edolstra added a commit to edolstra/nix that referenced this issue Feb 24, 2022
You can now write

  fetchTree {
    type = "github";
    owner = "NixOS";
    repo = "nixpkgs";
    rev = "0f316e4d72daed659233817ffe52bf08e081b5de";
    patches = [ ./thunderbird-1.patch ./thunderbird-2.patch ];
  };

to apply a list of patches to a tree. These are applied lazily - the
patched tree is not materialized unless you do something that causes
the entire tree to be copied to the store (like 'src = fetchTree {
... }'). The equivalent of '-p1' is implied.

File additions/deletions/renames are not yet handled.

Issue NixOS#3920.
edolstra added a commit to edolstra/nix that referenced this issue Feb 25, 2022
You can now write

  fetchTree {
    type = "github";
    owner = "NixOS";
    repo = "nixpkgs";
    rev = "0f316e4d72daed659233817ffe52bf08e081b5de";
    patches = [ ./thunderbird-1.patch ./thunderbird-2.patch ];
  };

to apply a list of patches to a tree. These are applied lazily - the
patched tree is not materialized unless you do something that causes
the entire tree to be copied to the store (like 'src = fetchTree {
... }'). The equivalent of '-p1' is implied.

File additions/deletions/renames are not yet handled.

Issue NixOS#3920.
edolstra added a commit to edolstra/nix that referenced this issue Feb 28, 2022
You can now write

  fetchTree {
    type = "github";
    owner = "NixOS";
    repo = "nixpkgs";
    rev = "0f316e4d72daed659233817ffe52bf08e081b5de";
    patches = [ ./thunderbird-1.patch ./thunderbird-2.patch ];
  };

to apply a list of patches to a tree. These are applied lazily - the
patched tree is not materialized unless you do something that causes
the entire tree to be copied to the store (like 'src = fetchTree {
... }'). The equivalent of '-p1' is implied.

File additions/deletions/renames are not yet handled.

Issue NixOS#3920.
@thufschmitt thufschmitt moved this from To discuss to Backlog in Nix UX Mar 3, 2022
edolstra added a commit to edolstra/nix that referenced this issue Mar 4, 2022
You can now write

  fetchTree {
    type = "github";
    owner = "NixOS";
    repo = "nixpkgs";
    rev = "0f316e4d72daed659233817ffe52bf08e081b5de";
    patches = [ ./thunderbird-1.patch ./thunderbird-2.patch ];
  };

to apply a list of patches to a tree. These are applied lazily - the
patched tree is not materialized unless you do something that causes
the entire tree to be copied to the store (like 'src = fetchTree {
... }'). The equivalent of '-p1' is implied.

File additions/deletions/renames are not yet handled.

Issue NixOS#3920.
edolstra added a commit to edolstra/nix that referenced this issue Mar 24, 2022
You can now write

  fetchTree {
    type = "github";
    owner = "NixOS";
    repo = "nixpkgs";
    rev = "0f316e4d72daed659233817ffe52bf08e081b5de";
    patches = [ ./thunderbird-1.patch ./thunderbird-2.patch ];
  };

to apply a list of patches to a tree. These are applied lazily - the
patched tree is not materialized unless you do something that causes
the entire tree to be copied to the store (like 'src = fetchTree {
... }'). The equivalent of '-p1' is implied.

File additions/deletions/renames are not yet handled.

Issue NixOS#3920.
edolstra added a commit to edolstra/nix that referenced this issue Mar 29, 2022
You can now write

  fetchTree {
    type = "github";
    owner = "NixOS";
    repo = "nixpkgs";
    rev = "0f316e4d72daed659233817ffe52bf08e081b5de";
    patches = [ ./thunderbird-1.patch ./thunderbird-2.patch ];
  };

to apply a list of patches to a tree. These are applied lazily - the
patched tree is not materialized unless you do something that causes
the entire tree to be copied to the store (like 'src = fetchTree {
... }'). The equivalent of '-p1' is implied.

File additions/deletions/renames are not yet handled.

Issue NixOS#3920.
@edolstra edolstra linked a pull request May 13, 2022 that will close this issue
9 tasks
@dbaynard
Copy link

It seems using the changed fetchTree will be a great solution, but for now I have written a short workaround. I haven’t seen it elsewhere, possibly because a one line flake evaluator feels a little evil…

I wanted to patch nix-darwin.

  # No `darwin` here as I define it later
  outputs = { self, nixpkgs, ... }@inputs:
    let
      # Store just the contents of my `patches` directory
      patches = builtins.path {
        name = "patches";
        path = ./patches;
      };

      darwin =
        let
          src = nixpkgs.legacyPackages."aarch64-darwin".applyPatches {
            name = "nix-darwin";
            src = inputs.darwin;
            patches = [ "${patches}/fonts.patch" ];
          };
        in
        # The evaluator
        nixpkgs.lib.fix (self: (import "${src}/flake.nix").outputs { inherit self nixpkgs; });
    in# Expressions which use `darwin.lib.darwinSystem`

So that is

  1. import "${src}/flake.nix" to import the flake.nix file from the patched directory, as an expression
  2. _.outputs to extract the outputs.
  3. self: _ { inherit self nixpkgs; } to evaluate outputs in terms of itself, passing nixpkgs from my own flake inputs.
  4. nixpkgs.lib.fix _ to find the fixed point — in this case, an attrset.

The resulting attrset has none of the flake metadata but does have the check. darwinModules and lib attrs, like the source darwin flake. This should be fine? As long as I don’t need any of the flake metadata — I think I don’t.

I suppose this is only viable because the flake.nix is so restricted in terms of its contents (so well done with the design).

@edolstra
Copy link
Member

@dbaynard The downside with that approach is that it requires import-from-derivation (namely import "${src}/..."), which isn't always allowed (e.g. in nix flake check or Hydra).

@yajo
Copy link
Contributor

yajo commented Jul 7, 2022

Would this UX make sense?

{
  inputs = rec {
    patch1 = { url = "https://github.com/nix-community/nixops-vbox/pull/27.patch"; flake=false;};
    patch2 = { url = "https://github.com/nix-community/nixops-vbox/pull/28.patch"; flake=false;};
    nixops-vbox = { url = github:nix-community/nixops-vbox; patches = [patch1 patch2];};
  };
  outputs = { nixops-vbox, ... }: {};
}

Possibly related to #4945 because I'd just use a mix of let and builtins.fetchurl to get those patches otherwise.

@nrdxp
Copy link

nrdxp commented Jul 7, 2022

@yajo, I like the concept of grabbing patches remotely, but perhaps a nicer ux would be to just assume that if a patch starts with "http(s)://" that it's a remote resource and should be fetched. That way, we could just write:

[ "https://url.to/some/patch" ]

The resource could then be locked in the lockfile under the input

@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/proper-way-of-applying-patch-to-system-managed-via-flake/21073/18

@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/how-to-override-let-variables/23741/7

@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/proper-way-of-applying-patch-to-system-managed-via-flake/21073/26

@kjeremy
Copy link
Contributor

kjeremy commented Aug 14, 2023

I just ran into this while trying to test out a PR to nixpkgs master. I guess the alternative is to create my own nixpkgs fork with the PR applied.

@LiGoldragon
Copy link

That's the job of the version management tool (e.g. Git)

In the real world, when someone doesnt do his job right, others have to do it for him.

@Dessix
Copy link

Dessix commented Dec 1, 2023

I guess the alternative is to create my own nixpkgs fork with the PR applied.

Is there any recommended pattern for doing this with multiple unmerged PRs, until this fix exists? Comparing making a single "everything merged" fork-of-forks versus overlaying multiple nixpkgs repos and overriding, both have significant manual overhead.

@ibizaman
Copy link

ibizaman commented Dec 1, 2023

I came across this comment a while ago NixOS/nixpkgs#142273 (comment); if you refine it to just include stuff related to patches, you get the following which I've used in my flake.nix already:

let
  system = "x86_64-linux";
  patches = [
    {
      url = "https://patch-diff.githubusercontent.com/raw/NixOS/nixpkgs/pull/268168.patch";
      hash = "sha256-WIMDnmZV0eL1eFVD0ldHUBrulZWsjdFOmcN4i8+RgFA=";
    }
  ];
  originPkgs = nixpkgs.legacyPackages.${system};
  patchednixpkgs = originPkgs.applyPatches {
    name = "nixpkgs-patched";
    src = nixpkgs;
    patches = map originPkgs.fetchpatch patches;
  };
in
  {
    nixpkgs = import patchednixpkgs { inherit system; };
  };

It's not as nice as it being available at the flake inputs level but the syntax is not too bad. Also, I'm not sure of all the implications of doing this, maybe there are some use cases not supported. But I thought it might be worth mentioning here.

@yajo
Copy link
Contributor

yajo commented Dec 11, 2023

That's an IFD AFAIK. Not nice indeed.

@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/best-pattern-to-include-multiples-patches-prs-to-nixpgs-in-flake-nix/40917/2

@musjj
Copy link

musjj commented Nov 11, 2024

Any progress here? I wanted to patch arbitrary inputs, so the applyPatches hack isn't an option for me.

@nazarewk
Copy link
Member

I made a workaround for keeping my "fork" up to date using https://github.com/katrinafyi/nix-patcher , added notes on it at my README.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Feature request or proposal flakes UX The way in which users interact with Nix. Higher level than UI.
Projects
Status: Backlog
Development

Successfully merging a pull request may close this issue.