diff options
Diffstat (limited to 'plumbing/protocol/packp/srvresp.go')
-rw-r--r-- | plumbing/protocol/packp/srvresp.go | 49 |
1 files changed, 46 insertions, 3 deletions
diff --git a/plumbing/protocol/packp/srvresp.go b/plumbing/protocol/packp/srvresp.go index 0c89e47..a5bec9c 100644 --- a/plumbing/protocol/packp/srvresp.go +++ b/plumbing/protocol/packp/srvresp.go @@ -1,6 +1,7 @@ package packp import ( + "bufio" "bytes" "errors" "fmt" @@ -18,8 +19,8 @@ type ServerResponse struct { } // Decode decodes the response into the struct, isMultiACK should be true, if -// the request was done with multi_ack or multi_ack_detailed capabilities -func (r *ServerResponse) Decode(reader io.Reader, isMultiACK bool) error { +// the request was done with multi_ack or multi_ack_detailed capabilities. +func (r *ServerResponse) Decode(reader *bufio.Reader, isMultiACK bool) error { // TODO: implement support for multi_ack or multi_ack_detailed responses if isMultiACK { return errors.New("multi_ack and multi_ack_detailed are not supported") @@ -34,7 +35,15 @@ func (r *ServerResponse) Decode(reader io.Reader, isMultiACK bool) error { return err } - if !isMultiACK { + // we need to detect when the end of a response header and the begining + // of a packfile header happend, some requests to the git daemon + // produces a duplicate ACK header even when multi_ack is not supported. + isEnd, err := r.endReached(reader) + if err != nil { + return err + } + + if isEnd { break } } @@ -42,6 +51,40 @@ func (r *ServerResponse) Decode(reader io.Reader, isMultiACK bool) error { return s.Err() } +func (r *ServerResponse) endReached(reader *bufio.Reader) (bool, error) { + isPack, err := r.isPACKHeader(reader) + if err == io.EOF { + return true, nil + } + + return isPack, err + +} + +// isPACKHeader detects when a header of a packfile is found, with this goal +// the function is reading from the reader without moving the read pointer. +func (r *ServerResponse) isPACKHeader(reader *bufio.Reader) (bool, error) { + ahead, err := reader.Peek(9) + if err != nil { + return false, err + } + + if len(ahead) == 0 { + return true, nil + } + + if len(ahead) > 4 && string(ahead[0:4]) == "PACK" { + return true, nil + } + + if len(ahead) == 9 && string(ahead[5:]) == "PACK" { + return true, nil + } + + return true, nil + +} + func (r *ServerResponse) decodeLine(line []byte) error { if len(line) == 0 { return fmt.Errorf("unexpected flush") |