@@ -2438,6 +2438,15 @@ static int fn_out_consume(void *priv, char *line, unsigned long len)
24382438 return 0 ;
24392439}
24402440
2441+ static int quick_consume (void * priv , char * line UNUSED , unsigned long len UNUSED )
2442+ {
2443+ struct emit_callback * ecbdata = priv ;
2444+ struct diff_options * o = ecbdata -> opt ;
2445+
2446+ o -> found_changes = 1 ;
2447+ return 1 ;
2448+ }
2449+
24412450static void pprint_rename (struct strbuf * name , const char * a , const char * b )
24422451{
24432452 const char * old_name = a ;
@@ -3753,8 +3762,21 @@ static void builtin_diff(const char *name_a,
37533762
37543763 if (o -> word_diff )
37553764 init_diff_words_data (& ecbdata , o , one , two );
3756- if (xdi_diff_outf (& mf1 , & mf2 , NULL , fn_out_consume ,
3757- & ecbdata , & xpp , & xecfg ))
3765+ if (o -> dry_run ) {
3766+ /*
3767+ * Unlike the !dry_run case, we need to ignore the
3768+ * return value from xdi_diff_outf() here, because
3769+ * xdi_diff_outf() takes non-zero return from its
3770+ * callback function as a sign of error and returns
3771+ * early (which is why we return non-zero from our
3772+ * callback, quick_consume()). Unfortunately,
3773+ * xdi_diff_outf() signals an error by returning
3774+ * non-zero.
3775+ */
3776+ xdi_diff_outf (& mf1 , & mf2 , NULL , quick_consume ,
3777+ & ecbdata , & xpp , & xecfg );
3778+ } else if (xdi_diff_outf (& mf1 , & mf2 , NULL , fn_out_consume ,
3779+ & ecbdata , & xpp , & xecfg ))
37583780 die ("unable to generate diff for %s" , one -> path );
37593781 if (o -> word_diff )
37603782 free_diff_words_data (& ecbdata );
@@ -6144,6 +6166,22 @@ static void diff_flush_patch(struct diff_filepair *p, struct diff_options *o)
61446166 run_diff (p , o );
61456167}
61466168
6169+ /* return 1 if any change is found; otherwise, return 0 */
6170+ static int diff_flush_patch_quietly (struct diff_filepair * p , struct diff_options * o )
6171+ {
6172+ int saved_dry_run = o -> dry_run ;
6173+ int saved_found_changes = o -> found_changes ;
6174+ int ret ;
6175+
6176+ o -> dry_run = 1 ;
6177+ o -> found_changes = 0 ;
6178+ diff_flush_patch (p , o );
6179+ ret = o -> found_changes ;
6180+ o -> dry_run = saved_dry_run ;
6181+ o -> found_changes |= saved_found_changes ;
6182+ return ret ;
6183+ }
6184+
61476185static void diff_flush_stat (struct diff_filepair * p , struct diff_options * o ,
61486186 struct diffstat_t * diffstat )
61496187{
@@ -6772,8 +6810,15 @@ void diff_flush(struct diff_options *options)
67726810 DIFF_FORMAT_CHECKDIFF )) {
67736811 for (i = 0 ; i < q -> nr ; i ++ ) {
67746812 struct diff_filepair * p = q -> queue [i ];
6775- if (check_pair_status (p ))
6776- flush_one_pair (p , options );
6813+
6814+ if (!check_pair_status (p ))
6815+ continue ;
6816+
6817+ if (options -> flags .diff_from_contents &&
6818+ !diff_flush_patch_quietly (p , options ))
6819+ continue ;
6820+
6821+ flush_one_pair (p , options );
67776822 }
67786823 separator ++ ;
67796824 }
@@ -6825,19 +6870,10 @@ void diff_flush(struct diff_options *options)
68256870 if (output_format & DIFF_FORMAT_NO_OUTPUT &&
68266871 options -> flags .exit_with_status &&
68276872 options -> flags .diff_from_contents ) {
6828- /*
6829- * run diff_flush_patch for the exit status. setting
6830- * options->file to /dev/null should be safe, because we
6831- * aren't supposed to produce any output anyway.
6832- */
6833- diff_free_file (options );
6834- options -> file = xfopen ("/dev/null" , "w" );
6835- options -> close_file = 1 ;
6836- options -> color_moved = 0 ;
68376873 for (i = 0 ; i < q -> nr ; i ++ ) {
68386874 struct diff_filepair * p = q -> queue [i ];
68396875 if (check_pair_status (p ))
6840- diff_flush_patch (p , options );
6876+ diff_flush_patch_quietly (p , options );
68416877 if (options -> found_changes )
68426878 break ;
68436879 }
0 commit comments