@@ -8,11 +8,12 @@ use crate::types::{BlameEntry, Change, Either, LineRange, Offset, UnblamedHunk};
88
99pub ( super ) mod function;
1010
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.
1414///
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*.
1617fn process_change (
1718 new_hunks_to_blame : & mut Vec < UnblamedHunk > ,
1819 offset : & mut Offset ,
@@ -320,36 +321,41 @@ fn process_change(
320321
321322/// Consume `hunks_to_blame` and `changes` to pair up matches ranges (also overlapping) with each other.
322323/// 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.
323330fn process_changes (
324331 hunks_to_blame : Vec < UnblamedHunk > ,
325332 changes : Vec < Change > ,
326333 suspect : ObjectId ,
327334 parent : ObjectId ,
328335) -> 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 ( ) ;
331337
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 ) ;
334340
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+ }
353359 }
354360 }
355361 new_hunks_to_blame
0 commit comments