@@ -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