Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

plumbing: protocol, fix handling multiple ACK on upload-pack and test… #475

Merged
merged 1 commit into from
Jul 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions plumbing/protocol/packp/srvresp.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,51 +38,51 @@ func (r *ServerResponse) Decode(reader *bufio.Reader, isMultiACK bool) error {
// 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)
stop, err := r.stopReading(reader)
if err != nil {
return err
}

if isEnd {
if stop {
break
}
}

return s.Err()
}

func (r *ServerResponse) endReached(reader *bufio.Reader) (bool, error) {
isPack, err := r.isPACKHeader(reader)
// stopReading detects when a valid command such as ACK or NAK is found to be
// read in the buffer without moving the read pointer.
func (r *ServerResponse) stopReading(reader *bufio.Reader) (bool, error) {
ahead, err := reader.Peek(7)
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) > 4 && r.isValidCommand(ahead[0:3]) {
return false, nil
}

if len(ahead) == 9 && string(ahead[5:]) == "PACK" {
return true, nil
if len(ahead) == 7 && r.isValidCommand(ahead[4:]) {
return false, nil
}

return true, nil
}

func (r *ServerResponse) isValidCommand(b []byte) bool {
commands := [][]byte{ack, nak}
for _, c := range commands {
if bytes.Compare(b, c) == 0 {
return true
}
}

return false
}

func (r *ServerResponse) decodeLine(line []byte) error {
Expand Down
25 changes: 22 additions & 3 deletions plumbing/protocol/packp/srvresp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,33 @@ func (s *ServerResponseSuite) TestDecodeACK(c *C) {
}

func (s *ServerResponseSuite) TestDecodeMultipleACK(c *C) {
raw := "0031ACK 6ecf0ef2c2dffb796033e5a02219af86ec6584e5\n0031ACK 6ecf0ef2c2dffb796033e5a02219af86ec6584e5\n"
raw := "" +
"0031ACK 1111111111111111111111111111111111111111\n" +
"0031ACK 6ecf0ef2c2dffb796033e5a02219af86ec6584e5\n" +
"00080PACK\n"

sr := &ServerResponse{}
err := sr.Decode(bufio.NewReader(bytes.NewBufferString(raw)), false)
c.Assert(err, IsNil)

c.Assert(sr.ACKs, HasLen, 1)
c.Assert(sr.ACKs[0], Equals, plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"))
c.Assert(sr.ACKs, HasLen, 2)
c.Assert(sr.ACKs[0], Equals, plumbing.NewHash("1111111111111111111111111111111111111111"))
c.Assert(sr.ACKs[1], Equals, plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"))
}

func (s *ServerResponseSuite) TestDecodeMultipleACKWithSideband(c *C) {
raw := "" +
"0031ACK 1111111111111111111111111111111111111111\n" +
"0031ACK 6ecf0ef2c2dffb796033e5a02219af86ec6584e5\n" +
"00080aaaa\n"

sr := &ServerResponse{}
err := sr.Decode(bufio.NewReader(bytes.NewBufferString(raw)), false)
c.Assert(err, IsNil)

c.Assert(sr.ACKs, HasLen, 2)
c.Assert(sr.ACKs[0], Equals, plumbing.NewHash("1111111111111111111111111111111111111111"))
c.Assert(sr.ACKs[1], Equals, plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"))
}

func (s *ServerResponseSuite) TestDecodeMalformed(c *C) {
Expand Down