@@ -262,6 +262,16 @@ impl UnblamedHunk {
262262 self . suspects . insert ( to, range_in_suspect) ;
263263 }
264264 }
265+
266+ fn clone_blame ( & mut self , from : ObjectId , to : ObjectId ) {
267+ if let Some ( range_in_suspect) = self . suspects . get ( & from) {
268+ self . suspects . insert ( to, range_in_suspect. clone ( ) ) ;
269+ }
270+ }
271+
272+ fn remove_blame ( & mut self , suspect : ObjectId ) {
273+ let _ = self . suspects . remove ( & suspect) ;
274+ }
265275}
266276
267277#[ derive( Clone , Debug , PartialEq ) ]
@@ -336,7 +346,11 @@ pub fn process_change(
336346) -> ( Option < UnblamedHunk > , Option < Change > ) {
337347 match ( hunk, change) {
338348 ( Some ( hunk) , Some ( Change :: Unchanged ( unchanged) ) ) => {
339- let range_in_suspect = hunk. suspects . get ( & suspect) . expect ( "TODO" ) ;
349+ let Some ( range_in_suspect) = hunk. suspects . get ( & suspect) else {
350+ new_hunks_to_blame. push ( hunk) ;
351+
352+ return ( None , Some ( Change :: Unchanged ( unchanged) ) ) ;
353+ } ;
340354
341355 match (
342356 // Since `unchanged` is a range that is not inclusive at the end,
@@ -799,46 +813,55 @@ pub fn blame_file<E>(
799813 break ;
800814 }
801815
802- if parent_ids. len ( ) > 1 {
803- todo ! ( "passing blame to more than one parent is not implemented yet" ) ;
804- }
816+ if parent_ids. len ( ) == 1 {
817+ let parent_id: ObjectId = * parent_ids. last ( ) . unwrap ( ) ;
805818
806- let last_parent_id : ObjectId = * parent_ids . last ( ) . unwrap ( ) ;
819+ let changes_for_file_path = get_changes_for_file_path ( & odb , file_path , item . id , parent_id ) ;
807820
808- let changes_for_file_path = get_changes_for_file_path ( & odb, file_path, item. id , last_parent_id) ;
821+ let [ ref modification] : [ gix_diff:: tree:: recorder:: Change ] = changes_for_file_path[ ..] else {
822+ // None of the changes affected the file we’re currently blaming. Pass blame to parent.
823+ hunks_to_blame
824+ . iter_mut ( )
825+ . for_each ( |unblamed_hunk| unblamed_hunk. pass_blame ( suspect, parent_id) ) ;
809826
810- let [ ref modification] : [ gix_diff:: tree:: recorder:: Change ] = changes_for_file_path[ ..] else {
811- // None of the changes affected the file we’re currently blaming. Pass blame to parent.
812- hunks_to_blame
813- . iter_mut ( )
814- . for_each ( |unblamed_hunk| unblamed_hunk. pass_blame ( suspect, last_parent_id) ) ;
827+ continue ;
828+ } ;
815829
816- continue ;
817- } ;
830+ match modification {
831+ gix_diff:: tree:: recorder:: Change :: Addition { .. } => {
832+ // Every line that has not been blamed yet on a commit, is expected to have been
833+ // added when the file was added to the repository.
834+ out. extend (
835+ hunks_to_blame
836+ . iter ( )
837+ . map ( |hunk| BlameEntry :: from_unblamed_hunk ( hunk, suspect) ) ,
838+ ) ;
818839
819- match modification {
820- gix_diff:: tree:: recorder:: Change :: Addition { .. } => {
821- // Every line that has not been blamed yet on a commit, is expected to have been
822- // added when the file was added to the repository.
823- out. extend (
824- hunks_to_blame
825- . iter ( )
826- . map ( |hunk| BlameEntry :: from_unblamed_hunk ( hunk, suspect) ) ,
827- ) ;
840+ hunks_to_blame = vec ! [ ] ;
828841
829- hunks_to_blame = vec ! [ ] ;
842+ break ;
843+ }
844+ gix_diff:: tree:: recorder:: Change :: Deletion { .. } => todo ! ( ) ,
845+ gix_diff:: tree:: recorder:: Change :: Modification { previous_oid, oid, .. } => {
846+ let changes = get_changes ( & odb, resource_cache, * oid, * previous_oid, file_path) ;
830847
831- break ;
848+ hunks_to_blame = process_changes ( & mut out, & hunks_to_blame, & changes, suspect) ;
849+ hunks_to_blame
850+ . iter_mut ( )
851+ . for_each ( |unblamed_hunk| unblamed_hunk. pass_blame ( suspect, parent_id) ) ;
852+ }
832853 }
833- gix_diff:: tree:: recorder:: Change :: Deletion { .. } => todo ! ( ) ,
834- gix_diff:: tree:: recorder:: Change :: Modification { previous_oid, oid, .. } => {
835- let changes = get_changes ( & odb, resource_cache, * oid, * previous_oid, file_path) ;
836-
837- hunks_to_blame = process_changes ( & mut out, & hunks_to_blame, & changes, suspect) ;
854+ } else {
855+ for parent_id in parent_ids {
856+ // Pass blame to parent.
838857 hunks_to_blame
839858 . iter_mut ( )
840- . for_each ( |unblamed_hunk| unblamed_hunk. pass_blame ( suspect, last_parent_id ) ) ;
859+ . for_each ( |unblamed_hunk| unblamed_hunk. clone_blame ( suspect, parent_id ) ) ;
841860 }
861+
862+ hunks_to_blame
863+ . iter_mut ( )
864+ . for_each ( |unblamed_hunk| unblamed_hunk. remove_blame ( suspect) ) ;
842865 }
843866 }
844867
0 commit comments