mirror of
https://github.com/martinvonz/jj.git
synced 2025-02-01 00:50:57 +00:00
conflicts: extract function for materializing hunk
This will make it easier to add a second code path for Git-style conflicts in a later commit.
This commit is contained in:
parent
d2b06b9cf9
commit
54c453ba8d
1 changed files with 70 additions and 65 deletions
|
@ -278,6 +278,30 @@ fn materialize_conflict_hunks(
|
||||||
hunks: &[Merge<BString>],
|
hunks: &[Merge<BString>],
|
||||||
conflict_marker_style: ConflictMarkerStyle,
|
conflict_marker_style: ConflictMarkerStyle,
|
||||||
output: &mut dyn Write,
|
output: &mut dyn Write,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
let num_conflicts = hunks
|
||||||
|
.iter()
|
||||||
|
.filter(|hunk| hunk.as_resolved().is_none())
|
||||||
|
.count();
|
||||||
|
let mut conflict_index = 0;
|
||||||
|
for hunk in hunks {
|
||||||
|
if let Some(content) = hunk.as_resolved() {
|
||||||
|
output.write_all(content)?;
|
||||||
|
} else {
|
||||||
|
conflict_index += 1;
|
||||||
|
let conflict_info = format!("Conflict {conflict_index} of {num_conflicts}");
|
||||||
|
|
||||||
|
materialize_jj_style_conflict(hunk, &conflict_info, conflict_marker_style, output)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn materialize_jj_style_conflict(
|
||||||
|
hunk: &Merge<BString>,
|
||||||
|
conflict_info: &str,
|
||||||
|
conflict_marker_style: ConflictMarkerStyle,
|
||||||
|
output: &mut dyn Write,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
// Write a positive snapshot (side) of a conflict
|
// Write a positive snapshot (side) of a conflict
|
||||||
fn write_side(add_index: usize, data: &[u8], output: &mut dyn Write) -> io::Result<()> {
|
fn write_side(add_index: usize, data: &[u8], output: &mut dyn Write) -> io::Result<()> {
|
||||||
|
@ -310,76 +334,57 @@ fn materialize_conflict_hunks(
|
||||||
write_diff_hunks(diff, output)
|
write_diff_hunks(diff, output)
|
||||||
}
|
}
|
||||||
|
|
||||||
let num_conflicts = hunks
|
writeln!(output, "{CONFLICT_START_LINE} {conflict_info}")?;
|
||||||
.iter()
|
let mut add_index = 0;
|
||||||
.filter(|hunk| hunk.as_resolved().is_none())
|
for (base_index, left) in hunk.removes().enumerate() {
|
||||||
.count();
|
// The vast majority of conflicts one actually tries to resolve manually have 1
|
||||||
let mut conflict_index = 0;
|
// base.
|
||||||
for hunk in hunks {
|
let base_str = if hunk.removes().len() == 1 {
|
||||||
if let Some(content) = hunk.as_resolved() {
|
"base".to_string()
|
||||||
output.write_all(content)?;
|
|
||||||
} else {
|
} else {
|
||||||
conflict_index += 1;
|
format!("base #{}", base_index + 1)
|
||||||
writeln!(
|
};
|
||||||
output,
|
|
||||||
"{CONFLICT_START_LINE} Conflict {conflict_index} of {num_conflicts}"
|
|
||||||
)?;
|
|
||||||
let mut add_index = 0;
|
|
||||||
for (base_index, left) in hunk.removes().enumerate() {
|
|
||||||
// The vast majority of conflicts one actually tries to
|
|
||||||
// resolve manually have 1 base.
|
|
||||||
let base_str = if hunk.removes().len() == 1 {
|
|
||||||
"base".to_string()
|
|
||||||
} else {
|
|
||||||
format!("base #{}", base_index + 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(right1) = hunk.get_add(add_index) else {
|
let Some(right1) = hunk.get_add(add_index) else {
|
||||||
// If we have no more positive terms, emit the remaining negative
|
// If we have no more positive terms, emit the remaining negative terms as
|
||||||
// terms as snapshots.
|
// snapshots.
|
||||||
write_base(&base_str, left, output)?;
|
write_base(&base_str, left, output)?;
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
// For any style other than "diff", always emit sides and bases separately
|
// For any style other than "diff", always emit sides and bases separately
|
||||||
if conflict_marker_style != ConflictMarkerStyle::Diff {
|
if conflict_marker_style != ConflictMarkerStyle::Diff {
|
||||||
write_side(add_index, right1, output)?;
|
write_side(add_index, right1, output)?;
|
||||||
write_base(&base_str, left, output)?;
|
write_base(&base_str, left, output)?;
|
||||||
add_index += 1;
|
add_index += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
let diff1 = Diff::by_line([&left, &right1]).hunks().collect_vec();
|
|
||||||
// Check if the diff against the next positive term is better. Since
|
|
||||||
// we want to preserve the order of the terms, we don't match against
|
|
||||||
// any later positive terms.
|
|
||||||
if let Some(right2) = hunk.get_add(add_index + 1) {
|
|
||||||
let diff2 = Diff::by_line([&left, &right2]).hunks().collect_vec();
|
|
||||||
if diff_size(&diff2) < diff_size(&diff1) {
|
|
||||||
// If the next positive term is a better match, emit
|
|
||||||
// the current positive term as a snapshot and the next
|
|
||||||
// positive term as a diff.
|
|
||||||
write_side(add_index, right1, output)?;
|
|
||||||
write_diff(&base_str, add_index + 1, &diff2, output)?;
|
|
||||||
add_index += 2;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
write_diff(&base_str, add_index, &diff1, output)?;
|
|
||||||
add_index += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit the remaining positive terms as snapshots.
|
|
||||||
for (add_index, slice) in hunk.adds().enumerate().skip(add_index) {
|
|
||||||
write_side(add_index, slice, output)?;
|
|
||||||
}
|
|
||||||
writeln!(
|
|
||||||
output,
|
|
||||||
"{CONFLICT_END_LINE} Conflict {conflict_index} of {num_conflicts} ends"
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let diff1 = Diff::by_line([&left, &right1]).hunks().collect_vec();
|
||||||
|
// Check if the diff against the next positive term is better. Since we want to
|
||||||
|
// preserve the order of the terms, we don't match against any later positive
|
||||||
|
// terms.
|
||||||
|
if let Some(right2) = hunk.get_add(add_index + 1) {
|
||||||
|
let diff2 = Diff::by_line([&left, &right2]).hunks().collect_vec();
|
||||||
|
if diff_size(&diff2) < diff_size(&diff1) {
|
||||||
|
// If the next positive term is a better match, emit the current positive term
|
||||||
|
// as a snapshot and the next positive term as a diff.
|
||||||
|
write_side(add_index, right1, output)?;
|
||||||
|
write_diff(&base_str, add_index + 1, &diff2, output)?;
|
||||||
|
add_index += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write_diff(&base_str, add_index, &diff1, output)?;
|
||||||
|
add_index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emit the remaining positive terms as snapshots.
|
||||||
|
for (add_index, slice) in hunk.adds().enumerate().skip(add_index) {
|
||||||
|
write_side(add_index, slice, output)?;
|
||||||
|
}
|
||||||
|
writeln!(output, "{CONFLICT_END_LINE} {conflict_info} ends")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue