From ff5fd2947935f1d25b2a08520691a521ab4315b4 Mon Sep 17 00:00:00 2001 From: Ivan Studinsky Date: Sat, 29 Apr 2023 18:28:03 +0700 Subject: [PATCH] Add ability to skip hooks by branches --- pre_commit/clientlib.py | 2 ++ pre_commit/commands/run.py | 25 ++++++++++++++++++++++++- pre_commit/hook.py | 2 ++ tests/repository_test.py | 2 ++ 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/pre_commit/clientlib.py b/pre_commit/clientlib.py index d0651cae..a76ea10f 100644 --- a/pre_commit/clientlib.py +++ b/pre_commit/clientlib.py @@ -110,6 +110,8 @@ MANIFEST_HOOK_DICT = cfgv.Map( cfgv.Optional('files', check_string_regex, ''), cfgv.Optional('exclude', check_string_regex, '^$'), + cfgv.Optional('branches', check_string_regex, ''), + cfgv.Optional('exclude_branches', check_string_regex, '^$'), cfgv.Optional('types', cfgv.check_array(check_type_tag), ['file']), cfgv.Optional('types_or', cfgv.check_array(check_type_tag), []), cfgv.Optional('exclude_types', cfgv.check_array(check_type_tag), []), diff --git a/pre_commit/commands/run.py b/pre_commit/commands/run.py index c867799e..786ee80a 100644 --- a/pre_commit/commands/run.py +++ b/pre_commit/commands/run.py @@ -26,6 +26,7 @@ from pre_commit.repository import all_hooks from pre_commit.repository import install_hook_envs from pre_commit.staged_files_only import staged_files_only from pre_commit.store import Store +from pre_commit.util import cmd_output from pre_commit.util import cmd_output_b @@ -131,6 +132,28 @@ def _get_skips(environ: MutableMapping[str, str]) -> set[str]: return {skip.strip() for skip in skips.split(',') if skip.strip()} +def _get_branch_name() -> str: + _, name, _ = cmd_output('git', 'branch', '--show-current') + return name + + +def _get_branch_skips(config: dict[str, Any], store: Store) -> set[str]: + current_branch = _get_branch_name() + to_skip = set() + + for hook in all_hooks(config, store): + include_re = re.compile(hook.branches) + exclude_re = re.compile(hook.exclude_branches) + + if ( + not include_re.search(current_branch) or + exclude_re.search(current_branch) + ): + to_skip.add(hook.name) + + return to_skip + + SKIPPED = 'Skipped' NO_FILES = '(no files to check)' @@ -433,7 +456,7 @@ def run( ) return 1 - skips = _get_skips(environ) + skips = _get_skips(environ) | _get_branch_skips(config, store) to_install = [ hook for hook in hooks diff --git a/pre_commit/hook.py b/pre_commit/hook.py index 6d436ca3..4e2831a5 100644 --- a/pre_commit/hook.py +++ b/pre_commit/hook.py @@ -35,6 +35,8 @@ class Hook(NamedTuple): require_serial: bool stages: Sequence[str] verbose: bool + branches: str + exclude_branches: str @property def install_key(self) -> tuple[Prefix, str, str, tuple[str, ...]]: diff --git a/tests/repository_test.py b/tests/repository_test.py index b8dde99b..738ec8a3 100644 --- a/tests/repository_test.py +++ b/tests/repository_test.py @@ -475,6 +475,8 @@ def test_manifest_hooks(tempdir_factory, store): entry='bin/hook.sh', exclude='^$', exclude_types=[], + branches='', + exclude_branches='^$', files='', id='bash_hook', language='script',