Description
Say I am using the hpack
hook and I want it to use my version of hpack
and not the default one. I will do something such as:
tools = {
hpack = myHpack;
};
which will change nothing at all.
This is because the tool behind the hpack
hook is actually called hpack-dir
; it's a Shell script defined in a Nix file somewhere in this repository that is then callPackage
d, which will pick up nixpkgs
's version of hpack
and not the one I specified. This analysis requires inside knowledge, though, and the behaviour would feel rather suprising to random users. Moreover, even with the inside knowledge, I'm a bit stuck and I don't have many options:
-
I could specify my own
hpack-dir
tool, but that would basically be a copy-paste of this repository's, except relying on my version ofhpack
. This would be rather verbose and could fall out of sync with this repository if fixes/improvements are brought to thehpack-dir
tool. -
While I'm at it, it's only a few more lines to specify my own
hpack
hook, and it would probably just be a copy-paste of this repository's including thehpack-dir
tool. This would have the same downsides as the options above. -
If my
hpack
tool happens to come fromnixpkgs
, makingpre-commit-hooks
'snixpkgs
input follow mine would work. But only in that scenario, which is very restrictive and won't work if I'm gettinghpack
from ad-hoc Haskell configurations.
Other ideas would involve building my overlay of nixpkgs
with my hpack
and then trying to call the /nix/default.nix
file of this repository with it, but that's hardly possible. I could also try to callPackage
the /nix/hpack-dir/default.nix
file of this repository; again hardly possible. I could try to access the tools and re-callPackage
the callPackage
d version of hpack-dir
, but I'm not sure how that'd work since the tools are not really exposed in the flake.
Am I missing something? Is there a good way for me to just override the hpack
tool and have my hpack
hook rely on it, without having to even know about this hpack-dir
business?
Note that the question applies to all the other hooks that introduce an intermediary tool. When the hook is exactly the name of a tool that exists, but there is a differently-named intermediary tool, then it becomes extra disturbing, which is the case for hpack
but also at least for cabal2nix
and terraform
.
In general, in this example, I don't think hpack-dir
is a tool. I rather think it is an artifact that is sadly necessary to interface the actual tool, hpack
, and pre-commit-hooks.nix
. I would maybe expect one of the two to be true:
-
hpack-dir
does not even show up in the tools because it is not actually a tool.hpack
appears there instead. The hook, however, introduceshpack-dir
temporarily because it needs it, for instance with something like:{ name = "hpack"; description = "..."; entry = let hpack-dir = pkgs.writeShellApplication { name = "hpack-dir"; text = '' ...the Shell script here... ''; }; in "${hpack-dir}/bin/hpack-dir"; files = "(\\.l?hs(-boot)?$)|(\\.cabal$)|((^|/)package\\.yaml$)"; pass_filenames = false; }
-
The set of tools is somehow recursive and the
callPackage
calls rely on this set of tools before going to look things up innixpkgs
, causing a change of one tool, even from the outside, to update all the tools or intermediary Shell scripts that rely on the first one to change accordingly.
The first approach is the one that I take spontaneously when writing a hook because at least everything is in the same place, and the Shell scripts are usually very short anyways. In this repository, this is the approach taken by the hooks rustfmt
, clippy
, revive
and staticcheck
at least, so it wouldn't be unprecedented. I would happily open a PR integrating this change if that was something you'd find interesting, relevant, and if you'd think that'd be the right way to change things. I can also accept that life is life and work around it in the ways described at the beginning of this issue.