Skip to content

Commit 01a628d

Browse files
committed
Make verbose output less special
1 parent 74fd04c commit 01a628d

File tree

8 files changed

+96
-105
lines changed

8 files changed

+96
-105
lines changed

pre_commit/color.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
GREEN = '\033[42m'
1616
YELLOW = '\033[43;30m'
1717
TURQUOISE = '\033[46;30m'
18+
SUBTLE = '\033[2m'
1819
NORMAL = '\033[0m'
1920

2021

pre_commit/commands/run.py

Lines changed: 46 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import os
55
import re
66
import subprocess
7-
import sys
87

98
from identify.identify import tags_from_path
109

@@ -71,15 +70,15 @@ def _get_skips(environ):
7170
return {skip.strip() for skip in skips.split(',') if skip.strip()}
7271

7372

74-
def _hook_msg_start(hook, verbose):
75-
return '{}{}'.format('[{}] '.format(hook.id) if verbose else '', hook.name)
76-
77-
7873
SKIPPED = 'Skipped'
7974
NO_FILES = '(no files to check)'
8075

8176

82-
def _run_single_hook(classifier, hook, args, skips, cols, use_color):
77+
def _subtle_line(s, use_color):
78+
output.write_line(color.format_color(s, color.SUBTLE, use_color))
79+
80+
81+
def _run_single_hook(classifier, hook, skips, cols, verbose, use_color):
8382
filenames = classifier.filenames_for_hook(hook)
8483

8584
if hook.language == 'pcre':
@@ -93,92 +92,78 @@ def _run_single_hook(classifier, hook, args, skips, cols, use_color):
9392
if hook.id in skips or hook.alias in skips:
9493
output.write(
9594
get_hook_message(
96-
_hook_msg_start(hook, args.verbose),
95+
hook.name,
9796
end_msg=SKIPPED,
9897
end_color=color.YELLOW,
99-
use_color=args.color,
98+
use_color=use_color,
10099
cols=cols,
101100
),
102101
)
103-
return 0
102+
retcode = 0
103+
files_modified = False
104+
out = b''
104105
elif not filenames and not hook.always_run:
105106
output.write(
106107
get_hook_message(
107-
_hook_msg_start(hook, args.verbose),
108+
hook.name,
108109
postfix=NO_FILES,
109110
end_msg=SKIPPED,
110111
end_color=color.TURQUOISE,
111-
use_color=args.color,
112+
use_color=use_color,
112113
cols=cols,
113114
),
114115
)
115-
return 0
116-
117-
# Print the hook and the dots first in case the hook takes hella long to
118-
# run.
119-
output.write(
120-
get_hook_message(
121-
_hook_msg_start(hook, args.verbose), end_len=6, cols=cols,
122-
),
123-
)
124-
sys.stdout.flush()
116+
retcode = 0
117+
files_modified = False
118+
out = b''
119+
else:
120+
# print hook and dots first in case the hook takes a while to run
121+
output.write(get_hook_message(hook.name, end_len=6, cols=cols))
125122

126-
diff_before = cmd_output_b('git', 'diff', '--no-ext-diff', retcode=None)
127-
filenames = tuple(filenames) if hook.pass_filenames else ()
128-
retcode, out = hook.run(filenames, use_color)
129-
diff_after = cmd_output_b('git', 'diff', '--no-ext-diff', retcode=None)
123+
diff_cmd = ('git', 'diff', '--no-ext-diff')
124+
diff_before = cmd_output_b(*diff_cmd, retcode=None)
125+
filenames = tuple(filenames) if hook.pass_filenames else ()
126+
retcode, out = hook.run(filenames, use_color)
127+
diff_after = cmd_output_b(*diff_cmd, retcode=None)
130128

131-
file_modifications = diff_before != diff_after
129+
# if the hook makes changes, fail the commit
130+
files_modified = diff_before != diff_after
132131

133-
# If the hook makes changes, fail the commit
134-
if file_modifications:
135-
retcode = 1
132+
if retcode or files_modified:
133+
print_color = color.RED
134+
status = 'Failed'
135+
else:
136+
print_color = color.GREEN
137+
status = 'Passed'
136138

137-
if retcode:
138-
retcode = 1
139-
print_color = color.RED
140-
pass_fail = 'Failed'
141-
else:
142-
retcode = 0
143-
print_color = color.GREEN
144-
pass_fail = 'Passed'
139+
output.write_line(color.format_color(status, print_color, use_color))
145140

146-
output.write_line(color.format_color(pass_fail, print_color, args.color))
141+
if verbose or hook.verbose or retcode or files_modified:
142+
_subtle_line('- hook id: {}'.format(hook.id), use_color)
147143

148-
if (
149-
(out or file_modifications) and
150-
(retcode or args.verbose or hook.verbose)
151-
):
152-
output.write_line('hookid: {}\n'.format(hook.id))
144+
if retcode:
145+
_subtle_line('- exit code: {}'.format(retcode), use_color)
153146

154147
# Print a message if failing due to file modifications
155-
if file_modifications:
156-
output.write('Files were modified by this hook.')
157-
158-
if out:
159-
output.write_line(' Additional output:')
160-
161-
output.write_line()
148+
if files_modified:
149+
_subtle_line('- files were modified by this hook', use_color)
162150

163151
if out.strip():
152+
output.write_line()
164153
output.write_line(out.strip(), logfile_name=hook.log_file)
165-
output.write_line()
154+
output.write_line()
166155

167-
return retcode
156+
return files_modified or bool(retcode)
168157

169158

170-
def _compute_cols(hooks, verbose):
159+
def _compute_cols(hooks):
171160
"""Compute the number of columns to display hook messages. The widest
172161
that will be displayed is in the no files skipped case:
173162
174163
Hook name...(no files to check) Skipped
175-
176-
or in the verbose case
177-
178-
Hook name [hookid]...(no files to check) Skipped
179164
"""
180165
if hooks:
181-
name_len = max(len(_hook_msg_start(hook, verbose)) for hook in hooks)
166+
name_len = max(len(hook.name) for hook in hooks)
182167
else:
183168
name_len = 0
184169

@@ -204,7 +189,7 @@ def _all_filenames(args):
204189
def _run_hooks(config, hooks, args, environ):
205190
"""Actually run the hooks."""
206191
skips = _get_skips(environ)
207-
cols = _compute_cols(hooks, args.verbose)
192+
cols = _compute_cols(hooks)
208193
filenames = _all_filenames(args)
209194
filenames = filter_by_include_exclude(
210195
filenames, config['files'], config['exclude'],
@@ -213,7 +198,8 @@ def _run_hooks(config, hooks, args, environ):
213198
retval = 0
214199
for hook in hooks:
215200
retval |= _run_single_hook(
216-
classifier, hook, args, skips, cols, args.color,
201+
classifier, hook, skips, cols,
202+
verbose=args.verbose, use_color=args.color,
217203
)
218204
if retval and config['fail_fast']:
219205
break

pre_commit/xargs.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -135,17 +135,9 @@ def run_cmd_partition(run_cmd):
135135
results = thread_map(run_cmd_partition, partitions)
136136

137137
for proc_retcode, proc_out, _ in results:
138-
# This is *slightly* too clever so I'll explain it.
139-
# First the xor boolean table:
140-
# T | F |
141-
# +-------+
142-
# T | F | T |
143-
# --+-------+
144-
# F | T | F |
145-
# --+-------+
146-
# When negate is True, it has the effect of flipping the return
147-
# code. Otherwise, the returncode is unchanged.
148-
retcode |= bool(proc_retcode) ^ negate
138+
if negate:
139+
proc_retcode = not proc_retcode
140+
retcode = max(retcode, proc_retcode)
149141
stdout += proc_out
150142

151143
return retcode, stdout

tests/commands/install_uninstall_test.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,8 @@ def test_environment_not_sourced(tempdir_factory, store):
288288
FAILING_PRE_COMMIT_RUN = re.compile(
289289
r'^\[INFO\] Initializing environment for .+\.\r?\n'
290290
r'Failing hook\.+Failed\r?\n'
291-
r'hookid: failing_hook\r?\n'
291+
r'- hook id: failing_hook\r?\n'
292+
r'- exit code: 1\r?\n'
292293
r'\r?\n'
293294
r'Fail\r?\n'
294295
r'foo\r?\n'
@@ -548,7 +549,7 @@ def test_pre_push_integration_failing(tempdir_factory, store):
548549
assert 'Failing hook' in output
549550
assert 'Failed' in output
550551
assert 'foo zzz' in output # both filenames should be printed
551-
assert 'hookid: failing_hook' in output
552+
assert 'hook id: failing_hook' in output
552553

553554

554555
def test_pre_push_integration_accepted(tempdir_factory, store):
@@ -647,8 +648,11 @@ def test_commit_msg_integration_failing(
647648
install(C.CONFIG_FILE, store, hook_types=['commit-msg'])
648649
retc, out = _get_commit_output(tempdir_factory)
649650
assert retc == 1
650-
assert out.startswith('Must have "Signed off by:"...')
651-
assert out.strip().endswith('...Failed')
651+
assert out.replace('\r', '') == '''\
652+
Must have "Signed off by:"...............................................Failed
653+
- hook id: must-have-signoff
654+
- exit code: 1
655+
'''
652656

653657

654658
def test_commit_msg_integration_passing(
@@ -691,16 +695,18 @@ def test_prepare_commit_msg_integration_failing(
691695
install(C.CONFIG_FILE, store, hook_types=['prepare-commit-msg'])
692696
retc, out = _get_commit_output(tempdir_factory)
693697
assert retc == 1
694-
assert out.startswith('Add "Signed off by:"...')
695-
assert out.strip().endswith('...Failed')
698+
assert out.replace('\r', '') == '''\
699+
Add "Signed off by:".....................................................Failed
700+
- hook id: add-signoff
701+
- exit code: 1
702+
'''
696703

697704

698705
def test_prepare_commit_msg_integration_passing(
699706
prepare_commit_msg_repo, tempdir_factory, store,
700707
):
701708
install(C.CONFIG_FILE, store, hook_types=['prepare-commit-msg'])
702-
msg = 'Hi'
703-
retc, out = _get_commit_output(tempdir_factory, msg=msg)
709+
retc, out = _get_commit_output(tempdir_factory, msg='Hi')
704710
assert retc == 0
705711
first_line = out.splitlines()[0]
706712
assert first_line.startswith('Add "Signed off by:"...')
@@ -730,8 +736,7 @@ def test_prepare_commit_msg_legacy(
730736

731737
install(C.CONFIG_FILE, store, hook_types=['prepare-commit-msg'])
732738

733-
msg = 'Hi'
734-
retc, out = _get_commit_output(tempdir_factory, msg=msg)
739+
retc, out = _get_commit_output(tempdir_factory, msg='Hi')
735740
assert retc == 0
736741
first_line, second_line = out.splitlines()[:2]
737742
assert first_line == 'legacy'

tests/commands/run_test.py

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def test_run_all_hooks_failing(cap_out, store, repo_with_failing_hook):
9494
(
9595
b'Failing hook',
9696
b'Failed',
97-
b'hookid: failing_hook',
97+
b'hook id: failing_hook',
9898
b'Fail\nfoo.py\n',
9999
),
100100
expected_ret=1,
@@ -125,14 +125,14 @@ def test_hook_that_modifies_but_returns_zero(cap_out, store, tempdir_factory):
125125
# The first should fail
126126
b'Failed',
127127
# With a modified file (default message + the hook's output)
128-
b'Files were modified by this hook. Additional output:\n\n'
128+
b'- files were modified by this hook\n\n'
129129
b'Modified: foo.py',
130130
# The next hook should pass despite the first modifying
131131
b'Passed',
132132
# The next hook should fail
133133
b'Failed',
134134
# bar.py was modified, but provides no additional output
135-
b'Files were modified by this hook.\n',
135+
b'- files were modified by this hook\n',
136136
),
137137
1,
138138
True,
@@ -176,7 +176,7 @@ def test_global_exclude(cap_out, store, tempdir_factory):
176176
ret, printed = _do_run(cap_out, store, git_path, opts)
177177
assert ret == 0
178178
# Does not contain foo.py since it was excluded
179-
expected = b'hookid: bash_hook\n\nbar.py\nHello World\n\n'
179+
expected = b'- hook id: bash_hook\n\nbar.py\nHello World\n\n'
180180
assert printed.endswith(expected)
181181

182182

@@ -192,7 +192,7 @@ def test_global_files(cap_out, store, tempdir_factory):
192192
ret, printed = _do_run(cap_out, store, git_path, opts)
193193
assert ret == 0
194194
# Does not contain foo.py since it was not included
195-
expected = b'hookid: bash_hook\n\nbar.py\nHello World\n\n'
195+
expected = b'- hook id: bash_hook\n\nbar.py\nHello World\n\n'
196196
assert printed.endswith(expected)
197197

198198

@@ -422,23 +422,21 @@ def test_merge_conflict_resolved(cap_out, store, in_merge_conflict):
422422

423423

424424
@pytest.mark.parametrize(
425-
('hooks', 'verbose', 'expected'),
425+
('hooks', 'expected'),
426426
(
427-
([], True, 80),
428-
([auto_namedtuple(id='a', name='a' * 51)], False, 81),
429-
([auto_namedtuple(id='a', name='a' * 51)], True, 85),
427+
([], 80),
428+
([auto_namedtuple(id='a', name='a' * 51)], 81),
430429
(
431430
[
432431
auto_namedtuple(id='a', name='a' * 51),
433432
auto_namedtuple(id='b', name='b' * 52),
434433
],
435-
False,
436434
82,
437435
),
438436
),
439437
)
440-
def test_compute_cols(hooks, verbose, expected):
441-
assert _compute_cols(hooks, verbose) == expected
438+
def test_compute_cols(hooks, expected):
439+
assert _compute_cols(hooks) == expected
442440

443441

444442
@pytest.mark.parametrize(
@@ -492,7 +490,7 @@ def test_hook_id_in_verbose_output(cap_out, store, repo_with_passing_hook):
492490
ret, printed = _do_run(
493491
cap_out, store, repo_with_passing_hook, run_opts(verbose=True),
494492
)
495-
assert b'[bash_hook] Bash hook' in printed
493+
assert b'- hook id: bash_hook' in printed
496494

497495

498496
def test_multiple_hooks_same_id(cap_out, store, repo_with_passing_hook):

tests/commands/try_repo_test.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,17 @@ def test_try_repo_repo_only(cap_out, tempdir_factory):
5454
' - id: bash_hook3\n$',
5555
config,
5656
)
57-
assert rest == (
58-
'[bash_hook] Bash hook................................(no files to check)Skipped\n' # noqa: E501
59-
'[bash_hook2] Bash hook...................................................Passed\n' # noqa: E501
60-
'hookid: bash_hook2\n'
61-
'\n'
62-
'test-file\n'
63-
'\n'
64-
'[bash_hook3] Bash hook...............................(no files to check)Skipped\n' # noqa: E501
65-
)
57+
assert rest == '''\
58+
Bash hook............................................(no files to check)Skipped
59+
- hook id: bash_hook
60+
Bash hook................................................................Passed
61+
- hook id: bash_hook2
62+
63+
test-file
64+
65+
Bash hook............................................(no files to check)Skipped
66+
- hook id: bash_hook3
67+
'''
6668

6769

6870
def test_try_repo_with_specific_hook(cap_out, tempdir_factory):
@@ -77,7 +79,10 @@ def test_try_repo_with_specific_hook(cap_out, tempdir_factory):
7779
' - id: bash_hook\n$',
7880
config,
7981
)
80-
assert rest == '[bash_hook] Bash hook................................(no files to check)Skipped\n' # noqa: E501
82+
assert rest == '''\
83+
Bash hook............................................(no files to check)Skipped
84+
- hook id: bash_hook
85+
'''
8186

8287

8388
def test_try_repo_relative_path(cap_out, tempdir_factory):

0 commit comments

Comments
 (0)