@@ -69,12 +69,12 @@ where
69
69
70
70
let mut stats = Statistics :: default ( ) ;
71
71
let ( mut buf, mut buf2, mut buf3) = ( Vec :: new ( ) , Vec :: new ( ) , Vec :: new ( ) ) ;
72
- let blamed_file_entry = find_path_entry_in_commit ( & odb, & suspect, file_path, & mut buf, & mut buf2, & mut stats) ?
72
+ let blamed_file_entry_id = find_path_entry_in_commit ( & odb, & suspect, file_path, & mut buf, & mut buf2, & mut stats) ?
73
73
. ok_or_else ( || Error :: FileMissing {
74
- file_path : file_path. to_owned ( ) ,
75
- commit_id : suspect,
76
- } ) ?;
77
- let blamed_file_blob = odb. find_blob ( & blamed_file_entry . oid , & mut buf) ?. data . to_vec ( ) ;
74
+ file_path : file_path. to_owned ( ) ,
75
+ commit_id : suspect,
76
+ } ) ?;
77
+ let blamed_file_blob = odb. find_blob ( & blamed_file_entry_id , & mut buf) ?. data . to_vec ( ) ;
78
78
let num_lines_in_blamed = {
79
79
let mut interner = gix_diff:: blob:: intern:: Interner :: new ( blamed_file_blob. len ( ) / 100 ) ;
80
80
tokens_for_diffing ( & blamed_file_blob)
98
98
99
99
let mut out = Vec :: new ( ) ;
100
100
let mut diff_state = gix_diff:: tree:: State :: default ( ) ;
101
+ let mut previous_entry: Option < ( ObjectId , ObjectId ) > = None ;
101
102
' outer: while let Some ( item) = traverse. next ( ) {
102
103
if hunks_to_blame. is_empty ( ) {
103
104
break ;
@@ -123,15 +124,27 @@ where
123
124
continue ;
124
125
}
125
126
126
- let Some ( entry) = find_path_entry_in_commit ( & odb, & suspect, file_path, & mut buf, & mut buf2, & mut stats) ? else {
127
+ let mut entry = previous_entry
128
+ . take ( )
129
+ . filter ( |( id, _) | * id == suspect)
130
+ . map ( |( _, entry) | entry) ;
131
+ if entry. is_none ( ) {
132
+ entry = find_path_entry_in_commit ( & odb, & suspect, file_path, & mut buf, & mut buf2, & mut stats) ?;
133
+ }
134
+
135
+ let Some ( entry_id) = entry else {
127
136
continue ;
128
137
} ;
129
138
130
- for parent_id in & parent_ids {
131
- if let Some ( parent_entry ) =
139
+ for ( pid , parent_id) in parent_ids. iter ( ) . enumerate ( ) {
140
+ if let Some ( parent_entry_id ) =
132
141
find_path_entry_in_commit ( & odb, parent_id, file_path, & mut buf, & mut buf2, & mut stats) ?
133
142
{
134
- if entry. oid == parent_entry. oid {
143
+ let no_change_in_entry = entry_id == parent_entry_id;
144
+ if pid == 0 {
145
+ previous_entry = Some ( ( * parent_id, parent_entry_id) ) ;
146
+ }
147
+ if no_change_in_entry {
135
148
pass_blame_from_to ( suspect, * parent_id, & mut hunks_to_blame) ;
136
149
continue ' outer;
137
150
}
@@ -170,10 +183,8 @@ where
170
183
// Do nothing under the assumption that this always (or almost always)
171
184
// implies that the file comes from a different parent, compared to which
172
185
// it was modified, not added.
173
- } else {
174
- if unblamed_to_out_is_done ( & mut hunks_to_blame, & mut out, suspect) {
175
- break ' outer;
176
- }
186
+ } else if unblamed_to_out_is_done ( & mut hunks_to_blame, & mut out, suspect) {
187
+ break ' outer;
177
188
}
178
189
}
179
190
gix_diff:: tree:: recorder:: Change :: Deletion { .. } => {
@@ -418,7 +429,7 @@ fn find_path_entry_in_commit(
418
429
buf : & mut Vec < u8 > ,
419
430
buf2 : & mut Vec < u8 > ,
420
431
stats : & mut Statistics ,
421
- ) -> Result < Option < gix_object :: tree :: Entry > , Error > {
432
+ ) -> Result < Option < ObjectId > , Error > {
422
433
let commit_id = odb. find_commit ( commit, buf) ?. tree ( ) ;
423
434
stats. commits_to_tree += 1 ;
424
435
let tree_iter = odb. find_tree_iter ( & commit_id, buf) ?;
@@ -430,7 +441,7 @@ fn find_path_entry_in_commit(
430
441
file_path. split ( |b| * b == b'/' ) . inspect ( |_| stats. trees_decoded += 1 ) ,
431
442
) ?;
432
443
stats. trees_decoded -= 1 ;
433
- Ok ( res)
444
+ Ok ( res. map ( |e| e . oid ) )
434
445
}
435
446
436
447
/// Return an iterator over tokens for use in diffing. These usually lines, but iit's important to unify them
0 commit comments