Is it possible to patch package.nix from github PR in override/overlay?

I wanted to test a fix for usb-modeswitch issue from this PR. I create an override (I know, I know, overlay is da wai):

{ pkgs, ... }:
let
  patched-usb-modeswitch = pkgs.usb-modeswitch.overrideAttrs (oldAttrs: {
    patches = (oldAttrs.patches or [ ]) ++ [
      (pkgs.fetchpatch {
        url = "https://patch-diff.githubusercontent.com/raw/NixOS/nixpkgs/pull/481179.patch";
        hash = "sha256-MvVBGcuLnD9fApjijsx1ljDnyV2/BJzI+bRZzFEDolI=";
      })
    ];
  });
in
{
  networking.modemmanager.enable = true;
  hardware.usb-modeswitch.enable = true;

  services.udev.packages = with pkgs; [
    usb-modeswitch-data
  ];

  environment.systemPackages = with pkgs; [
    modemmanager
    patched-usb-modeswitch
  ];
}

The patch fails since it can’t find package.nix (since the patch applies to package itself not only to packaged application/service). Is it possible to somehow dirty-patch a package like that? I know I could clone whole nixpkgs, add it as an input or some devshell, but this is a ton of annoying work and I want a flow that will let me check things the quick and dirty way :wink:

I mean, tbh, adding it as a separate input is much simpler. Depending on your intentions re disk space/stability it’s arguably also the dirty way. You’re kinda doing the slow & clean thing right now.

The reaaally quick and dirty would be this:

{ pkgs, ... }:
let
  pkgs-pr = import (pkgs.fetchFromGitHub {
    owner = "yzhou216";
    repo = "nixpkgs";
    rev = "e5dd8d7ee483824bcbaee5f9b3f3ee24c2a5519f";
    hash = "";
  }) { };
  patched-usb-modeswitch = pkgs-pr.usb-modeswitch;
in
{
  networking.modemmanager.enable = true;
  hardware.usb-modeswitch.enable = true;

  services.udev.packages = [
    pkgs.usb-modeswitch-data
  ];

  environment.systemPackages = [
    pkgs.modemmanager
    patched-usb-modeswitch
  ];
}

I got rid of the with since the scoping gets confusing otherwise.

Ideally you’d tie it to your flake inputs or channels or npins, but if you never want to update this is fine.

Overlays are a hammer and when given such you might come to believe everything’s a nail. They’re useful for specific things. They shouldn’t be your first answer to everything.

If you want to override every instance of a package recursively, including any references that may exist to it as a dependency in other packages or random modules, yeah, that’s what you want.

A lot of the time all you want is to add a package to environment.systemPackages or swap out a .package option though; overlays don’t make anywhere near as much sense there and are either pointlessly indirect or even overreach, making you break other packages accidentally.

Don’t think of overlays as a cure-all, always appropriate, let alone “better” solution.

1 Like

Thanks! This is awesome!

In case anyone else has similar problem - here is the full solution. I had to pass { system = pkgs.system; } to pkgs-pr block and instead of using hardware.usb-modeswitch.enable to set things up I had to do this manually since the config option relies on original package:

{ pkgs, ... }:
let
  pkgs-pr = import (pkgs.fetchFromGitHub {
    owner = "yzhou216";
    repo = "nixpkgs";
    rev = "e5dd8d7ee483824bcbaee5f9b3f3ee24c2a5519f";
    hash = "sha256-JYoKMUqI//YgNxUrFlUV0qaGnWa3MuTva95WE1LGBig=";
  }) { system = pkgs.system; };
  patched-usb-modeswitch = pkgs-pr.usb-modeswitch;
  patched-usb-modeswitch-data = pkgs-pr.usb-modeswitch-data;
in
{
  networking.modemmanager.enable = true;
  # hardware.usb-modeswitch.enable = true;
  systemd.packages = [ patched-usb-modeswitch ];

  services.udev.packages = [
    patched-usb-modeswitch-data
  ];

  environment.systemPackages = with pkgs; [
    modemmanager
    # patched-usb-modeswitch
  ];
}
1 Like