@@ -2438,6 +2438,15 @@ static int fn_out_consume(void *priv, char *line, unsigned long len)
2438
2438
return 0 ;
2439
2439
}
2440
2440
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
+
2441
2450
static void pprint_rename (struct strbuf * name , const char * a , const char * b )
2442
2451
{
2443
2452
const char * old_name = a ;
@@ -3703,6 +3712,7 @@ static void builtin_diff(const char *name_a,
3703
3712
xdemitconf_t xecfg ;
3704
3713
struct emit_callback ecbdata ;
3705
3714
const struct userdiff_funcname * pe ;
3715
+ int dry_run = o -> diff_optimize == DIFF_OPT_DRY_RUN ;
3706
3716
3707
3717
if (must_show_header ) {
3708
3718
emit_diff_symbol (o , DIFF_SYMBOL_HEADER ,
@@ -3735,16 +3745,17 @@ static void builtin_diff(const char *name_a,
3735
3745
xpp .ignore_regex_nr = o -> ignore_regex_nr ;
3736
3746
xpp .anchors = o -> anchors ;
3737
3747
xpp .anchors_nr = o -> anchors_nr ;
3738
- xecfg .ctxlen = o -> context ;
3739
- xecfg .interhunkctxlen = o -> interhunkcontext ;
3748
+ xecfg .ctxlen = dry_run ? 0 : o -> context ;
3749
+ xecfg .interhunkctxlen = dry_run ? 0 : o -> interhunkcontext ;
3740
3750
xecfg .flags = XDL_EMIT_FUNCNAMES ;
3741
3751
if (o -> flags .funccontext )
3742
3752
xecfg .flags |= XDL_EMIT_FUNCCONTEXT ;
3743
3753
if (pe )
3744
3754
xdiff_set_find_func (& xecfg , pe -> pattern , pe -> cflags );
3745
3755
3746
3756
diffopts = getenv ("GIT_DIFF_OPTS" );
3747
- if (!diffopts )
3757
+ /* ignore ctxlen if we are in dry run mode */
3758
+ if (!diffopts || dry_run )
3748
3759
;
3749
3760
else if (skip_prefix (diffopts , "--unified=" , & v ))
3750
3761
xecfg .ctxlen = strtoul (v , NULL , 10 );
@@ -3753,8 +3764,11 @@ static void builtin_diff(const char *name_a,
3753
3764
3754
3765
if (o -> word_diff )
3755
3766
init_diff_words_data (& ecbdata , o , one , two );
3756
- if (xdi_diff_outf (& mf1 , & mf2 , NULL , fn_out_consume ,
3757
- & ecbdata , & xpp , & xecfg ))
3767
+ if (dry_run )
3768
+ xdi_diff_outf (& mf1 , & mf2 , NULL , quick_consume ,
3769
+ & ecbdata , & xpp , & xecfg );
3770
+ else if (xdi_diff_outf (& mf1 , & mf2 , NULL , fn_out_consume ,
3771
+ & ecbdata , & xpp , & xecfg ))
3758
3772
die ("unable to generate diff for %s" , one -> path );
3759
3773
if (o -> word_diff )
3760
3774
free_diff_words_data (& ecbdata );
@@ -4985,6 +4999,8 @@ void diff_setup_done(struct diff_options *options)
4985
4999
4986
5000
if (options -> pathspec .has_wildcard && options -> max_depth_valid )
4987
5001
die ("max-depth cannot be used with wildcard pathspecs" );
5002
+
5003
+ options -> diff_optimize = DIFF_OPT_NONE ;
4988
5004
}
4989
5005
4990
5006
int parse_long_opt (const char * opt , const char * * argv ,
@@ -6163,6 +6179,22 @@ static void diff_flush_patch(struct diff_filepair *p, struct diff_options *o)
6163
6179
run_diff (p , o );
6164
6180
}
6165
6181
6182
+ /* return 1 if any change is found; otherwise, return 0 */
6183
+ static int diff_flush_patch_quiet (struct diff_filepair * p , struct diff_options * o )
6184
+ {
6185
+ int diff_opt = o -> diff_optimize ;
6186
+ int found_changes = o -> found_changes ;
6187
+ int ret ;
6188
+
6189
+ o -> diff_optimize = DIFF_OPT_DRY_RUN ;
6190
+ o -> found_changes = 0 ;
6191
+ diff_flush_patch (p , o );
6192
+ ret = o -> found_changes ;
6193
+ o -> diff_optimize = diff_opt ;
6194
+ o -> found_changes |= found_changes ;
6195
+ return ret ;
6196
+ }
6197
+
6166
6198
static void diff_flush_stat (struct diff_filepair * p , struct diff_options * o ,
6167
6199
struct diffstat_t * diffstat )
6168
6200
{
@@ -6791,7 +6823,19 @@ void diff_flush(struct diff_options *options)
6791
6823
DIFF_FORMAT_CHECKDIFF )) {
6792
6824
for (i = 0 ; i < q -> nr ; i ++ ) {
6793
6825
struct diff_filepair * p = q -> queue [i ];
6794
- if (check_pair_status (p ))
6826
+ int need_flush = 1 ;
6827
+
6828
+ if (!check_pair_status (p ))
6829
+ continue ;
6830
+
6831
+ if (options -> flags .diff_from_contents ) {
6832
+ if (diff_flush_patch_quiet (p , options ))
6833
+ need_flush = 1 ;
6834
+ else
6835
+ need_flush = 0 ;
6836
+ }
6837
+
6838
+ if (need_flush )
6795
6839
flush_one_pair (p , options );
6796
6840
}
6797
6841
separator ++ ;
@@ -6844,19 +6888,10 @@ void diff_flush(struct diff_options *options)
6844
6888
if (output_format & DIFF_FORMAT_NO_OUTPUT &&
6845
6889
options -> flags .exit_with_status &&
6846
6890
options -> flags .diff_from_contents ) {
6847
- /*
6848
- * run diff_flush_patch for the exit status. setting
6849
- * options->file to /dev/null should be safe, because we
6850
- * aren't supposed to produce any output anyway.
6851
- */
6852
- diff_free_file (options );
6853
- options -> file = xfopen ("/dev/null" , "w" );
6854
- options -> close_file = 1 ;
6855
- options -> color_moved = 0 ;
6856
6891
for (i = 0 ; i < q -> nr ; i ++ ) {
6857
6892
struct diff_filepair * p = q -> queue [i ];
6858
6893
if (check_pair_status (p ))
6859
- diff_flush_patch (p , options );
6894
+ diff_flush_patch_quiet (p , options );
6860
6895
if (options -> found_changes )
6861
6896
break ;
6862
6897
}
0 commit comments