@@ -480,7 +480,9 @@ void blame_coalesce(struct blame_scoreboard *sb)
480
480
481
481
for (ent = sb -> ent ; ent && (next = ent -> next ); ent = next ) {
482
482
if (ent -> suspect == next -> suspect &&
483
- ent -> s_lno + ent -> num_lines == next -> s_lno ) {
483
+ ent -> s_lno + ent -> num_lines == next -> s_lno &&
484
+ ent -> ignored == next -> ignored &&
485
+ ent -> unblamable == next -> unblamable ) {
484
486
ent -> num_lines += next -> num_lines ;
485
487
ent -> next = next -> next ;
486
488
blame_origin_decref (next -> suspect );
@@ -732,6 +734,11 @@ static void split_overlap(struct blame_entry *split,
732
734
int chunk_end_lno ;
733
735
memset (split , 0 , sizeof (struct blame_entry [3 ]));
734
736
737
+ split [0 ].ignored = split [1 ].ignored = split [2 ].ignored = e -> ignored ;
738
+ split [0 ].unblamable = e -> unblamable ;
739
+ split [1 ].unblamable = e -> unblamable ;
740
+ split [2 ].unblamable = e -> unblamable ;
741
+
735
742
if (e -> s_lno < tlno ) {
736
743
/* there is a pre-chunk part not blamed on parent */
737
744
split [0 ].suspect = blame_origin_incref (e -> suspect );
@@ -839,6 +846,27 @@ static struct blame_entry *reverse_blame(struct blame_entry *head,
839
846
return tail ;
840
847
}
841
848
849
+ /* Splits a blame entry into two entries at 'len' lines. The original 'e'
850
+ * consists of len lines, i.e. [e->lno, e->lno + len), and the second part,
851
+ * which is returned, consists of the remainder: [e->lno + len, e->lno +
852
+ * e->num_lines). The caller needs to sort out the reference counting for the
853
+ * new entry's suspect. */
854
+ static struct blame_entry * split_blame_at (struct blame_entry * e , int len ,
855
+ struct blame_origin * new_suspect )
856
+ {
857
+ struct blame_entry * n = xcalloc (1 , sizeof (struct blame_entry ));
858
+
859
+ n -> suspect = new_suspect ;
860
+ n -> ignored = e -> ignored ;
861
+ n -> unblamable = e -> unblamable ;
862
+ n -> lno = e -> lno + len ;
863
+ n -> s_lno = e -> s_lno + len ;
864
+ n -> num_lines = e -> num_lines - len ;
865
+ e -> num_lines = len ;
866
+ e -> score = 0 ;
867
+ return n ;
868
+ }
869
+
842
870
/*
843
871
* Process one hunk from the patch between the current suspect for
844
872
* blame_entry e and its parent. This first blames any unfinished
@@ -851,10 +879,10 @@ static struct blame_entry *reverse_blame(struct blame_entry *head,
851
879
*/
852
880
static void blame_chunk (struct blame_entry * * * dstq , struct blame_entry * * * srcq ,
853
881
int tlno , int offset , int same ,
854
- struct blame_origin * parent )
882
+ struct blame_origin * parent , int ignore_diffs , int delta )
855
883
{
856
884
struct blame_entry * e = * * srcq ;
857
- struct blame_entry * samep = NULL , * diffp = NULL ;
885
+ struct blame_entry * samep = NULL , * diffp = NULL , * ignoredp = NULL ;
858
886
859
887
while (e && e -> s_lno < tlno ) {
860
888
struct blame_entry * next = e -> next ;
@@ -865,14 +893,9 @@ static void blame_chunk(struct blame_entry ***dstq, struct blame_entry ***srcq,
865
893
*/
866
894
if (e -> s_lno + e -> num_lines > tlno ) {
867
895
/* Move second half to a new record */
868
- int len = tlno - e -> s_lno ;
869
- struct blame_entry * n = xcalloc (1 , sizeof (struct blame_entry ));
870
- n -> suspect = e -> suspect ;
871
- n -> lno = e -> lno + len ;
872
- n -> s_lno = e -> s_lno + len ;
873
- n -> num_lines = e -> num_lines - len ;
874
- e -> num_lines = len ;
875
- e -> score = 0 ;
896
+ struct blame_entry * n ;
897
+
898
+ n = split_blame_at (e , tlno - e -> s_lno , e -> suspect );
876
899
/* Push new record to diffp */
877
900
n -> next = diffp ;
878
901
diffp = n ;
@@ -919,22 +942,45 @@ static void blame_chunk(struct blame_entry ***dstq, struct blame_entry ***srcq,
919
942
* Move second half to a new record to be
920
943
* processed by later chunks
921
944
*/
922
- int len = same - e -> s_lno ;
923
- struct blame_entry * n = xcalloc (1 , sizeof (struct blame_entry ));
924
- n -> suspect = blame_origin_incref (e -> suspect );
925
- n -> lno = e -> lno + len ;
926
- n -> s_lno = e -> s_lno + len ;
927
- n -> num_lines = e -> num_lines - len ;
928
- e -> num_lines = len ;
929
- e -> score = 0 ;
945
+ struct blame_entry * n ;
946
+
947
+ n = split_blame_at (e , same - e -> s_lno ,
948
+ blame_origin_incref (e -> suspect ));
930
949
/* Push new record to samep */
931
950
n -> next = samep ;
932
951
samep = n ;
933
952
}
934
- e -> next = diffp ;
935
- diffp = e ;
953
+ if (ignore_diffs ) {
954
+ /* These go to the parent, like the ones before tlno. */
955
+ blame_origin_decref (e -> suspect );
956
+ e -> suspect = blame_origin_incref (parent );
957
+ e -> s_lno += offset ;
958
+ e -> ignored = 1 ;
959
+ /* The top part of any ignored diff will not exist in
960
+ * the parent, and we will never be able to accurately
961
+ * blame it. We'll keep it on the blame list for the
962
+ * target and mark it during the output. */
963
+ if (delta > 0 ) {
964
+ struct blame_entry * n ;
965
+
966
+ n = split_blame_at (e , e -> num_lines - delta ,
967
+ blame_origin_incref (e -> suspect ));
968
+ n -> unblamable = 1 ;
969
+ n -> next = diffp ;
970
+ diffp = n ;
971
+ }
972
+ e -> next = ignoredp ;
973
+ ignoredp = e ;
974
+ } else {
975
+ e -> next = diffp ;
976
+ diffp = e ;
977
+ }
936
978
e = next ;
937
979
}
980
+ if (ignoredp ) {
981
+ * * dstq = reverse_blame (ignoredp , * * dstq );
982
+ * dstq = & ignoredp -> next ;
983
+ }
938
984
* * srcq = reverse_blame (diffp , reverse_blame (samep , e ));
939
985
/* Move across elements that are in the unblamable portion */
940
986
if (diffp )
@@ -944,6 +990,7 @@ static void blame_chunk(struct blame_entry ***dstq, struct blame_entry ***srcq,
944
990
struct blame_chunk_cb_data {
945
991
struct blame_origin * parent ;
946
992
long offset ;
993
+ int ignore_diffs ;
947
994
struct blame_entry * * dstq ;
948
995
struct blame_entry * * srcq ;
949
996
};
@@ -956,7 +1003,7 @@ static int blame_chunk_cb(long start_a, long count_a,
956
1003
if (start_a - start_b != d -> offset )
957
1004
die ("internal error in blame::blame_chunk_cb" );
958
1005
blame_chunk (& d -> dstq , & d -> srcq , start_b , start_a - start_b ,
959
- start_b + count_b , d -> parent );
1006
+ start_b + count_b , d -> parent , d -> ignore_diffs , count_b - count_a );
960
1007
d -> offset = start_a + count_a - (start_b + count_b );
961
1008
return 0 ;
962
1009
}
@@ -968,7 +1015,7 @@ static int blame_chunk_cb(long start_a, long count_a,
968
1015
*/
969
1016
static void pass_blame_to_parent (struct blame_scoreboard * sb ,
970
1017
struct blame_origin * target ,
971
- struct blame_origin * parent )
1018
+ struct blame_origin * parent , int ignore_diffs )
972
1019
{
973
1020
mmfile_t file_p , file_o ;
974
1021
struct blame_chunk_cb_data d ;
@@ -979,6 +1026,7 @@ static void pass_blame_to_parent(struct blame_scoreboard *sb,
979
1026
980
1027
d .parent = parent ;
981
1028
d .offset = 0 ;
1029
+ d .ignore_diffs = ignore_diffs ;
982
1030
d .dstq = & newdest ; d .srcq = & target -> suspects ;
983
1031
984
1032
fill_origin_blob (& sb -> revs -> diffopt , parent , & file_p , & sb -> num_read_blob );
@@ -990,7 +1038,7 @@ static void pass_blame_to_parent(struct blame_scoreboard *sb,
990
1038
oid_to_hex (& parent -> commit -> object .oid ),
991
1039
oid_to_hex (& target -> commit -> object .oid ));
992
1040
/* The rest are the same as the parent */
993
- blame_chunk (& d .dstq , & d .srcq , INT_MAX , d .offset , INT_MAX , parent );
1041
+ blame_chunk (& d .dstq , & d .srcq , INT_MAX , d .offset , INT_MAX , parent , 0 , 0 );
994
1042
* d .dstq = NULL ;
995
1043
queue_blames (sb , parent , newdest );
996
1044
@@ -1495,11 +1543,28 @@ static void pass_blame(struct blame_scoreboard *sb, struct blame_origin *origin,
1495
1543
blame_origin_incref (porigin );
1496
1544
origin -> previous = porigin ;
1497
1545
}
1498
- pass_blame_to_parent (sb , origin , porigin );
1546
+ pass_blame_to_parent (sb , origin , porigin , 0 );
1499
1547
if (!origin -> suspects )
1500
1548
goto finish ;
1501
1549
}
1502
1550
1551
+ /*
1552
+ * Pass remaining suspects for ignored commits to their parents.
1553
+ */
1554
+ if (oidset_contains (& sb -> ignore_list , & commit -> object .oid )) {
1555
+ for (i = 0 , sg = first_scapegoat (revs , commit , sb -> reverse );
1556
+ i < num_sg && sg ;
1557
+ sg = sg -> next , i ++ ) {
1558
+ struct blame_origin * porigin = sg_origin [i ];
1559
+
1560
+ if (!porigin )
1561
+ continue ;
1562
+ pass_blame_to_parent (sb , origin , porigin , 1 );
1563
+ if (!origin -> suspects )
1564
+ goto finish ;
1565
+ }
1566
+ }
1567
+
1503
1568
/*
1504
1569
* Optionally find moves in parents' files.
1505
1570
*/
0 commit comments