mirror of
https://github.com/pre-commit/pre-commit.git
synced 2026-04-15 01:51:46 +04:00
Merge df8102f57d into 894862462d
This commit is contained in:
commit
75f71745c1
4 changed files with 72 additions and 29 deletions
|
|
@ -8,6 +8,7 @@ import pkg_resources
|
|||
|
||||
from pre_commit import color
|
||||
from pre_commit import five
|
||||
from pre_commit import git
|
||||
from pre_commit.commands.autoupdate import autoupdate
|
||||
from pre_commit.commands.clean import clean
|
||||
from pre_commit.commands.install_uninstall import install
|
||||
|
|
@ -110,7 +111,8 @@ def main(argv=None):
|
|||
help='Run on all the files in the repo. Implies --no-stash.',
|
||||
)
|
||||
run_mutex_group.add_argument(
|
||||
'--files', nargs='*', help='Specific filenames to run hooks on.',
|
||||
'--files', nargs='*', default=[],
|
||||
help='Specific filenames to run hooks on.',
|
||||
)
|
||||
|
||||
help = subparsers.add_parser(
|
||||
|
|
@ -122,6 +124,11 @@ def main(argv=None):
|
|||
if len(argv) == 0:
|
||||
argv = ['run']
|
||||
args = parser.parse_args(argv)
|
||||
if args.command == 'run':
|
||||
args.files = [
|
||||
os.path.relpath(os.path.abspath(filename), git.get_root())
|
||||
for filename in args.files
|
||||
]
|
||||
|
||||
if args.command == 'help':
|
||||
if args.help_cmd:
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class Runner(object):
|
|||
def create(cls):
|
||||
"""Creates a PreCommitRunner by doing the following:
|
||||
- Finds the root of the current git repository
|
||||
- chdirs to that directory
|
||||
- chdir to that directory
|
||||
"""
|
||||
root = git.get_root()
|
||||
os.chdir(root)
|
||||
|
|
|
|||
|
|
@ -110,8 +110,14 @@ def add_config_to_repo(git_path, config):
|
|||
return git_path
|
||||
|
||||
|
||||
def make_consuming_repo(tempdir_factory, repo_source):
|
||||
def make_consuming_repo(tempdir_factory, repo_source, local_hooks=None):
|
||||
path = make_repo(tempdir_factory, repo_source)
|
||||
config = make_config_from_repo(path)
|
||||
if local_hooks:
|
||||
config = OrderedDict((
|
||||
('repo', 'local'),
|
||||
('hooks', local_hooks),
|
||||
))
|
||||
else:
|
||||
config = make_config_from_repo(path)
|
||||
git_path = git_dir(tempdir_factory)
|
||||
return add_config_to_repo(git_path, config)
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ def repo_with_failing_hook(tempdir_factory):
|
|||
yield git_path
|
||||
|
||||
|
||||
def stage_a_file(filename='foo.py'):
|
||||
def stage_a_file(filename):
|
||||
cmd_output('touch', filename)
|
||||
cmd_output('git', 'add', filename)
|
||||
|
||||
|
|
@ -83,14 +83,15 @@ def _do_run(repo, args, environ={}):
|
|||
runner = Runner(repo)
|
||||
write_mock = mock.Mock()
|
||||
write_fn = functools.partial(sys_stdout_write_wrapper, stream=write_mock)
|
||||
ret = run(runner, args, write=write_fn, environ=environ)
|
||||
with cwd(runner.git_root): # replicates Runner.create behaviour
|
||||
ret = run(runner, args, write=write_fn, environ=environ)
|
||||
printed = get_write_mock_output(write_mock)
|
||||
return ret, printed
|
||||
|
||||
|
||||
def _test_run(repo, options, expected_outputs, expected_ret, stage):
|
||||
if stage:
|
||||
stage_a_file()
|
||||
def _test_run(repo, options, expected_outputs, expected_ret, file_to_stage):
|
||||
if file_to_stage:
|
||||
stage_a_file(file_to_stage)
|
||||
args = _get_opts(**options)
|
||||
ret, printed = _do_run(repo, args)
|
||||
|
||||
|
|
@ -112,14 +113,14 @@ def test_run_all_hooks_failing(
|
|||
b'Fail\nfoo.py\n',
|
||||
),
|
||||
1,
|
||||
True,
|
||||
'foo.py',
|
||||
)
|
||||
|
||||
|
||||
def test_arbitrary_bytes_hook(tempdir_factory, mock_out_store_directory):
|
||||
git_path = make_consuming_repo(tempdir_factory, 'arbitrary_bytes_repo')
|
||||
with cwd(git_path):
|
||||
_test_run(git_path, {}, (b'\xe2\x98\x83\xb2\n',), 1, True)
|
||||
_test_run(git_path, {}, (b'\xe2\x98\x83\xb2\n',), 1, 'foo.py')
|
||||
|
||||
|
||||
def test_hook_that_modifies_but_returns_zero(
|
||||
|
|
@ -147,30 +148,30 @@ def test_hook_that_modifies_but_returns_zero(
|
|||
b'Files were modified by this hook.\n',
|
||||
),
|
||||
1,
|
||||
True,
|
||||
'foo.py',
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
('options', 'outputs', 'expected_ret', 'stage'),
|
||||
('options', 'outputs', 'expected_ret', 'file_to_stage'),
|
||||
(
|
||||
({}, (b'Bash hook', b'Passed'), 0, True),
|
||||
({'verbose': True}, (b'foo.py\nHello World',), 0, True),
|
||||
({'hook': 'bash_hook'}, (b'Bash hook', b'Passed'), 0, True),
|
||||
({'hook': 'nope'}, (b'No hook with id `nope`',), 1, True),
|
||||
({}, (b'Bash hook', b'Passed'), 0, 'foo.py'),
|
||||
({'verbose': True}, (b'foo.py\nHello World',), 0, 'foo.py'),
|
||||
({'hook': 'bash_hook'}, (b'Bash hook', b'Passed'), 0, 'foo.py'),
|
||||
({'hook': 'nope'}, (b'No hook with id `nope`',), 1, 'foo.py'),
|
||||
(
|
||||
{'all_files': True, 'verbose': True},
|
||||
(b'foo.py',),
|
||||
0,
|
||||
True,
|
||||
'foo.py',
|
||||
),
|
||||
(
|
||||
{'files': ('foo.py',), 'verbose': True},
|
||||
(b'foo.py',),
|
||||
0,
|
||||
True,
|
||||
'foo.py',
|
||||
),
|
||||
({}, (b'Bash hook', b'(no files to check)', b'Skipped'), 0, False),
|
||||
({}, (b'Bash hook', b'(no files to check)', b'Skipped'), 0, None),
|
||||
)
|
||||
)
|
||||
def test_run(
|
||||
|
|
@ -178,16 +179,17 @@ def test_run(
|
|||
options,
|
||||
outputs,
|
||||
expected_ret,
|
||||
stage,
|
||||
file_to_stage,
|
||||
mock_out_store_directory,
|
||||
):
|
||||
_test_run(repo_with_passing_hook, options, outputs, expected_ret, stage)
|
||||
_test_run(repo_with_passing_hook, options, outputs, expected_ret,
|
||||
file_to_stage)
|
||||
|
||||
|
||||
def test_always_run(repo_with_passing_hook, mock_out_store_directory):
|
||||
with modify_config() as config:
|
||||
config[0]['hooks'][0]['always_run'] = True
|
||||
_test_run(repo_with_passing_hook, {}, (b'Bash hook', b'Passed'), 0, False)
|
||||
_test_run(repo_with_passing_hook, {}, (b'Bash hook', b'Passed'), 0, None)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
|
@ -229,7 +231,7 @@ def test_no_stash(
|
|||
expect_stash,
|
||||
mock_out_store_directory,
|
||||
):
|
||||
stage_a_file()
|
||||
stage_a_file('foo.py')
|
||||
# Make unstaged changes
|
||||
with open('foo.py', 'w') as foo_file:
|
||||
foo_file.write('import os\n')
|
||||
|
|
@ -323,7 +325,7 @@ def test_multiple_hooks_same_id(
|
|||
# Add bash hook on there again
|
||||
with modify_config() as config:
|
||||
config[0]['hooks'].append({'id': 'bash_hook'})
|
||||
stage_a_file()
|
||||
stage_a_file('foo.py')
|
||||
|
||||
ret, output = _do_run(repo_with_passing_hook, _get_opts())
|
||||
assert ret == 0
|
||||
|
|
@ -352,7 +354,7 @@ def test_stdout_write_bug_py26(
|
|||
with cwd(repo_with_failing_hook):
|
||||
with modify_config() as config:
|
||||
config[0]['hooks'][0]['args'] = ['☃']
|
||||
stage_a_file()
|
||||
stage_a_file('foo.py')
|
||||
|
||||
install(Runner(repo_with_failing_hook))
|
||||
|
||||
|
|
@ -489,7 +491,7 @@ def test_local_hook_for_stages(
|
|||
{'hook_stage': hook_stage},
|
||||
expected_outputs=expected_output,
|
||||
expected_ret=0,
|
||||
stage=False
|
||||
file_to_stage=None
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -521,7 +523,7 @@ def test_local_hook_passes(repo_with_passing_hook, mock_out_store_directory):
|
|||
options={},
|
||||
expected_outputs=[b''],
|
||||
expected_ret=0,
|
||||
stage=False
|
||||
file_to_stage=None
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -547,7 +549,7 @@ def test_local_hook_fails(repo_with_passing_hook, mock_out_store_directory):
|
|||
options={},
|
||||
expected_outputs=[b''],
|
||||
expected_ret=1,
|
||||
stage=False,
|
||||
file_to_stage=None
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -595,3 +597,31 @@ def test_unstaged_message_suppressed(
|
|||
args = _get_opts(**opts)
|
||||
ret, printed = _do_run(modified_config_repo, args)
|
||||
assert b'Your .pre-commit-config.yaml is unstaged.' not in printed
|
||||
|
||||
|
||||
def test_invoke_precommit_in_subdir(
|
||||
tempdir_factory, mock_out_store_directory,
|
||||
):
|
||||
subdir_hook = OrderedDict((
|
||||
('id', 'subdir_bash_hook'),
|
||||
('name', 'Selective Bash hook'),
|
||||
('language', 'system'),
|
||||
('entry', 'echo OK'),
|
||||
('files', '^subdir/'),
|
||||
))
|
||||
git_path = make_consuming_repo(
|
||||
tempdir_factory,
|
||||
'script_hooks_repo',
|
||||
local_hooks=[subdir_hook],
|
||||
)
|
||||
with cwd(git_path):
|
||||
os.mkdir('subdir/')
|
||||
with cwd('subdir/'):
|
||||
cmd_output('touch', 'foo.py')
|
||||
_test_run(
|
||||
git_path,
|
||||
options={'files': ('subdir/foo.py',), 'verbose': True},
|
||||
expected_outputs=(b'foo.py',),
|
||||
expected_ret=0,
|
||||
file_to_stage=None,
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue