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 install_environment( prefix, version, additional_dependencies, ): # pragma: windows no cover additional_dependencies = tuple(additional_dependencies) assert prefix.exists('package.json') envdir = _envdir(prefix, version) # https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx?f=255&MSPPError=-2147217396#maxpath if sys.platform == 'win32': # pragma: no cover envdir = '\\\\?\\' + os.path.normpath(envdir) with clean_path_on_failure(envdir): cmd = [ sys.executable, '-mnodeenv', '--prebuilt', '--clean-src', envdir, ] if version != C.DEFAULT: cmd.extend(['-n', version]) cmd_output(*cmd) with in_env(prefix, version): # https://npm.community/t/npm-install-g-git-vs-git-clone-cd-npm-install-g/5449 # install as if we installed from git helpers.run_setup_cmd(prefix, ('npm', 'install')) helpers.run_setup_cmd( prefix, ('npm', 'install', '-g', '.') + additional_dependencies, )
def commit(repo='.'): env = no_git_env() name, email = 'pre-commit', '*****@*****.**' env['GIT_AUTHOR_NAME'] = env['GIT_COMMITTER_NAME'] = name env['GIT_AUTHOR_EMAIL'] = env['GIT_COMMITTER_EMAIL'] = email cmd = ('git', 'commit', '--no-edit', '--no-gpg-sign', '-n', '-minit') cmd_output(*cmd, cwd=repo, env=env)
def test_local_hook_fails(cap_out, store, repo_with_passing_hook): config = { 'repo': 'local', 'hooks': [{ 'id': 'no-todo', 'name': 'No TODO', 'entry': 'sh -c "! grep -iI todo $@" --', 'language': 'system', }], } add_config_to_repo(repo_with_passing_hook, config) with io.open('dummy.py', 'w') as staged_file: staged_file.write('"""TODO: something"""\n') cmd_output('git', 'add', 'dummy.py') _test_run( cap_out, store, repo_with_passing_hook, opts={}, expected_outputs=[b''], expected_ret=1, stage=False, )
def test_local_hook_passes(repo_with_passing_hook, mock_out_store_directory): config = OrderedDict(( ('repo', 'local'), ('hooks', (OrderedDict(( ('id', 'pylint'), ('name', 'PyLint'), ('entry', 'python -m pylint.__main__'), ('language', 'system'), ('files', r'\.py$'), )), OrderedDict(( ('id', 'do_not_commit'), ('name', 'Block if "DO NOT COMMIT" is found'), ('entry', 'DO NOT COMMIT'), ('language', 'pcre'), ('files', '^(.*)$'), )))) )) add_config_to_repo(repo_with_passing_hook, config) with io.open('dummy.py', 'w') as staged_file: staged_file.write('"""TODO: something"""\n') cmd_output('git', 'add', 'dummy.py') _test_run( repo_with_passing_hook, options={}, expected_outputs=[b''], expected_ret=0, stage=False )
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_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 make_archive(name, repo, ref, destdir): """Makes an archive of a repository in the given destdir. :param text name: Name to give the archive. For instance foo. The file that is created will be called foo.tar.gz. :param text repo: Repository to clone. :param text ref: Tag/SHA/branch to check out. :param text destdir: Directory to place archives in. """ output_path = os.path.join(destdir, name + '.tar.gz') with tmpdir() as tempdir: # Clone the repository to the temporary directory cmd_output('git', 'clone', repo, tempdir) with cwd(tempdir): cmd_output('git', 'checkout', ref) # We don't want the '.git' directory # It adds a bunch of size to the archive and we don't use it at # runtime rmtree(os.path.join(tempdir, '.git')) with tarfile.open(five.n(output_path), 'w|gz') as tf: tf.add(tempdir, name) return output_path
def test_lots_of_files(mock_out_store_directory, tempdir_factory): # windows xargs seems to have a bug, here's a regression test for # our workaround git_path = make_consuming_repo(tempdir_factory, 'python_hooks_repo') with cwd(git_path): # Override files so we run against them with modify_config() as config: config[0]['hooks'][0]['files'] = '' # Write a crap ton of files for i in range(400): filename = '{0}{1}'.format('a' * 100, i) open(filename, 'w').close() cmd_output('bash', '-c', 'git add .') install(Runner(git_path)) # Don't want to write to home directory env = dict(os.environ, PRE_COMMIT_HOME=tempdir_factory.get()) cmd_output( 'git', 'commit', '-m', 'Commit!', # git commit puts pre-commit to stderr stderr=subprocess.STDOUT, env=env, )
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_merge_conflict_resolved(in_merge_conflict, mock_out_store_directory): cmd_output('git', 'add', '.') ret, printed = _do_run(in_merge_conflict, _get_opts()) for msg in ( b'Checking merge-conflict files only.', b'Bash hook', b'Passed', ): assert msg in printed
def clone_strategy(directory): cmd_output( 'git', 'clone', '--no-checkout', repo, directory, env=no_git_env(), ) with cwd(directory): cmd_output('git', 'reset', ref, '--hard', env=no_git_env())
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 _git_apply(patch): args = ('apply', '--whitespace=nowarn', patch) try: cmd_output('git', *args, encoding=None) except CalledProcessError: # Retry with autocrlf=false -- see #570 cmd_output('git', '-c', 'core.autocrlf=false', *args, encoding=None)
def install_environment(repo_cmd_runner, version, additional_dependencies): helpers.assert_version_default('golang', version) directory = repo_cmd_runner.path( helpers.environment_dir(ENVIRONMENT_DIR, 'default'), ) with clean_path_on_failure(directory): remote = git.get_remote_url(repo_cmd_runner.path()) repo_src_dir = os.path.join(directory, 'src', guess_go_dir(remote)) # Clone into the goenv we'll create helpers.run_setup_cmd( repo_cmd_runner, ('git', 'clone', '.', repo_src_dir), ) if sys.platform == 'cygwin': # pragma: no cover _, gopath, _ = cmd_output('cygpath', '-w', directory) gopath = gopath.strip() else: gopath = directory env = dict(os.environ, GOPATH=gopath) cmd_output('go', 'get', './...', cwd=repo_src_dir, env=env) for dependency in additional_dependencies: cmd_output('go', 'get', dependency, cwd=repo_src_dir, env=env) # Same some disk space, we don't need these after installation rmtree(repo_cmd_runner.path(directory, 'src')) rmtree(repo_cmd_runner.path(directory, 'pkg'))
def img_staged(tempdir_factory): path = git_dir(tempdir_factory) with cwd(path): img_filename = os.path.join(path, 'img.jpg') shutil.copy(get_resource_path('img1.jpg'), img_filename) cmd_output('git', 'add', 'img.jpg') yield auto_namedtuple(path=path, img_filename=img_filename)
def clone(self, url, sha): """Clone the given url and checkout the specific sha.""" self.require_created() # Check if we already exist with sqlite3.connect(self.db_path) as db: result = db.execute( 'SELECT path FROM repos WHERE repo = ? AND ref = ?', [url, sha], ).fetchone() if result: return result[0] logger.info('Initializing environment for {0}.'.format(url)) dir = tempfile.mkdtemp(prefix='repo', dir=self.directory) with clean_path_on_failure(dir): cmd_output( 'git', 'clone', '--no-checkout', url, dir, env=no_git_env(), ) with cwd(dir): cmd_output('git', 'reset', sha, '--hard', env=no_git_env()) # Update our db with the created repo with sqlite3.connect(self.db_path) as db: db.execute( 'INSERT INTO repos (repo, ref, path) VALUES (?, ?, ?)', [url, sha, dir], ) return dir
def _update_repository(repo_config, runner): """Updates a repository to the tip of `master`. If the repository cannot be updated because a hook that is configured does not exist in `master`, this raises a RepositoryCannotBeUpdatedError Args: repo_config - A config for a repository """ repo = Repository.create(repo_config, runner.store) with cwd(repo.repo_path_getter.repo_path): cmd_output('git', 'fetch') head_sha = cmd_output('git', 'rev-parse', 'origin/master')[1].strip() # Don't bother trying to update if our sha is the same if head_sha == repo_config['sha']: return repo_config # Construct a new config with the head sha new_config = OrderedDict(repo_config) new_config['sha'] = head_sha new_repo = Repository.create(new_config, runner.store) # See if any of our hooks were deleted with the new commits hooks = set(hook_id for hook_id, _ in repo.hooks) hooks_missing = hooks - (hooks & set(new_repo.manifest.hooks.keys())) if hooks_missing: raise RepositoryCannotBeUpdatedError( 'Cannot update because the tip of master is missing these hooks:\n' '{0}'.format(', '.join(sorted(hooks_missing))) ) return new_config
def test_local_hook_passes(cap_out, store, repo_with_passing_hook): config = { 'repo': 'local', 'hooks': [ { 'id': 'flake8', 'name': 'flake8', 'entry': "'{}' -m flake8".format(sys.executable), 'language': 'system', 'files': r'\.py$', }, { '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) with io.open('dummy.py', 'w') as staged_file: staged_file.write('"""TODO: something"""\n') cmd_output('git', 'add', 'dummy.py') _test_run( cap_out, store, repo_with_passing_hook, opts={}, expected_outputs=[b''], expected_ret=0, stage=False, )
def test_stdout_write_bug_py26( repo_with_failing_hook, mock_out_store_directory, tmpdir_factory, ): with cwd(repo_with_failing_hook): # Add bash hook on there again with io.open( '.pre-commit-config.yaml', 'a+', encoding='UTF-8', ) as config_file: config_file.write(' args: ["☃"]\n') cmd_output('git', 'add', '.pre-commit-config.yaml') stage_a_file() install(Runner(repo_with_failing_hook)) # Don't want to write to home directory env = dict(os.environ, PRE_COMMIT_HOME=tmpdir_factory.get()) # Have to use subprocess because pytest monkeypatches sys.stdout _, stdout, _ = cmd_output( 'git', 'commit', '-m', 'Commit!', # git commit puts pre-commit to stderr stderr=subprocess.STDOUT, env=env, retcode=None, ) assert 'UnicodeEncodeError' not in stdout # Doesn't actually happen, but a reasonable assertion assert 'UnicodeDecodeError' not in stdout
def test_clone(store, tempdir_factory, log_info_mock): path = git_dir(tempdir_factory) with cwd(path): cmd_output('git', 'commit', '--allow-empty', '-m', 'foo') sha = get_head_sha(path) cmd_output('git', 'commit', '--allow-empty', '-m', 'bar') ret = store.clone(path, sha) # 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 sha we specified assert get_head_sha(ret) == sha # Assert there's an entry in the sqlite db for this with sqlite3.connect(store.db_path) as db: path, = db.execute( 'SELECT path from repos WHERE repo = ? and ref = ?', [path, sha], ).fetchone() assert path == ret
def make_repo(tempdir_factory, repo_source): path = git_dir(tempdir_factory) copy_tree_to_path(get_resource_path(repo_source), path) with cwd(path): cmd_output('git', 'add', '.') cmd_output('git', 'commit', '-m', 'Add hooks') return path
def test_local_hook_fails( cap_out, repo_with_passing_hook, mock_out_store_directory, ): config = OrderedDict(( ('repo', 'local'), ('hooks', [OrderedDict(( ('id', 'no-todo'), ('name', 'No TODO'), ('entry', 'sh -c "! grep -iI todo $@" --'), ('language', 'system'), ('files', ''), ))]) )) add_config_to_repo(repo_with_passing_hook, config) with io.open('dummy.py', 'w') as staged_file: staged_file.write('"""TODO: something"""\n') cmd_output('git', 'add', 'dummy.py') _test_run( cap_out, repo_with_passing_hook, opts={}, expected_outputs=[b''], expected_ret=1, stage=False, )
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 modify_manifest(path): """Modify the manifest yielded by this context to write to hooks.yaml.""" manifest_path = os.path.join(path, C.MANIFEST_FILE) manifest = ordered_load(io.open(manifest_path).read()) yield manifest with io.open(manifest_path, 'w') as manifest_file: manifest_file.write(ordered_dump(manifest, **C.YAML_DUMP_KWARGS)) cmd_output('git', 'commit', '-am', 'update hooks.yaml', cwd=path)
def test_get_conflicted_files(in_merge_conflict): resolve_conflict() with open('other_file', 'w') as other_file: other_file.write('oh hai') cmd_output('git', 'add', 'other_file') ret = set(git.get_conflicted_files()) assert ret == set(('conflict_file', 'other_file'))
def test_get_conflicted_files(in_merge_conflict): resolve_conflict() with open("other_file", "w") as other_file: other_file.write("oh hai") cmd_output("git", "add", "other_file") ret = set(git.get_conflicted_files()) assert ret == set(("conflict_file", "other_file"))
def foo_staged(tempdir_factory): path = git_dir(tempdir_factory) with cwd(path): with io.open('foo', 'w') as foo_file: foo_file.write(FOO_CONTENTS) cmd_output('git', 'add', 'foo') foo_filename = os.path.join(path, 'foo') yield auto_namedtuple(path=path, foo_filename=foo_filename)
def test_intent_to_add(in_git_dir, patch_dir): """Regression test for #881""" _write(b'hello\nworld\n') cmd_output('git', 'add', '--intent-to-add', 'foo') assert git.intent_to_add_files() == ['foo'] with staged_files_only(patch_dir): assert_no_diff() assert git.intent_to_add_files() == ['foo']
def stage_a_file(filename='foo.py'): open(filename, 'a').close() cmd_output('git', 'add', filename)
def get_all_files() -> List[str]: return zsplit(cmd_output('git', 'ls-files', '-z')[1])
def run_setup_cmd(prefix, cmd): cmd_output(*cmd, cwd=prefix.prefix_dir, encoding=None)
def head_rev(remote: str) -> str: _, out, _ = cmd_output('git', 'ls-remote', '--exit-code', remote, 'HEAD') return out.split()[0]
def test_intent_to_add(in_git_dir): in_git_dir.join('a').ensure() cmd_output('git', 'add', '--intent-to-add', 'a') assert git.intent_to_add_files() == ['a']
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 git_path(name: str, repo: str = '.') -> str: _, out, _ = cmd_output('git', 'rev-parse', '--git-path', name, cwd=repo) return os.path.join(repo, out.strip())
def test_rev_info_update_non_master_default_branch(out_of_date): # change the default branch to be not-master cmd_output('git', '-C', out_of_date.path, 'branch', '-m', 'dev') test_rev_info_update_out_of_date_repo(out_of_date)
def _run_single_hook(classifier, hook, args, skips, cols): filenames = classifier.filenames_for_hook(hook) if hook.language == 'pcre': logger.warning( '`{}` (from {}) uses the deprecated pcre language.\n' 'The pcre language is scheduled for removal in pre-commit 2.x.\n' 'The pygrep language is a more portable (and usually drop-in) ' 'replacement.'.format(hook.id, hook.src), ) if hook.id in skips or hook.alias in skips: output.write( get_hook_message( _hook_msg_start(hook, args.verbose), end_msg=SKIPPED, end_color=color.YELLOW, use_color=args.color, cols=cols, ), ) return 0 elif not filenames and not hook.always_run: output.write( get_hook_message( _hook_msg_start(hook, args.verbose), postfix=NO_FILES, end_msg=SKIPPED, end_color=color.TURQUOISE, use_color=args.color, cols=cols, ), ) return 0 # Print the hook and the dots first in case the hook takes hella long to # run. output.write( get_hook_message( _hook_msg_start(hook, args.verbose), end_len=6, cols=cols, ), ) sys.stdout.flush() diff_before = cmd_output( 'git', 'diff', '--no-ext-diff', retcode=None, encoding=None, ) retcode, stdout, stderr = hook.run( tuple(filenames) if hook.pass_filenames else (), ) diff_after = cmd_output( 'git', 'diff', '--no-ext-diff', retcode=None, encoding=None, ) file_modifications = diff_before != diff_after # If the hook makes changes, fail the commit if file_modifications: retcode = 1 if retcode: retcode = 1 print_color = color.RED pass_fail = 'Failed' else: retcode = 0 print_color = color.GREEN pass_fail = 'Passed' output.write_line(color.format_color(pass_fail, print_color, args.color)) if ((stdout or stderr or file_modifications) and (retcode or args.verbose or hook.verbose)): output.write_line('hookid: {}\n'.format(hook.id)) # Print a message if failing due to file modifications if file_modifications: output.write('Files were modified by this hook.') if stdout or stderr: output.write_line(' Additional output:') output.write_line() for out in (stdout, stderr): assert type(out) is bytes, type(out) if out.strip(): output.write_line(out.strip(), logfile_name=hook.log_file) output.write_line() return retcode
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 get_all_files(): return cmd_output('git', 'ls-files')[1].splitlines()
def tagged_repo_with_more_commits(tagged_repo): cmd_output('git', 'commit', '--allow-empty', '-mfoo', cwd=tagged_repo.path) yield tagged_repo
def tagged_repo(out_of_date_repo): cmd_output('git', 'tag', 'v1.2.3', cwd=out_of_date_repo.path) yield out_of_date_repo
def resolve_conflict(): with open('conflict_file', 'w') as conflicted_file: conflicted_file.write('herp\nderp\n') cmd_output('git', 'add', 'conflict_file')
def stage_a_file(filename='foo.py'): cmd_output('touch', filename) cmd_output('git', 'add', filename)
def _has_unmerged_paths(): _, stdout, _ = cmd_output('git', 'ls-files', '--unmerged') return bool(stdout.strip())
def get_staged_files(): return cmd_output('git', 'diff', '--staged', '--name-only')[1].splitlines()
def tagged(out_of_date): cmd_output('git', 'tag', 'v1.2.3', cwd=out_of_date.path) yield out_of_date
def docker_is_running(): # pragma: windows no cover try: return cmd_output('docker', 'ps')[0] == 0 except CalledProcessError: return False
def test_staged_files_non_ascii(non_ascii_repo): non_ascii_repo.join('интервью').write('hi') cmd_output('git', 'add', '.') assert git.get_staged_files() == ['интервью']
def run_setup_cmd(runner, cmd): cmd_output(*cmd, cwd=runner.prefix_dir, encoding=None)
def get_remote_url(git_root: str) -> str: _, out, _ = cmd_output('git', 'config', 'remote.origin.url', cwd=git_root) return out.strip()
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 _run_single_hook(hook, repo, args, skips, cols): filenames = get_filenames(args, hook['files'], hook['exclude']) if hook['id'] in skips: output.write( get_hook_message( _hook_msg_start(hook, args.verbose), end_msg=SKIPPED, end_color=color.YELLOW, use_color=args.color, cols=cols, )) return 0 elif not filenames and not hook['always_run']: output.write( get_hook_message( _hook_msg_start(hook, args.verbose), postfix=NO_FILES, end_msg=SKIPPED, end_color=color.TURQUOISE, use_color=args.color, cols=cols, )) return 0 # Print the hook and the dots first in case the hook takes hella long to # run. output.write( get_hook_message( _hook_msg_start(hook, args.verbose), end_len=6, cols=cols, )) sys.stdout.flush() diff_before = cmd_output('git', 'diff', retcode=None, encoding=None) retcode, stdout, stderr = repo.run_hook(hook, tuple(filenames)) diff_after = cmd_output('git', 'diff', retcode=None, encoding=None) file_modifications = diff_before != diff_after # If the hook makes changes, fail the commit if file_modifications: retcode = 1 if retcode: retcode = 1 print_color = color.RED pass_fail = 'Failed' else: retcode = 0 print_color = color.GREEN pass_fail = 'Passed' output.write_line(color.format_color(pass_fail, print_color, args.color)) if (stdout or stderr or file_modifications) and (retcode or args.verbose): output.write_line('hookid: {}\n'.format(hook['id'])) # Print a message if failing due to file modifications if file_modifications: output.write('Files were modified by this hook.') if stdout or stderr: output.write_line(' Additional output:') output.write_line() for out in (stdout, stderr): assert type(out) is bytes, type(out) if out.strip(): output.write_line(out.strip()) output.write_line() return retcode
def test_get_conflicted_files_non_ascii(in_merge_conflict): open('интервью', 'a').close() cmd_output('git', 'add', '.') ret = git.get_conflicted_files() assert ret == {'conflict_file', 'интервью'}
def test_cherry_pick_conflict(in_merge_conflict): cmd_output('git', 'merge', '--abort') foo_ref = cmd_output('git', 'rev-parse', 'foo')[1].strip() cmd_output('git', 'cherry-pick', foo_ref, retcode=None) assert git.is_in_merge_conflict() is False