Add wildcard matching to no-commit-to-branch hook so that commits can

be blocked on, for example, all release branches with 'release/*'
This commit is contained in:
Marc Jay 2019-04-09 23:53:39 +01:00
parent aa9c202b9b
commit d6847c4827
3 changed files with 19 additions and 4 deletions

View file

@ -79,7 +79,7 @@ Add this to your `.pre-commit-config.yaml`
- `name-tests-test` - Assert that files in tests/ end in `_test.py`. - `name-tests-test` - Assert that files in tests/ end in `_test.py`.
- Use `args: ['--django']` to match `test*.py` instead. - Use `args: ['--django']` to match `test*.py` instead.
- `no-commit-to-branch` - Protect specific branches from direct checkins. - `no-commit-to-branch` - Protect specific branches from direct checkins.
- Use `args: [--branch, staging, --branch, master]` to set the branch. - Use `args: [--branch, staging, --branch, master, --branch, release/*]` to set the branch.
`master` is the default if no argument is set. `master` is the default if no argument is set.
- `-b` / `--branch` may be specified multiple times to protect multiple - `-b` / `--branch` may be specified multiple times to protect multiple
branches. branches.

View file

@ -1,6 +1,7 @@
from __future__ import print_function from __future__ import print_function
import argparse import argparse
import fnmatch
from typing import Optional from typing import Optional
from typing import Sequence from typing import Sequence
from typing import Set from typing import Set
@ -11,11 +12,12 @@ from pre_commit_hooks.util import cmd_output
def is_on_branch(protected): # type: (Set[str]) -> bool def is_on_branch(protected): # type: (Set[str]) -> bool
try: try:
branch = cmd_output('git', 'symbolic-ref', 'HEAD') ref_name = cmd_output('git', 'symbolic-ref', 'HEAD')
except CalledProcessError: except CalledProcessError:
return False return False
chunks = branch.strip().split('/') chunks = ref_name.strip().split('/')
return '/'.join(chunks[2:]) in protected branch_name = '/'.join(chunks[2:])
return any(fnmatch.fnmatch(branch_name, s) for s in protected)
def main(argv=None): # type: (Optional[Sequence[str]]) -> int def main(argv=None): # type: (Optional[Sequence[str]]) -> int

View file

@ -44,6 +44,19 @@ def test_forbid_multiple_branches(temp_git_dir, branch_name):
assert main(('--branch', 'b1', '--branch', 'b2')) assert main(('--branch', 'b1', '--branch', 'b2'))
def test_branch_wildcard_fail(temp_git_dir):
with temp_git_dir.as_cwd():
cmd_output('git', 'checkout', '-b', 'another/branch')
assert is_on_branch({'another/*'}) is True
@pytest.mark.parametrize('branch_name', ('master', 'another/branch'))
def test_branch_wildcard_multiple_branches_fail(temp_git_dir, branch_name):
with temp_git_dir.as_cwd():
cmd_output('git', 'checkout', '-b', branch_name)
assert main(('--branch', 'master', '--branch', 'another/*'))
def test_main_default_call(temp_git_dir): def test_main_default_call(temp_git_dir):
with temp_git_dir.as_cwd(): with temp_git_dir.as_cwd():
cmd_output('git', 'checkout', '-b', 'anotherbranch') cmd_output('git', 'checkout', '-b', 'anotherbranch')