git-hooks.nix
git-hooks.nix copied to clipboard
How to override tools that are wrapped in an intermediary Shell script?
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 callPackaged, 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-dirtool, 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-dirtool. -
While I'm at it, it's only a few more lines to specify my own
hpackhook, and it would probably just be a copy-paste of this repository's including thehpack-dirtool. This would have the same downsides as the options above. -
If my
hpacktool happens to come fromnixpkgs, makingpre-commit-hooks'snixpkgsinput follow mine would work. But only in that scenario, which is very restrictive and won't work if I'm gettinghpackfrom 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 callPackaged 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-dirdoes not even show up in the tools because it is not actually a tool.hpackappears there instead. The hook, however, introduceshpack-dirtemporarily 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
callPackagecalls 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.
See #196 how this would work once we redesign the api.
Now documented in https://github.com/cachix/pre-commit-hooks.nix?tab=readme-ov-file#nix
Amazing; thank you!