mirror of
https://github.com/martinvonz/jj.git
synced 2025-02-12 07:24:11 +00:00
merge: make trivial_merge()
return a reference
I don't know why I made it return an owned value. It seems like an unnecessary restriction that the value implements `Clone`, so let's return a reference instead.
This commit is contained in:
parent
3ca42908ee
commit
a5883eba15
3 changed files with 35 additions and 41 deletions
|
@ -227,7 +227,7 @@ pub fn merge(removes: &[&[u8]], adds: &[&[u8]]) -> MergeResult {
|
||||||
}
|
}
|
||||||
DiffHunk::Different(parts) => {
|
DiffHunk::Different(parts) => {
|
||||||
if let Some(resolved) = trivial_merge(&parts[..num_diffs], &parts[num_diffs..]) {
|
if let Some(resolved) = trivial_merge(&parts[..num_diffs], &parts[num_diffs..]) {
|
||||||
resolved_hunk.extend(resolved);
|
resolved_hunk.extend(*resolved);
|
||||||
} else {
|
} else {
|
||||||
if !resolved_hunk.is_empty() {
|
if !resolved_hunk.is_empty() {
|
||||||
merge_hunks.push(MergeHunk::Resolved(resolved_hunk));
|
merge_hunks.push(MergeHunk::Resolved(resolved_hunk));
|
||||||
|
|
|
@ -19,9 +19,9 @@ use itertools::Itertools;
|
||||||
|
|
||||||
/// Attempt to resolve trivial conflicts between the inputs. There must be
|
/// Attempt to resolve trivial conflicts between the inputs. There must be
|
||||||
/// exactly one more adds than removes.
|
/// exactly one more adds than removes.
|
||||||
pub fn trivial_merge<T>(removes: &[T], adds: &[T]) -> Option<T>
|
pub fn trivial_merge<'a, T>(removes: &'a [T], adds: &'a [T]) -> Option<&'a T>
|
||||||
where
|
where
|
||||||
T: Eq + Hash + Clone,
|
T: Eq + Hash,
|
||||||
{
|
{
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
adds.len(),
|
adds.len(),
|
||||||
|
@ -32,11 +32,11 @@ where
|
||||||
// Optimize the common case of a 3-way merge
|
// Optimize the common case of a 3-way merge
|
||||||
if adds.len() == 2 {
|
if adds.len() == 2 {
|
||||||
return if adds[0] == adds[1] {
|
return if adds[0] == adds[1] {
|
||||||
Some(adds[0].clone())
|
Some(&adds[0])
|
||||||
} else if adds[0] == removes[0] {
|
} else if adds[0] == removes[0] {
|
||||||
Some(adds[1].clone())
|
Some(&adds[1])
|
||||||
} else if adds[1] == removes[0] {
|
} else if adds[1] == removes[0] {
|
||||||
Some(adds[0].clone())
|
Some(&adds[0])
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -50,24 +50,18 @@ where
|
||||||
// and maybe add a more lenient version that is used when the user explicitly
|
// and maybe add a more lenient version that is used when the user explicitly
|
||||||
// asks for conflict resolution.
|
// asks for conflict resolution.
|
||||||
if removes.iter().all_equal() && adds.iter().all_equal() {
|
if removes.iter().all_equal() && adds.iter().all_equal() {
|
||||||
return Some(adds[0].clone());
|
return Some(&adds[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Number of occurrences of each value, with positive indexes counted as +1 and
|
// Number of occurrences of each value, with positive indexes counted as +1 and
|
||||||
// negative as -1, thereby letting positive and negative terms with the same
|
// negative as -1, thereby letting positive and negative terms with the same
|
||||||
// value (i.e. key in the map) cancel each other.
|
// value (i.e. key in the map) cancel each other.
|
||||||
let mut counts: HashMap<T, i32> = HashMap::new();
|
let mut counts: HashMap<&T, i32> = HashMap::new();
|
||||||
for value in adds.iter() {
|
for value in adds.iter() {
|
||||||
counts
|
counts.entry(value).and_modify(|e| *e += 1).or_insert(1);
|
||||||
.entry(value.clone())
|
|
||||||
.and_modify(|e| *e += 1)
|
|
||||||
.or_insert(1);
|
|
||||||
}
|
}
|
||||||
for value in removes.iter() {
|
for value in removes.iter() {
|
||||||
counts
|
counts.entry(value).and_modify(|e| *e -= 1).or_insert(-1);
|
||||||
.entry(value.clone())
|
|
||||||
.and_modify(|e| *e -= 1)
|
|
||||||
.or_insert(-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is a single value (i.e. key in the map) with a count of 1 left, then
|
// If there is a single value (i.e. key in the map) with a count of 1 left, then
|
||||||
|
@ -78,7 +72,7 @@ where
|
||||||
.filter(|&(_, count)| *count != 0)
|
.filter(|&(_, count)| *count != 0)
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
match x[..] {
|
match x[..] {
|
||||||
[(value, 1)] => Some(value.clone()),
|
[(value, 1)] => Some(value),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,52 +83,52 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_trivial_merge() {
|
fn test_trivial_merge() {
|
||||||
assert_eq!(trivial_merge(&[], &[0]), Some(0));
|
assert_eq!(trivial_merge(&[], &[0]), Some(&0));
|
||||||
assert_eq!(trivial_merge(&[0], &[0, 0]), Some(0));
|
assert_eq!(trivial_merge(&[0], &[0, 0]), Some(&0));
|
||||||
assert_eq!(trivial_merge(&[0], &[0, 1]), Some(1));
|
assert_eq!(trivial_merge(&[0], &[0, 1]), Some(&1));
|
||||||
assert_eq!(trivial_merge(&[0], &[1, 0]), Some(1));
|
assert_eq!(trivial_merge(&[0], &[1, 0]), Some(&1));
|
||||||
assert_eq!(trivial_merge(&[0], &[1, 1]), Some(1));
|
assert_eq!(trivial_merge(&[0], &[1, 1]), Some(&1));
|
||||||
assert_eq!(trivial_merge(&[0], &[1, 2]), None);
|
assert_eq!(trivial_merge(&[0], &[1, 2]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 0], &[0, 0, 0]), Some(0));
|
assert_eq!(trivial_merge(&[0, 0], &[0, 0, 0]), Some(&0));
|
||||||
assert_eq!(trivial_merge(&[0, 0], &[0, 0, 1]), Some(1));
|
assert_eq!(trivial_merge(&[0, 0], &[0, 0, 1]), Some(&1));
|
||||||
assert_eq!(trivial_merge(&[0, 0], &[0, 1, 0]), Some(1));
|
assert_eq!(trivial_merge(&[0, 0], &[0, 1, 0]), Some(&1));
|
||||||
assert_eq!(trivial_merge(&[0, 0], &[0, 1, 1]), None);
|
assert_eq!(trivial_merge(&[0, 0], &[0, 1, 1]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 0], &[0, 1, 2]), None);
|
assert_eq!(trivial_merge(&[0, 0], &[0, 1, 2]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 0], &[1, 0, 0]), Some(1));
|
assert_eq!(trivial_merge(&[0, 0], &[1, 0, 0]), Some(&1));
|
||||||
assert_eq!(trivial_merge(&[0, 0], &[1, 0, 1]), None);
|
assert_eq!(trivial_merge(&[0, 0], &[1, 0, 1]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 0], &[1, 0, 2]), None);
|
assert_eq!(trivial_merge(&[0, 0], &[1, 0, 2]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 0], &[1, 1, 0]), None);
|
assert_eq!(trivial_merge(&[0, 0], &[1, 1, 0]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 0], &[1, 1, 1]), Some(1));
|
assert_eq!(trivial_merge(&[0, 0], &[1, 1, 1]), Some(&1));
|
||||||
assert_eq!(trivial_merge(&[0, 0], &[1, 1, 2]), None);
|
assert_eq!(trivial_merge(&[0, 0], &[1, 1, 2]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 0], &[1, 2, 0]), None);
|
assert_eq!(trivial_merge(&[0, 0], &[1, 2, 0]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 0], &[1, 2, 1]), None);
|
assert_eq!(trivial_merge(&[0, 0], &[1, 2, 1]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 0], &[1, 2, 2]), None);
|
assert_eq!(trivial_merge(&[0, 0], &[1, 2, 2]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 0], &[1, 2, 3]), None);
|
assert_eq!(trivial_merge(&[0, 0], &[1, 2, 3]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[0, 0, 0]), None);
|
assert_eq!(trivial_merge(&[0, 1], &[0, 0, 0]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[0, 0, 1]), Some(0));
|
assert_eq!(trivial_merge(&[0, 1], &[0, 0, 1]), Some(&0));
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[0, 0, 2]), None);
|
assert_eq!(trivial_merge(&[0, 1], &[0, 0, 2]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[0, 1, 0]), Some(0));
|
assert_eq!(trivial_merge(&[0, 1], &[0, 1, 0]), Some(&0));
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[0, 1, 1]), Some(1));
|
assert_eq!(trivial_merge(&[0, 1], &[0, 1, 1]), Some(&1));
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[0, 1, 2]), Some(2));
|
assert_eq!(trivial_merge(&[0, 1], &[0, 1, 2]), Some(&2));
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[0, 2, 0]), None);
|
assert_eq!(trivial_merge(&[0, 1], &[0, 2, 0]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[0, 2, 1]), Some(2));
|
assert_eq!(trivial_merge(&[0, 1], &[0, 2, 1]), Some(&2));
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[0, 2, 2]), None);
|
assert_eq!(trivial_merge(&[0, 1], &[0, 2, 2]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[0, 2, 3]), None);
|
assert_eq!(trivial_merge(&[0, 1], &[0, 2, 3]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[1, 0, 0]), Some(0));
|
assert_eq!(trivial_merge(&[0, 1], &[1, 0, 0]), Some(&0));
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[1, 0, 1]), Some(1));
|
assert_eq!(trivial_merge(&[0, 1], &[1, 0, 1]), Some(&1));
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[1, 0, 2]), Some(2));
|
assert_eq!(trivial_merge(&[0, 1], &[1, 0, 2]), Some(&2));
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[1, 1, 0]), Some(1));
|
assert_eq!(trivial_merge(&[0, 1], &[1, 1, 0]), Some(&1));
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[1, 1, 1]), None);
|
assert_eq!(trivial_merge(&[0, 1], &[1, 1, 1]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[1, 1, 2]), None);
|
assert_eq!(trivial_merge(&[0, 1], &[1, 1, 2]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[1, 2, 0]), Some(2));
|
assert_eq!(trivial_merge(&[0, 1], &[1, 2, 0]), Some(&2));
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[1, 2, 1]), None);
|
assert_eq!(trivial_merge(&[0, 1], &[1, 2, 1]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[1, 2, 2]), None);
|
assert_eq!(trivial_merge(&[0, 1], &[1, 2, 2]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[1, 2, 3]), None);
|
assert_eq!(trivial_merge(&[0, 1], &[1, 2, 3]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[2, 0, 0]), None);
|
assert_eq!(trivial_merge(&[0, 1], &[2, 0, 0]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[2, 0, 1]), Some(2));
|
assert_eq!(trivial_merge(&[0, 1], &[2, 0, 1]), Some(&2));
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[2, 0, 2]), None);
|
assert_eq!(trivial_merge(&[0, 1], &[2, 0, 2]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[2, 0, 3]), None);
|
assert_eq!(trivial_merge(&[0, 1], &[2, 0, 3]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[2, 1, 0]), Some(2));
|
assert_eq!(trivial_merge(&[0, 1], &[2, 1, 0]), Some(&2));
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[2, 1, 1]), None);
|
assert_eq!(trivial_merge(&[0, 1], &[2, 1, 1]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[2, 1, 2]), None);
|
assert_eq!(trivial_merge(&[0, 1], &[2, 1, 2]), None);
|
||||||
assert_eq!(trivial_merge(&[0, 1], &[2, 1, 3]), None);
|
assert_eq!(trivial_merge(&[0, 1], &[2, 1, 3]), None);
|
||||||
|
|
|
@ -545,7 +545,7 @@ pub fn merge_trees(
|
||||||
assert_eq!(side2_tree.dir(), dir);
|
assert_eq!(side2_tree.dir(), dir);
|
||||||
|
|
||||||
if let Some(resolved) = trivial_merge(&[&base_tree.id], &[&side1_tree.id, &side2_tree.id]) {
|
if let Some(resolved) = trivial_merge(&[&base_tree.id], &[&side1_tree.id, &side2_tree.id]) {
|
||||||
return Ok(resolved.clone());
|
return Ok((*resolved).clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start with a tree identical to side 1 and modify based on changes from base
|
// Start with a tree identical to side 1 and modify based on changes from base
|
||||||
|
@ -738,7 +738,7 @@ fn try_resolve_file_conflict(
|
||||||
&added_contents.iter().map(Vec::as_slice).collect_vec(),
|
&added_contents.iter().map(Vec::as_slice).collect_vec(),
|
||||||
);
|
);
|
||||||
match merge_result {
|
match merge_result {
|
||||||
MergeResult::Resolved(merged_content) => Ok(Some((merged_content, executable))),
|
MergeResult::Resolved(merged_content) => Ok(Some((merged_content, *executable))),
|
||||||
MergeResult::Conflict(_) => Ok(None),
|
MergeResult::Conflict(_) => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue