@@ -134,9 +134,10 @@ def _run_single_hook(
134134 hook : Hook ,
135135 skips : Set [str ],
136136 cols : int ,
137+ diff_before : bytes ,
137138 verbose : bool ,
138139 use_color : bool ,
139- ) -> bool :
140+ ) -> Tuple [ bool , bytes ] :
140141 filenames = classifier .filenames_for_hook (hook )
141142
142143 if hook .id in skips or hook .alias in skips :
@@ -151,6 +152,7 @@ def _run_single_hook(
151152 )
152153 duration = None
153154 retcode = 0
155+ diff_after = diff_before
154156 files_modified = False
155157 out = b''
156158 elif not filenames and not hook .always_run :
@@ -166,21 +168,20 @@ def _run_single_hook(
166168 )
167169 duration = None
168170 retcode = 0
171+ diff_after = diff_before
169172 files_modified = False
170173 out = b''
171174 else :
172175 # print hook and dots first in case the hook takes a while to run
173176 output .write (_start_msg (start = hook .name , end_len = 6 , cols = cols ))
174177
175- diff_cmd = ('git' , 'diff' , '--no-ext-diff' )
176- diff_before = cmd_output_b (* diff_cmd , retcode = None )
177178 if not hook .pass_filenames :
178179 filenames = ()
179180 time_before = time .time ()
180181 language = languages [hook .language ]
181182 retcode , out = language .run_hook (hook , filenames , use_color )
182183 duration = round (time .time () - time_before , 2 ) or 0
183- diff_after = cmd_output_b ( * diff_cmd , retcode = None )
184+ diff_after = _get_diff ( )
184185
185186 # if the hook makes changes, fail the commit
186187 files_modified = diff_before != diff_after
@@ -212,7 +213,7 @@ def _run_single_hook(
212213 output .write_line_b (out .strip (), logfile_name = hook .log_file )
213214 output .write_line ()
214215
215- return files_modified or bool (retcode )
216+ return files_modified or bool (retcode ), diff_after
216217
217218
218219def _compute_cols (hooks : Sequence [Hook ]) -> int :
@@ -248,6 +249,11 @@ def _all_filenames(args: argparse.Namespace) -> Collection[str]:
248249 return git .get_staged_files ()
249250
250251
252+ def _get_diff () -> bytes :
253+ _ , out , _ = cmd_output_b ('git' , 'diff' , '--no-ext-diff' , retcode = None )
254+ return out
255+
256+
251257def _run_hooks (
252258 config : Dict [str , Any ],
253259 hooks : Sequence [Hook ],
@@ -261,14 +267,16 @@ def _run_hooks(
261267 _all_filenames (args ), config ['files' ], config ['exclude' ],
262268 )
263269 retval = 0
270+ prior_diff = _get_diff ()
264271 for hook in hooks :
265- retval | = _run_single_hook (
266- classifier , hook , skips , cols ,
272+ current_retval , prior_diff = _run_single_hook (
273+ classifier , hook , skips , cols , prior_diff ,
267274 verbose = args .verbose , use_color = args .color ,
268275 )
276+ retval |= current_retval
269277 if retval and config ['fail_fast' ]:
270278 break
271- if retval and args .show_diff_on_failure and git . has_diff () :
279+ if retval and args .show_diff_on_failure and prior_diff :
272280 if args .all_files :
273281 output .write_line (
274282 'pre-commit hook(s) made changes.\n '
0 commit comments