Skip to content

Commit e2c6ae3

Browse files
committed
plumbing: handle pktline erro-line as errors
Error when encountering an error-line See https://git-scm.com/docs/pack-protocol Update plumbing/format/pktline/error.go Co-authored-by: Paulo Gomes <[email protected]> Update plumbing/format/pktline/error.go Co-authored-by: Paulo Gomes <[email protected]> feat: format newline
1 parent e187533 commit e2c6ae3

File tree

3 files changed

+128
-0
lines changed

3 files changed

+128
-0
lines changed

plumbing/format/pktline/error.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package pktline
2+
3+
import (
4+
"bytes"
5+
"errors"
6+
"io"
7+
"strings"
8+
)
9+
10+
var (
11+
// ErrInvalidErrorLine is returned by Decode when the packet line is not an
12+
// error line.
13+
ErrInvalidErrorLine = errors.New("expected an error-line")
14+
15+
errPrefix = []byte("ERR ")
16+
)
17+
18+
// ErrorLine is a packet line that contains an error message.
19+
// Once this packet is sent by client or server, the data transfer process is
20+
// terminated.
21+
// See https://git-scm.com/docs/pack-protocol#_pkt_line_format
22+
type ErrorLine struct {
23+
Text string
24+
}
25+
26+
// Error implements the error interface.
27+
func (e *ErrorLine) Error() string {
28+
return e.Text
29+
}
30+
31+
// Encode encodes the ErrorLine into a packet line.
32+
func (e *ErrorLine) Encode(w io.Writer) error {
33+
p := NewEncoder(w)
34+
return p.Encodef("%s%s\n", string(errPrefix), e.Text)
35+
}
36+
37+
// Decode decodes a packet line into an ErrorLine.
38+
func (e *ErrorLine) Decode(r io.Reader) error {
39+
s := NewScanner(r)
40+
if !s.Scan() {
41+
return s.Err()
42+
}
43+
44+
line := s.Bytes()
45+
if !bytes.HasPrefix(line, errPrefix) {
46+
return ErrInvalidErrorLine
47+
}
48+
49+
e.Text = strings.TrimSpace(string(line[4:]))
50+
return nil
51+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package pktline
2+
3+
import (
4+
"bytes"
5+
"errors"
6+
"io"
7+
"testing"
8+
)
9+
10+
func TestEncodeEmptyErrorLine(t *testing.T) {
11+
e := &ErrorLine{}
12+
err := e.Encode(io.Discard)
13+
if err != nil {
14+
t.Fatal(err)
15+
}
16+
}
17+
18+
func TestEncodeErrorLine(t *testing.T) {
19+
e := &ErrorLine{
20+
Text: "something",
21+
}
22+
var buf bytes.Buffer
23+
err := e.Encode(&buf)
24+
if err != nil {
25+
t.Fatal(err)
26+
}
27+
if buf.String() != "0012ERR something\n" {
28+
t.Fatalf("unexpected encoded error line: %q", buf.String())
29+
}
30+
}
31+
32+
func TestDecodeEmptyErrorLine(t *testing.T) {
33+
var buf bytes.Buffer
34+
e := &ErrorLine{}
35+
err := e.Decode(&buf)
36+
if err != nil {
37+
t.Fatal(err)
38+
}
39+
if e.Text != "" {
40+
t.Fatalf("unexpected error line: %q", e.Text)
41+
}
42+
}
43+
44+
func TestDecodeErrorLine(t *testing.T) {
45+
var buf bytes.Buffer
46+
buf.WriteString("000eERR foobar")
47+
var e *ErrorLine
48+
err := e.Decode(&buf)
49+
if !errors.As(err, &e) {
50+
t.Fatalf("expected error line, got: %T: %v", err, err)
51+
}
52+
if e.Text != "foobar" {
53+
t.Fatalf("unexpected error line: %q", e.Text)
54+
}
55+
}
56+
57+
func TestDecodeErrorLineLn(t *testing.T) {
58+
var buf bytes.Buffer
59+
buf.WriteString("000fERR foobar\n")
60+
var e *ErrorLine
61+
err := e.Decode(&buf)
62+
if !errors.As(err, &e) {
63+
t.Fatalf("expected error line, got: %T: %v", err, err)
64+
}
65+
if e.Text != "foobar" {
66+
t.Fatalf("unexpected error line: %q", e.Text)
67+
}
68+
}

plumbing/format/pktline/scanner.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package pktline
22

33
import (
4+
"bytes"
45
"errors"
56
"io"
7+
"strings"
68

79
"github.com/go-git/go-git/v5/utils/trace"
810
)
@@ -69,6 +71,13 @@ func (s *Scanner) Scan() bool {
6971
s.payload = s.payload[:l]
7072
trace.Packet.Printf("packet: < %04x %s", l, s.payload)
7173

74+
if bytes.HasPrefix(s.payload, errPrefix) {
75+
s.err = &ErrorLine{
76+
Text: strings.TrimSpace(string(s.payload[4:])),
77+
}
78+
return false
79+
}
80+
7281
return true
7382
}
7483

0 commit comments

Comments
 (0)