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

Commit bd81c1f

Browse files
authored
Merge pull request #552 from mcarmonaa/fix/packp-adv-refs-encode
packp: fixed encoding when HEAD is not a valid ref
2 parents 118a8c7 + af398e5 commit bd81c1f

File tree

2 files changed

+56
-38
lines changed

2 files changed

+56
-38
lines changed

plumbing/protocol/packp/advrefs_encode.go

+54-34
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package packp
22

33
import (
44
"bytes"
5+
"fmt"
56
"io"
67
"sort"
78

@@ -21,9 +22,13 @@ func (a *AdvRefs) Encode(w io.Writer) error {
2122
}
2223

2324
type advRefsEncoder struct {
24-
data *AdvRefs // data to encode
25-
pe *pktline.Encoder // where to write the encoded data
26-
err error // sticky error
25+
data *AdvRefs // data to encode
26+
pe *pktline.Encoder // where to write the encoded data
27+
firstRefName string // reference name to encode in the first pkt-line (HEAD if present)
28+
firstRefHash plumbing.Hash // hash referenced to encode in the first pkt-line (HEAD if present)
29+
sortedRefs []string // hash references to encode ordered by increasing order
30+
err error // sticky error
31+
2732
}
2833

2934
func newAdvRefsEncoder(w io.Writer) *advRefsEncoder {
@@ -34,6 +39,8 @@ func newAdvRefsEncoder(w io.Writer) *advRefsEncoder {
3439

3540
func (e *advRefsEncoder) Encode(v *AdvRefs) error {
3641
e.data = v
42+
e.sortRefs()
43+
e.setFirstRef()
3744

3845
for state := encodePrefix; state != nil; {
3946
state = state(e)
@@ -42,6 +49,32 @@ func (e *advRefsEncoder) Encode(v *AdvRefs) error {
4249
return e.err
4350
}
4451

52+
func (e *advRefsEncoder) sortRefs() {
53+
if len(e.data.References) > 0 {
54+
refs := make([]string, 0, len(e.data.References))
55+
for refName := range e.data.References {
56+
refs = append(refs, refName)
57+
}
58+
59+
sort.Strings(refs)
60+
e.sortedRefs = refs
61+
}
62+
}
63+
64+
func (e *advRefsEncoder) setFirstRef() {
65+
if e.data.Head != nil {
66+
e.firstRefName = head
67+
e.firstRefHash = *e.data.Head
68+
return
69+
}
70+
71+
if len(e.sortedRefs) > 0 {
72+
refName := e.sortedRefs[0]
73+
e.firstRefName = refName
74+
e.firstRefHash = e.data.References[refName]
75+
}
76+
}
77+
4578
type encoderStateFn func(*advRefsEncoder) encoderStateFn
4679

4780
func encodePrefix(e *advRefsEncoder) encoderStateFn {
@@ -61,33 +94,27 @@ func encodePrefix(e *advRefsEncoder) encoderStateFn {
6194
}
6295

6396
// Adds the first pkt-line payload: head hash, head ref and capabilities.
64-
// Also handle the special case when no HEAD ref is found.
97+
// If HEAD ref is not found, the first reference ordered in increasing order will be used.
98+
// If there aren't HEAD neither refs, the first line will be "PKT-LINE(zero-id SP "capabilities^{}" NUL capability-list)".
99+
// See: https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt
100+
// See: https://github.com/git/git/blob/master/Documentation/technical/protocol-common.txt
65101
func encodeFirstLine(e *advRefsEncoder) encoderStateFn {
66-
head := formatHead(e.data.Head)
67-
separator := formatSeparator(e.data.Head)
102+
const formatFirstLine = "%s %s\x00%s\n"
103+
var firstLine string
68104
capabilities := formatCaps(e.data.Capabilities)
69105

70-
if e.err = e.pe.Encodef("%s %s\x00%s\n", head, separator, capabilities); e.err != nil {
71-
return nil
72-
}
106+
if e.firstRefName == "" {
107+
firstLine = fmt.Sprintf(formatFirstLine, plumbing.ZeroHash.String(), "capabilities^{}", capabilities)
108+
} else {
109+
firstLine = fmt.Sprintf(formatFirstLine, e.firstRefHash.String(), e.firstRefName, capabilities)
73110

74-
return encodeRefs
75-
}
76-
77-
func formatHead(h *plumbing.Hash) string {
78-
if h == nil {
79-
return plumbing.ZeroHash.String()
80111
}
81112

82-
return h.String()
83-
}
84-
85-
func formatSeparator(h *plumbing.Hash) string {
86-
if h == nil {
87-
return noHead
113+
if e.err = e.pe.EncodeString(firstLine); e.err != nil {
114+
return nil
88115
}
89116

90-
return head
117+
return encodeRefs
91118
}
92119

93120
func formatCaps(c *capability.List) string {
@@ -101,8 +128,11 @@ func formatCaps(c *capability.List) string {
101128
// Adds the (sorted) refs: hash SP refname EOL
102129
// and their peeled refs if any.
103130
func encodeRefs(e *advRefsEncoder) encoderStateFn {
104-
refs := sortRefs(e.data.References)
105-
for _, r := range refs {
131+
for _, r := range e.sortedRefs {
132+
if r == e.firstRefName {
133+
continue
134+
}
135+
106136
hash, _ := e.data.References[r]
107137
if e.err = e.pe.Encodef("%s %s\n", hash.String(), r); e.err != nil {
108138
return nil
@@ -118,16 +148,6 @@ func encodeRefs(e *advRefsEncoder) encoderStateFn {
118148
return encodeShallow
119149
}
120150

121-
func sortRefs(m map[string]plumbing.Hash) []string {
122-
ret := make([]string, 0, len(m))
123-
for k := range m {
124-
ret = append(ret, k)
125-
}
126-
sort.Strings(ret)
127-
128-
return ret
129-
}
130-
131151
// Adds the (sorted) shallows: "shallow" SP hash EOL
132152
func encodeShallow(e *advRefsEncoder) encoderStateFn {
133153
sorted := sortShallows(e.data.Shallows)

plumbing/protocol/packp/advrefs_encode_test.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,7 @@ func (s *AdvRefsEncodeSuite) TestRefs(c *C) {
9999
}
100100

101101
expected := pktlines(c,
102-
"0000000000000000000000000000000000000000 capabilities^{}\x00\n",
103-
"a6930aaee06755d1bdcfd943fbf614e4d92bb0c7 refs/heads/master\n",
102+
"a6930aaee06755d1bdcfd943fbf614e4d92bb0c7 refs/heads/master\x00\n",
104103
"5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c refs/tags/v2.6.11-tree\n",
105104
"1111111111111111111111111111111111111111 refs/tags/v2.6.12-tree\n",
106105
"2222222222222222222222222222222222222222 refs/tags/v2.6.13-tree\n",
@@ -129,8 +128,7 @@ func (s *AdvRefsEncodeSuite) TestPeeled(c *C) {
129128
}
130129

131130
expected := pktlines(c,
132-
"0000000000000000000000000000000000000000 capabilities^{}\x00\n",
133-
"a6930aaee06755d1bdcfd943fbf614e4d92bb0c7 refs/heads/master\n",
131+
"a6930aaee06755d1bdcfd943fbf614e4d92bb0c7 refs/heads/master\x00\n",
134132
"5dc01c595e6c6ec9ccda4f6f69c131c0dd945f8c refs/tags/v2.6.11-tree\n",
135133
"1111111111111111111111111111111111111111 refs/tags/v2.6.12-tree\n",
136134
"5555555555555555555555555555555555555555 refs/tags/v2.6.12-tree^{}\n",

0 commit comments

Comments
 (0)