@@ -3,9 +3,9 @@ use crate::{BlameEntry, Error, Outcome, Statistics};
3
3
use gix_diff:: blob:: intern:: TokenSource ;
4
4
use gix_hash:: ObjectId ;
5
5
use gix_object:: { bstr:: BStr , FindExt } ;
6
+ use std:: num:: NonZeroU32 ;
6
7
use std:: ops:: Range ;
7
8
8
- // TODO: do not instantiate anything, get everything passed as argument.
9
9
/// Produce a list of consecutive [`BlameEntry`] instances to indicate in which commits the ranges of the file
10
10
/// at `traverse[0]:<file_path>` originated in.
11
11
///
@@ -142,8 +142,8 @@ where
142
142
) ?;
143
143
let Some ( modification) = changes_for_file_path else {
144
144
if more_than_one_parent {
145
- // None of the changes affected the file we’re currently blaming. Pass blame
146
- // to parent.
145
+ // None of the changes affected the file we’re currently blaming.
146
+ // Copy blame to parent.
147
147
for unblamed_hunk in & mut hunks_to_blame {
148
148
unblamed_hunk. clone_blame ( suspect, parent_id) ;
149
149
}
@@ -159,8 +159,6 @@ where
159
159
// Do nothing under the assumption that this always (or almost always)
160
160
// implies that the file comes from a different parent, compared to which
161
161
// it was modified, not added.
162
- //
163
- // TODO: I still have to figure out whether this is correct in all cases.
164
162
} else {
165
163
unblamed_to_out ( & mut hunks_to_blame, & mut out, suspect) ;
166
164
break ;
@@ -191,25 +189,26 @@ where
191
189
192
190
// I don’t know yet whether it would make sense to use a data structure instead that preserves
193
191
// order on insertion.
194
- out. sort_by ( |a, b| a. range_in_blamed_file . start . cmp ( & b. range_in_blamed_file . start ) ) ;
192
+ out. sort_by ( |a, b| a. start_in_blamed_file . cmp ( & b. start_in_blamed_file ) ) ;
195
193
Ok ( Outcome {
196
194
entries : coalesce_blame_entries ( out) ,
197
195
blob : blamed_file_blob,
198
196
statistics : stats,
199
197
} )
200
198
}
201
199
202
- /// The blobs storing the blamed file in `entry` and `parent_entry` are identical which is why
203
- /// we can pass blame to the parent without further checks.
200
+ /// Pass ownership of each unblamed hunk of `from` to `to`.
201
+ ///
202
+ /// This happens when `from` didn't actually change anything in the blamed file.
204
203
fn pass_blame_from_to ( from : ObjectId , to : ObjectId , hunks_to_blame : & mut Vec < UnblamedHunk > ) {
205
204
for unblamed_hunk in hunks_to_blame {
206
205
unblamed_hunk. pass_blame ( from, to) ;
207
206
}
208
207
}
209
208
209
+ /// Convert each of the unblamed hunk in `hunks_to_blame` into a [`BlameEntry`], consuming them in the process.
210
+ /// `suspect` is expected to be present in the suspect-map in each [`UnblamedHunk`].
210
211
fn unblamed_to_out ( hunks_to_blame : & mut Vec < UnblamedHunk > , out : & mut Vec < BlameEntry > , suspect : ObjectId ) {
211
- // Every line that has not been blamed yet on a commit, is expected to have been
212
- // added when the file was added to the repository.
213
212
out. extend (
214
213
hunks_to_blame
215
214
. drain ( ..)
@@ -234,14 +233,21 @@ fn coalesce_blame_entries(lines_blamed: Vec<BlameEntry>) -> Vec<BlameEntry> {
234
233
let previous_entry = acc. last ( ) ;
235
234
236
235
if let Some ( previous_entry) = previous_entry {
236
+ let previous_blamed_range = previous_entry. range_in_blamed_file ( ) ;
237
+ let current_blamed_range = entry. range_in_blamed_file ( ) ;
238
+ let previous_source_range = previous_entry. range_in_source_file ( ) ;
239
+ let current_source_range = entry. range_in_source_file ( ) ;
237
240
if previous_entry. commit_id == entry. commit_id
238
- && previous_entry . range_in_blamed_file . end == entry . range_in_blamed_file . start
241
+ && previous_blamed_range . end == current_blamed_range . start
239
242
// As of 2024-09-19, the check below only is in `git`, but not in `libgit2`.
240
- && previous_entry . range_in_source_file . end == entry . range_in_source_file . start
243
+ && previous_source_range . end == current_source_range . start
241
244
{
245
+ // let combined_range =
242
246
let coalesced_entry = BlameEntry {
243
- range_in_blamed_file : previous_entry. range_in_blamed_file . start ..entry. range_in_blamed_file . end ,
244
- range_in_source_file : previous_entry. range_in_source_file . start ..entry. range_in_source_file . end ,
247
+ start_in_blamed_file : previous_blamed_range. start as u32 ,
248
+ start_in_source_file : previous_source_range. start as u32 ,
249
+ len : NonZeroU32 :: new ( ( current_source_range. end - previous_source_range. start ) as u32 )
250
+ . expect ( "BUG: hunks are never zero-sized" ) ,
245
251
commit_id : previous_entry. commit_id ,
246
252
} ;
247
253
0 commit comments