1package packp
2
3import (
4	"bytes"
5	"strings"
6
7	"github.com/go-git/go-git/v5/plumbing"
8	"github.com/go-git/go-git/v5/plumbing/format/pktline"
9	"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
10
11	. "gopkg.in/check.v1"
12)
13
14type AdvRefsEncodeSuite struct{}
15
16var _ = Suite(&AdvRefsEncodeSuite{})
17
18func testEncode(c *C, input *AdvRefs, expected []byte) {
19	var buf bytes.Buffer
20	c.Assert(input.Encode(&buf), IsNil)
21	obtained := buf.Bytes()
22
23	comment := Commentf("\nobtained = %s\nexpected = %s\n", string(obtained), string(expected))
24
25	c.Assert(obtained, DeepEquals, expected, comment)
26}
27
28func (s *AdvRefsEncodeSuite) TestZeroValue(c *C) {
29	ar := &AdvRefs{}
30
31	expected := pktlines(c,
32		"0000000000000000000000000000000000000000 capabilities^{}\x00\n",
33		pktline.FlushString,
34	)
35
36	testEncode(c, ar, expected)
37}
38
39func (s *AdvRefsEncodeSuite) TestHead(c *C) {
40	hash := plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
41	ar := &AdvRefs{
42		Head: &hash,
43	}
44
45	expected := pktlines(c,
46		"6ecf0ef2c2dffb796033e5a02219af86ec6584e5 HEAD\x00\n",
47		pktline.FlushString,
48	)
49
50	testEncode(c, ar, expected)
51}
52
53func (s *AdvRefsEncodeSuite) TestCapsNoHead(c *C) {
54	capabilities := capability.NewList()
55	capabilities.Add(capability.MultiACK)
56	capabilities.Add(capability.OFSDelta)
57	capabilities.Add(capability.SymRef, "HEAD:/refs/heads/master")
58	ar := &AdvRefs{
59		Capabilities: capabilities,
60	}
61
62	expected := pktlines(c,
63		"0000000000000000000000000000000000000000 capabilities^{}\x00multi_ack ofs-delta symref=HEAD:/refs/heads/master\n",
64		pktline.FlushString,
65	)
66
67	testEncode(c, ar, expected)
68}
69
70func (s *AdvRefsEncodeSuite) TestCapsWithHead(c *C) {
71	hash := plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
72	capabilities := capability.NewList()
73	capabilities.Add(capability.MultiACK)
74	capabilities.Add(capability.OFSDelta)
75	capabilities.Add(capability.SymRef, "HEAD:/refs/heads/master")
76	ar := &AdvRefs{
77		Head:         &hash,
78		Capabilities: capabilities,
79	}
80
81	expected := pktlines(c,
82		"6ecf0ef2c2dffb796033e5a02219af86ec6584e5 HEAD\x00multi_ack ofs-delta symref=HEAD:/refs/heads/master\n",
83		pktline.FlushString,
84	)
85
86	testEncode(c, ar, expected)
87}
88
89func (s *AdvRefsEncodeSuite) TestRefs(c *C) {
90	references := map[string]plumbing.Hash{
91		"refs/heads/master":      plumbing.NewHash("a6930aaee06755d1bdcfd943fbf614e4d92bb0c7"),
92		"refs/tags/v2.6.12-tree": plumbing.NewHash("1111111111111111111111111111111111111111"),
93		"refs/tags/v2.7.13-tree": plumbing.NewHash("3333333333333333333333333333333333333333"),
94		"refs/tags/v2.6.13-tree": plumbing.NewHash("2222222222222222222222222222222222222222"),
95		"refs/tags/v2.6.11-tree": plumbing.NewHash("5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c"),
96	}
97	ar := &AdvRefs{
98		References: references,
99	}
100
101	expected := pktlines(c,
102		"a6930aaee06755d1bdcfd943fbf614e4d92bb0c7 refs/heads/master\x00\n",
103		"5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c refs/tags/v2.6.11-tree\n",
104		"1111111111111111111111111111111111111111 refs/tags/v2.6.12-tree\n",
105		"2222222222222222222222222222222222222222 refs/tags/v2.6.13-tree\n",
106		"3333333333333333333333333333333333333333 refs/tags/v2.7.13-tree\n",
107		pktline.FlushString,
108	)
109
110	testEncode(c, ar, expected)
111}
112
113func (s *AdvRefsEncodeSuite) TestPeeled(c *C) {
114	references := map[string]plumbing.Hash{
115		"refs/heads/master":      plumbing.NewHash("a6930aaee06755d1bdcfd943fbf614e4d92bb0c7"),
116		"refs/tags/v2.6.12-tree": plumbing.NewHash("1111111111111111111111111111111111111111"),
117		"refs/tags/v2.7.13-tree": plumbing.NewHash("3333333333333333333333333333333333333333"),
118		"refs/tags/v2.6.13-tree": plumbing.NewHash("2222222222222222222222222222222222222222"),
119		"refs/tags/v2.6.11-tree": plumbing.NewHash("5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c"),
120	}
121	peeled := map[string]plumbing.Hash{
122		"refs/tags/v2.7.13-tree": plumbing.NewHash("4444444444444444444444444444444444444444"),
123		"refs/tags/v2.6.12-tree": plumbing.NewHash("5555555555555555555555555555555555555555"),
124	}
125	ar := &AdvRefs{
126		References: references,
127		Peeled:     peeled,
128	}
129
130	expected := pktlines(c,
131		"a6930aaee06755d1bdcfd943fbf614e4d92bb0c7 refs/heads/master\x00\n",
132		"5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c refs/tags/v2.6.11-tree\n",
133		"1111111111111111111111111111111111111111 refs/tags/v2.6.12-tree\n",
134		"5555555555555555555555555555555555555555 refs/tags/v2.6.12-tree^{}\n",
135		"2222222222222222222222222222222222222222 refs/tags/v2.6.13-tree\n",
136		"3333333333333333333333333333333333333333 refs/tags/v2.7.13-tree\n",
137		"4444444444444444444444444444444444444444 refs/tags/v2.7.13-tree^{}\n",
138		pktline.FlushString,
139	)
140
141	testEncode(c, ar, expected)
142}
143
144func (s *AdvRefsEncodeSuite) TestShallow(c *C) {
145	shallows := []plumbing.Hash{
146		plumbing.NewHash("1111111111111111111111111111111111111111"),
147		plumbing.NewHash("4444444444444444444444444444444444444444"),
148		plumbing.NewHash("3333333333333333333333333333333333333333"),
149		plumbing.NewHash("2222222222222222222222222222222222222222"),
150	}
151	ar := &AdvRefs{
152		Shallows: shallows,
153	}
154
155	expected := pktlines(c,
156		"0000000000000000000000000000000000000000 capabilities^{}\x00\n",
157		"shallow 1111111111111111111111111111111111111111\n",
158		"shallow 2222222222222222222222222222222222222222\n",
159		"shallow 3333333333333333333333333333333333333333\n",
160		"shallow 4444444444444444444444444444444444444444\n",
161		pktline.FlushString,
162	)
163
164	testEncode(c, ar, expected)
165}
166
167func (s *AdvRefsEncodeSuite) TestAll(c *C) {
168	hash := plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
169
170	capabilities := capability.NewList()
171	capabilities.Add(capability.MultiACK)
172	capabilities.Add(capability.OFSDelta)
173	capabilities.Add(capability.SymRef, "HEAD:/refs/heads/master")
174
175	references := map[string]plumbing.Hash{
176		"refs/heads/master":      plumbing.NewHash("a6930aaee06755d1bdcfd943fbf614e4d92bb0c7"),
177		"refs/tags/v2.6.12-tree": plumbing.NewHash("1111111111111111111111111111111111111111"),
178		"refs/tags/v2.7.13-tree": plumbing.NewHash("3333333333333333333333333333333333333333"),
179		"refs/tags/v2.6.13-tree": plumbing.NewHash("2222222222222222222222222222222222222222"),
180		"refs/tags/v2.6.11-tree": plumbing.NewHash("5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c"),
181	}
182
183	peeled := map[string]plumbing.Hash{
184		"refs/tags/v2.7.13-tree": plumbing.NewHash("4444444444444444444444444444444444444444"),
185		"refs/tags/v2.6.12-tree": plumbing.NewHash("5555555555555555555555555555555555555555"),
186	}
187
188	shallows := []plumbing.Hash{
189		plumbing.NewHash("1111111111111111111111111111111111111111"),
190		plumbing.NewHash("4444444444444444444444444444444444444444"),
191		plumbing.NewHash("3333333333333333333333333333333333333333"),
192		plumbing.NewHash("2222222222222222222222222222222222222222"),
193	}
194
195	ar := &AdvRefs{
196		Head:         &hash,
197		Capabilities: capabilities,
198		References:   references,
199		Peeled:       peeled,
200		Shallows:     shallows,
201	}
202
203	expected := pktlines(c,
204		"6ecf0ef2c2dffb796033e5a02219af86ec6584e5 HEAD\x00multi_ack ofs-delta symref=HEAD:/refs/heads/master\n",
205		"a6930aaee06755d1bdcfd943fbf614e4d92bb0c7 refs/heads/master\n",
206		"5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c refs/tags/v2.6.11-tree\n",
207		"1111111111111111111111111111111111111111 refs/tags/v2.6.12-tree\n",
208		"5555555555555555555555555555555555555555 refs/tags/v2.6.12-tree^{}\n",
209		"2222222222222222222222222222222222222222 refs/tags/v2.6.13-tree\n",
210		"3333333333333333333333333333333333333333 refs/tags/v2.7.13-tree\n",
211		"4444444444444444444444444444444444444444 refs/tags/v2.7.13-tree^{}\n",
212		"shallow 1111111111111111111111111111111111111111\n",
213		"shallow 2222222222222222222222222222222222222222\n",
214		"shallow 3333333333333333333333333333333333333333\n",
215		"shallow 4444444444444444444444444444444444444444\n",
216		pktline.FlushString,
217	)
218
219	testEncode(c, ar, expected)
220}
221
222func (s *AdvRefsEncodeSuite) TestErrorTooLong(c *C) {
223	references := map[string]plumbing.Hash{
224		strings.Repeat("a", pktline.MaxPayloadSize): plumbing.NewHash("a6930aaee06755d1bdcfd943fbf614e4d92bb0c7"),
225	}
226	ar := &AdvRefs{
227		References: references,
228	}
229
230	var buf bytes.Buffer
231	err := ar.Encode(&buf)
232	c.Assert(err, ErrorMatches, ".*payload is too long.*")
233}
234