aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plumbing/hash.go15
-rw-r--r--plumbing/hash_test.go12
-rw-r--r--plumbing/protocol/packp/ulreq_encode.go51
-rw-r--r--plumbing/protocol/packp/ulreq_encode_test.go90
-rw-r--r--plumbing/protocol/packp/uppackreq.go11
-rw-r--r--plumbing/protocol/packp/uppackreq_test.go27
6 files changed, 164 insertions, 42 deletions
diff --git a/plumbing/hash.go b/plumbing/hash.go
index 7fa953d..8e60877 100644
--- a/plumbing/hash.go
+++ b/plumbing/hash.go
@@ -1,9 +1,11 @@
package plumbing
import (
+ "bytes"
"crypto/sha1"
"encoding/hex"
"hash"
+ "sort"
"strconv"
)
@@ -56,3 +58,16 @@ func (h Hasher) Sum() (hash Hash) {
copy(hash[:], h.Hash.Sum(nil))
return
}
+
+// HashesSort sorts a slice of Hashes in increasing order.
+func HashesSort(a []Hash) {
+ sort.Sort(HashSlice(a))
+}
+
+// HashSlice attaches the methods of sort.Interface to []Hash, sorting in
+// increasing order.
+type HashSlice []Hash
+
+func (p HashSlice) Len() int { return len(p) }
+func (p HashSlice) Less(i, j int) bool { return bytes.Compare(p[i][:], p[j][:]) < 0 }
+func (p HashSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
diff --git a/plumbing/hash_test.go b/plumbing/hash_test.go
index 370811e..fc2428b 100644
--- a/plumbing/hash_test.go
+++ b/plumbing/hash_test.go
@@ -40,3 +40,15 @@ func (s *HashSuite) TestNewHasher(c *C) {
hasher.Write([]byte(content))
c.Assert(hasher.Sum().String(), Equals, "dc42c3cc80028d0ec61f0a6b24cadd1c195c4dfc")
}
+
+func (s *HashSuite) TestHashesSort(c *C) {
+ i := []Hash{
+ NewHash("2222222222222222222222222222222222222222"),
+ NewHash("1111111111111111111111111111111111111111"),
+ }
+
+ HashesSort(i)
+
+ c.Assert(i[0], Equals, NewHash("1111111111111111111111111111111111111111"))
+ c.Assert(i[1], Equals, NewHash("2222222222222222222222222222222222222222"))
+}
diff --git a/plumbing/protocol/packp/ulreq_encode.go b/plumbing/protocol/packp/ulreq_encode.go
index b2ca491..4a26e74 100644
--- a/plumbing/protocol/packp/ulreq_encode.go
+++ b/plumbing/protocol/packp/ulreq_encode.go
@@ -1,9 +1,9 @@
package packp
import (
+ "bytes"
"fmt"
"io"
- "sort"
"time"
"gopkg.in/src-d/go-git.v4/plumbing"
@@ -21,10 +21,9 @@ func (u *UploadRequest) Encode(w io.Writer) error {
}
type ulReqEncoder struct {
- pe *pktline.Encoder // where to write the encoded data
- data *UploadRequest // the data to encode
- sortedWants []string
- err error // sticky error
+ pe *pktline.Encoder // where to write the encoded data
+ data *UploadRequest // the data to encode
+ err error // sticky error
}
func newUlReqEncoder(w io.Writer) *ulReqEncoder {
@@ -34,13 +33,13 @@ func newUlReqEncoder(w io.Writer) *ulReqEncoder {
}
func (e *ulReqEncoder) Encode(v *UploadRequest) error {
+ e.data = v
+
if len(v.Wants) == 0 {
return fmt.Errorf("empty wants provided")
}
- e.data = v
- e.sortedWants = sortHashes(v.Wants)
-
+ plumbing.HashesSort(e.data.Wants)
for state := e.encodeFirstWant; state != nil; {
state = state()
}
@@ -48,27 +47,18 @@ func (e *ulReqEncoder) Encode(v *UploadRequest) error {
return e.err
}
-func sortHashes(list []plumbing.Hash) []string {
- sorted := make([]string, len(list))
- for i, hash := range list {
- sorted[i] = hash.String()
- }
- sort.Strings(sorted)
-
- return sorted
-}
-
func (e *ulReqEncoder) encodeFirstWant() stateFn {
var err error
if e.data.Capabilities.IsEmpty() {
- err = e.pe.Encodef("want %s\n", e.sortedWants[0])
+ err = e.pe.Encodef("want %s\n", e.data.Wants[0])
} else {
err = e.pe.Encodef(
"want %s %s\n",
- e.sortedWants[0],
+ e.data.Wants[0],
e.data.Capabilities.String(),
)
}
+
if err != nil {
e.err = fmt.Errorf("encoding first want line: %s", err)
return nil
@@ -78,23 +68,38 @@ func (e *ulReqEncoder) encodeFirstWant() stateFn {
}
func (e *ulReqEncoder) encodeAditionalWants() stateFn {
- for _, w := range e.sortedWants[1:] {
+ last := e.data.Wants[0]
+ for _, w := range e.data.Wants[1:] {
+ if bytes.Compare(last[:], w[:]) == 0 {
+ continue
+ }
+
if err := e.pe.Encodef("want %s\n", w); err != nil {
e.err = fmt.Errorf("encoding want %q: %s", w, err)
return nil
}
+
+ last = w
}
return e.encodeShallows
}
func (e *ulReqEncoder) encodeShallows() stateFn {
- sorted := sortHashes(e.data.Shallows)
- for _, s := range sorted {
+ plumbing.HashesSort(e.data.Shallows)
+
+ var last plumbing.Hash
+ for _, s := range e.data.Shallows {
+ if bytes.Compare(last[:], s[:]) == 0 {
+ continue
+ }
+
if err := e.pe.Encodef("shallow %s\n", s); err != nil {
e.err = fmt.Errorf("encoding shallow %q: %s", s, err)
return nil
}
+
+ last = s
}
return e.encodeDepth
diff --git a/plumbing/protocol/packp/ulreq_encode_test.go b/plumbing/protocol/packp/ulreq_encode_test.go
index 3b3b6c2..b414a37 100644
--- a/plumbing/protocol/packp/ulreq_encode_test.go
+++ b/plumbing/protocol/packp/ulreq_encode_test.go
@@ -76,11 +76,13 @@ func (s *UlReqEncodeSuite) TestOneWantWithCapabilities(c *C) {
func (s *UlReqEncodeSuite) TestWants(c *C) {
ur := NewUploadRequest()
- ur.Wants = append(ur.Wants, plumbing.NewHash("4444444444444444444444444444444444444444"))
- ur.Wants = append(ur.Wants, plumbing.NewHash("1111111111111111111111111111111111111111"))
- ur.Wants = append(ur.Wants, plumbing.NewHash("3333333333333333333333333333333333333333"))
- ur.Wants = append(ur.Wants, plumbing.NewHash("2222222222222222222222222222222222222222"))
- ur.Wants = append(ur.Wants, plumbing.NewHash("5555555555555555555555555555555555555555"))
+ ur.Wants = append(ur.Wants,
+ plumbing.NewHash("4444444444444444444444444444444444444444"),
+ plumbing.NewHash("1111111111111111111111111111111111111111"),
+ plumbing.NewHash("3333333333333333333333333333333333333333"),
+ plumbing.NewHash("2222222222222222222222222222222222222222"),
+ plumbing.NewHash("5555555555555555555555555555555555555555"),
+ )
expected := []string{
"want 1111111111111111111111111111111111111111\n",
@@ -94,13 +96,37 @@ func (s *UlReqEncodeSuite) TestWants(c *C) {
testUlReqEncode(c, ur, expected)
}
+func (s *UlReqEncodeSuite) TestWantsDuplicates(c *C) {
+ ur := NewUploadRequest()
+ ur.Wants = append(ur.Wants,
+ plumbing.NewHash("4444444444444444444444444444444444444444"),
+ plumbing.NewHash("1111111111111111111111111111111111111111"),
+ plumbing.NewHash("3333333333333333333333333333333333333333"),
+ plumbing.NewHash("1111111111111111111111111111111111111111"),
+ plumbing.NewHash("2222222222222222222222222222222222222222"),
+ plumbing.NewHash("1111111111111111111111111111111111111111"),
+ )
+
+ expected := []string{
+ "want 1111111111111111111111111111111111111111\n",
+ "want 2222222222222222222222222222222222222222\n",
+ "want 3333333333333333333333333333333333333333\n",
+ "want 4444444444444444444444444444444444444444\n",
+ pktline.FlushString,
+ }
+
+ testUlReqEncode(c, ur, expected)
+}
+
func (s *UlReqEncodeSuite) TestWantsWithCapabilities(c *C) {
ur := NewUploadRequest()
- ur.Wants = append(ur.Wants, plumbing.NewHash("4444444444444444444444444444444444444444"))
- ur.Wants = append(ur.Wants, plumbing.NewHash("1111111111111111111111111111111111111111"))
- ur.Wants = append(ur.Wants, plumbing.NewHash("3333333333333333333333333333333333333333"))
- ur.Wants = append(ur.Wants, plumbing.NewHash("2222222222222222222222222222222222222222"))
- ur.Wants = append(ur.Wants, plumbing.NewHash("5555555555555555555555555555555555555555"))
+ ur.Wants = append(ur.Wants,
+ plumbing.NewHash("4444444444444444444444444444444444444444"),
+ plumbing.NewHash("1111111111111111111111111111111111111111"),
+ plumbing.NewHash("3333333333333333333333333333333333333333"),
+ plumbing.NewHash("2222222222222222222222222222222222222222"),
+ plumbing.NewHash("5555555555555555555555555555555555555555"),
+ )
ur.Capabilities.Add(capability.MultiACK)
ur.Capabilities.Add(capability.OFSDelta)
@@ -139,10 +165,12 @@ func (s *UlReqEncodeSuite) TestManyShallows(c *C) {
ur := NewUploadRequest()
ur.Wants = append(ur.Wants, plumbing.NewHash("1111111111111111111111111111111111111111"))
ur.Capabilities.Add(capability.MultiACK)
- ur.Shallows = append(ur.Shallows, plumbing.NewHash("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"))
- ur.Shallows = append(ur.Shallows, plumbing.NewHash("dddddddddddddddddddddddddddddddddddddddd"))
- ur.Shallows = append(ur.Shallows, plumbing.NewHash("cccccccccccccccccccccccccccccccccccccccc"))
- ur.Shallows = append(ur.Shallows, plumbing.NewHash("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
+ ur.Shallows = append(ur.Shallows,
+ plumbing.NewHash("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"),
+ plumbing.NewHash("dddddddddddddddddddddddddddddddddddddddd"),
+ plumbing.NewHash("cccccccccccccccccccccccccccccccccccccccc"),
+ plumbing.NewHash("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
+ )
expected := []string{
"want 1111111111111111111111111111111111111111 multi_ack\n",
@@ -156,6 +184,28 @@ func (s *UlReqEncodeSuite) TestManyShallows(c *C) {
testUlReqEncode(c, ur, expected)
}
+func (s *UlReqEncodeSuite) TestShallowsDuplicate(c *C) {
+ ur := NewUploadRequest()
+ ur.Wants = append(ur.Wants, plumbing.NewHash("1111111111111111111111111111111111111111"))
+ ur.Capabilities.Add(capability.MultiACK)
+ ur.Shallows = append(ur.Shallows,
+ plumbing.NewHash("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"),
+ plumbing.NewHash("cccccccccccccccccccccccccccccccccccccccc"),
+ plumbing.NewHash("cccccccccccccccccccccccccccccccccccccccc"),
+ plumbing.NewHash("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
+ )
+
+ expected := []string{
+ "want 1111111111111111111111111111111111111111 multi_ack\n",
+ "shallow aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n",
+ "shallow bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n",
+ "shallow cccccccccccccccccccccccccccccccccccccccc\n",
+ pktline.FlushString,
+ }
+
+ testUlReqEncode(c, ur, expected)
+}
+
func (s *UlReqEncodeSuite) TestDepthCommits(c *C) {
ur := NewUploadRequest()
ur.Wants = append(ur.Wants, plumbing.NewHash("1111111111111111111111111111111111111111"))
@@ -220,11 +270,13 @@ func (s *UlReqEncodeSuite) TestDepthReference(c *C) {
func (s *UlReqEncodeSuite) TestAll(c *C) {
ur := NewUploadRequest()
- ur.Wants = append(ur.Wants, plumbing.NewHash("4444444444444444444444444444444444444444"))
- ur.Wants = append(ur.Wants, plumbing.NewHash("1111111111111111111111111111111111111111"))
- ur.Wants = append(ur.Wants, plumbing.NewHash("3333333333333333333333333333333333333333"))
- ur.Wants = append(ur.Wants, plumbing.NewHash("2222222222222222222222222222222222222222"))
- ur.Wants = append(ur.Wants, plumbing.NewHash("5555555555555555555555555555555555555555"))
+ ur.Wants = append(ur.Wants,
+ plumbing.NewHash("4444444444444444444444444444444444444444"),
+ plumbing.NewHash("1111111111111111111111111111111111111111"),
+ plumbing.NewHash("3333333333333333333333333333333333333333"),
+ plumbing.NewHash("2222222222222222222222222222222222222222"),
+ plumbing.NewHash("5555555555555555555555555555555555555555"),
+ )
ur.Capabilities.Add(capability.MultiACK)
ur.Capabilities.Add(capability.OFSDelta)
diff --git a/plumbing/protocol/packp/uppackreq.go b/plumbing/protocol/packp/uppackreq.go
index 2b1cb84..887d27a 100644
--- a/plumbing/protocol/packp/uppackreq.go
+++ b/plumbing/protocol/packp/uppackreq.go
@@ -1,6 +1,7 @@
package packp
import (
+ "bytes"
"fmt"
"io"
@@ -68,10 +69,20 @@ type UploadHaves struct {
// Encode encodes the UploadHaves into the Writer.
func (u *UploadHaves) Encode(w io.Writer) error {
e := pktline.NewEncoder(w)
+
+ plumbing.HashesSort(u.Haves)
+
+ var last plumbing.Hash
for _, have := range u.Haves {
+ if bytes.Compare(last[:], have[:]) == 0 {
+ continue
+ }
+
if err := e.Encodef("have %s\n", have); err != nil {
return fmt.Errorf("sending haves for %q: %s", have, err)
}
+
+ last = have
}
if len(u.Haves) != 0 {
diff --git a/plumbing/protocol/packp/uppackreq_test.go b/plumbing/protocol/packp/uppackreq_test.go
index 75b75b4..e551f45 100644
--- a/plumbing/protocol/packp/uppackreq_test.go
+++ b/plumbing/protocol/packp/uppackreq_test.go
@@ -4,6 +4,8 @@ import (
"gopkg.in/src-d/go-git.v4/plumbing"
"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/capability"
+ "bytes"
+
. "gopkg.in/check.v1"
)
@@ -40,3 +42,28 @@ func (s *UploadPackRequestSuite) TestIsEmpty(c *C) {
c.Assert(r.IsEmpty(), Equals, true)
}
+
+type UploadHavesSuite struct{}
+
+var _ = Suite(&UploadHavesSuite{})
+
+func (s *UploadHavesSuite) TestEncode(c *C) {
+ uh := &UploadHaves{}
+ uh.Haves = append(uh.Haves,
+ plumbing.NewHash("1111111111111111111111111111111111111111"),
+ plumbing.NewHash("3333333333333333333333333333333333333333"),
+ plumbing.NewHash("1111111111111111111111111111111111111111"),
+ plumbing.NewHash("2222222222222222222222222222222222222222"),
+ plumbing.NewHash("1111111111111111111111111111111111111111"),
+ )
+
+ buf := bytes.NewBuffer(nil)
+ err := uh.Encode(buf)
+ c.Assert(err, IsNil)
+ c.Assert(buf.String(), Equals, ""+
+ "0032have 1111111111111111111111111111111111111111\n"+
+ "0032have 2222222222222222222222222222222222222222\n"+
+ "0032have 3333333333333333333333333333333333333333\n"+
+ "0000",
+ )
+}