diff options
author | Zeger-Jan van de Weg <git@zjvandeweg.nl> | 2020-06-03 15:45:14 +0300 |
---|---|---|
committer | Zeger-Jan van de Weg <git@zjvandeweg.nl> | 2020-06-19 15:55:02 +0300 |
commit | e3b1d6e5d2379977de477a2614f960d4f19e6dea (patch) | |
tree | dcb8a1fa5018815d598b4b46b3ab150af8f30619 | |
parent | 779ca4726b48a426243bac59562b599c7d55ee46 (diff) |
lines.Send() takes SenderOpts for grouping options
The lines.Send() allows for a command to be passed in, so the output can
be split based on a delimiter. To control what would be send to the
client this package will be extended to allow for pagination and limits.
The lines.Send() function than would read from the passed in io.Reader,
and write to the sink passed as `lines.Sender`, and the logic that
alters the execution between these would be send as part of the
SenderOpts struct.
A small test was added, mostly to force compilation of the package when
running `go test`, as well as unit test coverage.
-rw-r--r-- | internal/helper/lines/send.go | 29 | ||||
-rw-r--r-- | internal/helper/lines/send_test.go | 25 | ||||
-rw-r--r-- | internal/service/ref/refs.go | 8 | ||||
-rw-r--r-- | internal/service/repository/search_files.go | 2 |
4 files changed, 49 insertions, 15 deletions
diff --git a/internal/helper/lines/send.go b/internal/helper/lines/send.go index 4414344d0..d46672c18 100644 --- a/internal/helper/lines/send.go +++ b/internal/helper/lines/send.go @@ -6,6 +6,10 @@ import ( "io" ) +type SenderOpts struct { + Delimiter []byte +} + // ItemsPerMessage establishes the threshold to flush the buffer when using the // `Send` function. It's a variable instead of a constant to make it possible to // override in tests. @@ -15,9 +19,9 @@ var ItemsPerMessage = 20 type Sender func([][]byte) error type writer struct { - sender Sender - lines [][]byte - delim []byte + sender Sender + lines [][]byte + options SenderOpts } // CopyAndAppend adds a newly allocated copy of `e` to the `s` slice. Useful to @@ -67,14 +71,14 @@ func (w *writer) consume(r io.Reader) error { for { // delim can be multiple bytes, so we read till the end byte of it ... - chunk, err := buf.ReadBytes(w.delim[len(w.delim)-1]) + chunk, err := buf.ReadBytes(w.delimiter()[len(w.delimiter())-1]) if err != nil && err != io.EOF { return err } line = append(line, chunk...) // ... then we check if the last bytes of line are the same as delim - if bytes.HasSuffix(line, w.delim) { + if bytes.HasSuffix(line, w.delimiter()) { break } @@ -84,7 +88,7 @@ func (w *writer) consume(r io.Reader) error { } } - line = bytes.TrimRight(line, string(w.delim)) + line = bytes.TrimRight(line, string(w.delimiter())) if len(line) == 0 { break } @@ -97,12 +101,15 @@ func (w *writer) consume(r io.Reader) error { return w.flush() } -// Send reads output from `r`, splits it at `delim`, then handles the buffered lines using `sender`. -func Send(r io.Reader, sender Sender, delim []byte) error { - if len(delim) == 0 { - delim = []byte{'\n'} +func (w *writer) delimiter() []byte { return w.options.Delimiter } + +// Send reads output from `r`, splits it at `opts.Delimiter``, then handles the +// buffered lines using `sender`. +func Send(r io.Reader, sender Sender, opts SenderOpts) error { + if len(opts.Delimiter) == 0 { + opts.Delimiter = []byte{'\n'} } - writer := &writer{sender: sender, delim: delim} + writer := &writer{sender: sender, options: opts} return writer.consume(r) } diff --git a/internal/helper/lines/send_test.go b/internal/helper/lines/send_test.go new file mode 100644 index 000000000..8e880fdea --- /dev/null +++ b/internal/helper/lines/send_test.go @@ -0,0 +1,25 @@ +package lines + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestLinesSend(t *testing.T) { + reader := bytes.NewBufferString("mepmep foo bar") + + var out [][]byte + sender := func(in [][]byte) error { out = in; return nil } + err := Send(reader, sender, SenderOpts{Delimiter: []byte(" ")}) + require.NoError(t, err) + + expected := [][]byte{ + []byte("mepmep"), + []byte("foo"), + []byte("bar"), + } + + require.Equal(t, expected, out) +} diff --git a/internal/service/ref/refs.go b/internal/service/ref/refs.go index c4a8e831f..381236c5c 100644 --- a/internal/service/ref/refs.go +++ b/internal/service/ref/refs.go @@ -32,8 +32,10 @@ var ( ) type findRefsOpts struct { - cmdArgs []git.Option - delim []byte + cmdArgs []git.Option + delim []byte + pageToken string + limit uint32 } func findRefs(ctx context.Context, writer lines.Sender, repo *gitalypb.Repository, patterns []string, opts *findRefsOpts) error { @@ -54,7 +56,7 @@ func findRefs(ctx context.Context, writer lines.Sender, repo *gitalypb.Repositor return err } - if err := lines.Send(cmd, writer, opts.delim); err != nil { + if err := lines.Send(cmd, writer, lines.SenderOpts{Delimiter: opts.delim}); err != nil { return err } diff --git a/internal/service/repository/search_files.go b/internal/service/repository/search_files.go index fac6ecbe0..26503f006 100644 --- a/internal/service/repository/search_files.go +++ b/internal/service/repository/search_files.go @@ -123,7 +123,7 @@ func (s *server) SearchFilesByName(req *gitalypb.SearchFilesByNameRequest, strea return stream.Send(&gitalypb.SearchFilesByNameResponse{Files: objs}) } - return lines.Send(cmd, lr, []byte{'\n'}) + return lines.Send(cmd, lr, lines.SenderOpts{Delimiter: []byte{'\n'}}) } type searchFilesRequest interface { |