Patching dependencies in go modules

I’m trying to package yubikey-agent. It depends on a go module gopass, which in turn calls pinentry from the PATH. I’d like to patch it to call a named pinentry package directly, and allow overriding the package with a choice of pinentry program. However, if I do this, patching the pinentry program will change the vendorSha256 value in an unpredictable way which makes it quite difficult for the caller to actually have a free choice of pinentry programs.

Here is my package:

{ stdenv, lib, fetchgit, buildGoModule, pcsclite, pinentry }:

buildGoModule rec {
  pname = "yubikey-agent";
  version = "0.1.3";

  src = fetchgit {
    url = "https://filippo.io/yubikey-agent";
    rev = "v${version}";
    sha256 = "07gix5wrakn4z846zhvl66lzwx58djrfnn6m8v7vc69l9jr3kihr";
  };

  buildInputs = if stdenv.isDarwin then null else [ (lib.getDev pcsclite) ];

  # patch go-piv to read PCSC headers from the right place
  # patch gopass to call pinentry directly rather than searching PATH
  overrideModAttrs = (_: if stdenv.isDarwin then {} else {
      postBuild = ''
      substituteInPlace vendor/github.com/go-piv/piv-go/piv/pcsc_unix.go \
        --replace '-I/usr/include/PCSC' '-I${lib.getDev pcsclite}/include/PCSC'
      substituteInPlace vendor/github.com/gopasspw/gopass/pkg/pinentry/pinentry_others.go \
        --replace 'return "pinentry"' 'return "${pinentry}/bin/pinentry"'
      '';
    });

  vendorSha256 = "1iamvp00l2fisb9mc3bwgs2jh8r5rw3sci88kvxrh1gcxpzizfp3";
  subPackages = [ "." ];

  meta = with lib; {
    description = "A seamless ssh-agent for YubiKeys";
    license = licenses.bsd3;
    homepage = "https://github.com/FiloSottile/yubikey-agent";
    maintainers = with lib.maintainers; [ philandstuff ];
    platforms = platforms.unix;
  };
}

This works fine as-is, but if I try to inject a different pinentry (for example, callPackage ../tools/security/yubikey-agent { pinentry = pinentry-gnome; }), it won’t work because the vendorSha256 value is only valid for the original pinentry program. (Actually, in this example, the vendorSha256 is for pinentry-gtk2; that only illustrates the point).

Is there another approach that might fit better here? If I patch gopass as part of the go-modules derivation, I have this vendorSha256 problem; if I try to patch it as part of the main derivation, I can’t, because the vendored go modules are in another package and so read-only.

2 Likes