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

Commit 01ea726

Browse files
authored
remote: sideband support (#164)
* remote: sideband support * changes
1 parent 5990aeb commit 01ea726

File tree

11 files changed

+139
-76
lines changed

11 files changed

+139
-76
lines changed

plumbing/protocol/packp/sideband/demux.go

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package sideband
22

33
import (
4-
"bytes"
54
"errors"
65
"fmt"
76
"io"
@@ -15,21 +14,22 @@ var ErrMaxPackedExceeded = errors.New("max. packed size exceeded")
1514
// Progress allows to read the progress information
1615
type Progress interface {
1716
io.Reader
17+
io.Writer
1818
}
1919

2020
// Demuxer demultiplex the progress reports and error info interleaved with the
2121
// packfile itself.
2222
//
23-
// A sideband has three different channels the main one call PackData contains
23+
// A sideband has three different channels the main one, call PackData, contains
2424
// the packfile data, the ErrorMessage channel, that contains server errors and
2525
// the last one ProgressMessage channel containing information about the ongoing
26-
// task happening in the server (optinal, can be suppressed sending NoProgress
26+
// task happening in the server (optional, can be suppressed sending NoProgress
2727
// or Quiet capabilities to the server)
2828
//
2929
// In order to demultiplex the data stream, method `Read` should be called to
3030
// retrieve the PackData channel, the incoming data from the ProgressMessage is
31-
// stored and can be read from `Progress` field, if any message is retrieved
32-
// from the ErrorMessage channel an error is returned and we can assume that the
31+
// written at `Progress` (if any), if any message is retrieved from the
32+
// ErrorMessage channel an error is returned and we can assume that the
3333
// connection has been closed.
3434
type Demuxer struct {
3535
t Type
@@ -39,7 +39,7 @@ type Demuxer struct {
3939
max int
4040
pending []byte
4141

42-
// Progress contains progress information
42+
// Progress is where the progress messages are stored
4343
Progress Progress
4444
}
4545

@@ -51,21 +51,19 @@ func NewDemuxer(t Type, r io.Reader) *Demuxer {
5151
}
5252

5353
return &Demuxer{
54-
t: t,
55-
r: r,
56-
max: max,
57-
s: pktline.NewScanner(r),
58-
Progress: bytes.NewBuffer(nil),
54+
t: t,
55+
r: r,
56+
max: max,
57+
s: pktline.NewScanner(r),
5958
}
6059
}
6160

6261
// Read reads up to len(p) bytes from the PackData channel into p, an error can
63-
// be return if an error happends when reading or if a message is sent in the
62+
// be return if an error happens when reading or if a message is sent in the
6463
// ErrorMessage channel.
6564
//
66-
// If a ProgressMessage is read, it won't be copied to b. Instead of this, it is
67-
// stored and can be read through the reader Progress. If the n value returned
68-
// is zero, err will be nil unless an error reading happens.
65+
// When a ProgressMessage is read, is not copy to b, instead of this is written
66+
// to the Progress
6967
func (d *Demuxer) Read(b []byte) (n int, err error) {
7068
var read, req int
7169

@@ -126,13 +124,17 @@ func (d *Demuxer) nextPackData() ([]byte, error) {
126124
case PackData:
127125
return content[1:], nil
128126
case ProgressMessage:
129-
_, err := d.Progress.(io.Writer).Write(content[1:])
130-
return nil, err
127+
if d.Progress != nil {
128+
_, err := d.Progress.Write(content[1:])
129+
return nil, err
130+
}
131131
case ErrorMessage:
132132
return nil, fmt.Errorf("unexpected error: %s", content[1:])
133133
default:
134134
return nil, fmt.Errorf("unknown channel %s", content)
135135
}
136+
137+
return nil, nil
136138
}
137139

138140
func (d *Demuxer) getPending() (b []byte) {

plumbing/protocol/packp/sideband/demux_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ func (s *SidebandSuite) TestDecode(c *C) {
2424
buf := bytes.NewBuffer(nil)
2525
e := pktline.NewEncoder(buf)
2626
e.Encode(PackData.WithPayload(expected[0:8]))
27+
e.Encode(ProgressMessage.WithPayload([]byte{'F', 'O', 'O', '\n'}))
2728
e.Encode(PackData.WithPayload(expected[8:16]))
2829
e.Encode(PackData.WithPayload(expected[16:26]))
2930

@@ -92,6 +93,8 @@ func (s *SidebandSuite) TestDecodeWithProgress(c *C) {
9293

9394
content := make([]byte, 26)
9495
d := NewDemuxer(Sideband64k, buf)
96+
d.Progress = bytes.NewBuffer(nil)
97+
9598
n, err := io.ReadFull(d, content)
9699
c.Assert(err, IsNil)
97100
c.Assert(n, Equals, 26)

plumbing/protocol/packp/ulreq.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ func NewUploadRequestFromCapabilities(adv *capability.List) *UploadRequest {
8282
r.Capabilities.Set(capability.MultiACK)
8383
}
8484

85+
if adv.Supports(capability.Sideband64k) {
86+
r.Capabilities.Set(capability.Sideband64k)
87+
} else if adv.Supports(capability.Sideband) {
88+
r.Capabilities.Set(capability.Sideband)
89+
}
90+
8591
if adv.Supports(capability.ThinPack) {
8692
r.Capabilities.Set(capability.ThinPack)
8793
}

plumbing/protocol/packp/ulreq_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func (s *UlReqSuite) TestNewUploadRequestFromCapabilities(c *C) {
2929

3030
r := NewUploadRequestFromCapabilities(cap)
3131
c.Assert(r.Capabilities.String(), Equals,
32-
"multi_ack_detailed thin-pack ofs-delta agent=go-git/4.x",
32+
"multi_ack_detailed side-band-64k thin-pack ofs-delta agent=go-git/4.x",
3333
)
3434
}
3535

plumbing/transport/common.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,6 @@ func transformSCPLikeIfNeeded(endpoint string) string {
131131
var UnsupportedCapabilities = []capability.Capability{
132132
capability.MultiACK,
133133
capability.MultiACKDetailed,
134-
capability.Sideband,
135-
capability.Sideband64k,
136134
capability.ThinPack,
137135
}
138136

plumbing/transport/http/fetch_pack.go

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"fmt"
66
"io"
77
"net/http"
8-
"strings"
8+
"strconv"
99

1010
"gopkg.in/src-d/go-git.v4/plumbing"
1111
"gopkg.in/src-d/go-git.v4/plumbing/format/pktline"
@@ -117,7 +117,7 @@ func (s *fetchPackSession) Close() error {
117117
return nil
118118
}
119119

120-
func (s *fetchPackSession) doRequest(method, url string, content *strings.Reader) (*http.Response, error) {
120+
func (s *fetchPackSession) doRequest(method, url string, content *bytes.Buffer) (*http.Response, error) {
121121
var body io.Reader
122122
if content != nil {
123123
body = content
@@ -144,44 +144,33 @@ func (s *fetchPackSession) doRequest(method, url string, content *strings.Reader
144144
return res, nil
145145
}
146146

147-
func (s *fetchPackSession) applyHeadersToRequest(req *http.Request, content *strings.Reader) {
147+
// it requires a bytes.Buffer, because we need to know the length
148+
func (s *fetchPackSession) applyHeadersToRequest(req *http.Request, content *bytes.Buffer) {
148149
req.Header.Add("User-Agent", "git/1.0")
149-
req.Header.Add("Host", "github.com")
150+
req.Header.Add("Host", s.endpoint.Host)
150151

151152
if content == nil {
152153
req.Header.Add("Accept", "*/*")
153-
} else {
154-
req.Header.Add("Accept", "application/x-git-upload-pack-result")
155-
req.Header.Add("Content-Type", "application/x-git-upload-pack-request")
156-
req.Header.Add("Content-Length", string(content.Len()))
154+
return
157155
}
156+
157+
req.Header.Add("Accept", "application/x-git-upload-pack-result")
158+
req.Header.Add("Content-Type", "application/x-git-upload-pack-request")
159+
req.Header.Add("Content-Length", strconv.Itoa(content.Len()))
158160
}
159161

160-
func uploadPackRequestToReader(r *packp.UploadPackRequest) (*strings.Reader, error) {
161-
var buf bytes.Buffer
162-
e := pktline.NewEncoder(&buf)
162+
func uploadPackRequestToReader(req *packp.UploadPackRequest) (*bytes.Buffer, error) {
163+
buf := bytes.NewBuffer(nil)
164+
e := pktline.NewEncoder(buf)
163165

164-
for _, want := range r.Wants {
165-
_ = e.Encodef("want %s\n", want)
166+
if err := req.UploadRequest.Encode(buf); err != nil {
167+
return nil, fmt.Errorf("sending upload-req message: %s", err)
166168
}
167169

168-
for _, have := range r.Haves {
169-
_ = e.Encodef("have %s\n", have)
170+
if err := req.UploadHaves.Encode(buf); err != nil {
171+
return nil, fmt.Errorf("sending haves message: %s", err)
170172
}
171173

172-
if r.Depth != nil {
173-
depth, ok := r.Depth.(packp.DepthCommits)
174-
if !ok {
175-
return nil, fmt.Errorf("only commit depth is supported")
176-
}
177-
178-
if depth != 0 {
179-
_ = e.Encodef("deepen %d\n", depth)
180-
}
181-
}
182-
183-
_ = e.Flush()
184174
_ = e.EncodeString("done\n")
185-
186-
return strings.NewReader(buf.String()), nil
175+
return buf, nil
187176
}

plumbing/transport/http/fetch_pack_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ func (s *FetchPackSuite) TestuploadPackRequestToReader(c *C) {
5151
c.Assert(err, IsNil)
5252
b, _ := ioutil.ReadAll(sr)
5353
c.Assert(string(b), Equals,
54-
"0032want d82f291cde9987322c8a0c81a325e1ba6159684c\n"+
55-
"0032want 2b41ef280fdb67a9b250678686a0c3e03b0a9989\n"+
54+
"0032want 2b41ef280fdb67a9b250678686a0c3e03b0a9989\n"+
55+
"0032want d82f291cde9987322c8a0c81a325e1ba6159684c\n0000"+
5656
"0032have 6ecf0ef2c2dffb796033e5a02219af86ec6584e5\n0000"+
5757
"0009done\n",
5858
)

remote.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"gopkg.in/src-d/go-git.v4/plumbing/format/packfile"
1111
"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp"
1212
"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/capability"
13+
"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/sideband"
1314
"gopkg.in/src-d/go-git.v4/plumbing/storer"
1415
"gopkg.in/src-d/go-git.v4/plumbing/transport"
1516
"gopkg.in/src-d/go-git.v4/plumbing/transport/client"
@@ -22,6 +23,7 @@ var NoErrAlreadyUpToDate = errors.New("already up-to-date")
2223
type Remote struct {
2324
c *config.RemoteConfig
2425
s Storer
26+
p sideband.Progress
2527

2628
// cache fields, there during the connection is open
2729
endpoint transport.Endpoint
@@ -31,8 +33,8 @@ type Remote struct {
3133
refs memory.ReferenceStorage
3234
}
3335

34-
func newRemote(s Storer, c *config.RemoteConfig) *Remote {
35-
return &Remote{s: s, c: c}
36+
func newRemote(s Storer, p sideband.Progress, c *config.RemoteConfig) *Remote {
37+
return &Remote{s: s, p: p, c: c}
3638
}
3739

3840
// Config return the config
@@ -125,7 +127,10 @@ func (r *Remote) Fetch(o *FetchOptions) (err error) {
125127
}
126128

127129
defer checkClose(reader, &err)
128-
if err := r.updateObjectStorage(reader); err != nil {
130+
131+
if err = r.updateObjectStorage(
132+
r.buildSidebandIfSupported(req.Capabilities, reader),
133+
); err != nil {
129134
return err
130135
}
131136

@@ -178,6 +183,10 @@ func (r *Remote) buildRequest(
178183
req.Capabilities.Set(capability.Shallow)
179184
}
180185

186+
if r.p == nil && r.advRefs.Capabilities.Supports(capability.NoProgress) {
187+
req.Capabilities.Set(capability.NoProgress)
188+
}
189+
181190
for _, ref := range refs {
182191
req.Wants = append(req.Wants, ref.Hash())
183192
}
@@ -221,6 +230,24 @@ func (r *Remote) updateObjectStorage(reader io.Reader) error {
221230
return err
222231
}
223232

233+
func (r *Remote) buildSidebandIfSupported(l *capability.List, reader io.Reader) io.Reader {
234+
var t sideband.Type
235+
236+
switch {
237+
case l.Supports(capability.Sideband):
238+
t = sideband.Sideband
239+
case l.Supports(capability.Sideband64k):
240+
t = sideband.Sideband64k
241+
default:
242+
return reader
243+
}
244+
245+
d := sideband.NewDemuxer(t, reader)
246+
d.Progress = r.p
247+
248+
return d
249+
}
250+
224251
func (r *Remote) updateLocalReferenceStorage(specs []config.RefSpec, refs []*plumbing.Reference) error {
225252
for _, spec := range specs {
226253
for _, ref := range refs {

0 commit comments

Comments
 (0)