fix: tac does not invent a newline on an unterminated last record - #92
Merged
Conversation
Co-authored-by: Dave Lucia <davelucianyc@gmail.com>
davydog187
marked this pull request as ready for review
August 21, 2026 18:22
This was referenced Aug 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #82
tacreversed by splitting on newlines and rejoining, which manufactured a separator the input never had.tacreverses records. A record is text up to and including its separator. The unterminated last record of"1\n2"is"2"— no separator — so reverse is"2"then"1\n", i.e."21\n".Two-file case
Pinned against
/usr/bin/tacon this host (notgtac; they are the same GNU binary here). Matches the string in #82:Ordering was already
tac a; tac bafter #74. The remaining hole was the same record split on each operand.tac | tacinvertibilityTerminated input is invertible:
"1\n2\n"→"2\n1\n"→"1\n2\n".Unterminated input is not invertible on GNU either. After the first reverse the missing separator is gone, so the second
tacsees the single record"21\n"and prints it again. Tests byte-compare that GNU result rather than claiming a round-trip the oracle does not do.rev
Single-file
revalready kept an unterminated last line ("ab\ncd"→"ba\ndc"). The analogous hole was two-file: concatenating first glued the last line ofnonto the first line ofaand reversed them as one record.tail -r
GNU
tailhas no-r. JustBashtaildoes not implement it. No reverse-record path there.Changes
tacsplits into records that carry their own separator and reverses those.revuses the same record split, and reverses each operand on its own (rev a; rev b).tac | tac.Type of Change
Testing
Local gates on this revision:
Checklist
mix formatmix credoand addressed any issues