def repository_is_pending_merge(in_tmpdir): # Make a (non-conflicting) merge cmd_output('git', 'init', 'repo1') with cwd('repo1'): io.open('f1', 'w').close() cmd_output('git', 'add', 'f1') cmd_output('git', 'commit', '-m' 'commit1') cmd_output('git', 'clone', 'repo1', 'repo2') # Commit in master with cwd('repo1'): write_file('f1', 'parent\n') cmd_output('git', 'commit', '-am', 'master commit2') # Commit in clone and pull without committing with cwd('repo2'): write_file('f2', 'child\n') cmd_output('git', 'add', 'f2') cmd_output('git', 'commit', '-m', 'clone commit2') cmd_output('git', 'pull', '--no-commit') # We should end up in a pending merge assert io.open('f1').read().startswith('parent\n') assert io.open('f2').read().startswith('child\n') assert os.path.exists(os.path.join('.git', 'MERGE_HEAD')) yield
def f1_is_a_conflict_file(in_tmpdir): # Make a merge conflict cmd_output('git', 'init', 'repo1') with cwd('repo1'): io.open('f1', 'w').close() cmd_output('git', 'add', 'f1') cmd_output('git', 'commit', '-m' 'commit1') cmd_output('git', 'clone', 'repo1', 'repo2') # Commit in master with cwd('repo1'): write_file('f1', 'parent\n') cmd_output('git', 'commit', '-am', 'master commit2') # Commit in clone and pull with cwd('repo2'): write_file('f1', 'child\n') cmd_output('git', 'commit', '-am', 'clone commit2') cmd_output('git', 'pull', retcode=None) # We should end up in a merge conflict! assert io.open('f1').read().startswith( '<<<<<<< HEAD\n' 'child\n' '=======\n' 'parent\n' '>>>>>>>' ) assert os.path.exists(os.path.join('.git', 'MERGE_MSG')) yield
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'): # Use subprocess to demonstrate behaviour in main _, stdout, _ = cmd_output_mocked_pre_commit_home( sys.executable, '-m', 'pre_commit.main', 'run', '-v', # Files relative to where we are (#339) '--files', 'foo.py', tempdir_factory=tempdir_factory, ) assert 'subdir/foo.py'.replace('/', os.sep) in stdout
def test_hook_that_modifies_but_returns_zero(cap_out, store, tempdir_factory): git_path = make_consuming_repo( tempdir_factory, 'modified_file_returns_zero_repo', ) with cwd(git_path): stage_a_file('bar.py') _test_run( cap_out, store, git_path, {}, ( # The first should fail b'Failed', # With a modified file (default message + the hook's output) b'Files were modified by this hook. Additional output:\n\n' b'Modified: foo.py', # The next hook should pass despite the first modifying b'Passed', # The next hook should fail b'Failed', # bar.py was modified, but provides no additional output b'Files were modified by this hook.\n', ), 1, True, )
def test_environment_not_sourced(tempdir_factory, store): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): # Patch the executable to simulate rming virtualenv with mock.patch.object(sys, 'executable', '/does-not-exist'): assert install(C.CONFIG_FILE, store) == 0 # Use a specific homedir to ignore --user installs homedir = tempdir_factory.get() ret, stdout, stderr = git_commit( env={ 'HOME': homedir, 'PATH': _path_without_us(), # Git needs this to make a commit 'GIT_AUTHOR_NAME': os.environ['GIT_AUTHOR_NAME'], 'GIT_COMMITTER_NAME': os.environ['GIT_COMMITTER_NAME'], 'GIT_AUTHOR_EMAIL': os.environ['GIT_AUTHOR_EMAIL'], 'GIT_COMMITTER_EMAIL': os.environ['GIT_COMMITTER_EMAIL'], }, retcode=None, ) assert ret == 1 assert stdout == '' assert stderr.replace('\r\n', '\n') == ( '`pre-commit` not found. ' 'Did you forget to activate your virtualenv?\n' )
def prepare_commit_msg_repo(tempdir_factory): path = git_dir(tempdir_factory) script_name = 'add_sign_off.sh' config = { 'repo': 'local', 'hooks': [{ 'id': 'add-signoff', 'name': 'Add "Signed off by:"', 'entry': './{}'.format(script_name), 'language': 'script', 'stages': ['prepare-commit-msg'], }], } write_config(path, config) with cwd(path): with io.open(script_name, 'w') as script_file: script_file.write( '#!/usr/bin/env bash\n' 'set -eu\n' 'echo "\nSigned off by: " >> "$1"\n', ) make_executable(script_name) cmd_output('git', 'add', '.') git_commit(msg=prepare_commit_msg_repo.__name__) yield path
def test_clone_shallow_failure_fallback_to_complete( store, tempdir_factory, log_info_mock, ): path = git_dir(tempdir_factory) with cwd(path): git_commit() rev = git.head_rev(path) git_commit() # Force shallow clone failure def fake_shallow_clone(self, *args, **kwargs): raise CalledProcessError(None, None, None) store._shallow_clone = fake_shallow_clone ret = store.clone(path, rev) # Should have printed some stuff assert log_info_mock.call_args_list[0][0][0].startswith( 'Initializing environment for ', ) # Should return a directory inside of the store assert os.path.exists(ret) assert ret.startswith(store.directory) # Directory should start with `repo` _, dirname = os.path.split(ret) assert dirname.startswith('repo') # Should be checked out to the rev we specified assert git.head_rev(ret) == rev # Assert there's an entry in the sqlite db for this assert store.select_all_repos() == [(path, rev, ret)]
def test_adding_something(temp_git_dir): with cwd(temp_git_dir): write_file('f.py', "print('hello world')") cmd_output('git', 'add', 'f.py') # Should fail with max size of 0 assert find_large_added_files(['f.py'], 0) == 1
def test_pre_push_legacy(tempdir_factory, store): upstream = make_consuming_repo(tempdir_factory, 'script_hooks_repo') path = tempdir_factory.get() cmd_output('git', 'clone', upstream, path) with cwd(path): mkdirp(os.path.join(path, '.git/hooks')) with io.open(os.path.join(path, '.git/hooks/pre-push'), 'w') as f: f.write( '#!/usr/bin/env bash\n' 'set -eu\n' 'read lr ls rr rs\n' 'test -n "$lr" -a -n "$ls" -a -n "$rr" -a -n "$rs"\n' 'echo legacy\n', ) make_executable(f.name) install(C.CONFIG_FILE, store, hook_type='pre-push') assert _get_commit_output(tempdir_factory)[0] == 0 retc, output = _get_push_output(tempdir_factory) assert retc == 0 first_line, _, third_line = output.splitlines()[:3] assert first_line == 'legacy' assert third_line.startswith('Bash hook') assert third_line.endswith('Passed')
def _test_sub_state(path, rev='rev1', status='A'): assert os.path.exists(path.sub_path) with cwd(path.sub_path): actual_rev = cmd_output('git', 'rev-parse', 'HEAD')[1].strip() assert actual_rev == getattr(path.submodule, rev) actual_status = get_short_git_status()['sub'] assert actual_status == status
def test_added_file_not_in_pre_commits_list(temp_git_dir): with cwd(temp_git_dir): write_file('f.py', "print('hello world')") cmd_output('git', 'add', 'f.py') # Should pass even with a size of 0 assert find_large_added_files(['g.py'], 0) == 0
def test_installed_from_venv(tempdir_factory, store): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): install(C.CONFIG_FILE, store) # No environment so pre-commit is not on the path when running! # Should still pick up the python from when we installed ret, output = _get_commit_output( tempdir_factory, env={ 'HOME': os.path.expanduser('~'), 'PATH': _path_without_us(), 'TERM': os.environ.get('TERM', ''), # Windows needs this to import `random` 'SYSTEMROOT': os.environ.get('SYSTEMROOT', ''), # Windows needs this to resolve executables 'PATHEXT': os.environ.get('PATHEXT', ''), # Git needs this to make a commit 'GIT_AUTHOR_NAME': os.environ['GIT_AUTHOR_NAME'], 'GIT_COMMITTER_NAME': os.environ['GIT_COMMITTER_NAME'], 'GIT_AUTHOR_EMAIL': os.environ['GIT_AUTHOR_EMAIL'], 'GIT_COMMITTER_EMAIL': os.environ['GIT_COMMITTER_EMAIL'], }, ) assert ret == 0 assert NORMAL_PRE_COMMIT_RUN.match(output)
def test_legacy_overwriting_legacy_hook(tempdir_factory, store): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): _write_legacy_hook(path) assert install(C.CONFIG_FILE, store) == 0 _write_legacy_hook(path) # this previously crashed on windows. See #1010 assert install(C.CONFIG_FILE, store) == 0
def in_conflicting_submodule(tempdir_factory): git_dir_1 = git_dir(tempdir_factory) git_dir_2 = git_dir(tempdir_factory) git_commit(msg=in_conflicting_submodule.__name__, cwd=git_dir_2) cmd_output('git', 'submodule', 'add', git_dir_2, 'sub', cwd=git_dir_1) with cwd(os.path.join(git_dir_1, 'sub')): _make_conflict() yield
def test_adding_something_with_conflict(temp_git_dir): with cwd(temp_git_dir): write_file('f.py', "print('hello world')") cmd_output('git', 'add', 'f.py') write_file('F.py', "print('hello world')") cmd_output('git', 'add', 'F.py') assert find_conflicting_filenames(['f.py', 'F.py']) == 1
def test_install_overwrite_no_existing_hooks(tempdir_factory, store): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): assert install(C.CONFIG_FILE, store, overwrite=True) == 0 ret, output = _get_commit_output(tempdir_factory) assert ret == 0 assert NORMAL_PRE_COMMIT_RUN.match(output)
def test_failing_hooks_returns_nonzero(tempdir_factory, store): path = make_consuming_repo(tempdir_factory, 'failing_hook_repo') with cwd(path): assert install(C.CONFIG_FILE, store) == 0 ret, output = _get_commit_output(tempdir_factory) assert ret == 1 assert FAILING_PRE_COMMIT_RUN.match(output)
def test_no_markdown_linebreak_ext_opt(filename, input_s, output, tmpdir): with cwd(tmpdir.strpath): with open(filename, 'w') as file_obj: file_obj.write(input_s) # pragma: no branch (26 coverage bug) ret = fix_trailing_whitespace(['--no-markdown-linebreak-ext', filename]) assert ret == 1 assert open(filename).read() == output
def test_fixes_trailing_markdown_whitespace(filename, input_s, output, tmpdir): with cwd(tmpdir.strpath): with open(filename, 'w') as file_obj: file_obj.write(input_s) # pragma: no branch (26 coverage bug) ret = fix_trailing_whitespace([filename]) assert ret == 1 assert open(filename).read() == output
def submodule_with_commits(tempdir_factory): path = git_dir(tempdir_factory) with cwd(path): git_commit() rev1 = cmd_output('git', 'rev-parse', 'HEAD')[1].strip() git_commit() rev2 = cmd_output('git', 'rev-parse', 'HEAD')[1].strip() yield auto_namedtuple(path=path, rev1=rev1, rev2=rev2)
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 aliased_repo(tempdir_factory): git_path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(git_path): with modify_config() as config: config['repos'][0]['hooks'].append( {'id': 'bash_hook', 'alias': 'foo_bash'}, ) stage_a_file() yield git_path
def test_non_ascii_hook_id(repo_with_passing_hook, tempdir_factory): with cwd(repo_with_passing_hook): _, stdout, _ = cmd_output_mocked_pre_commit_home( sys.executable, '-m', 'pre_commit.main', 'run', '☃', retcode=None, tempdir_factory=tempdir_factory, ) assert 'UnicodeDecodeError' not in stdout # Doesn't actually happen, but a reasonable assertion assert 'UnicodeEncodeError' not in stdout
def test_pre_push_force_push_without_fetch(tempdir_factory, store): upstream = make_consuming_repo(tempdir_factory, 'script_hooks_repo') path1 = tempdir_factory.get() path2 = tempdir_factory.get() cmd_output('git', 'clone', upstream, path1) cmd_output('git', 'clone', upstream, path2) with cwd(path1): assert _get_commit_output(tempdir_factory)[0] == 0 assert _get_push_output(tempdir_factory)[0] == 0 with cwd(path2): install(C.CONFIG_FILE, store, hook_type='pre-push') assert _get_commit_output(tempdir_factory, msg='force!')[0] == 0 retc, output = _get_push_output(tempdir_factory, opts=('--force',)) assert retc == 0 assert 'Bash hook' in output assert 'Passed' in output
def test_markdown_linebreak_ext_opt_all(filename, input_s, output, tmpdir): with cwd(tmpdir.strpath): with open(filename, 'w') as file_obj: file_obj.write(input_s) # pragma: no branch (26 coverage bug) # need to make sure filename is not treated as argument to option ret = fix_trailing_whitespace(['--markdown-linebreak-ext=*', filename]) assert ret == 1 assert open(filename).read() == output
def test_allows_gitlfs(temp_git_dir): # pragma: no cover with cwd(temp_git_dir): # Work around https://github.com/github/git-lfs/issues/913 cmd_output('git', 'commit', '--allow-empty', '-m', 'foo') cmd_output('git', 'lfs', 'install') write_file('f.py', 'a' * 10000) cmd_output('git', 'lfs', 'track', 'f.py') cmd_output('git', 'add', '.') # Should succeed assert main(('--maxkb', '9', 'f.py')) == 0
def test_pre_push_integration_empty_push(tempdir_factory, store): upstream = make_consuming_repo(tempdir_factory, 'script_hooks_repo') path = tempdir_factory.get() cmd_output('git', 'clone', upstream, path) with cwd(path): install(C.CONFIG_FILE, store, hook_type='pre-push') _get_push_output(tempdir_factory) retc, output = _get_push_output(tempdir_factory) assert output == 'Everything up-to-date\n' assert retc == 0
def test_file_conflicts_with_committed_file(temp_git_dir): with cwd(temp_git_dir): write_file('f.py', "print('hello world')") cmd_output('git', 'add', 'f.py') cmd_output('git', 'commit', '--no-verify', '-m', 'Add f.py') write_file('F.py', "print('hello world')") cmd_output('git', 'add', 'F.py') assert find_conflicting_filenames(['F.py']) == 1
def test_install_pre_commit_and_run_custom_path(tempdir_factory, store): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): cmd_output('git', 'mv', C.CONFIG_FILE, 'custom-config.yaml') git_commit(cwd=path) assert install('custom-config.yaml', store) == 0 ret, output = _get_commit_output(tempdir_factory) assert ret == 0 assert NORMAL_PRE_COMMIT_RUN.match(output)
def test_installs_hooks_with_hooks_True(tempdir_factory, store): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): install(C.CONFIG_FILE, store, hooks=True) ret, output = _get_commit_output( tempdir_factory, pre_commit_home=store.directory, ) assert ret == 0 assert PRE_INSTALLED.match(output)
def test_hook_types_not_matched(capsys, tempdir_factory, mock_store_dir): config = { 'repos': [ { 'repo': 'meta', 'hooks': [ { 'id': 'check-useless-excludes', 'types': ['python'], }, ], }, ], } repo = git_dir(tempdir_factory) add_config_to_repo(repo, config) with cwd(repo): assert check_hooks_apply.main(()) == 1 out, _ = capsys.readouterr() assert 'check-useless-excludes does not apply to this repository' in out
def test_hook_install_failure(mock_out_store_directory, tempdir_factory): git_path = make_consuming_repo(tempdir_factory, 'not_installable_repo') with cwd(git_path): install(Runner(git_path, C.CONFIG_FILE)) _, stdout, _ = cmd_output_mocked_pre_commit_home( 'git', 'commit', '-m', 'Commit!', # git commit puts pre-commit to stderr stderr=subprocess.STDOUT, retcode=None, encoding=None, tempdir_factory=tempdir_factory, ) assert b'UnicodeDecodeError' not in stdout # Doesn't actually happen, but a reasonable assertion assert b'UnicodeEncodeError' not in stdout # Sanity check our output assert ( b'An unexpected error has occurred: CalledProcessError: ' in stdout ) assert '☃'.encode('UTF-8') + '²'.encode('latin1') in stdout
def test_run_output_logfile(cap_out, store, tempdir_factory): expected_output = ( b'This is STDOUT output\n', b'This is STDERR output\n', ) git_path = make_consuming_repo(tempdir_factory, 'logfile_repo') with cwd(git_path): _test_run( cap_out, store, git_path, {}, expected_output, expected_ret=1, stage=True, ) logfile_path = os.path.join(git_path, 'test.log') assert os.path.exists(logfile_path) with open(logfile_path, 'rb') as logfile: logfile_content = logfile.readlines() for expected_output_part in expected_output: assert expected_output_part in logfile_content
def test_hook_excludes_everything(capsys, tempdir_factory, mock_store_dir): config = { 'repos': [ { 'repo': 'meta', 'hooks': [ { 'id': 'check-useless-excludes', 'exclude': '.pre-commit-config.yaml', }, ], }, ], } repo = git_dir(tempdir_factory) add_config_to_repo(repo, config) with cwd(repo): assert check_hooks_apply.main(()) == 1 out, _ = capsys.readouterr() assert 'check-useless-excludes does not apply to this repository' in out
def test_clone(store, tempdir_factory, log_info_mock): path = git_dir(tempdir_factory) with cwd(path): git_commit() rev = git.head_rev(path) git_commit() ret = store.clone(path, rev) # Should have printed some stuff assert log_info_mock.call_args_list[0][0][0].startswith( 'Initializing environment for ', ) # Should return a directory inside of the store assert os.path.exists(ret) assert ret.startswith(store.directory) # Directory should start with `repo` _, dirname = os.path.split(ret) assert dirname.startswith('repo') # Should be checked out to the rev we specified assert git.head_rev(ret) == rev # Assert there's an entry in the sqlite db for this assert store.select_all_repos() == [(path, rev, ret)]
def test_lots_of_files(store, tempdir_factory): # windows xargs seems to have a bug, here's a regression test for # our workaround git_path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(git_path): # Override files so we run against them with modify_config() as config: config['repos'][0]['hooks'][0]['files'] = '' # Write a crap ton of files for i in range(400): filename = '{}{}'.format('a' * 100, i) open(filename, 'w').close() cmd_output('git', 'add', '.') install(C.CONFIG_FILE, store) git_commit( fn=cmd_output_mocked_pre_commit_home, # git commit puts pre-commit to stderr stderr=subprocess.STDOUT, tempdir_factory=tempdir_factory, )
def test_replace_old_commit_script(tempdir_factory, store): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): runner = Runner(path, C.CONFIG_FILE) # Install a script that looks like our old script pre_commit_contents = io.open(resource_filename('hook-tmpl')).read() new_contents = pre_commit_contents.replace( CURRENT_HASH, PRIOR_HASHES[-1], ) mkdirp(os.path.join(path, '.git/hooks')) with io.open(os.path.join(path, '.git/hooks/pre-commit'), 'w') as f: f.write(new_contents) make_executable(f.name) # Install normally assert install(runner, store) == 0 ret, output = _get_commit_output(tempdir_factory) assert ret == 0 assert NORMAL_PRE_COMMIT_RUN.match(output)
def test_useless_exclude_global(capsys, tempdir_factory): config = { 'exclude': 'foo', 'repos': [ { 'repo': 'meta', 'hooks': [{ 'id': 'check-useless-excludes' }], }, ], } repo = git_dir(tempdir_factory) add_config_to_repo(repo, config) with cwd(repo): assert check_useless_excludes.main(()) == 1 out, _ = capsys.readouterr() out = out.strip() assert "The global exclude pattern 'foo' does not match any files" == out
def test_show_diff_on_failure( capfd, cap_out, tempdir_factory, mock_out_store_directory, ): git_path = make_consuming_repo( tempdir_factory, 'modified_file_returns_zero_repo', ) with cwd(git_path): stage_a_file('bar.py') _test_run( cap_out, git_path, {'show_diff_on_failure': True}, # we're only testing the output after running (), 1, True, ) out, _ = capfd.readouterr() assert 'diff --git' in out
def test_post_checkout_hook(cap_out, store, tempdir_factory): path = git_dir(tempdir_factory) config = { 'repo': 'meta', 'hooks': [ { 'id': 'identity', 'stages': ['post-checkout'] }, ], } add_config_to_repo(path, config) with cwd(path): _test_run( cap_out, store, path, {'hook_stage': 'post-checkout'}, expected_outputs=[b'identity...'], expected_ret=0, stage=False, )
def test_pre_push_legacy(tempdir_factory, store): upstream = make_consuming_repo(tempdir_factory, 'script_hooks_repo') path = tempdir_factory.get() cmd_output('git', 'clone', upstream, path) with cwd(path): os.makedirs(os.path.join(path, '.git/hooks'), exist_ok=True) with open(os.path.join(path, '.git/hooks/pre-push'), 'w') as f: f.write( '#!/usr/bin/env bash\n' 'set -eu\n' 'read lr ls rr rs\n' 'test -n "$lr" -a -n "$ls" -a -n "$rr" -a -n "$rs"\n' 'echo legacy\n', ) make_executable(f.name) install(C.CONFIG_FILE, store, hook_types=['pre-push']) assert _get_commit_output(tempdir_factory)[0] == 0 retc, output = _get_push_output(tempdir_factory) assert retc == 0 first_line, _, third_line = output.splitlines()[:3] assert first_line == 'legacy' assert third_line.startswith('Bash hook') assert third_line.endswith('Passed')
def test_environment_not_sourced(tempdir_factory, store): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): # Patch the executable to simulate rming virtualenv with mock.patch.object(sys, 'executable', '/does-not-exist'): assert not install(C.CONFIG_FILE, store, hook_types=['pre-commit']) # Use a specific homedir to ignore --user installs homedir = tempdir_factory.get() ret, out = git_commit( env={ 'HOME': homedir, 'PATH': _path_without_us(), # Git needs this to make a commit 'GIT_AUTHOR_NAME': os.environ['GIT_AUTHOR_NAME'], 'GIT_COMMITTER_NAME': os.environ['GIT_COMMITTER_NAME'], 'GIT_AUTHOR_EMAIL': os.environ['GIT_AUTHOR_EMAIL'], 'GIT_COMMITTER_EMAIL': os.environ['GIT_COMMITTER_EMAIL'], }, retcode=None, ) assert ret == 1 assert out == ('`pre-commit` not found. ' 'Did you forget to activate your virtualenv?\n')
def test_hook_types_excludes_everything( capsys, tempdir_factory, mock_store_dir, ): config = OrderedDict(( ('repo', 'meta'), ( 'hooks', (OrderedDict(( ('id', 'check-useless-excludes'), ('exclude_types', ['yaml']), )), ), ), )) repo = git_dir(tempdir_factory) add_config_to_repo(repo, config) with cwd(repo): assert check_hooks_apply.main(()) == 1 out, _ = capsys.readouterr() assert 'check-useless-excludes does not apply to this repository' in out
def test_install_existing_hooks_no_overwrite(tempdir_factory): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): runner = Runner(path, C.CONFIG_FILE) # Write out an "old" hook mkdirp(os.path.dirname(runner.pre_commit_path)) with io.open(runner.pre_commit_path, 'w') as hook_file: hook_file.write('#!/usr/bin/env bash\necho "legacy hook"\n') make_executable(runner.pre_commit_path) # Make sure we installed the "old" hook correctly ret, output = _get_commit_output(tempdir_factory, touch_file='baz') assert ret == 0 assert EXISTING_COMMIT_RUN.match(output) # Now install pre-commit (no-overwrite) assert install(runner) == 0 # We should run both the legacy and pre-commit hooks ret, output = _get_commit_output(tempdir_factory) assert ret == 0 assert output.startswith('legacy hook\n') assert NORMAL_PRE_COMMIT_RUN.match(output[len('legacy hook\n'):])
def test_post_commit_integration(tempdir_factory, store): path = git_dir(tempdir_factory) config = [ { 'repo': 'local', 'hooks': [{ 'id': 'post-commit', 'name': 'Post commit', 'entry': 'touch post-commit.tmp', 'language': 'system', 'always_run': True, 'verbose': True, 'stages': ['post-commit'], }], }, ] write_config(path, config) with cwd(path): _get_commit_output(tempdir_factory) assert not os.path.exists('post-commit.tmp') install(C.CONFIG_FILE, store, hook_types=['post-commit']) _get_commit_output(tempdir_factory) assert os.path.exists('post-commit.tmp')
def test_init_templatedir(tmpdir, tempdir_factory, store, cap_out): target = str(tmpdir.join('tmpl')) init_templatedir(C.CONFIG_FILE, store, target, hook_type='pre-commit') lines = cap_out.get().splitlines() assert lines[0].startswith('pre-commit installed at ') assert lines[1] == ( '[WARNING] `init.templateDir` not set to the target directory' ) assert lines[2].startswith( '[WARNING] maybe `git config --global init.templateDir', ) with envcontext([('GIT_TEMPLATE_DIR', target)]): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): retcode, output, _ = git_commit( fn=cmd_output_mocked_pre_commit_home, tempdir_factory=tempdir_factory, # git commit puts pre-commit to stderr stderr=subprocess.STDOUT, ) assert retcode == 0 assert 'Bash hook....' in output
def test_pre_merge_commit_integration(tempdir_factory, store): output_pattern = re_assert.Matches( r'^\[INFO\] Initializing environment for .+\n' r'Bash hook\.+Passed\n' r"Merge made by the '(ort|recursive)' strategy.\n" r' foo \| 0\n' r' 1 file changed, 0 insertions\(\+\), 0 deletions\(-\)\n' r' create mode 100644 foo\n$', ) path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): ret = install(C.CONFIG_FILE, store, hook_types=['pre-merge-commit']) assert ret == 0 cmd_output('git', 'checkout', 'master', '-b', 'feature') _get_commit_output(tempdir_factory) cmd_output('git', 'checkout', 'master') ret, output, _ = cmd_output_mocked_pre_commit_home( 'git', 'merge', '--no-ff', '--no-edit', 'feature', tempdir_factory=tempdir_factory, ) assert ret == 0 output_pattern.assert_matches(output)
def test_valid_exclude(capsys, tempdir_factory): config = { 'repos': [ { 'repo': 'meta', 'hooks': [ { 'id': 'check-useless-excludes', 'exclude': '.pre-commit-config.yaml', }, ], }, ], } repo = git_dir(tempdir_factory) add_config_to_repo(repo, config) with cwd(repo): assert check_useless_excludes.main(()) == 0 out, _ = capsys.readouterr() assert out == ''
def _do_run(cap_out, store, repo, args, environ={}, config_file=C.CONFIG_FILE): with cwd(repo): # replicates `main._adjust_args_and_chdir` behaviour ret = run(config_file, store, args, environ=environ) printed = cap_out.get_bytes() return ret, printed
def repo_with_passing_hook(tempdir_factory): git_path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(git_path): yield git_path
def _run_try_repo(tempdir_factory, **kwargs): repo = make_repo(tempdir_factory, 'modified_file_returns_zero_repo') with cwd(git_dir(tempdir_factory)): _add_test_file() assert not try_repo(try_repo_opts(repo, **kwargs))
def _create_repo_with_tags(tempdir_factory, src, tag): path = make_repo(tempdir_factory, src) with cwd(path): cmd_output('git', 'tag', tag) return path
def _do_run(cap_out, repo, args, environ={}, config_file=C.CONFIG_FILE): runner = Runner(repo, config_file) with cwd(runner.git_root): # replicates Runner.create behaviour ret = run(runner, args, environ=environ) printed = cap_out.get_bytes() return ret, printed
def in_tmpdir(tmpdir): with cwd(tmpdir.strpath): yield tmpdir
def in_tmpdir(tempdir_factory): path = tempdir_factory.get() with cwd(path): yield path
def test_install_refuses_core_hookspath(tempdir_factory, store): path = git_dir(tempdir_factory) with cwd(path): cmd_output('git', 'config', '--local', 'core.hooksPath', 'hooks') runner = Runner(path, C.CONFIG_FILE) assert install(runner, store)
def repo_with_failing_hook(tempdir_factory): git_path = make_consuming_repo(tempdir_factory, 'failing_hook_repo') with cwd(git_path): yield git_path
def test_is_not_in_merge_conflict(tempdir_factory): path = git_dir(tempdir_factory) with cwd(path): assert git.is_in_merge_conflict() is False
def test_arbitrary_bytes_hook(cap_out, store, tempdir_factory): git_path = make_consuming_repo(tempdir_factory, 'arbitrary_bytes_repo') with cwd(git_path): _test_run( cap_out, store, git_path, {}, (b'\xe2\x98\x83\xb2\n',), 1, True, )
def test_memoized_by_cwd_changes_with_different_cwd(memoized_by_cwd): ret = memoized_by_cwd('baz') with cwd('.git'): ret2 = memoized_by_cwd('baz') assert ret != ret2