conflicts: show "noeol" state separately for each side of a diff
Some checks are pending
binaries / Build binary artifacts (push) Waiting to run
website / prerelease-docs-build-deploy (ubuntu-24.04) (push) Waiting to run
Scorecards supply-chain security / Scorecards analysis (push) Waiting to run

Now that we can put the "from" and "to" sides on separate lines, we can
use the normal "(no terminating newline)" comment on each side
separately. This should also be more clear, since previously the
"(no terminating newline)" comment could possibly be confused for
"(removes terminating newline)".

Before:

```
<<<<<<< conflict 1 of 1
+++++++ rtsqusxu 2768b0b9 "commit A" (no terminating newline)
grapefruit
%%%%%%% diff from: vpxusssl 38d49363 "merge base"
\\\\\\\        to: ysrnknol 7a20f389 "commit B" (adds terminating newline)
-grape
+grape
>>>>>>> conflict 1 of 1 ends
```

After:

```
<<<<<<< conflict 1 of 1
+++++++ rtsqusxu 2768b0b9 "commit A" (no terminating newline)
grapefruit
%%%%%%% diff from: vpxusssl 38d49363 "merge base" (no terminating newline)
\\\\\\\        to: ysrnknol 7a20f389 "commit B"
-grape
+grape
>>>>>>> conflict 1 of 1 ends
```
This commit is contained in:
Scott Taylor 2025-12-19 22:40:11 -06:00
parent 33ad38bfed
commit 2ce2a445b0
4 changed files with 39 additions and 32 deletions

View file

@ -77,7 +77,7 @@ fn test_file_search_conflicts() {
// Test the setup
insta::assert_snapshot!(work_dir.read_file("file1"), @r"
<<<<<<< conflict 1 of 1
%%%%%%% diff from: rlvkpnrz 958d516d (parents of rebased commit)
%%%%%%% diff from: rlvkpnrz 958d516d (parents of rebased commit) (no terminating newline)
\\\\\\\ to: qpvuntsm 6da222ee (rebase destination) (no terminating newline)
--bar-
+-foo-

View file

@ -208,7 +208,8 @@ would look like this:
<<<<<<< conflict 1 of 1
+++++++ side #1 (no terminating newline)
grapefruit
%%%%%%% diff from base to side #2 (adds terminating newline)
%%%%%%% diff from: base (no terminating newline)
\\\\\\\ to: side #2
-grape
+grape
>>>>>>> conflict 1 of 1 ends

View file

@ -19,6 +19,7 @@ use std::io::Write;
use std::iter::zip;
use std::pin::Pin;
use bstr::BStr;
use bstr::BString;
use bstr::ByteSlice as _;
use futures::Stream;
@ -66,12 +67,6 @@ const CONFLICT_MARKER_LEN_INCREMENT: usize = 4;
/// Comment for missing terminating newline in a term of a conflict.
const NO_EOL_COMMENT: &str = " (no terminating newline)";
/// Comment for missing terminating newline in the "add" side of a diff.
const ADD_NO_EOL_COMMENT: &str = " (removes terminating newline)";
/// Comment for missing terminating newline in the "remove" side of a diff.
const REMOVE_NO_EOL_COMMENT: &str = " (adds terminating newline)";
fn write_diff_hunks(hunks: &[DiffHunk], file: &mut dyn Write) -> io::Result<()> {
for hunk in hunks {
match hunk.kind {
@ -614,30 +609,27 @@ fn materialize_jj_style_conflict(
// Write a diff from a negative term to a positive term
let write_diff =
|base_index: usize, add_index: usize, diff: &[DiffHunk], output: &mut dyn Write| {
let no_eol_remove = diff
let (remove_last_hunk, add_last_hunk) = diff
.last()
.is_some_and(|diff_hunk| has_no_eol(diff_hunk.contents[0]));
let no_eol_add = diff
.last()
.is_some_and(|diff_hunk| has_no_eol(diff_hunk.contents[1]));
let no_eol_comment = match (no_eol_remove, no_eol_add) {
(true, true) => NO_EOL_COMMENT,
(true, _) => REMOVE_NO_EOL_COMMENT,
(_, true) => ADD_NO_EOL_COMMENT,
_ => "",
};
if labels.get_add(add_index).is_none() && labels.get_remove(base_index).is_none() {
.map_or((BStr::new(""), BStr::new("")), |diff_hunk| {
(diff_hunk.contents[0], diff_hunk.contents[1])
});
if labels.get_add(add_index).is_none()
&& labels.get_remove(base_index).is_none()
&& !has_no_eol(remove_last_hunk)
&& !has_no_eol(add_last_hunk)
{
// TODO: remove this format when all conflicts have labels
// Use simple conflict markers when there are no conflict labels.
// Use simple conflict markers when there are no conflict labels and no comment
// for missing terminating newline.
write_conflict_marker(
output,
ConflictMarkerLineChar::Diff,
conflict_marker_len,
&format!(
"diff from {} to {}{}",
"diff from {} to {}",
get_base_label(base_index),
get_side_label(add_index),
no_eol_comment
get_side_label(add_index)
),
)?;
} else {
@ -645,13 +637,21 @@ fn materialize_jj_style_conflict(
output,
ConflictMarkerLineChar::Diff,
conflict_marker_len,
&format!("diff from: {}", get_base_label(base_index)),
&format!(
"diff from: {}{}",
get_base_label(base_index),
maybe_no_eol_comment(remove_last_hunk)
),
)?;
write_conflict_marker(
output,
ConflictMarkerLineChar::Note,
conflict_marker_len,
&format!(" to: {}{}", get_side_label(add_index), no_eol_comment),
&format!(
" to: {}{}",
get_side_label(add_index),
maybe_no_eol_comment(add_last_hunk)
),
)?;
}
write_diff_hunks(diff, output)

View file

@ -645,7 +645,8 @@ fn test_materialize_conflict_no_newlines_at_eof() {
insta::assert_snapshot!(materialized,
@r"
<<<<<<< conflict 1 of 1
%%%%%%% diff from base to side #1 (adds terminating newline)
%%%%%%% diff from: base (no terminating newline)
\\\\\\\ to: side #1
-base
+++++++ side #2 (no terminating newline)
right
@ -2114,7 +2115,8 @@ fn test_update_conflict_from_content_no_eol() {
+++++++ side #1
base
left
%%%%%%% diff from base to side #2 (no terminating newline)
%%%%%%% diff from: base (no terminating newline)
\\\\\\\ to: side #2 (no terminating newline)
-base
+right
>>>>>>> conflict 2 of 2 ends
@ -2248,15 +2250,18 @@ fn test_update_conflict_from_content_no_eol_in_diff_hunk() {
<<<<<<< conflict 1 of 1
+++++++ side #1
side
%%%%%%% diff from base #1 to side #2 (adds terminating newline)
%%%%%%% diff from: base #1 (no terminating newline)
\\\\\\\ to: side #2
add newline
-line
+line
%%%%%%% diff from base #2 to side #3 (removes terminating newline)
%%%%%%% diff from: base #2
\\\\\\\ to: side #3 (no terminating newline)
remove newline
-line
+line
%%%%%%% diff from base #3 to side #4 (no terminating newline)
%%%%%%% diff from: base #3 (no terminating newline)
\\\\\\\ to: side #4 (no terminating newline)
no newline
-line 1
+line 2
@ -2302,7 +2307,8 @@ fn test_update_conflict_from_content_only_no_eol_change() {
@r"
line 1
<<<<<<< conflict 1 of 1
%%%%%%% diff from base to side #1 (removes terminating newline)
%%%%%%% diff from: base
\\\\\\\ to: side #1 (no terminating newline)
+line 2
+++++++ side #2
line 2