def test_merge_conflict_resolved(cap_out, store, in_merge_conflict): cmd_output('git', 'add', '.') ret, printed = _do_run(cap_out, store, in_merge_conflict, run_opts()) for msg in ( b'Checking merge-conflict files only.', b'Bash hook', b'Passed', ): assert msg in printed
def test_origin_source_error_msg_error( cap_out, store, repo_with_passing_hook, origin, source, ): args = run_opts(origin=origin, source=source) ret, printed = _do_run(cap_out, store, repo_with_passing_hook, args) assert ret == 1 assert b'Specify both --origin and --source.' in printed
def test_skip_hook(cap_out, store, repo_with_passing_hook): ret, printed = _do_run( cap_out, store, repo_with_passing_hook, run_opts(), {'SKIP': 'bash_hook'}, ) for msg in (b'Bash hook', b'Skipped'): assert msg in printed
def test_aliased_hook_run(cap_out, store, aliased_repo): ret, output = _do_run( cap_out, store, aliased_repo, run_opts(verbose=True, hook='bash_hook'), ) assert ret == 0 # Both hooks will run since they share the same ID assert output.count(b'Bash hook') == 2 ret, output = _do_run( cap_out, store, aliased_repo, run_opts(verbose=True, hook='foo_bash'), ) assert ret == 0 # Only the aliased hook runs assert output.count(b'Bash hook') == 1
def test_hook_id_not_in_non_verbose_output( cap_out, store, repo_with_passing_hook, ): ret, printed = _do_run( cap_out, store, repo_with_passing_hook, run_opts(verbose=False), ) assert b'[bash_hook]' not in printed
def _run_for_stage(stage): args = run_opts(hook_stage=stage) ret, printed = _do_run(cap_out, store, repo_with_passing_hook, args) assert not ret, (ret, printed) # this test should only run one hook assert printed.count(b'hook ') == 1 return printed
def test_args_hook_only(cap_out, store, repo_with_passing_hook): config = { 'repo': 'local', 'hooks': [ { 'id': 'flake8', 'name': 'flake8', 'entry': "'{}' -m flake8".format(sys.executable), 'language': 'system', 'stages': ['commit'], }, { 'id': 'do_not_commit', 'name': 'Block if "DO NOT COMMIT" is found', 'entry': 'DO NOT COMMIT', 'language': 'pygrep', }, ], } add_config_to_repo(repo_with_passing_hook, config) stage_a_file() ret, printed = _do_run( cap_out, store, repo_with_passing_hook, run_opts(hook='do_not_commit'), ) assert b'flake8' not in printed
def test_types_hook_repository(cap_out, store, tempdir_factory): git_path = make_consuming_repo(tempdir_factory, 'types_repo') with cwd(git_path): stage_a_file('bar.py') stage_a_file('bar.notpy') ret, printed = _do_run(cap_out, store, git_path, run_opts()) assert ret == 1 assert b'bar.py' in printed assert b'bar.notpy' not in printed
def test_merge_conflict_modified(cap_out, store, in_merge_conflict): # Touch another file so we have unstaged non-conflicting things assert os.path.exists('dummy') with open('dummy', 'w') as dummy_file: dummy_file.write('bar\nbaz\n') ret, printed = _do_run(cap_out, store, in_merge_conflict, run_opts()) assert ret == 1 assert b'Unmerged files. Resolve before committing.' in printed
def test_no_unstaged_error_with_all_files_or_files( cap_out, modified_config_repo, mock_out_store_directory, opts, ): args = run_opts(**opts) ret, printed = _do_run(cap_out, modified_config_repo, args) assert b'Your .pre-commit-config.yaml is unstaged.' not in printed
def test_skip_hook(cap_out, repo_with_passing_hook, mock_out_store_directory): ret, printed = _do_run( cap_out, repo_with_passing_hook, run_opts(), {'SKIP': 'bash_hook'}, ) for msg in (b'Bash hook', b'Skipped'): assert msg in printed
def test_error_with_unstaged_config( cap_out, modified_config_repo, mock_out_store_directory, ): args = run_opts() ret, printed = _do_run(cap_out, modified_config_repo, args) assert b'Your .pre-commit-config.yaml is unstaged.' in printed assert ret == 1
def test_all_push_options_ok(cap_out, store, repo_with_passing_hook): args = run_opts( from_ref='master', to_ref='master', remote_name='origin', remote_url='https://example.com/repo', ) ret, printed = _do_run(cap_out, store, repo_with_passing_hook, args) assert ret == 0 assert b'Specify both --from-ref and --to-ref.' not in printed
def test_multiple_hooks_same_id(cap_out, store, repo_with_passing_hook): with cwd(repo_with_passing_hook): # Add bash hook on there again with modify_config() as config: config['repos'][0]['hooks'].append({'id': 'bash_hook'}) stage_a_file() ret, output = _do_run(cap_out, store, repo_with_passing_hook, run_opts()) assert ret == 0 assert output.count(b'Bash hook') == 2
def test_skip_aliased_hook(cap_out, store, aliased_repo): ret, printed = _do_run( cap_out, store, aliased_repo, run_opts(hook='foo_bash'), {'SKIP': 'foo_bash'}, ) assert ret == 0 # Only the aliased hook runs and is skipped for msg in (b'Bash hook', b'Skipped'): assert printed.count(msg) == 1
def test_fail_fast(cap_out, store, repo_with_failing_hook): with modify_config() as config: # More than one hook config['fail_fast'] = True config['repos'][0]['hooks'] *= 2 stage_a_file() ret, printed = _do_run(cap_out, store, repo_with_failing_hook, run_opts()) # it should have only run one hook assert printed.count(b'Failing hook') == 1
def test_pre_commit_env_variable_set(cap_out, store, repo_with_passing_hook): args = run_opts() environ: MutableMapping[str, str] = {} ret, printed = _do_run( cap_out, store, repo_with_passing_hook, args, environ, ) assert environ['PRE_COMMIT'] == '1'
def test_hook_id_in_verbose_output( cap_out, repo_with_passing_hook, mock_out_store_directory, ): ret, printed = _do_run( cap_out, repo_with_passing_hook, run_opts(verbose=True), ) assert b'[bash_hook] Bash hook' in printed
def test_checkout_type(cap_out, store, repo_with_passing_hook): args = run_opts(from_ref='', to_ref='', checkout_type='1') environ: MutableMapping[str, str] = {} ret, printed = _do_run( cap_out, store, repo_with_passing_hook, args, environ, ) assert environ['PRE_COMMIT_CHECKOUT_TYPE'] == '1'
def test_from_ref_to_ref_error_msg_error( cap_out, store, repo_with_passing_hook, from_ref, to_ref, ): args = run_opts(from_ref=from_ref, to_ref=to_ref) ret, printed = _do_run(cap_out, store, repo_with_passing_hook, args) assert ret == 1 assert b'Specify both --from-ref and --to-ref.' in printed
def test_is_squash_merge(cap_out, store, repo_with_passing_hook): args = run_opts(is_squash_merge='1') environ: MutableMapping[str, str] = {} ret, printed = _do_run( cap_out, store, repo_with_passing_hook, args, environ, ) assert environ['PRE_COMMIT_IS_SQUASH_MERGE'] == '1'
def _test_run( cap_out, store, repo, opts, expected_outputs, expected_ret, stage, config_file=C.CONFIG_FILE, ): if stage: stage_a_file() args = run_opts(**opts) ret, printed = _do_run(cap_out, store, repo, args, config_file=config_file) assert ret == expected_ret, (ret, expected_ret, printed) for expected_output_part in expected_outputs: assert expected_output_part in printed
def test_exclude_types_hook_repository(cap_out, store, tempdir_factory): git_path = make_consuming_repo(tempdir_factory, 'exclude_types_repo') with cwd(git_path): with open('exe', 'w') as exe: exe.write('#!/usr/bin/env python3\n') make_executable('exe') cmd_output('git', 'add', 'exe') stage_a_file('bar.py') ret, printed = _do_run(cap_out, store, git_path, run_opts()) assert ret == 1 assert b'bar.py' in printed assert b'exe' not in printed
def test_exclude_types_hook_repository(cap_out, store, tempdir_factory): git_path = make_consuming_repo(tempdir_factory, 'exclude_types_repo') with cwd(git_path): with io.open('exe', 'w') as exe: exe.write('#!/usr/bin/env python3\n') make_executable('exe') cmd_output('git', 'add', 'exe') stage_a_file('bar.py') ret, printed = _do_run(cap_out, store, git_path, run_opts()) assert ret == 1 assert b'bar.py' in printed assert b'exe' not in printed
def test_origin_source_error_msg( repo_with_passing_hook, origin, source, expect_failure, mock_out_store_directory, cap_out, ): args = run_opts(origin=origin, source=source) ret, printed = _do_run(cap_out, repo_with_passing_hook, args) warning_msg = b'Specify both --origin and --source.' if expect_failure: assert ret == 1 assert warning_msg in printed else: assert ret == 0 assert warning_msg not in printed
def test_pass_filenames( cap_out, store, repo_with_passing_hook, pass_filenames, hook_args, expected_out, ): with modify_config() as config: config['repos'][0]['hooks'][0]['pass_filenames'] = pass_filenames config['repos'][0]['hooks'][0]['args'] = hook_args stage_a_file() ret, printed = _do_run( cap_out, store, repo_with_passing_hook, run_opts(verbose=True), ) assert expected_out + b'\nHello World' in printed assert (b'foo.py' in printed) == pass_filenames
def test_merge_conflict_resolved( cap_out, in_merge_conflict, mock_out_store_directory, ): cmd_output('git', 'add', '.') ret, printed = _do_run(cap_out, in_merge_conflict, run_opts()) for msg in ( b'Checking merge-conflict files only.', b'Bash hook', b'Passed', ): assert msg in printed
def test_global_exclude(cap_out, tempdir_factory, mock_out_store_directory): git_path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(git_path): with modify_config() as config: config['exclude'] = '^foo.py$' open('foo.py', 'a').close() open('bar.py', 'a').close() cmd_output('git', 'add', '.') ret, printed = _do_run(cap_out, git_path, run_opts(verbose=True)) assert ret == 0 # Does not contain foo.py since it was excluded expected = b'hookid: bash_hook\n\nbar.py\nHello World\n\n' assert printed.endswith(expected)
def test_global_exclude(cap_out, store, tempdir_factory): git_path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(git_path): with modify_config() as config: config['exclude'] = '^foo.py$' open('foo.py', 'a').close() open('bar.py', 'a').close() cmd_output('git', 'add', '.') opts = run_opts(verbose=True) ret, printed = _do_run(cap_out, store, git_path, opts) assert ret == 0 # Does not contain foo.py since it was excluded expected = b'hookid: bash_hook\n\nbar.py\nHello World\n\n' assert printed.endswith(expected)
def test_global_files(cap_out, store, in_git_dir): config = { 'files': r'^bar\.py$', 'repos': [{'repo': 'meta', 'hooks': [{'id': 'identity'}]}], } write_config('.', config) open('foo.py', 'a').close() open('bar.py', 'a').close() cmd_output('git', 'add', '.') opts = run_opts(verbose=True) ret, printed = _do_run(cap_out, store, str(in_git_dir), opts) assert ret == 0 # Does not contain foo.py since it was excluded assert printed.startswith(f'identity{"." * 65}Passed\n'.encode()) assert printed.endswith(b'\n\nbar.py\n\n')
def test_global_exclude(cap_out, store, in_git_dir): config = { 'exclude': r'^foo\.py$', 'repos': [{ 'repo': 'meta', 'hooks': [{ 'id': 'identity' }] }], } write_config('.', config) open('foo.py', 'a').close() open('bar.py', 'a').close() cmd_output('git', 'add', '.') opts = run_opts(verbose=True) ret, printed = _do_run(cap_out, store, str(in_git_dir), opts) assert ret == 0 # Does not contain foo.py since it was excluded assert printed.startswith(b'identity' + b'.' * 65 + b'Passed\n') assert printed.endswith(b'\n\n.pre-commit-config.yaml\nbar.py\n\n')
def test_skip_bypasses_installation(cap_out, store, repo_with_passing_hook): config = { 'repo': 'local', 'hooks': [ { 'id': 'skipme', 'name': 'skipme', 'entry': 'skipme', 'language': 'python', 'additional_dependencies': ['/pre-commit-does-not-exist'], }, ], } add_config_to_repo(repo_with_passing_hook, config) ret, printed = _do_run( cap_out, store, repo_with_passing_hook, run_opts(all_files=True), {'SKIP': 'skipme'}, ) assert ret == 0
def test_args_hook_only(cap_out, store, repo_with_passing_hook): config = { 'repo': 'local', 'hooks': [ { 'id': 'identity-copy', 'name': 'identity-copy', 'entry': '{} -m pre_commit.meta_hooks.identity'.format( shlex.quote(sys.executable), ), 'language': 'system', 'files': r'\.py$', 'stages': ['commit'], }, { 'id': 'do_not_commit', 'name': 'Block if "DO NOT COMMIT" is found', 'entry': 'DO NOT COMMIT', 'language': 'pygrep', }, ], } add_config_to_repo(repo_with_passing_hook, config) stage_a_file() ret, printed = _do_run( cap_out, store, repo_with_passing_hook, run_opts(hook='do_not_commit'), ) assert b'identity-copy' not in printed
def test_merge_conflict(cap_out, store, in_merge_conflict): ret, printed = _do_run(cap_out, store, in_merge_conflict, run_opts()) assert ret == 1 assert b'Unmerged files. Resolve before committing.' in printed
def test_merge_conflict(cap_out, in_merge_conflict, mock_out_store_directory): ret, printed = _do_run(cap_out, in_merge_conflict, run_opts()) assert ret == 1 assert b'Unmerged files. Resolve before committing.' in printed
def test_error_with_unstaged_config(cap_out, store, modified_config_repo): args = run_opts() ret, printed = _do_run(cap_out, store, modified_config_repo, args) assert b'Your pre-commit configuration is unstaged.' in printed assert ret == 1
def test_hook_id_in_verbose_output(cap_out, store, repo_with_passing_hook): ret, printed = _do_run( cap_out, store, repo_with_passing_hook, run_opts(verbose=True), ) assert b'[bash_hook] Bash hook' in printed
def test_hook_id_in_verbose_output(cap_out, store, repo_with_passing_hook): ret, printed = _do_run( cap_out, store, repo_with_passing_hook, run_opts(verbose=True), ) assert b'- hook id: bash_hook' in printed
def modified_config_repo(repo_with_passing_hook): with modify_config(repo_with_passing_hook, commit=False) as config: # Some minor modification config['repos'][0]['hooks'][0]['files'] = '' yield repo_with_passing_hook def test_error_with_unstaged_config(cap_out, store, modified_config_repo): args = run_opts() ret, printed = _do_run(cap_out, store, modified_config_repo, args) assert b'Your pre-commit configuration is unstaged.' in printed assert ret == 1 @pytest.mark.parametrize( 'opts', (run_opts(all_files=True), run_opts(files=[C.CONFIG_FILE])), ) def test_no_unstaged_error_with_all_files_or_files( cap_out, store, modified_config_repo, opts, ): ret, printed = _do_run(cap_out, store, modified_config_repo, opts) assert b'Your pre-commit configuration is unstaged.' not in printed def test_files_running_subdir(repo_with_passing_hook, tempdir_factory): with cwd(repo_with_passing_hook): os.mkdir('subdir') open('subdir/foo.py', 'w').close() cmd_output('git', 'add', 'subdir/foo.py') with cwd('subdir'):
def test_origin_source_both_ok(cap_out, store, repo_with_passing_hook): args = run_opts(origin='master', source='master') ret, printed = _do_run(cap_out, store, repo_with_passing_hook, args) assert ret == 0 assert b'Specify both --origin and --source.' not in printed