Skip to content

Commit 28fbeb8

Browse files
authored
Merge pull request GitoxideLabs#2420 from cruessler/remove-imara-diff-0-1-in-gix-blame
Switch to `imara-diff` 0.2 in `gix-blame`
2 parents a4b5ae5 + f4064e5 commit 28fbeb8

7 files changed

Lines changed: 10 additions & 137 deletions

File tree

Cargo.toml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,6 @@ http-client-reqwest = ["gix/blocking-http-transport-reqwest-rust-tls"]
155155
## Use async client networking.
156156
gitoxide-core-async-client = ["gitoxide-core/async-client", "futures-lite"]
157157

158-
#! ### Experimental Features
159-
#!
160-
## An experimental use of the v0.2 branch of `imara-diff` in `gix-diff` and `gix-blame`, to allow trying the new diff algorithm.
161-
blame-experimental = ["gitoxide-core/blame-experimental"]
162-
163158
[dependencies]
164159
anyhow = "1.0.98"
165160

gitoxide-core/Cargo.toml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,6 @@ async-client = ["gix/async-network-client-async-std", "gix-transport-configurati
4646
## Data structures implement `serde::Serialize` and `serde::Deserialize`.
4747
serde = ["gix/serde", "dep:serde_json", "dep:serde", "bytesize/serde"]
4848

49-
#! ### Experimental
50-
## An experimental use of the v0.2 branch of `imara-diff` in `gix-diff` and `gix-blame`, to allow trying the new diff algorithm.
51-
blame-experimental = ["gix/blame-experimental"]
52-
5349
[dependencies]
5450
# deselect everything else (like "performance") as this should be controllable by the parent application.
5551
gix = { version = "^0.78.0", path = "../gix", default-features = false, features = ["merge", "blob-diff", "blame", "revision", "mailmap", "excludes", "attributes", "worktree-mutation", "credentials", "interrupt", "status", "dirwalk"] }

gix-blame/Cargo.toml

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,13 @@ authors = ["Christoph Rüßler <christoph.ruessler@mailbox.org>", "Sebastian Thi
1010
edition = "2021"
1111
rust-version = "1.82"
1212

13-
[features]
14-
## An experimental use of the v0.2 branch of `imara-diff` to allow trying it out, and for writing tests against it more easily.
15-
## We will decide later how it should actually be exposed.
16-
blob-experimental = ["gix-diff/blob-experimental"]
17-
1813
[dependencies]
1914
gix-error = { version = "^0.0.0", path = "../gix-error" }
2015
gix-commitgraph = { version = "^0.32.0", path = "../gix-commitgraph" }
2116
gix-revwalk = { version = "^0.26.0", path = "../gix-revwalk" }
2217
gix-trace = { version = "^0.1.17", path = "../gix-trace" }
2318
gix-date = { version = "^0.13.0", path = "../gix-date" }
24-
gix-diff = { version = "^0.58.0", path = "../gix-diff", default-features = false, features = ["blob"] }
19+
gix-diff = { version = "^0.58.0", path = "../gix-diff", default-features = false, features = ["blob", "blob-experimental"] }
2520
gix-object = { version = "^0.55.0", path = "../gix-object" }
2621
gix-hash = { version = "^0.22.0", path = "../gix-hash" }
2722
gix-worktree = { version = "^0.47.0", path = "../gix-worktree", default-features = false, features = ["attributes"] }

gix-blame/src/file/function.rs

Lines changed: 0 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -748,102 +748,6 @@ fn tree_diff_with_rewrites_at_file_path(
748748
}
749749

750750
#[allow(clippy::too_many_arguments)]
751-
#[cfg(not(feature = "blob-experimental"))]
752-
fn blob_changes(
753-
odb: impl gix_object::Find + gix_object::FindHeader,
754-
resource_cache: &mut gix_diff::blob::Platform,
755-
oid: ObjectId,
756-
previous_oid: ObjectId,
757-
file_path: &BStr,
758-
previous_file_path: &BStr,
759-
diff_algorithm: gix_diff::blob::Algorithm,
760-
stats: &mut Statistics,
761-
) -> Result<Vec<Change>, Error> {
762-
use std::ops::Range;
763-
764-
/// Record all [`Change`]s to learn about additions, deletions and unchanged portions of a *Source File*.
765-
struct ChangeRecorder {
766-
last_seen_after_end: u32,
767-
hunks: Vec<Change>,
768-
total_number_of_lines: u32,
769-
}
770-
771-
impl ChangeRecorder {
772-
/// `total_number_of_lines` is used to fill in the last unchanged hunk if needed
773-
/// so that the entire file is represented by [`Change`].
774-
fn new(total_number_of_lines: u32) -> Self {
775-
ChangeRecorder {
776-
last_seen_after_end: 0,
777-
hunks: Vec::new(),
778-
total_number_of_lines,
779-
}
780-
}
781-
}
782-
783-
impl gix_diff::blob::Sink for ChangeRecorder {
784-
type Out = Vec<Change>;
785-
786-
fn process_change(&mut self, before: Range<u32>, after: Range<u32>) {
787-
// This checks for unchanged hunks.
788-
if after.start > self.last_seen_after_end {
789-
self.hunks
790-
.push(Change::Unchanged(self.last_seen_after_end..after.start));
791-
}
792-
793-
match (!before.is_empty(), !after.is_empty()) {
794-
(_, true) => {
795-
self.hunks.push(Change::AddedOrReplaced(
796-
after.start..after.end,
797-
before.end - before.start,
798-
));
799-
}
800-
(true, false) => {
801-
self.hunks.push(Change::Deleted(after.start, before.end - before.start));
802-
}
803-
(false, false) => unreachable!("BUG: imara-diff provided a non-change"),
804-
}
805-
self.last_seen_after_end = after.end;
806-
}
807-
808-
fn finish(mut self) -> Self::Out {
809-
if self.total_number_of_lines > self.last_seen_after_end {
810-
self.hunks
811-
.push(Change::Unchanged(self.last_seen_after_end..self.total_number_of_lines));
812-
}
813-
self.hunks
814-
}
815-
}
816-
817-
resource_cache.set_resource(
818-
previous_oid,
819-
gix_object::tree::EntryKind::Blob,
820-
previous_file_path,
821-
gix_diff::blob::ResourceKind::OldOrSource,
822-
&odb,
823-
)?;
824-
resource_cache.set_resource(
825-
oid,
826-
gix_object::tree::EntryKind::Blob,
827-
file_path,
828-
gix_diff::blob::ResourceKind::NewOrDestination,
829-
&odb,
830-
)?;
831-
832-
let outcome = resource_cache.prepare_diff()?;
833-
let input = gix_diff::blob::intern::InternedInput::new(
834-
tokens_for_diffing(outcome.old.data.as_slice().unwrap_or_default()),
835-
tokens_for_diffing(outcome.new.data.as_slice().unwrap_or_default()),
836-
);
837-
let number_of_lines_in_destination = input.after.len();
838-
let change_recorder = ChangeRecorder::new(number_of_lines_in_destination as u32);
839-
840-
let res = gix_diff::blob::diff(diff_algorithm, &input, change_recorder);
841-
stats.blobs_diffed += 1;
842-
Ok(res)
843-
}
844-
845-
#[allow(clippy::too_many_arguments)]
846-
#[cfg(feature = "blob-experimental")]
847751
fn blob_changes(
848752
odb: impl gix_object::Find + gix_object::FindHeader,
849753
resource_cache: &mut gix_diff::blob::Platform,

gix-blame/tests/blame.rs

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -307,28 +307,16 @@ mktest!(
307307
3
308308
);
309309

310-
/// As of 2024-09-24, the Myers-related test is expected to fail. Both tests use `imara-diff` 0.1
311-
/// under the hood.
310+
/// As of 2025-12-07, both algorithms are expected to pass. They use `imara-diff` 0.2 under the
311+
/// hood. One of them failed with `imara-diff` 0.1.
312312
///
313313
/// Context: https://github.com/Byron/gitoxide/pull/1453#issuecomment-2371013904
314314
#[test]
315-
#[should_panic = "empty-lines-myers"]
316-
#[cfg(not(feature = "blob-experimental"))]
317-
fn diff_disparity_imara_diff_v1() {
318-
diff_disparity_base();
319-
}
320-
321-
/// As of 2025-12-07, both algorithms are expected to pass. They use `imara-diff` 0.2 under the hood.
322-
///
323-
/// Context: https://github.com/Byron/gitoxide/pull/1453#issuecomment-2371013904
324-
#[test]
325-
#[cfg(feature = "blob-experimental")]
326-
fn diff_disparity_imara_diff_v2() {
327-
diff_disparity_base();
328-
}
329-
330-
fn diff_disparity_base() {
331-
for case in ["empty-lines-myers", "empty-lines-histogram"] {
315+
fn diff_algorithm_parity() {
316+
for (case, diff_algorithm) in [
317+
("empty-lines-myers", gix_diff::blob::Algorithm::Myers),
318+
("empty-lines-histogram", gix_diff::blob::Algorithm::Histogram),
319+
] {
332320
let Fixture {
333321
odb,
334322
mut resource_cache,
@@ -344,7 +332,7 @@ fn diff_disparity_base() {
344332
&mut resource_cache,
345333
source_file_name.as_ref(),
346334
gix_blame::Options {
347-
diff_algorithm: gix_diff::blob::Algorithm::Histogram,
335+
diff_algorithm,
348336
ranges: BlameRanges::default(),
349337
since: None,
350338
rewrites: Some(gix_diff::Rewrites::default()),

gix/Cargo.toml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -318,11 +318,6 @@ progress-tree = ["prodash/progress-tree"]
318318
## Print debugging information about usage of object database caches, useful for tuning cache sizes.
319319
cache-efficiency-debug = ["gix-features/cache-efficiency-debug"]
320320

321-
#! #### Experimental Features
322-
## Use the v0.2 branch of `imara-diff` in `gix-diff` and `gix-blame`, to allow trying the new diff algorithm.
323-
blame-experimental = ["blame", "gix-blame/blob-experimental"]
324-
325-
326321
[dependencies]
327322
gix-error = { version = "^0.0.0", path = "../gix-error" }
328323
gix-utils = { version = "^0.3.1", path = "../gix-utils" }

justfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ unit-tests:
180180
cargo nextest run -p gix-transport --features async-client --no-fail-fast
181181
cargo nextest run -p gix-protocol --features blocking-client --no-fail-fast
182182
cargo nextest run -p gix-protocol --features async-client --no-fail-fast
183-
cargo nextest run -p gix-blame --features blob-experimental --no-fail-fast
183+
cargo nextest run -p gix-blame --no-fail-fast
184184
cargo nextest run -p gix --no-default-features --no-fail-fast
185185
cargo nextest run -p gix --no-default-features --features basic,comfort,max-performance-safe --no-fail-fast
186186
cargo nextest run -p gix --no-default-features --features basic,extras,comfort,need-more-recent-msrv --no-fail-fast

0 commit comments

Comments
 (0)