@@ -615,6 +615,50 @@ pub fn process_changes(
615615 new_hunks_to_blame
616616}
617617
618+ fn get_changes_for_file_path (
619+ odb : impl gix_object:: Find + gix_object:: FindHeader ,
620+ file_path : & BStr ,
621+ id : ObjectId ,
622+ parent_id : ObjectId ,
623+ ) -> Vec < gix_diff:: tree:: recorder:: Change > {
624+ let mut buffer = Vec :: new ( ) ;
625+
626+ let parent = odb. find_commit ( & parent_id, & mut buffer) . unwrap ( ) ;
627+
628+ let mut buffer = Vec :: new ( ) ;
629+ let parent_tree_iter = odb
630+ . find ( & parent. tree ( ) , & mut buffer)
631+ . unwrap ( )
632+ . try_into_tree_iter ( )
633+ . unwrap ( ) ;
634+
635+ let mut buffer = Vec :: new ( ) ;
636+ let commit = odb. find_commit ( & id, & mut buffer) . unwrap ( ) ;
637+
638+ let mut buffer = Vec :: new ( ) ;
639+ let tree_iter = odb
640+ . find ( & commit. tree ( ) , & mut buffer)
641+ . unwrap ( )
642+ . try_into_tree_iter ( )
643+ . unwrap ( ) ;
644+
645+ let mut recorder = gix_diff:: tree:: Recorder :: default ( ) ;
646+ gix_diff:: tree:: Changes :: from ( parent_tree_iter)
647+ . needed_to_obtain ( tree_iter, gix_diff:: tree:: State :: default ( ) , & odb, & mut recorder)
648+ . unwrap ( ) ;
649+
650+ recorder
651+ . records
652+ . iter ( )
653+ . filter ( |change| match change {
654+ gix_diff:: tree:: recorder:: Change :: Modification { path, .. } => path == file_path,
655+ gix_diff:: tree:: recorder:: Change :: Addition { path, .. } => path == file_path,
656+ gix_diff:: tree:: recorder:: Change :: Deletion { path, .. } => path == file_path,
657+ } )
658+ . cloned ( )
659+ . collect ( )
660+ }
661+
618662/// This function merges adjacent blame entries. It merges entries that are adjacent both in the
619663/// blamed file and in the original file that introduced them. This follows `git`’s
620664/// behaviour. `libgit2`, as of 2024-09-19, only checks whether two entries are adjacent in the
@@ -731,43 +775,9 @@ pub fn blame_file<E>(
731775
732776 let last_parent_id: ObjectId = * parent_ids. last ( ) . unwrap ( ) ;
733777
734- let mut buffer = Vec :: new ( ) ;
735-
736- let last_parent = odb. find_commit ( & last_parent_id, & mut buffer) . unwrap ( ) ;
737-
738- let mut buffer = Vec :: new ( ) ;
739- let last_parent_tree_iter = odb
740- . find ( & last_parent. tree ( ) , & mut buffer)
741- . unwrap ( )
742- . try_into_tree_iter ( )
743- . unwrap ( ) ;
744-
745- let mut buffer = Vec :: new ( ) ;
746- let commit = odb. find_commit ( & item. id , & mut buffer) . unwrap ( ) ;
747-
748- let mut buffer = Vec :: new ( ) ;
749- let tree_iter = odb
750- . find ( & commit. tree ( ) , & mut buffer)
751- . unwrap ( )
752- . try_into_tree_iter ( )
753- . unwrap ( ) ;
754-
755- let mut recorder = gix_diff:: tree:: Recorder :: default ( ) ;
756- gix_diff:: tree:: Changes :: from ( last_parent_tree_iter)
757- . needed_to_obtain ( tree_iter, gix_diff:: tree:: State :: default ( ) , & odb, & mut recorder)
758- . unwrap ( ) ;
778+ let changes_for_file_path = get_changes_for_file_path ( & odb, file_path, item. id , last_parent_id) ;
759779
760- let records_for_file_path: Vec < & gix_diff:: tree:: recorder:: Change > = recorder
761- . records
762- . iter ( )
763- . filter ( |change| match change {
764- gix_diff:: tree:: recorder:: Change :: Modification { path, .. } => path == file_path,
765- gix_diff:: tree:: recorder:: Change :: Addition { path, .. } => path == file_path,
766- gix_diff:: tree:: recorder:: Change :: Deletion { path, .. } => path == file_path,
767- } )
768- . collect ( ) ;
769-
770- let [ modification] : [ & gix_diff:: tree:: recorder:: Change ] = records_for_file_path[ ..] else {
780+ let [ ref modification] : [ gix_diff:: tree:: recorder:: Change ] = changes_for_file_path[ ..] else {
771781 // None of the changes affected the file we’re currently blaming.
772782 continue ;
773783 } ;
0 commit comments