This only updates to Go 1.21 baseline, which is what the module still
specifies as the minimum version. I'll need to run this again when
moving to Go 1.25 or 1.26 as minimum.
The previous version of the golangci-lint action would install its own
version of Go, which eventually conflicted with the old pinned version
of the linter I was using. Upgrade the action to avoid this, but also
update Go and the linter while I'm here.
Remove the Applier type and replace it with TextApplier and
BinaryApplier, both of which operate on fragments instead of on full
files. Move the logic that previously existed in Applier.ApplyFile to
the top-level Apply function.
Also restructure arguments and methods to make it clear that appliers
are one-time-use objects. The destination is now set when creating an
applier and the Reset() method was replaced by Close().
If a file was an exact multiple of 1024 bytes (the size of an internal
buffer) and was missing a final newline, the LineReaderAt implementation
would drop the last line, leading to an unexpected EOF error on apply.
In addition to fixing the bug, slightly change the behavior of
ReadLineAt to reflect how it is actually used:
1. Clarify that the return value n includes all lines instead of only
lines with a final newline. This was already true except in the
case of the bug fixed by this commit.
2. Only return io.EOF if fewer lines are read than requested. The
previous implementation also returned io.EOF if the last line was
missing a final newline, but this was confusing and didn't really
serve a purpose.
This is technically a breaking change for external implementations but
an implementation that exactly followed the "spec" was already broken in
certain edge cases.
When applying a text fragment that deletes all content in the file, make
sure there is no content left in the source after using all the lines in
the fragment. If there is is extra content, it's a conflict: something
added more lines to the file after generating the patch.
This removes the distinction between "strict" and "fuzzy" application
by allowing future methods on Applier that control settings. It also
avoids state tracking in the text fragment apply signature by moving it
into the Applier type.
While in practice, an Applier will be used once and discarded, the
capability is provided to reset it for multiple uses.
This is functionally equivalent to the previous version (except for one
error case), but uses the new interface. I think the code is simpler
overall because it removes the line tracking.
Covers basic literal and delta application. Input files were created by
using dd and the 'conv=notrunc' option to modify sections of files
created from /dev/urandom. All file start with two null bytes to
convince Git they are binary.
Conflict errors are now represented by an exported type that is
compatible with errors.Is instead of using the method defined on
ApplyError. This makes the tests slightly cleaner and should be more
idiomatic for clients.
This wraps the underlying error with optional position information and
provides a way to test if the error was due to a conflict. At the
moment, details about the conflict are not exposed outside of the
message string.