Skip to content

Commit ac2ea10

Browse files
committed
Skip suspects that have no associated unblamed hunks
Pass blame to parent in `process_change`. `git`’s algorithm only seems to keep the current suspect for unblamed hunks that were the direct result of splitting an existing unblamed hunk because it matched with a change. All other hunks appear to be blamed on the parent without further checks.
1 parent 3f7dea2 commit ac2ea10

File tree

3 files changed

+51
-42
lines changed

3 files changed

+51
-42
lines changed

gix-blame/src/file/function.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ where
120120
type CommitTime = i64;
121121

122122
let mut queue: gix_revwalk::PriorityQueue<CommitTime, ObjectId> = gix_revwalk::PriorityQueue::new();
123-
let mut seen: HashSet<ObjectId> = HashSet::new();
124123

125124
// TODO
126125
// This is a simplified version of `gen_and_commit_time` in
@@ -157,10 +156,11 @@ where
157156
break;
158157
}
159158

160-
let was_inserted = seen.insert(suspect);
159+
let is_still_suspect = hunks_to_blame.iter().any(|hunk| hunk.suspects.contains_key(&suspect));
161160

162-
if !was_inserted {
163-
// We have already visited `suspect` and can continue with the next one.
161+
if !is_still_suspect {
162+
// There are no `UnblamedHunk`s associated with this `suspect`, so we can continue with
163+
// the next one.
164164
continue 'outer;
165165
}
166166

gix-blame/src/file/mod.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ fn process_change(
6666

6767
// Nothing to do with `hunk` except shifting it,
6868
// but `unchanged` needs to be checked against the next hunk to catch up.
69-
new_hunks_to_blame.push(hunk.cloned_blame(suspect, parent).shift_by(parent, *offset));
69+
new_hunks_to_blame.push(hunk.passed_blame(suspect, parent).shift_by(parent, *offset));
7070
(None, Some(Change::Unchanged(unchanged)))
7171
}
7272
(false, false) => {
@@ -95,7 +95,7 @@ fn process_change(
9595

9696
// Nothing to do with `hunk` except shifting it,
9797
// but `unchanged` needs to be checked against the next hunk to catch up.
98-
new_hunks_to_blame.push(hunk.cloned_blame(suspect, parent).shift_by(parent, *offset));
98+
new_hunks_to_blame.push(hunk.passed_blame(suspect, parent).shift_by(parent, *offset));
9999
(None, Some(Change::Unchanged(unchanged)))
100100
}
101101
}
@@ -125,7 +125,7 @@ fn process_change(
125125
}
126126
Either::Right((before, after)) => {
127127
// requeue the left side `before` after offsetting it…
128-
new_hunks_to_blame.push(before.cloned_blame(suspect, parent).shift_by(parent, *offset));
128+
new_hunks_to_blame.push(before.passed_blame(suspect, parent).shift_by(parent, *offset));
129129
// …and treat `after` as `new_hunk`, which contains the `added` range.
130130
after
131131
}
@@ -162,7 +162,7 @@ fn process_change(
162162
Either::Left(hunk) => hunk,
163163
Either::Right((before, after)) => {
164164
// Keep looking for the left side of the unblamed portion.
165-
new_hunks_to_blame.push(before.cloned_blame(suspect, parent).shift_by(parent, *offset));
165+
new_hunks_to_blame.push(before.passed_blame(suspect, parent).shift_by(parent, *offset));
166166
after
167167
}
168168
};
@@ -220,7 +220,7 @@ fn process_change(
220220
// <----> (added)
221221

222222
// Retry `hunk` once there is overlapping changes to process.
223-
new_hunks_to_blame.push(hunk.cloned_blame(suspect, parent).shift_by(parent, *offset));
223+
new_hunks_to_blame.push(hunk.passed_blame(suspect, parent).shift_by(parent, *offset));
224224

225225
// Let hunks catchup with this change.
226226
(
@@ -273,7 +273,7 @@ fn process_change(
273273
}
274274
Either::Right((before, after)) => {
275275
// `before` isn't affected by deletion, so keep it for later.
276-
new_hunks_to_blame.push(before.cloned_blame(suspect, parent).shift_by(parent, *offset));
276+
new_hunks_to_blame.push(before.passed_blame(suspect, parent).shift_by(parent, *offset));
277277
// after will be affected by offset, and we will see if there are more changes affecting it.
278278
after
279279
}
@@ -285,7 +285,7 @@ fn process_change(
285285
// | (line_number_in_destination)
286286

287287
// Catchup with changes.
288-
new_hunks_to_blame.push(hunk.cloned_blame(suspect, parent).shift_by(parent, *offset));
288+
new_hunks_to_blame.push(hunk.passed_blame(suspect, parent).shift_by(parent, *offset));
289289

290290
(
291291
None,
@@ -295,7 +295,7 @@ fn process_change(
295295
}
296296
(Some(hunk), None) => {
297297
// nothing to do - changes are exhausted, re-evaluate `hunk`.
298-
new_hunks_to_blame.push(hunk.cloned_blame(suspect, parent).shift_by(parent, *offset));
298+
new_hunks_to_blame.push(hunk.passed_blame(suspect, parent).shift_by(parent, *offset));
299299
(None, None)
300300
}
301301
(None, Some(Change::Unchanged(_))) => {
@@ -402,6 +402,15 @@ impl UnblamedHunk {
402402
}
403403
}
404404

405+
/// This is like [`Self::pass_blame()`], but easier to use in places where the 'passing' is
406+
/// done 'inline'.
407+
fn passed_blame(mut self, from: ObjectId, to: ObjectId) -> Self {
408+
if let Some(range_in_suspect) = self.suspects.remove(&from) {
409+
self.suspects.insert(to, range_in_suspect);
410+
}
411+
self
412+
}
413+
405414
/// Transfer all ranges from the commit at `from` to the commit at `to`.
406415
fn pass_blame(&mut self, from: ObjectId, to: ObjectId) {
407416
if let Some(range_in_suspect) = self.suspects.remove(&from) {

gix-blame/src/file/tests.rs

Lines changed: 30 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ mod process_change {
115115
[
116116
UnblamedHunk {
117117
range_in_blamed_file: 0..2,
118-
suspects: [(suspect, 0..2), (parent, 0..2)].into()
118+
suspects: [(parent, 0..2)].into()
119119
},
120120
UnblamedHunk {
121121
range_in_blamed_file: 2..3,
@@ -155,7 +155,7 @@ mod process_change {
155155
[
156156
UnblamedHunk {
157157
range_in_blamed_file: 10..12,
158-
suspects: [(suspect, 10..12), (parent, 5..7)].into()
158+
suspects: [(parent, 5..7)].into()
159159
},
160160
UnblamedHunk {
161161
range_in_blamed_file: 12..13,
@@ -196,7 +196,7 @@ mod process_change {
196196
[
197197
UnblamedHunk {
198198
range_in_blamed_file: 12..14,
199-
suspects: [(suspect, 7..9), (parent, 7..9)].into()
199+
suspects: [(parent, 7..9)].into()
200200
},
201201
UnblamedHunk {
202202
range_in_blamed_file: 14..15,
@@ -306,7 +306,7 @@ mod process_change {
306306
[
307307
UnblamedHunk {
308308
range_in_blamed_file: 3..4,
309-
suspects: [(suspect, 2..3), (parent, 0..1)].into()
309+
suspects: [(parent, 0..1)].into()
310310
},
311311
UnblamedHunk {
312312
range_in_blamed_file: 4..6,
@@ -399,7 +399,7 @@ mod process_change {
399399
[
400400
UnblamedHunk {
401401
range_in_blamed_file: 71..107,
402-
suspects: [(suspect, 70..106), (parent, 70..106)].into()
402+
suspects: [(parent, 70..106)].into()
403403
},
404404
UnblamedHunk {
405405
range_in_blamed_file: 107..109,
@@ -434,7 +434,7 @@ mod process_change {
434434
[
435435
UnblamedHunk {
436436
range_in_blamed_file: 149..155,
437-
suspects: [(suspect, 137..143), (parent, 137..143)].into()
437+
suspects: [(parent, 137..143)].into()
438438
},
439439
UnblamedHunk {
440440
range_in_blamed_file: 155..156,
@@ -468,7 +468,7 @@ mod process_change {
468468
new_hunks_to_blame,
469469
[UnblamedHunk {
470470
range_in_blamed_file: 3..6,
471-
suspects: [(suspect, 2..5), (parent, 5..8)].into()
471+
suspects: [(parent, 5..8)].into()
472472
}]
473473
);
474474
assert_eq!(offset_in_destination, Offset::Deleted(3));
@@ -584,7 +584,7 @@ mod process_change {
584584
new_hunks_to_blame,
585585
[UnblamedHunk {
586586
range_in_blamed_file: 15..16,
587-
suspects: [(suspect, 17..18), (parent, 16..17)].into()
587+
suspects: [(parent, 16..17)].into()
588588
}]
589589
);
590590
assert_eq!(offset_in_destination, Offset::Added(1));
@@ -677,7 +677,7 @@ mod process_change {
677677
new_hunks_to_blame,
678678
[UnblamedHunk {
679679
range_in_blamed_file: 12..14,
680-
suspects: [(suspect, 13..15), (parent, 10..12)].into()
680+
suspects: [(parent, 10..12)].into()
681681
}]
682682
);
683683
assert_eq!(offset_in_destination, Offset::Added(1));
@@ -706,7 +706,7 @@ mod process_change {
706706
new_hunks_to_blame,
707707
[UnblamedHunk {
708708
range_in_blamed_file: 110..114,
709-
suspects: [(suspect, 109..113), (parent, 106..110)].into()
709+
suspects: [(parent, 106..110)].into()
710710
}]
711711
);
712712
assert_eq!(offset_in_destination, Offset::Added(3));
@@ -762,7 +762,7 @@ mod process_change {
762762
new_hunks_to_blame,
763763
[UnblamedHunk {
764764
range_in_blamed_file: 0..5,
765-
suspects: [(suspect, 0..5), (parent, 0..5)].into()
765+
suspects: [(parent, 0..5)].into()
766766
}]
767767
);
768768
assert_eq!(offset_in_destination, Offset::Added(0));
@@ -821,7 +821,7 @@ mod process_change {
821821
new_hunks_to_blame,
822822
[UnblamedHunk {
823823
range_in_blamed_file: 0..5,
824-
suspects: [(suspect, 0..5), (parent, 0..5)].into()
824+
suspects: [(parent, 0..5)].into()
825825
}]
826826
);
827827
assert_eq!(offset_in_destination, Offset::Added(0));
@@ -883,7 +883,7 @@ mod process_change {
883883
new_hunks_to_blame,
884884
[UnblamedHunk {
885885
range_in_blamed_file: 2..14,
886-
suspects: [(suspect, 2..14), (parent, 2..14)].into()
886+
suspects: [(parent, 2..14)].into()
887887
}]
888888
);
889889
assert_eq!(offset_in_destination, Offset::Deleted(4));
@@ -1003,7 +1003,7 @@ mod process_changes {
10031003
},
10041004
UnblamedHunk {
10051005
range_in_blamed_file: 4..6,
1006-
suspects: [(suspect, 4..6), (parent, 0..2)].into(),
1006+
suspects: [(parent, 0..2)].into(),
10071007
},
10081008
]
10091009
);
@@ -1026,15 +1026,15 @@ mod process_changes {
10261026
[
10271027
UnblamedHunk {
10281028
range_in_blamed_file: 0..2,
1029-
suspects: [(suspect, 0..2), (parent, 0..2)].into(),
1029+
suspects: [(parent, 0..2)].into(),
10301030
},
10311031
UnblamedHunk {
10321032
range_in_blamed_file: 2..4,
10331033
suspects: [(suspect, 2..4)].into(),
10341034
},
10351035
UnblamedHunk {
10361036
range_in_blamed_file: 4..6,
1037-
suspects: [(suspect, 4..6), (parent, 2..4)].into(),
1037+
suspects: [(parent, 2..4)].into(),
10381038
},
10391039
]
10401040
);
@@ -1065,7 +1065,7 @@ mod process_changes {
10651065
},
10661066
UnblamedHunk {
10671067
range_in_blamed_file: 4..6,
1068-
suspects: [(suspect, 4..6), (parent, 0..2)].into(),
1068+
suspects: [(parent, 0..2)].into(),
10691069
}
10701070
]
10711071
);
@@ -1088,7 +1088,7 @@ mod process_changes {
10881088
},
10891089
UnblamedHunk {
10901090
range_in_blamed_file: 1..6,
1091-
suspects: [(suspect, 1..6), (parent, 0..5)].into(),
1091+
suspects: [(parent, 0..5)].into(),
10921092
}
10931093
]
10941094
);
@@ -1111,7 +1111,7 @@ mod process_changes {
11111111
},
11121112
UnblamedHunk {
11131113
range_in_blamed_file: 3..6,
1114-
suspects: [(suspect, 1..4), (parent, 0..3)].into(),
1114+
suspects: [(parent, 0..3)].into(),
11151115
}
11161116
]
11171117
);
@@ -1134,7 +1134,7 @@ mod process_changes {
11341134
},
11351135
UnblamedHunk {
11361136
range_in_blamed_file: 4..6,
1137-
suspects: [(suspect, 4..6), (parent, 3..5)].into(),
1137+
suspects: [(parent, 3..5)].into(),
11381138
}
11391139
]
11401140
);
@@ -1152,7 +1152,7 @@ mod process_changes {
11521152
new_hunks_to_blame,
11531153
[UnblamedHunk {
11541154
range_in_blamed_file: 4..6,
1155-
suspects: [(suspect, 3..5), (parent, 0..2)].into(),
1155+
suspects: [(parent, 0..2)].into(),
11561156
}]
11571157
);
11581158
}
@@ -1174,7 +1174,7 @@ mod process_changes {
11741174
},
11751175
UnblamedHunk {
11761176
range_in_blamed_file: 2..3,
1177-
suspects: [(suspect, 1..2), (parent, 2..3)].into(),
1177+
suspects: [(parent, 2..3)].into(),
11781178
}
11791179
]
11801180
);
@@ -1201,7 +1201,7 @@ mod process_changes {
12011201
},
12021202
UnblamedHunk {
12031203
range_in_blamed_file: 2..3,
1204-
suspects: [(suspect, 2..3), (parent, 0..1)].into(),
1204+
suspects: [(parent, 0..1)].into(),
12051205
},
12061206
UnblamedHunk {
12071207
range_in_blamed_file: 3..4,
@@ -1237,19 +1237,19 @@ mod process_changes {
12371237
[
12381238
UnblamedHunk {
12391239
range_in_blamed_file: 0..16,
1240-
suspects: [(suspect, 0..16), (parent, 0..16)].into()
1240+
suspects: [(parent, 0..16)].into()
12411241
},
12421242
UnblamedHunk {
12431243
range_in_blamed_file: 16..17,
12441244
suspects: [(suspect, 16..17)].into()
12451245
},
12461246
UnblamedHunk {
12471247
range_in_blamed_file: 17..30,
1248-
suspects: [(suspect, 17..30), (parent, 16..29)].into()
1248+
suspects: [(parent, 16..29)].into()
12491249
},
12501250
UnblamedHunk {
12511251
range_in_blamed_file: 31..37,
1252-
suspects: [(suspect, 31..37), (parent, 30..36)].into()
1252+
suspects: [(parent, 30..36)].into()
12531253
}
12541254
]
12551255
);
@@ -1285,11 +1285,11 @@ mod process_changes {
12851285
[
12861286
UnblamedHunk {
12871287
range_in_blamed_file: 1..3,
1288-
suspects: [(suspect, 1..3), (parent, 1..3)].into(),
1288+
suspects: [(parent, 1..3)].into(),
12891289
},
12901290
UnblamedHunk {
12911291
range_in_blamed_file: 5..6,
1292-
suspects: [(suspect, 5..6), (parent, 5..6)].into(),
1292+
suspects: [(parent, 5..6)].into(),
12931293
},
12941294
UnblamedHunk {
12951295
range_in_blamed_file: 6..7,
@@ -1301,7 +1301,7 @@ mod process_changes {
13011301
},
13021302
UnblamedHunk {
13031303
range_in_blamed_file: 9..10,
1304-
suspects: [(suspect, 9..10), (parent, 6..7)].into(),
1304+
suspects: [(parent, 6..7)].into(),
13051305
},
13061306
]
13071307
);
@@ -1327,7 +1327,7 @@ mod process_changes {
13271327
},
13281328
UnblamedHunk {
13291329
range_in_blamed_file: 4..7,
1330-
suspects: [(suspect, 4..7), (parent, 3..6)].into()
1330+
suspects: [(parent, 3..6)].into()
13311331
}
13321332
]
13331333
);

0 commit comments

Comments
 (0)