@@ -688,20 +688,59 @@ int git_index__changed_relative_to(
688
688
return !!git_oid_cmp (& index -> checksum , checksum );
689
689
}
690
690
691
+ static bool is_racy_timestamp (git_time_t stamp , git_index_entry * entry )
692
+ {
693
+ /* Git special-cases submodules in the check */
694
+ if (S_ISGITLINK (entry -> mode ))
695
+ return false;
696
+
697
+ /* If we never read the index, we can't have this race either */
698
+ if (stamp == 0 )
699
+ return false;
700
+
701
+ /* If the timestamp is the same or newer than the index, it's racy */
702
+ return ((int32_t ) stamp ) <= entry -> mtime .seconds ;
703
+ }
704
+
691
705
/*
692
706
* Force the next diff to take a look at those entries which have the
693
707
* same timestamp as the current index.
694
708
*/
695
- static void truncate_racily_clean (git_index * index )
709
+ static int truncate_racily_clean (git_index * index )
696
710
{
697
711
size_t i ;
712
+ int error ;
698
713
git_index_entry * entry ;
699
714
git_time_t ts = index -> stamp .mtime ;
715
+ git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT ;
716
+ git_diff * diff ;
700
717
718
+ /* Nothing to do if there's no repo to talk about */
719
+ if (!INDEX_OWNER (index ))
720
+ return 0 ;
721
+
722
+ /* If there's no workdir, we can't know where to even check */
723
+ if (!git_repository_workdir (INDEX_OWNER (index )))
724
+ return 0 ;
725
+
726
+ diff_opts .flags |= GIT_DIFF_INCLUDE_TYPECHANGE | GIT_DIFF_IGNORE_SUBMODULES | GIT_DIFF_DISABLE_PATHSPEC_MATCH ;
701
727
git_vector_foreach (& index -> entries , i , entry ) {
702
- if (entry -> mtime .seconds == ts || ts == 0 )
728
+ if (!is_racy_timestamp (ts , entry ))
729
+ continue ;
730
+
731
+ diff_opts .pathspec .count = 1 ;
732
+ diff_opts .pathspec .strings = (char * * ) & entry -> path ;
733
+
734
+ if ((error = git_diff_index_to_workdir (& diff , INDEX_OWNER (index ), index , & diff_opts )) < 0 )
735
+ return error ;
736
+
737
+ if (git_diff_num_deltas (diff ) > 0 )
703
738
entry -> file_size = 0 ;
739
+
740
+ git_diff_free (diff );
704
741
}
742
+
743
+ return 0 ;
705
744
}
706
745
707
746
int git_index_write (git_index * index )
0 commit comments