Skip to content

fix(fs_write): suppress spurious trailing-newline diff lines#3717

Open
sandikodev wants to merge 1 commit intoaws:mainfrom
sandikodev:fix/diff-trailing-newline
Open

fix(fs_write): suppress spurious trailing-newline diff lines#3717
sandikodev wants to merge 1 commit intoaws:mainfrom
sandikodev:fix/diff-trailing-newline

Conversation

@sandikodev
Copy link
Copy Markdown

@sandikodev sandikodev commented Apr 4, 2026

Issue

Closes #923

Problem

When fs_write modifies a file, the diff shown to the user always has a spurious last line:

- 92    : fi
+     92: fi

The content is identical — the only difference is a trailing newline. This is a cosmetic artefact caused by write_to_file always appending \n to file content, while the diff compares the raw strings before normalization.

Fix

Strip at most one trailing newline from both sides before passing to TextDiff::from_lines:

// Before
let diff = similar::TextDiff::from_lines(&old_str.content, &new_str.content);

// After — strip_suffix removes at most one \n, preserving intentional multi-newline differences
let old_content = old_str.content.strip_suffix('\n').unwrap_or(&old_str.content);
let new_content = new_str.content.strip_suffix('\n').unwrap_or(&new_str.content);
let diff = similar::TextDiff::from_lines(old_content, new_content);

strip_suffix (not trim_end_matches) is used deliberately — it removes exactly one trailing newline so that intentional multi-newline differences (e.g. old has 1 trailing newline, new has 3) are still shown.

Testing

# Run the three targeted tests
cargo test -p chat_cli test_print_diff

# Run the full test suite to check for regressions
cargo test -p chat_cli

Three tests cover all scenarios:

  1. test_print_diff_trailing_newline_only_change_is_not_shown — the bug case: trailing-newline-only diff produces zero deletions and zero insertions
  2. test_print_diff_real_change_is_shown — regression guard: a genuine content change still appears (uses insta::assert_snapshot! for the exact formatted output)
  3. test_print_diff_multiple_trailing_newlines_difference_is_shown — edge case: intentional extra newlines are still shown as insertions

Tests use strip_ansi_escapes (already in the workspace) to strip terminal color codes before asserting.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

When the only difference between the old and new file content is a
trailing newline, similar::TextDiff produces a Delete/Insert pair for
the last line that clutters the diff output shown to the user.

Normalize both sides with trim_end_matches('\n') before diffing so
that a trailing-newline-only change is not shown as a modification.

Fixes aws#923
@sandikodev sandikodev force-pushed the fix/diff-trailing-newline branch from 1ff0155 to 1053fb5 Compare April 4, 2026 14:19
sandikodev added a commit to sandikodev/amazon-q-developer-cli that referenced this pull request Apr 4, 2026
The codebase has insta as a workspace dependency but its usage is
minimal and undocumented. Contributors currently have no guidance on:
- when to use assert_eq!/assert! vs insta snapshot testing
- how to run the cargo-insta review workflow
- how to handle ANSI escape codes in terminal output tests

Add TESTING.md at the repo root covering:
- Quick reference table for choosing assertion style
- Standard assertion examples
- Full insta workflow (write -> run -> review -> accept)
- ANSI escape code stripping pattern
- Real example referencing the pattern used in PR aws#3717

Add a one-line pointer in CONTRIBUTING.md.
@sandikodev
Copy link
Copy Markdown
Author

Update (amended commit): The fix was originally using trim_end_matches('\n') which strips all trailing newlines, silently hiding intentional multi-newline differences. Changed to strip_suffix('\n') which removes at most one — enough to eliminate the write_to_file artefact without swallowing real content changes.

Three tests were added covering all scenarios:

  1. Trailing-newline-only difference → not shown (the bug case)
  2. Real content change → still shown (regression guard)
  3. Multiple trailing newlines difference → still shown (edge case guard)

Tests use strip_ansi_escapes (already in the workspace) to strip terminal color codes before asserting, and insta::assert_snapshot! for the formatted diff output.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: diffs show trailing newline differences

1 participant