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 e47d56ca3..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 @@ -24,7 +24,7 @@ repos: hooks: - id: add-trailing-comma - repo: https://github.com/asottile/pyupgrade - rev: v3.21.1 + rev: v3.21.2 hooks: - id: pyupgrade args: [--py310-plus] @@ -37,7 +37,7 @@ repos: hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.18.2 + rev: v1.20.1 hooks: - id: mypy additional_dependencies: [types-pyyaml] diff --git a/CHANGELOG.md b/CHANGELOG.md index 1434728d0..0620a8ae0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +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 +================== + +### Fixes +- Fix `language: python` with `repo: local` without `additional_dependencies`. + - #3597 PR by @asottile. + 4.5.0 - 2025-11-22 ================== 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/pre_commit/resources/empty_template_setup.py b/pre_commit/resources/empty_template_setup.py index ef05eef84..e8b1ff02c 100644 --- a/pre_commit/resources/empty_template_setup.py +++ b/pre_commit/resources/empty_template_setup.py @@ -1,4 +1,4 @@ from setuptools import setup -setup(name='pre-commit-placeholder-package', version='0.0.0') +setup(name='pre-commit-placeholder-package', version='0.0.0', py_modules=[]) diff --git a/setup.cfg b/setup.cfg index 00c71759a..072fbbb0f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = pre_commit -version = 4.5.0 +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/testing/zipapp/make b/testing/zipapp/make index 165046f66..43bb4373f 100755 --- a/testing/zipapp/make +++ b/testing/zipapp/make @@ -107,9 +107,6 @@ def main() -> int: shebang = '/usr/bin/env python3' zipapp.create_archive(tmpdir, filename, interpreter=shebang) - with open(f'{filename}.sha256sum', 'w') as f: - subprocess.check_call(('sha256sum', filename), stdout=f) - return 0 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/languages/python_test.py b/tests/languages/python_test.py index 565525a40..593634b79 100644 --- a/tests/languages/python_test.py +++ b/tests/languages/python_test.py @@ -10,6 +10,8 @@ from pre_commit.envcontext import envcontext from pre_commit.languages import python from pre_commit.prefix import Prefix +from pre_commit.store import _make_local_repo +from pre_commit.util import cmd_output_b from pre_commit.util import make_executable from pre_commit.util import win_exe from testing.auto_namedtuple import auto_namedtuple @@ -351,3 +353,15 @@ def test_python_hook_weird_setup_cfg(tmp_path): ret = run_language(tmp_path, python, 'socks', [os.devnull]) assert ret == (0, f'[{os.devnull!r}]\nhello hello\n'.encode()) + + +def test_local_repo_with_other_artifacts(tmp_path): + cmd_output_b('git', 'init', tmp_path) + _make_local_repo(str(tmp_path)) + # pretend a rust install also ran here + tmp_path.joinpath('target').mkdir() + + ret, out = run_language(tmp_path, python, 'python --version') + + assert ret == 0 + assert out.startswith(b'Python ') 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', '.'))