@@ -4697,6 +4697,38 @@ static int diff_filespec_is_identical(struct diff_filespec *one,
46974697 return !memcmp (one -> data , two -> data , one -> size );
46984698}
46994699
4700+ static int diff_filespec_check_stat_unmatch (struct diff_filepair * p )
4701+ {
4702+ if (p -> done_skip_stat_unmatch )
4703+ return p -> skip_stat_unmatch_result ;
4704+
4705+ p -> done_skip_stat_unmatch = 1 ;
4706+ p -> skip_stat_unmatch_result = 0 ;
4707+ /*
4708+ * 1. Entries that come from stat info dirtiness
4709+ * always have both sides (iow, not create/delete),
4710+ * one side of the object name is unknown, with
4711+ * the same mode and size. Keep the ones that
4712+ * do not match these criteria. They have real
4713+ * differences.
4714+ *
4715+ * 2. At this point, the file is known to be modified,
4716+ * with the same mode and size, and the object
4717+ * name of one side is unknown. Need to inspect
4718+ * the identical contents.
4719+ */
4720+ if (!DIFF_FILE_VALID (p -> one ) || /* (1) */
4721+ !DIFF_FILE_VALID (p -> two ) ||
4722+ (p -> one -> sha1_valid && p -> two -> sha1_valid ) ||
4723+ (p -> one -> mode != p -> two -> mode ) ||
4724+ diff_populate_filespec (p -> one , 1 ) ||
4725+ diff_populate_filespec (p -> two , 1 ) ||
4726+ (p -> one -> size != p -> two -> size ) ||
4727+ !diff_filespec_is_identical (p -> one , p -> two )) /* (2) */
4728+ p -> skip_stat_unmatch_result = 1 ;
4729+ return p -> skip_stat_unmatch_result ;
4730+ }
4731+
47004732static void diffcore_skip_stat_unmatch (struct diff_options * diffopt )
47014733{
47024734 int i ;
@@ -4707,27 +4739,7 @@ static void diffcore_skip_stat_unmatch(struct diff_options *diffopt)
47074739 for (i = 0 ; i < q -> nr ; i ++ ) {
47084740 struct diff_filepair * p = q -> queue [i ];
47094741
4710- /*
4711- * 1. Entries that come from stat info dirtiness
4712- * always have both sides (iow, not create/delete),
4713- * one side of the object name is unknown, with
4714- * the same mode and size. Keep the ones that
4715- * do not match these criteria. They have real
4716- * differences.
4717- *
4718- * 2. At this point, the file is known to be modified,
4719- * with the same mode and size, and the object
4720- * name of one side is unknown. Need to inspect
4721- * the identical contents.
4722- */
4723- if (!DIFF_FILE_VALID (p -> one ) || /* (1) */
4724- !DIFF_FILE_VALID (p -> two ) ||
4725- (p -> one -> sha1_valid && p -> two -> sha1_valid ) ||
4726- (p -> one -> mode != p -> two -> mode ) ||
4727- diff_populate_filespec (p -> one , 1 ) ||
4728- diff_populate_filespec (p -> two , 1 ) ||
4729- (p -> one -> size != p -> two -> size ) ||
4730- !diff_filespec_is_identical (p -> one , p -> two )) /* (2) */
4742+ if (diff_filespec_check_stat_unmatch (p ))
47314743 diff_q (& outq , p );
47324744 else {
47334745 /*
@@ -4890,6 +4902,7 @@ void diff_change(struct diff_options *options,
48904902 unsigned old_dirty_submodule , unsigned new_dirty_submodule )
48914903{
48924904 struct diff_filespec * one , * two ;
4905+ struct diff_filepair * p ;
48934906
48944907 if (S_ISGITLINK (old_mode ) && S_ISGITLINK (new_mode ) &&
48954908 is_submodule_ignored (concatpath , options ))
@@ -4916,10 +4929,16 @@ void diff_change(struct diff_options *options,
49164929 fill_filespec (two , new_sha1 , new_sha1_valid , new_mode );
49174930 one -> dirty_submodule = old_dirty_submodule ;
49184931 two -> dirty_submodule = new_dirty_submodule ;
4932+ p = diff_queue (& diff_queued_diff , one , two );
49194933
4920- diff_queue (& diff_queued_diff , one , two );
4921- if (!DIFF_OPT_TST (options , DIFF_FROM_CONTENTS ))
4922- DIFF_OPT_SET (options , HAS_CHANGES );
4934+ if (DIFF_OPT_TST (options , DIFF_FROM_CONTENTS ))
4935+ return ;
4936+
4937+ if (DIFF_OPT_TST (options , QUICK ) && options -> skip_stat_unmatch &&
4938+ !diff_filespec_check_stat_unmatch (p ))
4939+ return ;
4940+
4941+ DIFF_OPT_SET (options , HAS_CHANGES );
49234942}
49244943
49254944struct diff_filepair * diff_unmerge (struct diff_options * options , const char * path )
0 commit comments