@@ -8,11 +8,12 @@ use crate::types::{BlameEntry, Change, Either, LineRange, Offset, UnblamedHunk};
8
8
9
9
pub ( super ) mod function;
10
10
11
- /// Compare a section from the *Blamed File* (`hunk`) with a change from a diff and see if there
12
- /// is an intersection with `change`. Based on that intersection, we may generate a [`BlameEntry`] for `out`
13
- /// and/or split the `hunk` into multiple.
11
+ /// Compare a section from a potential *Source File* (`hunk`) with a change from a diff and see if
12
+ /// there is an intersection with `change`. Based on that intersection, we may generate a
13
+ /// [`BlameEntry`] for `out` and/or split the `hunk` into multiple.
14
14
///
15
- /// This is the core of the blame implementation as it matches regions in *Source File* to the *Blamed File*.
15
+ /// This is the core of the blame implementation as it matches regions in *Blamed File* to
16
+ /// corresponding regions in one or more than one *Source File*.
16
17
fn process_change (
17
18
new_hunks_to_blame : & mut Vec < UnblamedHunk > ,
18
19
offset : & mut Offset ,
@@ -320,36 +321,41 @@ fn process_change(
320
321
321
322
/// Consume `hunks_to_blame` and `changes` to pair up matches ranges (also overlapping) with each other.
322
323
/// Once a match is found, it's pushed onto `out`.
324
+ ///
325
+ /// `process_changes` assumes that ranges coming from the same *Source File* can and do
326
+ /// occasionally overlap. If it were a desirable property of the blame algorithm as a whole to
327
+ /// never have two different lines from a *Blamed File* mapped to the same line in a *Source File*,
328
+ /// this property would need to be enforced at a higher level than `process_changes`.
329
+ /// Then the nested loops could potentially be flattened into one.
323
330
fn process_changes (
324
331
hunks_to_blame : Vec < UnblamedHunk > ,
325
332
changes : Vec < Change > ,
326
333
suspect : ObjectId ,
327
334
parent : ObjectId ,
328
335
) -> Vec < UnblamedHunk > {
329
- let mut hunks_iter = hunks_to_blame. into_iter ( ) ;
330
- let mut changes_iter = changes. into_iter ( ) ;
336
+ let mut new_hunks_to_blame = Vec :: new ( ) ;
331
337
332
- let mut hunk = hunks_iter . next ( ) ;
333
- let mut change = changes_iter . next ( ) ;
338
+ for mut hunk in hunks_to_blame . into_iter ( ) . map ( Some ) {
339
+ let mut offset_in_destination = Offset :: Added ( 0 ) ;
334
340
335
- let mut new_hunks_to_blame = Vec :: new ( ) ;
336
- let mut offset_in_destination = Offset :: Added ( 0 ) ;
337
-
338
- loop {
339
- ( hunk, change) = process_change (
340
- & mut new_hunks_to_blame,
341
- & mut offset_in_destination,
342
- suspect,
343
- parent,
344
- hunk,
345
- change,
346
- ) ;
347
-
348
- hunk = hunk . or_else ( || hunks_iter . next ( ) ) ;
349
- change = change . or_else ( || changes_iter . next ( ) ) ;
350
-
351
- if hunk . is_none ( ) && change . is_none ( ) {
352
- break ;
341
+ let mut changes_iter = changes . iter ( ) . cloned ( ) ;
342
+ let mut change = changes_iter . next ( ) ;
343
+
344
+ loop {
345
+ ( hunk, change) = process_change (
346
+ & mut new_hunks_to_blame,
347
+ & mut offset_in_destination,
348
+ suspect,
349
+ parent,
350
+ hunk,
351
+ change,
352
+ ) ;
353
+
354
+ change = change . or_else ( || changes_iter . next ( ) ) ;
355
+
356
+ if hunk . is_none ( ) {
357
+ break ;
358
+ }
353
359
}
354
360
}
355
361
new_hunks_to_blame
0 commit comments