89 Commits

Author SHA1 Message Date
Billy Keyes 09f3004fce Fix flushing when data is larger than the buffer (#2)
copyFrom and copyLinesFrom did not increment the start offset after
reading, so the same lines were copied over and over again.
2020-02-01 10:58:43 -08:00
Billy Keyes 9fc14fddb0 Add tests for file-level application
Also refactor the apply tests to use a common type now that there are
three variants that do almost the same thing for each test.
2020-01-27 22:35:13 -08:00
Billy Keyes 19ec1a24b4 Improve detection of in-progress application
Applying a file now rejects future text fragment applies under the
assumption that all relevant fragments were part of the file.
2020-01-26 15:02:42 -08:00
Billy Keyes 0f3872a5a4 Fix panic with empty input in LineReaderAt 2020-01-26 13:37:09 -08:00
Billy Keyes fa88623500 Improve clarity of LineReaderAt implementation
Try to avoid confusion about whether variables refer to byte or line
counts/positions. It still isn't perfect, but I'm not sure how to
further clarify without being overly verbose.
2020-01-25 22:27:59 -08:00
Billy Keyes 206a57eb7a Add tests for LineReaderAt implementation
This adds minimal new coverage, since the apply tests already exercise
this, but it's complicated enough that dedicated tests will be helpful.
2020-01-25 22:26:21 -08:00
Billy Keyes 18058d1e15 Move apply methods to an Applier type
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.
2020-01-25 17:01:43 -08:00
Billy Keyes 3d1274d16e Remove unused LineReader interface
This is no longer used for text application, so revert the parser back
to using StringReader.
2020-01-25 16:57:23 -08:00
Billy Keyes 0b7af3feaa Implement text application using LineReaderAt
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.
2020-01-25 16:56:33 -08:00
Billy Keyes f3702115a6 Add LineReaderAt interface and implementation
This is a line-oriented parallel to io.ReaderAt, meant for text applies.
While the mapping isn't quite as clean as in the binary case, a text
apply still reads a fixed chunk of lines starting at a specific line
number and modifies them. This also allows a consistent interface for
strict and fuzzy applies.

The implementation wraps an io.ReaderAt and reads data in chunks,
indexing line boundaries as it goes. This is probably not the most
efficient way to implement this interface, but it works and allows file
application to take a consistent interface.
2020-01-25 16:56:32 -08:00
Billy Keyes 131a046908 Use io.ReaderAt to implement binary applies
This better matches the actual contract of the delta patch, which reads
fixed size chunks of the source files at arbitrary positions.
2020-01-25 16:48:07 -08:00
Billy Keyes a34334d6ef Add error tests for BinaryFragment#Apply
These cover some of the possible errors with delta fragments. Many of
the same tests could be implemented slightly easier by testing the
helper functions, but the infrastructure is already set up to test the
full function.

This is made easier by the bin.go CLI, which can parse and encode binary
patch data. Once parsed, fragments were manipulated with truncate and
dd, encoded, and placed in the patch files.
2020-01-16 22:43:56 -08:00
Billy Keyes 194589f001 Add test for large binary delta application
This ensures a default size is used for large copy instructions.
2020-01-16 21:52:41 -08:00
Billy Keyes c50036a466 Abstract common file loading in apply tests 2020-01-16 21:52:41 -08:00
Billy Keyes 79aa2a9a77 Add positive tests for BinaryFragment#Apply
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.
2020-01-16 21:52:40 -08:00
Billy Keyes a1d21957e2 Implement binary fragment application
Currently untested, but based on code I validated against some generated
patches. Tests comming in a future commit.
2020-01-14 22:49:14 -08:00
Billy Keyes eb5f3de78c Improve conflict error detection
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.
2020-01-12 22:09:08 -08:00
Billy Keyes 1b341e0693 Add error tests for TextFragment#ApplyStrict
These cover the errors that can happen with a single fragment and no
additional manipulation by the caller of ApplyStrict.
2020-01-12 22:09:08 -08:00
Billy Keyes 6a055aa600 Add exact line test for TextFragment#ApplyStrict
This ensures the line number is used and application isn't based only on
matching context lines.
2020-01-12 22:08:15 -08:00
Billy Keyes 774281f01b Standardize on int64 for line numbers
This matches the type used for positions in text fragments.
2020-01-09 22:11:25 -08:00
Billy Keyes 7bd4e0bb0e Fix EOF handling in TextFragment#ApplyStrict
io.EOF was not properly accounted for when dealing with patches that are
missing trailing newline characters.
2020-01-09 22:05:24 -08:00
Billy Keyes 02f7ff4f79 Add positive tests for TextFragment#ApplyStrict
These cover all of the cases (I think) where application should succeed.
2020-01-08 23:04:44 -08:00
Billy Keyes ae704236bb Return ApplyError when ApplyString fails
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.
2020-01-07 22:59:25 -08:00
Billy Keyes 93d46e805c Add initial pass at ApplyStrict functions
Text fragment application is implemented but untested and with several
TODOs, binary fragment application is unimplemented and will panic.
2020-01-05 20:37:59 -08:00
Billy Keyes 25bee8cf2f Add validation function for text fragment
Applying a fragment requires the content to match the stored counts, so
there must be a way to check this. Parsed fragments should always be
valid, but manually created or modified fragments may be invalid.
2020-01-05 20:36:01 -08:00
Billy Keyes d471b7e1a3 Add internal function to unwrap LineReaders
When applying, we need to copy all data after the last fragment line.
This function provides a way to get back the possibly-buffered io.Reader
that backs the LineReader.
2020-01-04 23:32:16 -08:00
Billy Keyes 3ec1c74c34 Improve docs for StringReader and LineReader
Document the method as part of the type so it is processed by godoc.
2020-01-04 20:03:00 -08:00
Billy Keyes a1f934e852 Add LineReader and StringReader interfaces
LineReader is a wrapper around StringReader that counts line numbers.
This is not currently used by the parser, but will be used by the apply
functions.
2020-01-04 12:02:37 -08:00
Billy Keyes f65047b165 Avoid buffering when reader supports ReadString 2019-04-27 16:15:50 -07:00
Billy Keyes 1c950ee854 Split source files by patch type (text/binary)
The tests were already split up in this way, so it makes sense to have
the parsing functions split as well.
2019-04-17 21:36:46 -07:00
Billy Keyes d42fb0e93f Fix spelling mistakes, add Go Report Card badge 2019-04-14 19:53:39 -07:00
Billy Keyes ef3359a969 Add a package-level documentation comment 2019-04-14 19:44:06 -07:00
Billy Keyes 31777bd4b5 Add parser advancement tests for binary parsing 2019-04-14 19:27:34 -07:00
Billy Keyes 16539ad031 Add tests for parsing full binary fragments 2019-04-14 19:18:08 -07:00
Billy Keyes d104a6c22a Add error case tests for binary chunk parsing 2019-04-14 17:10:35 -07:00
Billy Keyes 62569e0d07 Add dedicated tests for base85 decoding
These are fairly basic as the decoder is also exercised by the fragment
parsing tests, but they cover some errror cases that may not be covered
otherwise.
2019-04-14 15:50:07 -07:00
Billy Keyes 8ce8cba533 Fix binary chunk decoding and inflating
Git uses a unique Base85 encoding with different characters than the
ascii85 encoding implemented by Go, so add a custom decoding function.
Once decoded, use zlib instead of the raw DEFLATE algorithm to
decompress the data.

These issues were caught by some basic parsing tests which are added
here as well.
2019-04-13 22:32:25 -07:00
Billy Keyes 22fb5076be Add test for binary fragment header parsing 2019-04-13 15:54:52 -07:00
Billy Keyes ddafbc8ba3 Split up binary parsing to match text parsing
Parse the fragment header separately from the fragment chunk, which
makes each function a bit more understandable.
2019-04-10 23:03:19 -07:00
Billy Keyes 0cfd720d4f Add test for binary marker parsing 2019-04-10 23:02:48 -07:00
Billy Keyes 5a521ed05f Implement binary fragment parsing
Parse forward and optionally reverse fragments, decoding and inflating
the ascii85 encoded data in a binary patch. This is completely untested
at the moment and probably has obvious and stupid bugs.
2019-04-09 22:54:41 -07:00
Billy Keyes 013e581989 Fix error return in ParseBinaryMarker 2019-04-08 23:09:19 -07:00
Billy Keyes b101b0d812 Add binary patch types and binary marker parsing
The binary marker is the text that appears where a text fragment
normally would and indicates that the file is binary. It's not quite a
header, because content is optional in a binary patch. If the patch does
include binary fragments, they have their own format, with a header.
2019-04-07 21:24:17 -07:00
Billy Keyes a0b33e37b4 Rename types in preparation for binary parsing
Fragment is now TextFragment to distinguish from a future
BinaryFragment. Also rename FragmentLine to Line, since the
text-orientation is implied by the name.
2019-04-07 20:33:21 -07:00
Billy Keyes 3398cfa890 Add additional parser advancement tests 2019-04-07 20:31:18 -07:00
Billy Keyes 69e4444419 Return preamble content when parsing files
This allows callers to provide patches with commit or email headers and
then retrieve that leading content for additional parsing without
having to identify where the first file in the patch starts.
2019-04-07 19:57:11 -07:00
Billy Keyes 07e5314a7c Remove second commit header from test file
While it's cool that this works, in a multi-file patch each file
immediately follow the final fragment of the previous file.
2019-04-07 17:49:15 -07:00
Billy Keyes 09c686917c Add test for multiple files in one patch
For simplicity, use the same fragments in both of these files and in the
single file test.
2019-04-06 19:13:42 -07:00
Billy Keyes 47d923e573 Add simple full file parsing test
For now, this uses JSON to print objects on error, which is hard to
debug. It should probably use something like google/go-cmp instead,
because these objects are now too large for direct comparison.
2019-04-03 23:01:44 -07:00
Billy Keyes a1149ed1c9 Add tests for finding the next file header
Primarily check that leading non-header content is ignored and that
special errors (like detached fragment headers) are raised.
2019-04-02 22:55:40 -07:00