Skip to content

Commit 381b673

Browse files
committed
Coalesce adjacent blame entries
1 parent 1e4191d commit 381b673

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

gix-blame/tests/blame.rs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,47 @@ mod baseline {
732732
}
733733
}
734734

735+
/// This function merges adjacent blame entries. It merges entries that are adjacent both in the
736+
/// blamed file as well as in the original file that introduced them. This follows `git`’s
737+
/// behaviour. `libgit2`, as of 2024-09-19, only checks whether two entries are adjacent in the
738+
/// blamed file which can result in different blames in certain edge cases. See [the commit][1]
739+
/// that introduced the extra check into `git` for context.
740+
///
741+
/// [1]: https://github.com/git/git/commit/c2ebaa27d63bfb7c50cbbdaba90aee4efdd45d0a
742+
fn coalesce_blame_entries(lines_blamed: Vec<BlameEntry>) -> Vec<BlameEntry> {
743+
// TODO
744+
// It’s possible this could better be done on insertion into `lines_blamed`.
745+
lines_blamed.into_iter().fold(vec![], |mut acc, entry| {
746+
let previous_entry = acc.last();
747+
748+
if let Some(previous_entry) = previous_entry {
749+
if previous_entry.commit_id == entry.commit_id
750+
&& previous_entry.range_in_blamed_file.end == entry.range_in_blamed_file.start
751+
// As of 2024-09-19, the check below only is in `git`, but not in `libgit2`.
752+
&& previous_entry.range_in_original_file.end == entry.range_in_original_file.start
753+
{
754+
let coalesced_entry = BlameEntry {
755+
range_in_blamed_file: previous_entry.range_in_blamed_file.start..entry.range_in_blamed_file.end,
756+
range_in_original_file: previous_entry.range_in_original_file.start
757+
..entry.range_in_original_file.end,
758+
commit_id: previous_entry.commit_id,
759+
};
760+
761+
acc.pop();
762+
acc.push(coalesced_entry);
763+
} else {
764+
acc.push(entry);
765+
}
766+
767+
acc
768+
} else {
769+
acc.push(entry);
770+
771+
acc
772+
}
773+
})
774+
}
775+
735776
fn blame_file(worktree_path: PathBuf, file_path: &BStr) -> Vec<BlameEntry> {
736777
// TODO
737778
// At a high level, what we want to do is the following:
@@ -944,7 +985,7 @@ fn blame_file(worktree_path: PathBuf, file_path: &BStr) -> Vec<BlameEntry> {
944985
// order on insertion.
945986
lines_blamed.sort_by(|a, b| a.range_in_blamed_file.start.cmp(&b.range_in_blamed_file.start));
946987

947-
lines_blamed
988+
coalesce_blame_entries(lines_blamed)
948989
}
949990

950991
macro_rules! mktest {
@@ -979,6 +1020,7 @@ mktest!(added_lines_around, "added-lines-around", 3);
9791020
mktest!(switched_lines, "switched-lines", 4);
9801021
mktest!(added_line_before_changed_line, "added-line-before-changed-line", 3);
9811022
mktest!(same_line_changed_twice, "same-line-changed-twice", 2);
1023+
mktest!(coalesce_adjacent_hunks, "coalesce-adjacent-hunks", 1);
9821024

9831025
#[test]
9841026
fn process_change_works() {

gix-blame/tests/fixtures/make_blame_repo.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ git commit -q -m c1.2
2222

2323
echo "line 2" >> added-lines.txt
2424
echo "line 2" >> added-lines-around.txt
25+
echo -e "line 1\nline 2" > coalesce-adjacent-hunks.txt
2526
git add added-lines.txt
2627
git add added-lines-around.txt
28+
git add coalesce-adjacent-hunks.txt
2729
git commit -q -m c1.3
2830

2931
echo "line 2" >> simple.txt
@@ -45,7 +47,9 @@ git add added-line-before-changed-line.txt
4547
git commit -q -m c2.3
4648

4749
echo -e "line 1\nline 2" > same-line-changed-twice.txt
50+
echo -e "line 1\nline in between\nline 2" > coalesce-adjacent-hunks.txt
4851
git add same-line-changed-twice.txt
52+
git add coalesce-adjacent-hunks.txt
4953
git commit -q -m c2.4
5054

5155
echo "line 3" >> simple.txt
@@ -65,7 +69,9 @@ git add changed-line-between-unchanged-lines.txt
6569
git commit -q -m c3.2
6670

6771
echo -e "line 2\nline 3" > added-line-before-changed-line.txt
72+
echo -e "line 1\nline 2" > coalesce-adjacent-hunks.txt
6873
git add added-line-before-changed-line.txt
74+
git add coalesce-adjacent-hunks.txt
6975
git commit -q -m c3.3
7076

7177
echo -e "line 1\nline 2 changed" > same-line-changed-twice.txt
@@ -121,3 +127,4 @@ git blame --porcelain added-lines-around.txt > .git/added-lines-around.baseline
121127
git blame --porcelain switched-lines.txt > .git/switched-lines.baseline
122128
git blame --porcelain added-line-before-changed-line.txt > .git/added-line-before-changed-line.baseline
123129
git blame --porcelain same-line-changed-twice.txt > .git/same-line-changed-twice.baseline
130+
git blame --porcelain coalesce-adjacent-hunks.txt > .git/coalesce-adjacent-hunks.baseline

0 commit comments

Comments
 (0)