diff --git a/.github/actions/pre-test/action.yml b/.github/actions/pre-test/action.yml index b70c942fe..f5272c847 100644 --- a/.github/actions/pre-test/action.yml +++ b/.github/actions/pre-test/action.yml @@ -6,4 +6,4 @@ runs: using: composite steps: - uses: asottile/workflows/.github/actions/latest-git@v1.4.0 - if: inputs.env == 'py39' && runner.os == 'Linux' + if: inputs.env == 'py310' && runner.os == 'Linux' diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 83ff03f3d..7ea4a444f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,7 +10,7 @@ repos: - id: name-tests-test - id: requirements-txt-fixer - repo: https://github.com/asottile/setup-cfg-fmt - rev: v3.1.0 + rev: v3.2.0 hooks: - id: setup-cfg-fmt - repo: https://github.com/asottile/reorder-python-imports @@ -37,7 +37,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.19.1 + rev: v1.20.1 hooks: - id: mypy additional_dependencies: [types-pyyaml] diff --git a/CHANGELOG.md b/CHANGELOG.md index 879ae0731..0620a8ae0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +4.6.0 - 2026-04-21 +================== + +### Features +- `pre-commit hook-impl`: allow `--hook-dir` to be missing to enable easier + usage with `git` 2.54+ git hooks. + - #3662 PR by @asottile. + +### Fixes +- `pre-commit hook-impl`: `--hook-type` is required. + - #3661 PR by @asottile. + 4.5.1 - 2025-12-16 ================== diff --git a/pre_commit/commands/hook_impl.py b/pre_commit/commands/hook_impl.py index de5c8f346..7b806f3b8 100644 --- a/pre_commit/commands/hook_impl.py +++ b/pre_commit/commands/hook_impl.py @@ -16,7 +16,7 @@ def _run_legacy( hook_type: str, - hook_dir: str, + hook_dir: str | None, args: Sequence[str], ) -> tuple[int, bytes]: if os.environ.get('PRE_COMMIT_RUNNING_LEGACY'): @@ -33,6 +33,9 @@ def _run_legacy( else: stdin = b'' + if hook_dir is None: # git 2.54+ hooks + return 0, stdin + # not running in legacy mode legacy_hook = os.path.join(hook_dir, f'{hook_type}.legacy') if not os.access(legacy_hook, os.X_OK): @@ -259,7 +262,7 @@ def hook_impl( config: str, color: bool, hook_type: str, - hook_dir: str, + hook_dir: str | None, skip_on_missing_config: bool, args: Sequence[str], ) -> int: diff --git a/pre_commit/main.py b/pre_commit/main.py index 0c3eefdaa..d46c0d5b7 100644 --- a/pre_commit/main.py +++ b/pre_commit/main.py @@ -357,7 +357,7 @@ def _add_cmd(name: str, *, help: str) -> argparse.ArgumentParser: hook_impl_parser = subparsers.add_parser('hook-impl') add_color_option(hook_impl_parser) _add_config_option(hook_impl_parser) - hook_impl_parser.add_argument('--hook-type') + hook_impl_parser.add_argument('--hook-type', required=True) hook_impl_parser.add_argument('--hook-dir') hook_impl_parser.add_argument( '--skip-on-missing-config', action='store_true', diff --git a/setup.cfg b/setup.cfg index a95ee4473..072fbbb0f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = pre_commit -version = 4.5.1 +version = 4.6.0 description = A framework for managing and maintaining multi-language pre-commit hooks. long_description = file: README.md long_description_content_type = text/markdown diff --git a/tests/commands/hook_impl_test.py b/tests/commands/hook_impl_test.py index d757e85c0..9aa93af53 100644 --- a/tests/commands/hook_impl_test.py +++ b/tests/commands/hook_impl_test.py @@ -63,6 +63,11 @@ def test_run_legacy_does_not_exist(tmpdir): assert (retv, stdin) == (0, b'') +def test_run_legacy_git_2_54(): + retv, stdin = hook_impl._run_legacy('pre-commit', None, ()) + assert (retv, stdin) == (0, b'') + + def test_run_legacy_executes_legacy_script(tmpdir, capfd): hook = tmpdir.join('pre-commit.legacy') hook.write('#!/usr/bin/env bash\necho hi "$@"\nexit 1\n') diff --git a/tests/main_test.py b/tests/main_test.py index fed085fc8..5194e9ea8 100644 --- a/tests/main_test.py +++ b/tests/main_test.py @@ -90,7 +90,7 @@ def test_adjust_args_try_repo_repo_relative(in_git_dir): FNS = ( - 'autoupdate', 'clean', 'gc', 'hook_impl', 'install', 'install_hooks', + 'autoupdate', 'clean', 'gc', 'install', 'install_hooks', 'migrate_config', 'run', 'sample_config', 'uninstall', 'validate_config', 'validate_manifest', ) @@ -169,6 +169,12 @@ def test_hazmat(mock_store_dir): assert arg.cmd == ['cmd', '--', 'f1', 'f2'] +def test_hook_impl(mock_store_dir): + with mock.patch.object(main, 'hook_impl') as mck: + main.main(('hook-impl', '--hook-type', 'pre-commit')) + assert mck.call_count == 1 + + def test_try_repo(mock_store_dir): with mock.patch.object(main, 'try_repo') as patch: main.main(('try-repo', '.'))