Skip to content

Commit 39cc3ed

Browse files
committed
Add UnblamedHunk::split_at
This greatly simplifies some parts of the code. One possible follow-up is the introduction of `BlameEntry::from_unblamed_hunk`. - Remove `LineRange`. This is not necessary anymore.
1 parent 92c6ff2 commit 39cc3ed

File tree

1 file changed

+58
-92
lines changed

1 file changed

+58
-92
lines changed

gix-blame/src/lib.rs

Lines changed: 58 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -82,37 +82,6 @@ impl SubAssign<u32> for Offset {
8282
}
8383
}
8484

85-
#[derive(Clone, Copy, Debug)]
86-
struct LineRange {
87-
start: u32,
88-
end: u32,
89-
}
90-
91-
impl LineRange {
92-
fn with_offset(range: Range<u32>, offset: Offset) -> Self {
93-
match offset {
94-
Offset::Added(added) => {
95-
assert!(range.start >= added, "{range:?} {offset:?}");
96-
97-
Self {
98-
start: range.start - added,
99-
end: range.end - added,
100-
}
101-
}
102-
Offset::Deleted(deleted) => Self {
103-
start: range.start + deleted,
104-
end: range.end + deleted,
105-
},
106-
}
107-
}
108-
}
109-
110-
impl From<LineRange> for Range<u32> {
111-
fn from(line_range: LineRange) -> Self {
112-
line_range.start..line_range.end
113-
}
114-
}
115-
11685
#[derive(Debug, PartialEq)]
11786
pub struct BlameEntry {
11887
pub range_in_blamed_file: Range<u32>,
@@ -173,6 +142,12 @@ pub struct UnblamedHunk {
173142
pub range_in_destination: Range<u32>,
174143
}
175144

145+
#[derive(Debug)]
146+
enum Either<T, U> {
147+
Left(T),
148+
Right(U),
149+
}
150+
176151
impl UnblamedHunk {
177152
pub fn new(range_in_blamed_file: Range<u32>, offset: Offset) -> Self {
178153
assert!(
@@ -231,6 +206,22 @@ impl UnblamedHunk {
231206
Self::new(self.range_in_blamed_file.clone(), combined_offset)
232207
}
233208

209+
fn split_at(self, line_number_in_destination: u32) -> Either<Self, (Self, Self)> {
210+
if line_number_in_destination > self.range_in_destination.start
211+
&& line_number_in_destination < self.range_in_destination.end
212+
{
213+
let first_range_in_destination = self.range_in_destination.start..line_number_in_destination;
214+
let second_range_in_destination = line_number_in_destination..self.range_in_destination.end;
215+
216+
Either::Right((
217+
Self::from_destination(first_range_in_destination, self.offset()),
218+
Self::from_destination(second_range_in_destination, self.offset()),
219+
))
220+
} else {
221+
Either::Left(self)
222+
}
223+
}
224+
234225
fn offset(&self) -> Offset {
235226
if self.range_in_blamed_file.start > self.range_in_destination.start {
236227
Offset::Added(self.range_in_blamed_file.start - self.range_in_destination.start)
@@ -379,59 +370,48 @@ pub fn process_change(
379370
// <---> (added)
380371
// <---> (blamed)
381372
// <--> <-> (new hunk)
382-
if added.start > hunk.range_in_destination.start {
383-
let line_range_in_next_destination = LineRange::with_offset(
384-
hunk.range_in_destination.start..added.start,
385-
*offset_in_destination,
386-
);
387-
388-
new_hunks_to_blame.push(UnblamedHunk::from_destination(
389-
line_range_in_next_destination.into(),
390-
hunk.offset() + *offset_in_destination,
391-
));
392-
}
373+
374+
let new_hunk = match hunk.split_at(added.start) {
375+
Either::Left(hunk) => hunk,
376+
Either::Right((before, after)) => {
377+
new_hunks_to_blame.push(before.shift_by(*offset_in_destination));
378+
379+
after
380+
}
381+
};
393382

394383
*offset_in_destination += added.end - added.start;
395384
*offset_in_destination -= number_of_lines_deleted;
396385

397-
out.push(BlameEntry::with_offset(added.clone(), suspect, hunk.offset()));
398-
399-
let new_hunk = if hunk.range_in_destination.end > added.end {
400-
Some(UnblamedHunk::from_destination(
401-
added.end..hunk.range_in_destination.end,
402-
hunk.offset(),
403-
))
404-
} else {
405-
None
406-
};
386+
out.push(BlameEntry::with_offset(added.clone(), suspect, new_hunk.offset()));
407387

408-
(new_hunk, None)
388+
match new_hunk.split_at(added.end) {
389+
Either::Left(_) => (None, None),
390+
Either::Right((_, after)) => (Some(after), None),
391+
}
409392
}
410393
(true, false) => {
411394
// <--------> (hunk)
412395
// <-------> (added)
413396
// <----> (blamed)
414397
// <--> (new hunk)
415398

416-
if added.start > hunk.range_in_destination.start {
417-
let line_range_in_next_destination = LineRange::with_offset(
418-
hunk.range_in_destination.start..added.start,
419-
*offset_in_destination,
420-
);
399+
let new_hunk = match hunk.split_at(added.start) {
400+
Either::Left(hunk) => hunk,
401+
Either::Right((before, after)) => {
402+
new_hunks_to_blame.push(before.shift_by(*offset_in_destination));
421403

422-
new_hunks_to_blame.push(UnblamedHunk::from_destination(
423-
line_range_in_next_destination.into(),
424-
hunk.offset() + *offset_in_destination,
425-
));
426-
}
404+
after
405+
}
406+
};
427407

428408
out.push(BlameEntry::with_offset(
429-
added.start..hunk.range_in_destination.end,
409+
added.start..new_hunk.range_in_destination.end,
430410
suspect,
431-
hunk.offset(),
411+
new_hunk.offset(),
432412
));
433413

434-
if added.end > hunk.range_in_destination.end {
414+
if added.end > new_hunk.range_in_destination.end {
435415
(None, Some(Change::Added(added, number_of_lines_deleted)))
436416
} else {
437417
todo!();
@@ -452,16 +432,10 @@ pub fn process_change(
452432
*offset_in_destination += added.end - added.start;
453433
*offset_in_destination -= number_of_lines_deleted;
454434

455-
let new_hunk = if hunk.range_in_destination.end > added.end {
456-
Some(UnblamedHunk::from_destination(
457-
added.end..hunk.range_in_destination.end,
458-
hunk.offset(),
459-
))
460-
} else {
461-
None
462-
};
463-
464-
(new_hunk, None)
435+
match hunk.split_at(added.end) {
436+
Either::Left(_) => (None, None),
437+
Either::Right((_, after)) => (Some(after), None),
438+
}
465439
}
466440
(false, false) => {
467441
// Any of the following cases are handled by this branch:
@@ -517,26 +491,18 @@ pub fn process_change(
517491
// <-----> (hunk)
518492
// | (line_number_in_destination)
519493

520-
if hunk.range_in_destination.start < line_number_in_destination {
521-
let line_range_in_next_destination = LineRange::with_offset(
522-
hunk.range_in_destination.start..line_number_in_destination,
523-
*offset_in_destination,
524-
);
494+
let new_hunk = match hunk.split_at(line_number_in_destination) {
495+
Either::Left(hunk) => hunk,
496+
Either::Right((before, after)) => {
497+
new_hunks_to_blame.push(before.shift_by(*offset_in_destination));
525498

526-
new_hunks_to_blame.push(UnblamedHunk::from_destination(
527-
line_range_in_next_destination.into(),
528-
hunk.offset() + *offset_in_destination,
529-
));
530-
}
499+
after
500+
}
501+
};
531502

532503
*offset_in_destination -= number_of_lines_deleted;
533504

534-
let new_hunk = Some(UnblamedHunk::from_destination(
535-
line_number_in_destination..hunk.range_in_destination.end,
536-
hunk.offset(),
537-
));
538-
539-
(new_hunk, None)
505+
(Some(new_hunk), None)
540506
} else {
541507
// <---> (hunk)
542508
// | (line_number_in_destination)

0 commit comments

Comments
 (0)