Skip to content

How to override tools that are wrapped in an intermediary Shell script? #255

Closed
@Niols

Description

@Niols

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-dir tool, but that would basically be a copy-paste of this repository's, except relying on my version of hpack. This would be rather verbose and could fall out of sync with this repository if fixes/improvements are brought to the hpack-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 the hpack-dir tool. This would have the same downsides as the options above.

  • If my hpack tool happens to come from nixpkgs, making pre-commit-hooks's nixpkgs input follow mine would work. But only in that scenario, which is very restrictive and won't work if I'm getting hpack 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 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:

  1. hpack-dir does not even show up in the tools because it is not actually a tool. hpack appears there instead. The hook, however, introduces hpack-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;
    }
  2. The set of tools is somehow recursive and the callPackage calls rely on this set of tools before going to look things up in nixpkgs, 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions