@@ -688,7 +688,7 @@ int git_diff_find_similar(
688
688
git_diff_find_options opts ;
689
689
size_t num_rewrites = 0 , num_updates = 0 ;
690
690
void * * cache ; /* cache of similarity metric file signatures */
691
- diff_find_match * matches ; /* cache of best matches */
691
+ diff_find_match * match_sources , * match_targets ; /* cache of best matches */
692
692
693
693
if ((error = normalize_find_opts (diff , & opts , given_opts )) < 0 )
694
694
return error ;
@@ -701,16 +701,18 @@ int git_diff_find_similar(
701
701
cache = git__calloc (cache_size , sizeof (void * ));
702
702
GITERR_CHECK_ALLOC (cache );
703
703
704
- matches = git__calloc (diff -> deltas .length , sizeof (diff_find_match ));
705
- GITERR_CHECK_ALLOC (matches );
704
+ match_sources = git__calloc (diff -> deltas .length , sizeof (diff_find_match ));
705
+ match_targets = git__calloc (diff -> deltas .length , sizeof (diff_find_match ));
706
+ GITERR_CHECK_ALLOC (match_sources );
707
+ GITERR_CHECK_ALLOC (match_targets );
706
708
707
709
/* next find the most similar delta for each rename / copy candidate */
708
710
709
711
git_vector_foreach (& diff -> deltas , i , to ) {
710
712
size_t tried_sources = 0 ;
711
713
712
- matches [i ].idx = i ;
713
- matches [i ].similarity = 0 ;
714
+ match_targets [i ].idx = i ;
715
+ match_targets [i ].similarity = 0 ;
714
716
715
717
/* skip things that are not rename targets */
716
718
if (!is_rename_target (diff , & opts , i , cache ))
@@ -738,23 +740,26 @@ int git_diff_find_similar(
738
740
continue ;
739
741
}
740
742
741
- if (matches [i ].similarity < (uint32_t )similarity ) {
742
- matches [i ].similarity = (uint32_t )similarity ;
743
- matches [i ].idx = j ;
743
+ if (match_targets [i ].similarity < (uint32_t )similarity &&
744
+ match_sources [j ].similarity < (uint32_t )similarity ) {
745
+ match_targets [i ].similarity = (uint32_t )similarity ;
746
+ match_sources [j ].similarity = (uint32_t )similarity ;
747
+ match_targets [i ].idx = j ;
748
+ match_sources [j ].idx = i ;
744
749
}
745
750
}
746
751
}
747
752
748
753
/* next rewrite the diffs with renames / copies */
749
754
750
755
git_vector_foreach (& diff -> deltas , i , to ) {
751
-
752
- /* check if this delta was matched to another one */
753
- if ((similarity = (int )matches [i ].similarity ) <= 0 )
756
+ /* check if this delta was the target of a similarity */
757
+ if ((similarity = (int )match_targets [i ].similarity ) <= 0 )
754
758
continue ;
759
+
755
760
assert (to && (to -> flags & GIT_DIFF_FLAG__IS_RENAME_TARGET ) != 0 );
756
761
757
- from = GIT_VECTOR_GET (& diff -> deltas , matches [i ].idx );
762
+ from = GIT_VECTOR_GET (& diff -> deltas , match_targets [i ].idx );
758
763
assert (from && (from -> flags & GIT_DIFF_FLAG__IS_RENAME_SOURCE ) != 0 );
759
764
760
765
/* possible scenarios:
@@ -851,14 +856,14 @@ int git_diff_find_similar(
851
856
/* in the off chance that we've just swapped the new
852
857
* element into the correct place, clear the SPLIT flag
853
858
*/
854
- if (matches [ matches [i ].idx ].idx == i &&
855
- matches [ matches [i ].idx ].similarity >
859
+ if (match_targets [ match_targets [i ].idx ].idx == i &&
860
+ match_targets [ match_targets [i ].idx ].similarity >
856
861
opts .rename_from_rewrite_threshold ) {
857
862
858
863
from -> status = GIT_DELTA_RENAMED ;
859
864
from -> similarity =
860
- (uint32_t )matches [ matches [i ].idx ].similarity ;
861
- matches [ matches [i ].idx ].similarity = 0 ;
865
+ (uint32_t )match_targets [ match_targets [i ].idx ].similarity ;
866
+ match_targets [ match_targets [i ].idx ].similarity = 0 ;
862
867
from -> flags &= ~GIT_DIFF_FLAG__TO_SPLIT ;
863
868
num_rewrites -- ;
864
869
}
@@ -886,7 +891,8 @@ int git_diff_find_similar(
886
891
FLAG_SET (& opts , GIT_DIFF_BREAK_REWRITES ));
887
892
888
893
cleanup :
889
- git__free (matches );
894
+ git__free (match_sources );
895
+ git__free (match_targets );
890
896
891
897
for (i = 0 ; i < cache_size ; ++ i ) {
892
898
if (cache [i ] != NULL )
0 commit comments