Skip to content

Commit

Permalink
Add sideband support for push
Browse files Browse the repository at this point in the history
  • Loading branch information
orirawlings committed Sep 1, 2017
1 parent 3ca3702 commit 76efca1
Show file tree
Hide file tree
Showing 8 changed files with 118 additions and 6 deletions.
3 changes: 3 additions & 0 deletions options.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ type PushOptions struct {
RefSpecs []config.RefSpec
// Auth credentials, if required, to use with the remote repository.
Auth transport.AuthMethod
// Progress is where the human readable information sent by the server is
// stored, if nil nothing is stored.
Progress sideband.Progress
}

// Validate validates the fields and sets the default values.
Expand Down
4 changes: 4 additions & 0 deletions plumbing/protocol/packp/updreq.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"gopkg.in/src-d/go-git.v4/plumbing"
"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/capability"
"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/sideband"
)

var (
Expand All @@ -21,6 +22,9 @@ type ReferenceUpdateRequest struct {
Shallow *plumbing.Hash
// Packfile contains an optional packfile reader.
Packfile io.ReadCloser

// Progress receives sideband progress messages from the server
Progress sideband.Progress
}

// New returns a pointer to a new ReferenceUpdateRequest value.
Expand Down
13 changes: 13 additions & 0 deletions plumbing/transport/http/receive_pack.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (

"gopkg.in/src-d/go-git.v4/plumbing"
"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp"
"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/capability"
"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/sideband"
"gopkg.in/src-d/go-git.v4/plumbing/transport"
"gopkg.in/src-d/go-git.v4/utils/ioutil"
)
Expand Down Expand Up @@ -52,6 +54,17 @@ func (s *rpSession) ReceivePack(ctx context.Context, req *packp.ReferenceUpdateR
return nil, err
}

var d *sideband.Demuxer
if req.Capabilities.Supports(capability.Sideband64k) {
d = sideband.NewDemuxer(sideband.Sideband64k, r)
} else if req.Capabilities.Supports(capability.Sideband) {
d = sideband.NewDemuxer(sideband.Sideband, r)
}
if d != nil {
d.Progress = req.Progress
r = d
}

rc := ioutil.NewReadCloser(r, res.Body)

report := packp.NewReportStatus()
Expand Down
18 changes: 16 additions & 2 deletions plumbing/transport/internal/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"gopkg.in/src-d/go-git.v4/plumbing/format/pktline"
"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp"
"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/capability"
"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp/sideband"
"gopkg.in/src-d/go-git.v4/plumbing/transport"
"gopkg.in/src-d/go-git.v4/utils/ioutil"
)
Expand Down Expand Up @@ -298,13 +299,26 @@ func (s *session) ReceivePack(ctx context.Context, req *packp.ReferenceUpdateReq
}

if !req.Capabilities.Supports(capability.ReportStatus) {
// If we have neither report-status or sideband, we can only
// If we don't have report-status, we can only
// check return value error.
return nil, s.Command.Close()
}

r := s.StdoutContext(ctx)

var d *sideband.Demuxer
if req.Capabilities.Supports(capability.Sideband64k) {
d = sideband.NewDemuxer(sideband.Sideband64k, r)
} else if req.Capabilities.Supports(capability.Sideband) {
d = sideband.NewDemuxer(sideband.Sideband, r)
}
if d != nil {
d.Progress = req.Progress
r = d
}

report := packp.NewReportStatus()
if err := report.Decode(s.StdoutContext(ctx)); err != nil {
if err := report.Decode(r); err != nil {
return nil, err
}

Expand Down
25 changes: 21 additions & 4 deletions remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ func (r *Remote) Push(o *PushOptions) error {
// operation is complete, an error is returned. The context only affects to the
// transport operations.
func (r *Remote) PushContext(ctx context.Context, o *PushOptions) error {
// TODO: Sideband support
if err := o.Validate(); err != nil {
return err
}
Expand Down Expand Up @@ -108,9 +107,8 @@ func (r *Remote) PushContext(ctx context.Context, o *PushOptions) error {
return ErrDeleteRefNotSupported
}

req := packp.NewReferenceUpdateRequestFromCapabilities(ar.Capabilities)
if err := r.addReferencesToUpdate(o.RefSpecs, remoteRefs, req); err != nil {

req, err := r.newReferenceUpdateRequest(o, remoteRefs, ar)
if err != nil {
return err
}

Expand Down Expand Up @@ -158,6 +156,25 @@ func (r *Remote) PushContext(ctx context.Context, o *PushOptions) error {
return r.updateRemoteReferenceStorage(req, rs)
}

func (r *Remote) newReferenceUpdateRequest(o *PushOptions, remoteRefs storer.ReferenceStorer, ar *packp.AdvRefs) (*packp.ReferenceUpdateRequest, error) {
req := packp.NewReferenceUpdateRequestFromCapabilities(ar.Capabilities)

if o.Progress != nil {
req.Progress = o.Progress
if ar.Capabilities.Supports(capability.Sideband64k) {
req.Capabilities.Set(capability.Sideband64k)
} else if ar.Capabilities.Supports(capability.Sideband) {
req.Capabilities.Set(capability.Sideband)
}
}

if err := r.addReferencesToUpdate(o.RefSpecs, remoteRefs, req); err != nil {
return nil, err
}

return req, nil
}

func (r *Remote) updateRemoteReferenceStorage(
req *packp.ReferenceUpdateRequest,
result *packp.ReportStatus,
Expand Down
41 changes: 41 additions & 0 deletions repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,47 @@ func (s *RepositorySuite) TestPushContext(c *C) {
c.Assert(err, NotNil)
}

// installPreReceiveHook installs a pre-receive hook in the .git
// directory at path which prints message m before exiting
// successfully.
func installPreReceiveHook(c *C, path, m string) {
hooks := filepath.Join(path, "hooks")
err := os.MkdirAll(hooks, 0777)
c.Assert(err, IsNil)

err = ioutil.WriteFile(filepath.Join(hooks, "pre-receive"), preReceiveHook(m), 0777)
c.Assert(err, IsNil)
}

func (s *RepositorySuite) TestPushWithProgress(c *C) {
url := c.MkDir()
server, err := PlainInit(url, true)
c.Assert(err, IsNil)

m := "Receiving..."
installPreReceiveHook(c, url, m)

_, err = s.Repository.CreateRemote(&config.RemoteConfig{
Name: "bar",
URLs: []string{url},
})
c.Assert(err, IsNil)

var p bytes.Buffer
err = s.Repository.Push(&PushOptions{
RemoteName: "bar",
Progress: &p,
})
c.Assert(err, IsNil)

AssertReferences(c, server, map[string]string{
"refs/heads/master": "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
"refs/heads/branch": "e8d3ffab552895c19b9fcf7aa264d277cde33881",
})

c.Assert((&p).Bytes(), DeepEquals, []byte(m))
}

func (s *RepositorySuite) TestPushDepth(c *C) {
url := c.MkDir()
server, err := PlainClone(url, true, &CloneOptions{
Expand Down
11 changes: 11 additions & 0 deletions repository_unix_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// +build !plan9,!windows

package git

import "fmt"

// preReceiveHook returns the bytes of a pre-receive hook script
// that prints m before exiting successfully
func preReceiveHook(m string) []byte {
return []byte(fmt.Sprintf("#!/bin/sh\nprintf '%s'\n", m))
}
9 changes: 9 additions & 0 deletions repository_windows_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package git

import "fmt"

// preReceiveHook returns the bytes of a pre-receive hook script
// that prints m before exiting successfully
func preReceiveHook(m string) []byte {
return []byte(fmt.Sprintf("#!C:/Program\\ Files/Git/usr/bin/sh.exe\nprintf '%s'\n", m))
}

0 comments on commit 76efca1

Please sign in to comment.