aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing/transport/internal/common/common.go
diff options
context:
space:
mode:
authorSantiago M. Mola <santi@mola.io>2016-12-09 14:44:03 +0100
committerGitHub <noreply@github.com>2016-12-09 14:44:03 +0100
commit0e1a52757a3938e97cf7d31e0dff3c9949001763 (patch)
tree8b998fdc3eaaf6b2d6c69a125759a778664207a5 /plumbing/transport/internal/common/common.go
parent4f16cc925238aae81586e917d26b8ff6b6a340bd (diff)
downloadgo-git-0e1a52757a3938e97cf7d31e0dff3c9949001763.tar.gz
transport: add git-send-pack support to local/ssh. (#163)
* protocol/packp: add Packfile field to ReferenceUpdateRequest. * protocol/packp: add NewReferenceUpdateRequestFromCapabilities. * NewReferenceUpdateRequestFromCapabilities can be used to create a ReferenceUpdateRequest with initial capabilities compatible with the server. * protocol/packp: fix new line handling on report status. * transport/file: test error on unexisting command.
Diffstat (limited to 'plumbing/transport/internal/common/common.go')
-rw-r--r--plumbing/transport/internal/common/common.go55
1 files changed, 46 insertions, 9 deletions
diff --git a/plumbing/transport/internal/common/common.go b/plumbing/transport/internal/common/common.go
index 12f4995..f0e1691 100644
--- a/plumbing/transport/internal/common/common.go
+++ b/plumbing/transport/internal/common/common.go
@@ -15,6 +15,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/transport"
"gopkg.in/src-d/go-git.v4/utils/ioutil"
)
@@ -91,7 +92,7 @@ func (c *client) NewFetchPackSession(ep transport.Endpoint) (
func (c *client) NewSendPackSession(ep transport.Endpoint) (
transport.SendPackSession, error) {
- return nil, errors.New("git send-pack not supported")
+ return c.newSession(transport.ReceivePackServiceName, ep)
}
type session struct {
@@ -99,10 +100,11 @@ type session struct {
Stdout io.Reader
Command Command
- advRefs *packp.AdvRefs
- packRun bool
- finished bool
- errLines chan string
+ isReceivePack bool
+ advRefs *packp.AdvRefs
+ packRun bool
+ finished bool
+ errLines chan string
}
func (c *client) newSession(s string, ep transport.Endpoint) (*session, error) {
@@ -140,10 +142,11 @@ func (c *client) newSession(s string, ep transport.Endpoint) (*session, error) {
}()
return &session{
- Stdin: stdin,
- Stdout: stdout,
- Command: cmd,
- errLines: errLines,
+ Stdin: stdin,
+ Stdout: stdout,
+ Command: cmd,
+ errLines: errLines,
+ isReceivePack: s == transport.ReceivePackServiceName,
}, nil
}
@@ -174,6 +177,11 @@ func (s *session) AdvertisedReferences() (*packp.AdvRefs, error) {
// advertised-references message. But valid. That is, it
// includes at least a flush.
if err == packp.ErrEmptyAdvRefs {
+ // Empty repositories are valid for git-receive-pack.
+ if s.isReceivePack {
+ return ar, nil
+ }
+
if err := s.finish(); err != nil {
return nil, err
}
@@ -229,6 +237,35 @@ func (s *session) FetchPack(req *packp.UploadPackRequest) (*packp.UploadPackResp
return DecodeUploadPackResponse(rc, req)
}
+func (s *session) SendPack(req *packp.ReferenceUpdateRequest) (*packp.ReportStatus, error) {
+ if _, err := s.AdvertisedReferences(); err != nil {
+ return nil, err
+ }
+
+ s.packRun = true
+
+ if err := req.Encode(s.Stdin); err != nil {
+ return nil, err
+ }
+
+ if !req.Capabilities.Supports(capability.ReportStatus) {
+ // If we have neither report-status or sideband, we can only
+ // check return value error.
+ return nil, s.Command.Wait()
+ }
+
+ report := packp.NewReportStatus()
+ if err := report.Decode(s.Stdout); err != nil {
+ return nil, err
+ }
+
+ if !report.Ok() {
+ return report, fmt.Errorf("report status: %s", report.UnpackStatus)
+ }
+
+ return report, s.Command.Wait()
+}
+
func (s *session) finish() error {
if s.finished {
return nil