-
-
Notifications
You must be signed in to change notification settings - Fork 312
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement
text
and binary
merge algorithms, also with baseline te…
…sts for correctness.
- Loading branch information
Showing
9 changed files
with
207 additions
and
20 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#!/usr/bin/env bash | ||
set -eu -o pipefail | ||
|
||
|
||
function baseline() { | ||
local ours=$DIR/${1:?1: our file}.blob; | ||
local base=$DIR/${2:?2: base file}.blob; | ||
local theirs=$DIR/${3:?3: their file}.blob; | ||
local output=$DIR/${4:?4: the name of the output file}.merged; | ||
|
||
shift 4 | ||
git merge-file --stdout "$@" "$ours" "$base" "$theirs" > "$output" || true | ||
|
||
echo "$ours" "$base" "$theirs" "$output" "$@" >> baseline.cases | ||
} | ||
|
||
git init | ||
mkdir simple | ||
(cd simple | ||
echo -e "line1-to-be-changed-by-both\nline2-to-be-changed-in-incoming" > ours.blob | ||
echo -e "line1-changed-by-both\nline2-to-be-changed-in-incoming" > base.blob | ||
echo -e "line1-changed-by-both\nline2-changed" > theirs.blob | ||
) | ||
|
||
DIR=simple | ||
baseline ours base theirs merge | ||
baseline ours base theirs diff3 --diff3 | ||
baseline ours base theirs zdiff3 --zdiff3 | ||
baseline ours base theirs merge-ours --ours | ||
baseline ours base theirs merge-theirs --theirs | ||
baseline ours base theirs merge-union --union |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
use gix_merge::blob::builtin_driver::binary::{Pick, ResolveWith}; | ||
use gix_merge::blob::{builtin_driver, Resolution}; | ||
|
||
#[test] | ||
fn binary() { | ||
assert_eq!( | ||
builtin_driver::binary(None), | ||
(Pick::Ours, Resolution::Conflict), | ||
"by default it picks ours and marks it as conflict" | ||
); | ||
assert_eq!( | ||
builtin_driver::binary(Some(ResolveWith::Ancestor)), | ||
(Pick::Ancestor, Resolution::Complete), | ||
"Otherwise we can pick anything and it will mark it as complete" | ||
); | ||
assert_eq!( | ||
builtin_driver::binary(Some(ResolveWith::Ours)), | ||
(Pick::Ours, Resolution::Complete) | ||
); | ||
assert_eq!( | ||
builtin_driver::binary(Some(ResolveWith::Theirs)), | ||
(Pick::Theirs, Resolution::Complete) | ||
); | ||
} | ||
|
||
mod text { | ||
use bstr::ByteSlice; | ||
use gix_merge::blob::Resolution; | ||
use pretty_assertions::assert_eq; | ||
|
||
#[test] | ||
fn run_baseline() -> crate::Result { | ||
let root = gix_testtools::scripted_fixture_read_only("text-baseline.sh")?; | ||
let cases = std::fs::read_to_string(root.join("baseline.cases"))?; | ||
let mut out = Vec::new(); | ||
for case in baseline::Expectations::new(&root, &cases) { | ||
let actual = | ||
gix_merge::blob::builtin_driver::text(&mut out, &case.ours, &case.base, &case.theirs, case.options); | ||
let expected_resolution = if case.expected.contains_str("<<<<<<<") { | ||
Resolution::Conflict | ||
} else { | ||
Resolution::Complete | ||
}; | ||
assert_eq!(actual, expected_resolution, "{}: resolution mismatch", case.name); | ||
assert_eq!(out.as_bstr(), case.expected, "{}: output mismatch", case.name); | ||
} | ||
Ok(()) | ||
} | ||
|
||
mod baseline { | ||
use bstr::BString; | ||
use gix_merge::blob::builtin_driver::text::{ConflictStyle, ResolveWith}; | ||
use std::path::Path; | ||
|
||
#[derive(Debug)] | ||
pub struct Expectation { | ||
pub ours: BString, | ||
pub theirs: BString, | ||
pub base: BString, | ||
pub name: BString, | ||
pub expected: BString, | ||
pub options: gix_merge::blob::builtin_driver::text::Options, | ||
} | ||
|
||
pub struct Expectations<'a> { | ||
root: &'a Path, | ||
lines: std::str::Lines<'a>, | ||
} | ||
|
||
impl<'a> Expectations<'a> { | ||
pub fn new(root: &'a Path, cases: &'a str) -> Self { | ||
Expectations { | ||
root, | ||
lines: cases.lines(), | ||
} | ||
} | ||
} | ||
|
||
impl Iterator for Expectations<'_> { | ||
type Item = Expectation; | ||
|
||
fn next(&mut self) -> Option<Self::Item> { | ||
let line = self.lines.next()?; | ||
let mut words = line.split(' '); | ||
let (Some(ours), Some(base), Some(theirs), Some(output)) = | ||
(words.next(), words.next(), words.next(), words.next()) | ||
else { | ||
panic!("need at least the input and output") | ||
}; | ||
|
||
let read = |rela_path: &str| read_blob(&self.root, rela_path); | ||
|
||
let mut options = gix_merge::blob::builtin_driver::text::Options::default(); | ||
for arg in words { | ||
match arg { | ||
"--diff3" => options.conflict_style = ConflictStyle::Diff3, | ||
"--zdiff3" => options.conflict_style = ConflictStyle::ZealousDiff3, | ||
"--ours" => options.on_conflict = Some(ResolveWith::Ours), | ||
"--theirs" => options.on_conflict = Some(ResolveWith::Theirs), | ||
"--union" => options.on_conflict = Some(ResolveWith::Union), | ||
_ => panic!("Unknown argument to parse into options: '{arg}'"), | ||
} | ||
} | ||
|
||
Some(Expectation { | ||
ours: read(ours), | ||
theirs: read(theirs), | ||
base: read(base), | ||
expected: read(output), | ||
name: output.into(), | ||
options, | ||
}) | ||
} | ||
} | ||
|
||
fn read_blob(root: &Path, rela_path: &str) -> BString { | ||
std::fs::read(root.join(rela_path)) | ||
.unwrap_or_else(|_| panic!("Failed to read '{rela_path}' in '{}'", root.display())) | ||
.into() | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
mod builtin_driver; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#[cfg(feature = "blob")] | ||
mod blob; | ||
|
||
pub use gix_testtools::Result; |