diff --git a/pre_commit/commands/install_uninstall.py b/pre_commit/commands/install_uninstall.py index f40b92b4..727118c2 100644 --- a/pre_commit/commands/install_uninstall.py +++ b/pre_commit/commands/install_uninstall.py @@ -146,7 +146,8 @@ def install( if not follow_hooks_path: logger.error( 'Cowardly refusing to install hooks with `core.hooksPath` set.' - '\nhint: `git config --unset-all core.hooksPath`', + '\nhint: `git config --unset-all core.hooksPath`, ' + 'or use the `--follow-custom-hooks-path` flag', ) return 1 diff --git a/pre_commit/main.py b/pre_commit/main.py index 4b075375..86f6c58d 100644 --- a/pre_commit/main.py +++ b/pre_commit/main.py @@ -271,7 +271,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int: '--follow-custom-hooks-path', action='store_true', default=False, help=( 'Whether to follow a custom core.hooksPath when attempting ' - 'to install the pre-comit hook.' + 'to install the pre-commit hook.' ), ) diff --git a/tests/commands/install_uninstall_test.py b/tests/commands/install_uninstall_test.py index 314b8b96..6605d3b3 100644 --- a/tests/commands/install_uninstall_test.py +++ b/tests/commands/install_uninstall_test.py @@ -110,6 +110,43 @@ def test_install_refuses_core_hookspath(in_git_dir, store): assert install(C.CONFIG_FILE, store, hook_types=['pre-commit']) +def test_install_custom_core_hookspath(in_git_dir, store): + cmd_output('git', 'config', '--local', 'core.hooksPath', 'hooks') + assert not install( + C.CONFIG_FILE, + store, + hook_types=['pre-commit'], + follow_hooks_path=True, + ) + + _, core_hookspath = git.has_core_hookpaths_set() + pre_commit = in_git_dir.join(os.path.join(core_hookspath, 'pre-commit')) + assert pre_commit.exists() and is_our_script(pre_commit) + + +def test_install_custom_core_hookspaths_with_existing_hook(in_git_dir, store): + cmd_output('git', 'config', '--local', 'core.hooksPath', 'hooks') + _, core_hookspath = git.has_core_hookpaths_set() + custom_hooks_path = in_git_dir.join(core_hookspath) + os.makedirs(custom_hooks_path, exist_ok=True) + + pre_defined_hook = os.path.join(custom_hooks_path, 'pre-commit') + with open(pre_defined_hook, 'w') as f: + f.write('#!/usr/bin/env bash\necho 1\n') + + assert not install( + C.CONFIG_FILE, + store, + hook_types=['pre-commit'], + follow_hooks_path=True, + ) + pre_defined_hook, \ + pre_commit = pre_defined_hook + '.legacy', pre_defined_hook + + assert os.path.exists(pre_commit) and is_our_script(pre_commit) \ + and os.path.exists(pre_defined_hook) + + def test_install_hooks_dead_symlink(in_git_dir, store): hook = in_git_dir.join('.git/hooks').ensure_dir().join('pre-commit') os.symlink('/fake/baz', hook.strpath)