diff options
author | Máximo Cuadros <mcuadros@gmail.com> | 2017-09-01 17:28:42 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-01 17:28:42 +0200 |
commit | c20028f6a4d0038d59898392aafe13baa9e84040 (patch) | |
tree | 49407f8b3b5aaef1c6a56363bdb1fc25cd56f5cb | |
parent | 8ce9f5f240730ce21f50e42409d17fac7d71e051 (diff) | |
parent | 76efca13092ba245caf15f232f467e68fa1f73ed (diff) | |
download | go-git-c20028f6a4d0038d59898392aafe13baa9e84040.tar.gz |
Merge pull request #573 from orirawlings/pushSideband
Add sideband support for push
-rw-r--r-- | options.go | 3 | ||||
-rw-r--r-- | plumbing/protocol/packp/updreq.go | 4 | ||||
-rw-r--r-- | plumbing/transport/http/receive_pack.go | 13 | ||||
-rw-r--r-- | plumbing/transport/internal/common/common.go | 18 | ||||
-rw-r--r-- | remote.go | 25 | ||||
-rw-r--r-- | repository_test.go | 41 | ||||
-rw-r--r-- | repository_unix_test.go | 11 | ||||
-rw-r--r-- | repository_windows_test.go | 9 |
8 files changed, 118 insertions, 6 deletions
@@ -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. diff --git a/plumbing/protocol/packp/updreq.go b/plumbing/protocol/packp/updreq.go index b246613..73be117 100644 --- a/plumbing/protocol/packp/updreq.go +++ b/plumbing/protocol/packp/updreq.go @@ -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 ( @@ -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. diff --git a/plumbing/transport/http/receive_pack.go b/plumbing/transport/http/receive_pack.go index b54b70f..d2dfeb7 100644 --- a/plumbing/transport/http/receive_pack.go +++ b/plumbing/transport/http/receive_pack.go @@ -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" ) @@ -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() diff --git a/plumbing/transport/internal/common/common.go b/plumbing/transport/internal/common/common.go index 2db8d54..598c6b1 100644 --- a/plumbing/transport/internal/common/common.go +++ b/plumbing/transport/internal/common/common.go @@ -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" ) @@ -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 } @@ -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 } @@ -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 } @@ -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, diff --git a/repository_test.go b/repository_test.go index e944251..6184949 100644 --- a/repository_test.go +++ b/repository_test.go @@ -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{ diff --git a/repository_unix_test.go b/repository_unix_test.go new file mode 100644 index 0000000..75682ae --- /dev/null +++ b/repository_unix_test.go @@ -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)) +} diff --git a/repository_windows_test.go b/repository_windows_test.go new file mode 100644 index 0000000..bec0acd --- /dev/null +++ b/repository_windows_test.go @@ -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)) +} |