def git_dir_with_git_dir(tmpdir): with tmpdir.as_cwd(): subprocess.check_call(('git', 'init', '.')) git_commit('--allow-empty', '-m', 'init') subprocess.check_call(('git', 'init', 'foo')) git_commit('--allow-empty', '-m', 'init', cwd=str(tmpdir.join('foo'))) yield
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 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_make_archive(in_git_dir, tmpdir): output_dir = tmpdir.join('output').ensure_dir() # Add a files to the git directory in_git_dir.join('foo').ensure() cmd_output('git', 'add', '.') git_commit() # We'll use this rev head_rev = git.head_rev('.') # And check that this file doesn't exist in_git_dir.join('bar').ensure() cmd_output('git', 'add', '.') git_commit() # Do the thing archive_path = make_archives.make_archive( 'foo', in_git_dir.strpath, head_rev, output_dir.strpath, ) expected = output_dir.join('foo.tar.gz') assert archive_path == expected.strpath assert expected.exists() extract_dir = tmpdir.join('extract').ensure_dir() with tarfile.open(archive_path) as tf: tf.extractall(extract_dir.strpath) # Verify the contents of the tar assert extract_dir.join('foo').isdir() assert extract_dir.join('foo/foo').exists() assert not extract_dir.join('foo/.git').exists() assert not extract_dir.join('foo/bar').exists()
def test_post_rewrite_integration(tempdir_factory, store): path = git_dir(tempdir_factory) config = [ { 'repo': 'local', 'hooks': [{ 'id': 'post-rewrite', 'name': 'Post rewrite', 'entry': 'touch post-rewrite.tmp', 'language': 'system', 'always_run': True, 'verbose': True, 'stages': ['post-rewrite'], }], }, ] write_config(path, config) with cwd(path): open('init', 'a').close() cmd_output('git', 'add', '.') install(C.CONFIG_FILE, store, hook_types=['post-rewrite']) git_commit() assert not os.path.exists('post-rewrite.tmp') git_commit('--amend', '-m', 'ammended message') assert os.path.exists('post-rewrite.tmp')
def test_rev_info_update_freeze_tag(tagged): git_commit(cwd=tagged.path) config = make_config_from_repo(tagged.path, rev=tagged.original_rev) info = RevInfo.from_config(config) new_info = info.update(tags_only=True, freeze=True) assert new_info.rev == tagged.head_rev assert new_info.frozen == 'v1.2.3'
def test_autoupdate_old_revision_broken(tempdir_factory, in_tmpdir, store): """In $FUTURE_VERSION, hooks.yaml will no longer be supported. This asserts that when that day comes, pre-commit will be able to autoupdate despite not being able to read hooks.yaml in that repository. """ path = make_repo(tempdir_factory, 'python_hooks_repo') config = make_config_from_repo(path, check=False) cmd_output('git', 'mv', C.MANIFEST_FILE, 'nope.yaml', cwd=path) git_commit(cwd=path) # Assume this is the revision the user's old repository was at rev = git.head_rev(path) cmd_output('git', 'mv', 'nope.yaml', C.MANIFEST_FILE, cwd=path) git_commit(cwd=path) update_rev = git.head_rev(path) config['rev'] = rev write_config('.', config) with open(C.CONFIG_FILE) as f: before = f.read() assert autoupdate(C.CONFIG_FILE, store, freeze=False, tags_only=False) == 0 with open(C.CONFIG_FILE) as f: after = f.read() assert before != after assert update_rev in after
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_autoupdate_old_revision_broken(tempdir_factory, in_tmpdir, store): """In $FUTURE_VERSION, hooks.yaml will no longer be supported. This asserts that when that day comes, pre-commit will be able to autoupdate despite not being able to read hooks.yaml in that repository. """ path = make_repo(tempdir_factory, 'python_hooks_repo') config = make_config_from_repo(path, check=False) cmd_output('git', 'mv', C.MANIFEST_FILE, 'nope.yaml', cwd=path) git_commit(cwd=path) # Assume this is the revision the user's old repository was at rev = git.head_rev(path) cmd_output('git', 'mv', 'nope.yaml', C.MANIFEST_FILE, cwd=path) git_commit(cwd=path) update_rev = git.head_rev(path) config['rev'] = rev write_config('.', config) with open(C.CONFIG_FILE) as f: before = f.read() ret = autoupdate(C.CONFIG_FILE, store, tags_only=False) with open(C.CONFIG_FILE) as f: after = f.read() assert ret == 0 assert before != after assert update_rev in after
def test_make_archive(in_git_dir, tmpdir): output_dir = tmpdir.join('output').ensure_dir() # Add a files to the git directory in_git_dir.join('foo').ensure() cmd_output('git', 'add', '.') git_commit() # We'll use this rev head_rev = git.head_rev('.') # And check that this file doesn't exist in_git_dir.join('bar').ensure() cmd_output('git', 'add', '.') git_commit() # Do the thing archive_path = make_archives.make_archive( 'foo', in_git_dir.strpath, head_rev, output_dir.strpath, ) expected = output_dir.join('foo.tar.gz') assert archive_path == expected.strpath assert expected.exists() extract_dir = tmpdir.join('extract').ensure_dir() with tarfile.open(archive_path) as tf: tf.extractall(extract_dir.strpath) # Verify the contents of the tar assert extract_dir.join('foo').isdir() assert extract_dir.join('foo/foo').exists() assert not extract_dir.join('foo/.git').exists() assert not extract_dir.join('foo/bar').exists()
def test_not_on_a_branch(temp_git_dir): with temp_git_dir.as_cwd(): git_commit('--allow-empty', '-m1') head = cmd_output('git', 'rev-parse', 'HEAD').strip() cmd_output('git', 'checkout', head) # we're not on a branch! assert main(()) == 0
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': f'./{script_name}', 'language': 'script', 'stages': ['prepare-commit-msg'], }], } write_config(path, config) with cwd(path): with 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_post_checkout_integration(tempdir_factory, store): path = git_dir(tempdir_factory) config = [ { 'repo': 'local', 'hooks': [{ 'id': 'post-checkout', 'name': 'Post checkout', 'entry': 'bash -c "echo ${PRE_COMMIT_TO_REF}"', 'language': 'system', 'always_run': True, 'verbose': True, 'stages': ['post-checkout'], }], }, {'repo': 'meta', 'hooks': [{'id': 'identity'}]}, ] write_config(path, config) with cwd(path): cmd_output('git', 'add', '.') git_commit() # add a file only on `feature`, it should not be passed to hooks cmd_output('git', 'checkout', '-b', 'feature') open('some_file', 'a').close() cmd_output('git', 'add', '.') git_commit() cmd_output('git', 'checkout', 'master') install(C.CONFIG_FILE, store, hook_types=['post-checkout']) retc, _, stderr = cmd_output('git', 'checkout', 'feature') assert stderr is not None assert retc == 0 assert git.head_rev(path) in stderr assert 'some_file' not in stderr
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 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 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 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_status_output_with_rename(in_git_dir): in_git_dir.join('a').write('1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n') cmd_output('git', 'add', 'a') git_commit() cmd_output('git', 'mv', 'a', 'b') in_git_dir.join('c').ensure() cmd_output('git', 'add', '--intent-to-add', 'c') assert git.intent_to_add_files() == ['c']
def test_get_root_worktree_in_git(tmpdir): src = tmpdir.join('src').ensure_dir() cmd_output('git', 'init', str(src)) git_commit(cwd=str(src)) cmd_output('git', 'worktree', 'add', '.git/trees/foo', 'HEAD', cwd=src) with src.join('.git/trees/foo').as_cwd(): assert git.get_root() == os.path.abspath('.')
def test_status_output_with_rename(in_git_dir): in_git_dir.join('a').write('1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n') cmd_output('git', 'add', 'a') git_commit() cmd_output('git', 'mv', 'a', 'b') in_git_dir.join('c').ensure() cmd_output('git', 'add', '--intent-to-add', 'c') assert git.intent_to_add_files() == ['c']
def push_example(tempdir_factory): src = git_dir(tempdir_factory) git_commit(cwd=src) src_head = git.head_rev(src) clone = tempdir_factory.get() cmd_output('git', 'clone', src, clone) git_commit(cwd=clone) clone_head = git.head_rev(clone) return (src, src_head, clone, clone_head)
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 repo_with_commits(tempdir_factory): path = git_dir(tempdir_factory) with cwd(path): open('foo', 'a+').close() cmd_output('git', 'add', 'foo') 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_autoupdate_tags_only(tagged, in_tmpdir, store): # add some commits after the tag git_commit(cwd=tagged.path) config = make_config_from_repo(tagged.path, rev=tagged.original_rev) write_config('.', config) assert autoupdate(C.CONFIG_FILE, store, freeze=False, tags_only=True) == 0 with open(C.CONFIG_FILE) as f: assert 'v1.2.3' in f.read()
def test_try_repo_specific_revision(cap_out, tempdir_factory): repo = make_repo(tempdir_factory, 'script_hooks_repo') ref = git.head_rev(repo) git_commit(cwd=repo) with cwd(git_dir(tempdir_factory)): _add_test_file() assert not try_repo(try_repo_opts(repo, ref=ref)) _, config, _ = _get_out(cap_out) assert ref in config
def test_file_conflicts_with_committed_dir(temp_git_dir): with temp_git_dir.as_cwd(): temp_git_dir.mkdir('dir').join('x').write('foo') cmd_output('git', 'add', '-A') git_commit('-m', 'Add f.py') temp_git_dir.join('DIR').write('foo') cmd_output('git', 'add', '-A') assert find_conflicting_filenames([]) == 1
def out_of_date_repo(tempdir_factory): path = make_repo(tempdir_factory, 'python_hooks_repo') original_rev = git.head_rev(path) git_commit(cwd=path) head_rev = git.head_rev(path) yield auto_namedtuple( path=path, original_rev=original_rev, head_rev=head_rev, )
def test_file_conflicts_with_committed_file(temp_git_dir): with temp_git_dir.as_cwd(): temp_git_dir.join('f.py').write("print('hello world')") cmd_output('git', 'add', 'f.py') git_commit('-m', 'Add f.py') temp_git_dir.join('F.py').write("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.yaml') git_commit(cwd=path) assert install('custom.yaml', store, hook_types=['pre-commit']) == 0 ret, output = _get_commit_output(tempdir_factory) assert ret == 0 assert NORMAL_PRE_COMMIT_RUN.match(output)
def out_of_date_repo(tempdir_factory): path = make_repo(tempdir_factory, 'python_hooks_repo') original_rev = git.head_rev(path) git_commit(cwd=path) head_rev = git.head_rev(path) yield auto_namedtuple( path=path, original_rev=original_rev, head_rev=head_rev, )
def in_merge_conflict(tempdir_factory): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') open(os.path.join(path, 'placeholder'), 'a').close() cmd_output('git', 'add', 'placeholder', cwd=path) git_commit(msg=in_merge_conflict.__name__, cwd=path) conflict_path = tempdir_factory.get() cmd_output('git', 'clone', path, conflict_path) with cwd(conflict_path): _make_conflict() yield os.path.join(conflict_path)
def in_merge_conflict(tempdir_factory): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') open(os.path.join(path, 'dummy'), 'a').close() cmd_output('git', 'add', 'dummy', cwd=path) git_commit(msg=in_merge_conflict.__name__, cwd=path) conflict_path = tempdir_factory.get() cmd_output('git', 'clone', path, conflict_path) with cwd(conflict_path): _make_conflict() yield os.path.join(conflict_path)
def test_get_changed_files(in_git_dir): git_commit() in_git_dir.join('a.txt').ensure() in_git_dir.join('b.txt').ensure() cmd_output('git', 'add', '.') git_commit() files = git.get_changed_files('HEAD', 'HEAD^') assert files == ['a.txt', 'b.txt'] # files changed in source but not in origin should not be returned files = git.get_changed_files('HEAD^', 'HEAD') assert files == []
def modify_manifest(path, commit=True): """Modify the manifest yielded by this context to write to .pre-commit-hooks.yaml. """ manifest_path = os.path.join(path, C.MANIFEST_FILE) with open(manifest_path) as f: manifest = yaml_load(f.read()) yield manifest with open(manifest_path, 'w') as manifest_file: manifest_file.write(yaml_dump(manifest)) if commit: git_commit(msg=modify_manifest.__name__, cwd=path)
def test_clone_tag_not_on_mainline(store, tempdir_factory): path = git_dir(tempdir_factory) with cwd(path): git_commit() cmd_output('git', 'checkout', 'master', '-b', 'branch') git_commit() cmd_output('git', 'tag', 'v1') cmd_output('git', 'checkout', 'master') cmd_output('git', 'branch', '-D', 'branch') # previously crashed on unreachable refs store.clone(path, 'v1')
def test_get_root_bare_worktree(tmpdir): src = tmpdir.join('src').ensure_dir() cmd_output('git', 'init', str(src)) git_commit(cwd=str(src)) bare = tmpdir.join('bare.git').ensure_dir() cmd_output('git', 'clone', '--bare', str(src), str(bare)) cmd_output('git', 'worktree', 'add', 'foo', 'HEAD', cwd=bare) with bare.join('foo').as_cwd(): assert git.get_root() == os.path.abspath('.')
def test_get_changed_files(in_git_dir): git_commit() in_git_dir.join('a.txt').ensure() in_git_dir.join('b.txt').ensure() cmd_output('git', 'add', '.') git_commit() files = git.get_changed_files('HEAD^', 'HEAD') assert files == ['a.txt', 'b.txt'] # files changed in source but not in origin should not be returned files = git.get_changed_files('HEAD', 'HEAD^') assert files == []
def test_install_in_submodule_and_run(tempdir_factory, store): src_path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') parent_path = git_dir(tempdir_factory) cmd_output('git', 'submodule', 'add', src_path, 'sub', cwd=parent_path) git_commit(cwd=parent_path) sub_pth = os.path.join(parent_path, 'sub') with cwd(sub_pth): assert install(C.CONFIG_FILE, store) == 0 ret, output = _get_commit_output(tempdir_factory) assert ret == 0 assert NORMAL_PRE_COMMIT_RUN.match(output)
def test_install_in_submodule_and_run(tempdir_factory, store): src_path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') parent_path = git_dir(tempdir_factory) cmd_output('git', 'submodule', 'add', src_path, 'sub', cwd=parent_path) git_commit(cwd=parent_path) sub_pth = os.path.join(parent_path, 'sub') with cwd(sub_pth): assert install(C.CONFIG_FILE, store, hook_types=['pre-commit']) == 0 ret, output = _get_commit_output(tempdir_factory) assert ret == 0 assert NORMAL_PRE_COMMIT_RUN.match(output)
def test_moves_with_gitlfs(temp_git_dir, monkeypatch): # pragma: no cover with temp_git_dir.as_cwd(): monkeypatch.setenv('HOME', str(temp_git_dir)) cmd_output('git', 'lfs', 'install') cmd_output('git', 'lfs', 'track', 'a.bin', 'b.bin') # First add the file we're going to move temp_git_dir.join('a.bin').write('a' * 10000) cmd_output('git', 'add', '--', '.') git_commit('-am', 'foo') # Now move it and make sure the hook still succeeds cmd_output('git', 'mv', 'a.bin', 'b.bin') assert main(('--maxkb', '9', 'b.bin')) == 0
def test_autocrlf_committed_crlf(in_git_dir, patch_dir): """Regression test for #570""" cmd_output('git', 'config', '--local', 'core.autocrlf', 'false') _write(b'1\r\n2\r\n') cmd_output('git', 'add', 'foo') git_commit() cmd_output('git', 'config', '--local', 'core.autocrlf', 'true') _write(b'1\r\n2\r\n\r\n\r\n\r\n') with staged_files_only(patch_dir): assert_no_diff()
def test_autocrlf_commited_crlf(in_git_dir, patch_dir): """Regression test for #570""" cmd_output('git', 'config', '--local', 'core.autocrlf', 'false') _write(b'1\r\n2\r\n') cmd_output('git', 'add', 'foo') git_commit() cmd_output('git', 'config', '--local', 'core.autocrlf', 'true') _write(b'1\r\n2\r\n\r\n\r\n\r\n') with staged_files_only(patch_dir): assert_no_diff()
def test_get_git_dir(tmpdir): """Regression test for #1972""" src = tmpdir.join('src').ensure_dir() cmd_output('git', 'init', str(src)) git_commit(cwd=str(src)) worktree = tmpdir.join('worktree').ensure_dir() cmd_output('git', 'worktree', 'add', '../worktree', cwd=src) with worktree.as_cwd(): assert git.get_git_dir() == src.ensure_dir('.git/worktrees/worktree', ) assert git.get_git_common_dir() == src.ensure_dir('.git')
def modify_config(path='.', commit=True): """Modify the config yielded by this context to write to .pre-commit-config.yaml """ config_path = os.path.join(path, C.CONFIG_FILE) with open(config_path) as f: config = yaml_load(f.read()) yield config with open(config_path, 'w', encoding='UTF-8') as config_file: config_file.write(yaml_dump(config)) if commit: git_commit(msg=modify_config.__name__, cwd=path)
def test_autoupdate_latest_no_config(out_of_date_repo, in_tmpdir, store): config = make_config_from_repo( out_of_date_repo.path, rev=out_of_date_repo.original_rev, ) write_config('.', config) cmd_output('git', 'rm', '-r', ':/', cwd=out_of_date_repo.path) git_commit(cwd=out_of_date_repo.path) ret = autoupdate(C.CONFIG_FILE, store, tags_only=False) assert ret == 1 with open(C.CONFIG_FILE) as f: assert out_of_date_repo.original_rev in f.read()
def test_commit_am(tempdir_factory, store): """Regression test for #322.""" path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): # Make an unstaged change open('unstaged', 'w').close() cmd_output('git', 'add', '.') git_commit(cwd=path) with io.open('unstaged', 'w') as foo_file: foo_file.write('Oh hai') assert install(C.CONFIG_FILE, store) == 0 ret, output = _get_commit_output(tempdir_factory) assert ret == 0
def test_unicode_merge_commit_message(tempdir_factory, store): path = make_consuming_repo(tempdir_factory, 'script_hooks_repo') with cwd(path): assert install(C.CONFIG_FILE, store) == 0 cmd_output('git', 'checkout', 'master', '-b', 'foo') git_commit('-n', cwd=path) cmd_output('git', 'checkout', 'master') cmd_output('git', 'merge', 'foo', '--no-ff', '--no-commit', '-m', '☃') # Used to crash git_commit( '--no-edit', msg=None, fn=cmd_output_mocked_pre_commit_home, tempdir_factory=tempdir_factory, )
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 commit_msg_repo(tempdir_factory): path = git_dir(tempdir_factory) config = { 'repo': 'local', 'hooks': [{ 'id': 'must-have-signoff', 'name': 'Must have "Signed off by:"', 'entry': 'grep -q "Signed off by:"', 'language': 'system', 'stages': ['commit-msg'], }], } write_config(path, config) with cwd(path): cmd_output('git', 'add', '.') git_commit(msg=commit_msg_repo.__name__) yield path
def failing_prepare_commit_msg_repo(tempdir_factory): path = git_dir(tempdir_factory) config = { 'repo': 'local', 'hooks': [{ 'id': 'add-signoff', 'name': 'Add "Signed off by:"', 'entry': 'bash -c "exit 1"', 'language': 'system', 'stages': ['prepare-commit-msg'], }], } write_config(path, config) with cwd(path): cmd_output('git', 'add', '.') git_commit(msg=failing_prepare_commit_msg_repo.__name__) yield path
def _make_conflict(): cmd_output('git', 'checkout', 'origin/master', '-b', 'foo') with io.open('conflict_file', 'w') as conflict_file: conflict_file.write('herp\nderp\n') cmd_output('git', 'add', 'conflict_file') with io.open('foo_only_file', 'w') as foo_only_file: foo_only_file.write('foo') cmd_output('git', 'add', 'foo_only_file') git_commit(msg=_make_conflict.__name__) cmd_output('git', 'checkout', 'origin/master', '-b', 'bar') with io.open('conflict_file', 'w') as conflict_file: conflict_file.write('harp\nddrp\n') cmd_output('git', 'add', 'conflict_file') with io.open('bar_only_file', 'w') as bar_only_file: bar_only_file.write('bar') cmd_output('git', 'add', 'bar_only_file') git_commit(msg=_make_conflict.__name__) cmd_output('git', 'merge', 'foo', retcode=None)
def test_gc(tempdir_factory, store, in_git_dir, cap_out): path = make_repo(tempdir_factory, 'script_hooks_repo') old_rev = git.head_rev(path) git_commit(cwd=path) write_config('.', make_config_from_repo(path, rev=old_rev)) store.mark_config_used(C.CONFIG_FILE) # update will clone both the old and new repo, making the old one gc-able assert not autoupdate(C.CONFIG_FILE, store, tags_only=False) assert _config_count(store) == 1 assert _repo_count(store) == 2 assert not gc(store) assert _config_count(store) == 1 assert _repo_count(store) == 1 assert cap_out.get().splitlines()[-1] == '1 repo(s) removed.' _remove_config_assert_cleared(store, cap_out)
def _get_commit_output(tempdir_factory, touch_file='foo', **kwargs): open(touch_file, 'a').close() cmd_output('git', 'add', touch_file) return git_commit( fn=cmd_output_mocked_pre_commit_home, # git commit puts pre-commit to stderr stderr=subprocess.STDOUT, retcode=None, tempdir_factory=tempdir_factory, **kwargs )[:2]
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_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_stdout_write_bug_py26(repo_with_failing_hook, store, tempdir_factory): with cwd(repo_with_failing_hook): with modify_config() as config: config['repos'][0]['hooks'][0]['args'] = ['☃'] stage_a_file() install(C.CONFIG_FILE, store) # Have to use subprocess because pytest monkeypatches sys.stdout _, stdout, _ = git_commit( fn=cmd_output_mocked_pre_commit_home, # git commit puts pre-commit to stderr stderr=subprocess.STDOUT, retcode=None, tempdir_factory=tempdir_factory, ) assert 'UnicodeEncodeError' not in stdout # Doesn't actually happen, but a reasonable assertion assert 'UnicodeDecodeError' not in stdout
def non_ascii_repo(in_git_dir): git_commit() in_git_dir.join('интервью').ensure() cmd_output('git', 'add', '.') git_commit() yield in_git_dir
def test_get_staged_files_deleted(in_git_dir): in_git_dir.join('test').ensure() cmd_output('git', 'add', 'test') git_commit() cmd_output('git', 'rm', '--cached', 'test') assert git.get_staged_files() == []
def tagged_repo_with_more_commits(tagged_repo): git_commit(cwd=tagged_repo.path) yield tagged_repo