Skip to content

Commit 6c08a5c

Browse files
committed
Make installation opt-out
... with a possiblity to opt back in on a per project basis by running the script.
1 parent abd9d26 commit 6c08a5c

File tree

2 files changed

+66
-6
lines changed

2 files changed

+66
-6
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@ https://devenv.sh/pre-commit-hooks/
7272
references the binaries, for speed and safe garbage collection
7373
- provide the `pre-commit` executable that `git commit` will invoke
7474

75+
## Opting out, opting in
76+
77+
Users can enforce their own preference by setting `NIX_PRE_COMMIT_HOOKS_INSTALL` to `0` or `1` in their environment, e.g. in `.profile` or in [`home.sessionVariables`](https://nix-community.github.io/home-manager/options.html#opt-home.sessionVariables) for home-manager users.
78+
79+
Furthermore, project maintainers can set a default preference via the `installByDefault` option.
80+
81+
Finally, regardless of these settings, you may install the hooks manually by running `nix-pre-commit-hooks-install` in your shell. This does what it says, and the shell hook will detect that the hooks exist and keep them up to date.
82+
83+
7584
## Optional
7685

7786
### Direnv

modules/pre-commit.nix

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,29 @@ in
291291
readOnly = true;
292292
};
293293

294+
installByDefault =
295+
mkOption {
296+
type = types.bool;
297+
default = true;
298+
description = lib.mdDoc ''
299+
Whether to install the hooks _by default_.
300+
301+
By priority, the behavior of `installationScript` (ie `nix develop`)
302+
is controlled by the user's `NIX_PRE_COMMIT_HOOKS_INSTALL` environment
303+
variable. The purpose of this variable is that users can globally override
304+
the use of `pre-commit` for all their projects.
305+
306+
Regardless of any settings, you can still install the hooks by running:
307+
308+
```bash
309+
nix-pre-commit-hooks-install
310+
```
311+
312+
After running that, the pre-commit hooks scripts and config file will be
313+
updated by `installationScript` (ie `nix develop`) as usual.
314+
'';
315+
};
316+
294317
src =
295318
lib.mkOption {
296319
description = lib.mdDoc ''
@@ -375,6 +398,8 @@ in
375398
installationScript = ''
376399
export PATH=${cfg.package}/bin:$PATH
377400
401+
export NIX_PRE_COMMIT_HOOKS_INSTALL="''${NIX_PRE_COMMIT_HOOKS_INSTALL:-${if cfg.installByDefault then "1" else "0"}}"
402+
378403
nix-pre-commit-hooks-update() {
379404
local git_dir
380405
if ! type -t git >/dev/null; then
@@ -389,7 +414,7 @@ in
389414
390415
if readlink .pre-commit-config.yaml >/dev/null \
391416
&& [[ $(readlink .pre-commit-config.yaml) == ${configFile} ]]; then
392-
echo 1>&2 "pre-commit-hooks.nix: hooks up to date"
417+
echo 1>&2 "pre-commit-hooks.nix: hooks config is up to date"
393418
else
394419
echo 1>&2 "pre-commit-hooks.nix: updating $PWD repo"
395420
@@ -405,9 +430,17 @@ in
405430
ln -s ${configFile} .pre-commit-config.yaml
406431
# Remove any previously installed hooks (since pre-commit itself has no convergent design)
407432
hooks="pre-commit pre-merge-commit pre-push prepare-commit-msg commit-msg post-checkout post-commit"
408-
for hook in $hooks; do
409-
pre-commit uninstall -t $hook
410-
done
433+
434+
# ... but if the user has opted out of automatic installation,
435+
# don't uninstall, because in that case already-installed hooks
436+
# represent a deliberate choice, and we don't want to keep them
437+
# and maintain them.
438+
if [[ "$NIX_PRE_COMMIT_HOOKS_INSTALL" == 1 ]]; then
439+
for hook in $hooks; do
440+
pre-commit uninstall -t $hook
441+
done
442+
fi
443+
411444
# Add hooks for configured stages (only) ...
412445
if [ ! -z "${concatStringsSep " " install_stages}" ]; then
413446
for stage in ${concatStringsSep " " install_stages}; do
@@ -426,17 +459,35 @@ in
426459
exit 1
427460
;;
428461
esac
429-
pre-commit install -t $stage
462+
# If the user environment doesn't want hooks, don't install them
463+
# If the hook already exists, update the embedded pre-commit package version,
464+
# because they may have opted in by running `nix-pre-commit-hooks-install`
465+
if [[ "$NIX_PRE_COMMIT_HOOKS_INSTALL" == 1 ]] || \
466+
[[ -e "$gitdir/hooks/$stage" ]]; then
467+
pre-commit install -t $stage
468+
fi
430469
done
431470
# ... or default 'pre-commit' hook
432471
else
433-
pre-commit install
472+
if [[ "$NIX_PRE_COMMIT_HOOKS_INSTALL" == 1 ]] || \
473+
[[ -e "$gitdir/hooks/pre-commit" ]]; then
474+
pre-commit install
475+
else
476+
echo 1>&2 "pre-commit-hooks.nix: skipping installation of pre-commit hook scripts. Run 'nix-pre-commit-hooks-install' to install them."
477+
fi
434478
fi
435479
fi
436480
fi
437481
fi
438482
}
439483
484+
nix-pre-commit-hooks-install() {
485+
# Make sure installation will run
486+
[ -L .pre-commit-config.yaml ] && unlink .pre-commit-config.yaml
487+
488+
NIX_PRE_COMMIT_HOOKS_INSTALL=1 nix-pre-commit-hooks-update
489+
}
490+
440491
nix-pre-commit-hooks-update
441492
'';
442493
};

0 commit comments

Comments
 (0)