Skip to content

fix(tac): preserve unterminated last line on reversal#1760

Merged
chaliy merged 1 commit into
mainfrom
fix/tac-no-trailing-newline
May 25, 2026
Merged

fix(tac): preserve unterminated last line on reversal#1760
chaliy merged 1 commit into
mainfrom
fix/tac-no-trailing-newline

Conversation

@chaliy
Copy link
Copy Markdown
Contributor

@chaliy chaliy commented May 25, 2026

What

Fix tac to match GNU tac behavior when input lacks a trailing newline.

Why

Real GNU tac splits input by newline separator and reverses records while keeping their original separators. An unterminated last line stays unterminated when reversed, so it concatenates directly with the previous reversed record (no inserted newline).

bashkit's reverse_lines always re-inserted a separator and appended a final newline, producing extra newlines for inputs lacking a trailing separator. Example:

  • Input: one\ntwo\nthree
  • Real tac: threetwo\none\n
  • Bashkit (before): three\ntwo\none\n

This was caught by coreutils_differential_tests::tac_no_trailing_newline, which the weekly Coreutils Args Drift workflow now flags as failing.

How

  • Build output by iterating lines in reverse and only emitting a newline after each line that originally had a trailing separator. The last input line gets a separator iff the input was newline-terminated.

Risk

  • Low. Behavior matches real tac. Existing tac differential cases (tac_file_input, tac_pipe_input) still pass — they use newline-terminated input.

Testing

  • BASHKIT_RUN_COREUTILS_DIFF=1 cargo test -p bashkit --test coreutils_differential_tests tac — all 6 tac cases pass, including the previously failing tac_no_trailing_newline.
  • cargo clippy -p bashkit --all-targets -- -D warnings clean.
  • cargo fmt --check.

Checklist

  • Tests added or updated
  • Backward compatibility considered

Generated by Claude Code

Real GNU tac splits input by newline separator and reverses records
while keeping their original separators. An unterminated last line
stays unterminated when reversed, so it concatenates directly with the
previous reversed record. Bashkit's reverse_lines always re-inserted
a separator and appended a final newline, producing extra newlines for
inputs lacking a trailing separator.

Reproduced by coreutils_differential_tests::tac_no_trailing_newline,
which the weekly Coreutils Args Drift workflow now flags.
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 25, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
bashkit b0aca29 Commit Preview URL

Branch Preview URL
May 25 2026, 03:08 PM

@chaliy chaliy merged commit 0f23e6d into main May 25, 2026
34 checks passed
@chaliy chaliy deleted the fix/tac-no-trailing-newline branch May 25, 2026 15:22
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.

1 participant