def try_repo(args): with tmpdir() as tempdir: repo, ref = _repo_ref(tempdir, args.repo, args.ref) store = Store(tempdir) if args.hook: hooks = [{'id': args.hook}] else: repo_path = store.clone(repo, ref) manifest = load_manifest(os.path.join(repo_path, C.MANIFEST_FILE)) manifest = sorted(manifest, key=lambda hook: hook['id']) hooks = [{'id': hook['id']} for hook in manifest] items = (('repo', repo), ('rev', ref), ('hooks', hooks)) config = {'repos': [collections.OrderedDict(items)]} config_s = ordered_dump(config, **C.YAML_DUMP_KWARGS) config_filename = os.path.join(tempdir, C.CONFIG_FILE) with open(config_filename, 'w') as cfg: cfg.write(config_s) output.write_line('=' * 79) output.write_line('Using config:') output.write_line('=' * 79) output.write(config_s) output.write_line('=' * 79) return run(config_filename, store, args)
def try_repo(args): ref = args.ref or git.head_rev(args.repo) with tmpdir() as tempdir: if args.hook: hooks = [{'id': args.hook}] else: repo_path = Store(tempdir).clone(args.repo, ref) manifest = load_manifest(os.path.join(repo_path, C.MANIFEST_FILE)) manifest = sorted(manifest, key=lambda hook: hook['id']) hooks = [{'id': hook['id']} for hook in manifest] items = (('repo', args.repo), ('rev', ref), ('hooks', hooks)) config = {'repos': [collections.OrderedDict(items)]} config_s = ordered_dump(config, **C.YAML_DUMP_KWARGS) config_filename = os.path.join(tempdir, C.CONFIG_FILE) with open(config_filename, 'w') as cfg: cfg.write(config_s) output.write_line('=' * 79) output.write_line('Using config:') output.write_line('=' * 79) output.write(config_s) output.write_line('=' * 79) runner = Runner('.', config_filename, store_dir=tempdir) return run(runner, args)
def try_repo(args: argparse.Namespace) -> int: with tmpdir() as tempdir: repo, ref = _repo_ref(tempdir, args.repo, args.ref) store = Store(tempdir) if args.hook: hooks = [{'id': args.hook}] else: repo_path = store.clone(repo, ref) manifest = load_manifest(os.path.join(repo_path, C.MANIFEST_FILE)) manifest = sorted(manifest, key=lambda hook: hook['id']) hooks = [{'id': hook['id']} for hook in manifest] config = {'repos': [{'repo': repo, 'rev': ref, 'hooks': hooks}]} config_s = yaml_dump(config) config_filename = os.path.join(tempdir, C.CONFIG_FILE) with open(config_filename, 'w') as cfg: cfg.write(config_s) output.write_line('=' * 79) output.write_line('Using config:') output.write_line('=' * 79) output.write(config_s) output.write_line('=' * 79) return run(config_filename, store, args)
def try_repo(args): ref = args.ref or git.head_sha(args.repo) with tmpdir() as tempdir: if args.hook: hooks = [{'id': args.hook}] else: manifest = Manifest(Store(tempdir).clone(args.repo, ref)) hooks = [{'id': hook_id} for hook_id in sorted(manifest.hooks)] items = (('repo', args.repo), ('sha', ref), ('hooks', hooks)) config = {'repos': [collections.OrderedDict(items)]} config_s = ordered_dump(config, **C.YAML_DUMP_KWARGS) config_filename = os.path.join(tempdir, C.CONFIG_FILE) with open(config_filename, 'w') as cfg: cfg.write(config_s) output.write_line('=' * 79) output.write_line('Using config:') output.write_line('=' * 79) output.write(config_s) output.write_line('=' * 79) runner = Runner('.', config_filename, store_dir=tempdir) return run(runner, args)
def try_repo(args: argparse.Namespace) -> int: with tmpdir() as tempdir: repo, ref = _repo_ref(tempdir, args.repo, args.ref) store = Store(tempdir) if args.hook: hooks = [{"id": args.hook}] else: repo_path = store.clone(repo, ref) manifest = load_manifest(os.path.join(repo_path, C.MANIFEST_FILE)) manifest = sorted(manifest, key=lambda hook: hook["id"]) hooks = [{"id": hook["id"]} for hook in manifest] config = {"repos": [{"repo": repo, "rev": ref, "hooks": hooks}]} config_s = yaml_dump(config) config_filename = os.path.join(tempdir, C.CONFIG_FILE) with open(config_filename, "w") as cfg: cfg.write(config_s) output.write_line("=" * 79) output.write_line("Using config:") output.write_line("=" * 79) output.write(config_s) output.write_line("=" * 79) return run(config_filename, store, args)
def _process_filename_by_line(pattern: Pattern[bytes], filename: str) -> int: retv = 0 with open(filename, "rb") as f: for line_no, line in enumerate(f, start=1): if pattern.search(line): retv = 1 output.write(f"{filename}:{line_no}:") output.write_line_b(line.rstrip(b"\r\n")) return retv
def _process_filename_by_line(pattern, filename): retv = 0 with open(filename, 'rb') as f: for line_no, line in enumerate(f, start=1): if pattern.search(line): retv = 1 output.write('{}:{}:'.format(filename, line_no)) output.write_line(line.rstrip(b'\r\n')) return retv
def _log_and_exit(msg, exc, formatted): error_msg = b''.join(( five.to_bytes(msg), b': ', five.to_bytes(type(exc).__name__), b': ', _to_bytes(exc), b'\n', )) output.write(error_msg) output.write_line('Check the log at ~/.pre-commit/pre-commit.log') store = Store() store.require_created() with open(os.path.join(store.directory, 'pre-commit.log'), 'wb') as log: output.write(error_msg, stream=log) output.write_line(formatted, stream=log) raise PreCommitSystemExit(1)
def autoupdate( config_file: str, store: Store, tags_only: bool, freeze: bool, repos: Sequence[str] = (), ) -> int: """Auto-update the pre-commit config to the latest versions of repos.""" migrate_config(config_file, quiet=True) retv = 0 rev_infos: List[Optional[RevInfo]] = [] changed = False config = load_config(config_file) for repo_config in config['repos']: if repo_config['repo'] in {LOCAL, META}: continue info = RevInfo.from_config(repo_config) if repos and info.repo not in repos: rev_infos.append(None) continue output.write(f'Updating {info.repo} ... ') new_info = info.update(tags_only=tags_only, freeze=freeze) try: _check_hooks_still_exist_at_rev(repo_config, new_info, store) except RepositoryCannotBeUpdatedError as error: output.write_line(error.args[0]) rev_infos.append(None) retv = 1 continue if new_info.rev != info.rev: changed = True if new_info.frozen: updated_to = f'{new_info.frozen} (frozen)' else: updated_to = new_info.rev msg = f'updating {info.rev} -> {updated_to}.' output.write_line(msg) rev_infos.append(new_info) else: output.write_line('already up to date.') rev_infos.append(None) if changed: _write_new_config(config_file, rev_infos) return retv
def _log_and_exit(msg, exc, formatted): error_msg = b''.join(( five.to_bytes(msg), b': ', five.to_bytes(type(exc).__name__), b': ', _to_bytes(exc), b'\n', )) output.write(error_msg) store = Store() log_path = os.path.join(store.directory, 'pre-commit.log') output.write_line('Check the log at {}'.format(log_path)) with open(log_path, 'wb') as log: output.write(error_msg, stream=log) output.write_line(formatted, stream=log) raise SystemExit(1)
def _log_and_exit(msg, exc, formatted): error_msg = b''.join(( five.to_bytes(msg), b': ', five.to_bytes(type(exc).__name__), b': ', _to_bytes(exc), b'\n', )) output.write(error_msg) output.write_line('Check the log at ~/.pre-commit/pre-commit.log') store = Store() store.require_created() with io.open(os.path.join(store.directory, 'pre-commit.log'), 'wb') as log: output.write(error_msg, stream=log) output.write_line(formatted, stream=log) raise PreCommitSystemExit(1)
def _process_filename_at_once(pattern: Pattern[bytes], filename: str) -> int: retv = 0 with open(filename, "rb") as f: contents = f.read() match = pattern.search(contents) if match: retv = 1 line_no = contents[: match.start()].count(b"\n") output.write(f"{filename}:{line_no + 1}:") matched_lines = match[0].split(b"\n") matched_lines[0] = contents.split(b"\n")[line_no] output.write_line_b(b"\n".join(matched_lines)) return retv
def _process_filename_at_once(pattern, filename): retv = 0 with open(filename, 'rb') as f: contents = f.read() match = pattern.search(contents) if match: retv = 1 line_no = contents[:match.start()].count(b'\n') output.write('{}:{}:'.format(filename, line_no + 1)) matched_lines = match.group().split(b'\n') matched_lines[0] = contents.split(b'\n')[line_no] output.write_line(b'\n'.join(matched_lines)) return retv
def autoupdate(config_file, store, tags_only, repos=()): """Auto-update the pre-commit config to the latest versions of repos.""" migrate_config(config_file, quiet=True) retv = 0 output_repos = [] changed = False input_config = load_config(config_file) for repo_config in input_config['repos']: if ( repo_config['repo'] in {LOCAL, META} or # Skip updating any repo_configs that aren't for the specified repo repos and repo_config['repo'] not in repos ): output_repos.append(repo_config) continue output.write('Updating {}...'.format(repo_config['repo'])) try: new_repo_config = _update_repo(repo_config, store, tags_only) except RepositoryCannotBeUpdatedError as error: output.write_line(error.args[0]) output_repos.append(repo_config) retv = 1 continue if new_repo_config['rev'] != repo_config['rev']: changed = True output.write_line( 'updating {} -> {}.'.format( repo_config['rev'], new_repo_config['rev'], ), ) output_repos.append(new_repo_config) else: output.write_line('already up to date.') output_repos.append(repo_config) if changed: output_config = input_config.copy() output_config['repos'] = output_repos _write_new_config_file(config_file, output_config) return retv
def autoupdate(runner): """Auto-update the pre-commit config to the latest versions of repos.""" retv = 0 output_configs = [] changed = False input_configs = load_config( runner.config_file_path, load_strategy=ordered_load, ) for repo_config in input_configs: if is_local_hooks(repo_config): output_configs.append(repo_config) continue output.write('Updating {}...'.format(repo_config['repo'])) try: new_repo_config = _update_repository(repo_config, runner) except RepositoryCannotBeUpdatedError as error: output.write_line(error.args[0]) output_configs.append(repo_config) retv = 1 continue if new_repo_config['sha'] != repo_config['sha']: changed = True output.write_line('updating {} -> {}.'.format( repo_config['sha'], new_repo_config['sha'], )) output_configs.append(new_repo_config) else: output.write_line('already up to date.') output_configs.append(repo_config) if changed: with open(runner.config_file_path, 'w') as config_file: config_file.write( ordered_dump( remove_defaults(output_configs, CONFIG_JSON_SCHEMA), **C.YAML_DUMP_KWARGS ) ) return retv
def autoupdate(config_file, store, tags_only, freeze, repos=()): """Auto-update the pre-commit config to the latest versions of repos.""" migrate_config(config_file, quiet=True) retv = 0 rev_infos = [] changed = False config = load_config(config_file) for repo_config in config['repos']: if repo_config['repo'] in {LOCAL, META}: continue info = RevInfo.from_config(repo_config) if repos and info.repo not in repos: rev_infos.append(None) continue output.write('Updating {} ... '.format(info.repo)) new_info = info.update(tags_only=tags_only, freeze=freeze) try: _check_hooks_still_exist_at_rev(repo_config, new_info, store) except RepositoryCannotBeUpdatedError as error: output.write_line(error.args[0]) rev_infos.append(None) retv = 1 continue if new_info.rev != info.rev: changed = True if new_info.frozen: updated_to = '{} (frozen)'.format(new_info.frozen) else: updated_to = new_info.rev msg = 'updating {} -> {}.'.format(info.rev, updated_to) output.write_line(msg) rev_infos.append(new_info) else: output.write_line('already up to date.') rev_infos.append(None) if changed: _write_new_config(config_file, rev_infos) return retv
def autoupdate(runner): """Auto-update the pre-commit config to the latest versions of repos.""" retv = 0 output_configs = [] changed = False input_configs = load_config( runner.config_file_path, load_strategy=ordered_load, ) for repo_config in input_configs: if is_local_hooks(repo_config): output_configs.append(repo_config) continue output.write('Updating {}...'.format(repo_config['repo'])) try: new_repo_config = _update_repository(repo_config, runner) except RepositoryCannotBeUpdatedError as error: output.write_line(error.args[0]) output_configs.append(repo_config) retv = 1 continue if new_repo_config['sha'] != repo_config['sha']: changed = True output.write_line('updating {} -> {}.'.format( repo_config['sha'], new_repo_config['sha'], )) output_configs.append(new_repo_config) else: output.write_line('already up to date.') output_configs.append(repo_config) if changed: with open(runner.config_file_path, 'w') as config_file: config_file.write( ordered_dump( remove_defaults(output_configs, CONFIG_JSON_SCHEMA), **C.YAML_DUMP_KWARGS)) return retv
def autoupdate(runner, tags_only, repo=None): """Auto-update the pre-commit config to the latest versions of repos.""" migrate_config(runner, quiet=True) retv = 0 output_repos = [] changed = False input_config = load_config(runner.config_file_path) for repo_config in input_config['repos']: if (is_local_repo(repo_config) or is_meta_repo(repo_config) or # Skip updating any repo_configs that aren't for the specified repo repo and repo != repo_config['repo']): output_repos.append(repo_config) continue output.write('Updating {}...'.format(repo_config['repo'])) try: new_repo_config = _update_repo(repo_config, runner, tags_only) except RepositoryCannotBeUpdatedError as error: output.write_line(error.args[0]) output_repos.append(repo_config) retv = 1 continue if new_repo_config['sha'] != repo_config['sha']: changed = True output.write_line('updating {} -> {}.'.format( repo_config['sha'], new_repo_config['sha'], )) output_repos.append(new_repo_config) else: output.write_line('already up to date.') output_repos.append(repo_config) if changed: output_config = input_config.copy() output_config['repos'] = output_repos _write_new_config_file(runner.config_file_path, output_config) return retv
def autoupdate(runner, tags_only): """Auto-update the pre-commit config to the latest versions of repos.""" retv = 0 output_configs = [] changed = False input_configs = load_config( runner.config_file_path, load_strategy=ordered_load, ) for repo_config in input_configs: if is_local_repo(repo_config): output_configs.append(repo_config) continue output.write('Updating {}...'.format(repo_config['repo'])) try: new_repo_config = _update_repo(repo_config, runner, tags_only) except RepositoryCannotBeUpdatedError as error: output.write_line(error.args[0]) output_configs.append(repo_config) retv = 1 continue if new_repo_config['sha'] != repo_config['sha']: changed = True output.write_line('updating {} -> {}.'.format( repo_config['sha'], new_repo_config['sha'], )) output_configs.append(new_repo_config) else: output.write_line('already up to date.') output_configs.append(repo_config) if changed: _write_new_config_file(runner.config_file_path, output_configs) return retv
def autoupdate(runner, tags_only): """Auto-update the pre-commit config to the latest versions of repos.""" migrate_config(runner, quiet=True) retv = 0 output_repos = [] changed = False input_config = load_config(runner.config_file_path) for repo_config in input_config['repos']: if is_local_repo(repo_config): output_repos.append(repo_config) continue output.write('Updating {}...'.format(repo_config['repo'])) try: new_repo_config = _update_repo(repo_config, runner, tags_only) except RepositoryCannotBeUpdatedError as error: output.write_line(error.args[0]) output_repos.append(repo_config) retv = 1 continue if new_repo_config['sha'] != repo_config['sha']: changed = True output.write_line('updating {} -> {}.'.format( repo_config['sha'], new_repo_config['sha'], )) output_repos.append(new_repo_config) else: output.write_line('already up to date.') output_repos.append(repo_config) if changed: output_config = input_config.copy() output_config['repos'] = output_repos _write_new_config_file(runner.config_file_path, output_config) return retv
def test_output_write_writes(): fake_stream = mock.Mock() output.write('hello world', fake_stream) assert fake_stream.write.call_count == 1
def _run_single_hook(hook, repo, args, skips, cols): filenames = get_filenames(args, hook['files'], hook['exclude']) filenames = filter_filenames_by_types( filenames, hook['types'], hook['exclude_types'], ) 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', '--no-ext-diff', retcode=None, encoding=None, ) retcode, stdout, stderr = repo.run_hook( hook, 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): 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 _run_single_hook( classifier: Classifier, hook: Hook, skips: Set[str], cols: int, diff_before: bytes, verbose: bool, use_color: bool, ) -> Tuple[bool, bytes]: filenames = classifier.filenames_for_hook(hook) if hook.id in skips or hook.alias in skips: output.write( _full_msg( start=hook.name, end_msg=SKIPPED, end_color=color.YELLOW, use_color=use_color, cols=cols, ), ) duration = None retcode = 0 diff_after = diff_before files_modified = False out = b'' elif not filenames and not hook.always_run: output.write( _full_msg( start=hook.name, postfix=NO_FILES, end_msg=SKIPPED, end_color=color.TURQUOISE, use_color=use_color, cols=cols, ), ) duration = None retcode = 0 diff_after = diff_before files_modified = False out = b'' else: # print hook and dots first in case the hook takes a while to run output.write(_start_msg(start=hook.name, end_len=6, cols=cols)) if not hook.pass_filenames: filenames = () time_before = time.time() language = languages[hook.language] retcode, out = language.run_hook(hook, filenames, use_color) duration = round(time.time() - time_before, 2) or 0 diff_after = _get_diff() # if the hook makes changes, fail the commit files_modified = diff_before != diff_after if retcode or files_modified: print_color = color.RED status = 'Failed' else: print_color = color.GREEN status = 'Passed' output.write_line(color.format_color(status, print_color, use_color)) if verbose or hook.verbose or retcode or files_modified: _subtle_line(f'- hook id: {hook.id}', use_color) if (verbose or hook.verbose) and duration is not None: _subtle_line(f'- duration: {duration}s', use_color) if retcode: _subtle_line(f'- exit code: {retcode}', use_color) # Print a message if failing due to file modifications if files_modified: _subtle_line('- files were modified by this hook', use_color) if out.strip(): output.write_line() output.write_line_b(out.strip(), logfile_name=hook.log_file) output.write_line() return files_modified or bool(retcode), diff_after
def _run_single_hook(filenames, hook, repo, args, skips, cols): include, exclude = hook['files'], hook['exclude'] filenames = _filter_by_include_exclude(filenames, include, exclude) types, exclude_types = hook['types'], hook['exclude_types'] filenames = _filter_by_types(filenames, types, exclude_types) 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'], repo.repo_config['repo']), ) 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', '--no-ext-diff', retcode=None, encoding=None, ) retcode, stdout, stderr = repo.run_hook( hook, 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
# skip blank lines elif line.strip() in ["", "#"]: continue else: h_lines.append(line) if len(h_lines) == 3: break return h_lines if __name__ == "__main__": retv = 0 for filename in sys.argv[1:]: filepath = Path(filename) if not filepath.is_file(): continue header_lines = get_header_lines(filepath) if len(header_lines) < 3: retv |= 1 output.write_line(f"{filename}: (not enough lines)") else: header = "".join(header_lines) if header != EXPECTED_HEADER: retv |= 1 output.write(f"{filename}:\n {' '.join(header_lines)}") else: retv |= 0 sys.exit(retv)
def _run_single_hook(classifier, hook, args, skips, cols, use_color): 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_b('git', 'diff', '--no-ext-diff', retcode=None) filenames = tuple(filenames) if hook.pass_filenames else () retcode, out = hook.run(filenames, use_color) diff_after = cmd_output_b('git', 'diff', '--no-ext-diff', retcode=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 ((out 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 out: output.write_line(' Additional output:') output.write_line() if out.strip(): output.write_line(out.strip(), logfile_name=hook.log_file) output.write_line() return retcode
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 _run_single_hook(classifier, hook, skips, cols, verbose, use_color): filenames = classifier.filenames_for_hook(hook) if hook.id in skips or hook.alias in skips: output.write( get_hook_message( hook.name, end_msg=SKIPPED, end_color=color.YELLOW, use_color=use_color, cols=cols, ), ) duration = None retcode = 0 files_modified = False out = b'' elif not filenames and not hook.always_run: output.write( get_hook_message( hook.name, postfix=NO_FILES, end_msg=SKIPPED, end_color=color.TURQUOISE, use_color=use_color, cols=cols, ), ) duration = None retcode = 0 files_modified = False out = b'' else: # print hook and dots first in case the hook takes a while to run output.write(get_hook_message(hook.name, end_len=6, cols=cols)) diff_cmd = ('git', 'diff', '--no-ext-diff') diff_before = cmd_output_b(*diff_cmd, retcode=None) filenames = tuple(filenames) if hook.pass_filenames else () time_before = time.time() retcode, out = hook.run(filenames, use_color) duration = round(time.time() - time_before, 2) or 0 diff_after = cmd_output_b(*diff_cmd, retcode=None) # if the hook makes changes, fail the commit files_modified = diff_before != diff_after if retcode or files_modified: print_color = color.RED status = 'Failed' else: print_color = color.GREEN status = 'Passed' output.write_line(color.format_color(status, print_color, use_color)) if verbose or hook.verbose or retcode or files_modified: _subtle_line('- hook id: {}'.format(hook.id), use_color) if (verbose or hook.verbose) and duration is not None: _subtle_line('- duration: {}s'.format(duration), use_color) if retcode: _subtle_line('- exit code: {}'.format(retcode), use_color) # Print a message if failing due to file modifications if files_modified: _subtle_line('- files were modified by this hook', use_color) if out.strip(): output.write_line() output.write_line(out.strip(), logfile_name=hook.log_file) output.write_line() return files_modified or bool(retcode)
def test_output_write_writes(): stream = io.BytesIO() output.write('hello world', stream) assert stream.getvalue() == b'hello world'
def _run_single_hook(hook, repo, args, skips, cols): filenames = get_filenames(args, hook.get('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', '--no-ext-diff', retcode=None, encoding=None, ) retcode, stdout, stderr = repo.run_hook( hook, 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): 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