I just discovered makeSetupHook
and an interesting use for it in shell.nix files.
In a few projects, I had shell.nix files that used shellHook
to run helper scripts I’d tucked away in a ./nix
subdirectory.
For example, in a few cases I wanted to spin up a database upon entering the shell and spin it down upon exiting:
{ pkgs ? import <nixpkgs> {} }:
with pkgs; mkShell {
name = "foo";
buildInputs = [ postgresql ];
shellHook = ''
trap "'$PWD/nix/pgSetup' remove" EXIT
nix/pgSetup
'';
}
One problem with this approach is it relies on the presence of these random shell scripts that are not represented as part of the derivation itself. Another problem is that I end up duplicating these scripts across projects.
I was going to address this by packing the helper scripts with writeShellScript
, but then I noticed makeSetupHook
. It sounds like it was designed with a different use-case in mind, but it lets me package the setup script and automatically runs it upon entering the shell as long as I include it in my buildInputs
:
{ pkgs ? import <nixpkgs> {} }:
let
pgSetup = with pkgs; makeSetupHook { } ./nix/pgSetup;
in with pkgs; mkShell {
name = "foo";
buildInputs = [ postgresql pgSetup ];
shellHook = ''
trap '${pgSetup}/nix-support/setup-hook remove' EXIT
'';
}
So ./nix/pgSetup
needs to exist relative to the derivation, but it doesn’t need to exist relative to nix-shell invocation, allowing, for example, using it like:
nix-shell https://github.com/path/to/nix-shells/archive/master.tar.gz -A foo
I might actually switch to using writeShellScript
, as it offers more flexibility and control, but I thought this was interesting.