diff options
author | Santiago M. Mola <santi@mola.io> | 2016-11-29 15:07:09 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-11-29 15:07:09 +0100 |
commit | 47007c70c5a696472576a522cd0e265a777f97a8 (patch) | |
tree | 2f49e52f42556a3707c24a263a571bcae39cfac6 /plumbing/transport/ssh/common.go | |
parent | 2c20b7e507a6514be2efa66143c13a60a87ee4b6 (diff) | |
download | go-git-47007c70c5a696472576a522cd0e265a777f97a8.tar.gz |
transport: add local transport (#145)
* transport: move common packp protocol out of ssh transport.
* fixtures: add fixture for empty repository.
* transport: add file:// transport
Diffstat (limited to 'plumbing/transport/ssh/common.go')
-rw-r--r-- | plumbing/transport/ssh/common.go | 139 |
1 files changed, 47 insertions, 92 deletions
diff --git a/plumbing/transport/ssh/common.go b/plumbing/transport/ssh/common.go index c327c41..a88a328 100644 --- a/plumbing/transport/ssh/common.go +++ b/plumbing/transport/ssh/common.go @@ -3,10 +3,10 @@ package ssh import ( "errors" "fmt" - "io" "strings" "gopkg.in/src-d/go-git.v4/plumbing/transport" + "gopkg.in/src-d/go-git.v4/plumbing/transport/internal/common" "golang.org/x/crypto/ssh" ) @@ -15,155 +15,110 @@ var ( errAlreadyConnected = errors.New("ssh session already created") ) -type client struct{} - // DefaultClient is the default SSH client. -var DefaultClient = &client{} - -func (c *client) NewFetchPackSession(ep transport.Endpoint) ( - transport.FetchPackSession, error) { +var DefaultClient = common.NewClient(&runner{}) - return newFetchPackSession(ep) -} +type runner struct{} -func (c *client) NewSendPackSession(ep transport.Endpoint) ( - transport.SendPackSession, error) { +func (r *runner) Command(cmd string, ep transport.Endpoint) (common.Command, error) { + c := &command{command: cmd, endpoint: ep} + if err := c.connect(); err != nil { + return nil, err + } - return newSendPackSession(ep) + return c, nil } -type session struct { - connected bool - endpoint transport.Endpoint - client *ssh.Client - session *ssh.Session - stdin io.WriteCloser - stdout io.Reader - stderr io.Reader - sessionDone chan error - auth AuthMethod +type command struct { + *ssh.Session + connected bool + command string + endpoint transport.Endpoint + client *ssh.Client + auth AuthMethod } -func (s *session) SetAuth(auth transport.AuthMethod) error { +func (c *command) SetAuth(auth transport.AuthMethod) error { a, ok := auth.(AuthMethod) if !ok { return transport.ErrInvalidAuthMethod } - s.auth = a + c.auth = a return nil } -// Close closes the SSH session. -func (s *session) Close() error { - if !s.connected { +func (c *command) Start() error { + return c.Session.Start(endpointToCommand(c.command, c.endpoint)) +} + +// Close closes the SSH session and connection. +func (c *command) Close() error { + if !c.connected { return nil } - s.connected = false + c.connected = false //XXX: If did read the full packfile, then the session might be already // closed. - _ = s.session.Close() + _ = c.Session.Close() - return s.client.Close() + return c.client.Close() } -// ensureConnected connects to the SSH server, unless a AuthMethod was set with +// connect connects to the SSH server, unless a AuthMethod was set with // SetAuth method, by default uses an auth method based on PublicKeysCallback, // it connects to a SSH agent, using the address stored in the SSH_AUTH_SOCK // environment var. -func (s *session) connect() error { - if s.connected { +func (c *command) connect() error { + if c.connected { return errAlreadyConnected } - if err := s.setAuthFromEndpoint(); err != nil { + if err := c.setAuthFromEndpoint(); err != nil { return err } var err error - s.client, err = ssh.Dial("tcp", s.getHostWithPort(), s.auth.clientConfig()) + c.client, err = ssh.Dial("tcp", c.getHostWithPort(), c.auth.clientConfig()) if err != nil { return err } - if err := s.openSSHSession(); err != nil { - _ = s.client.Close() + c.Session, err = c.client.NewSession() + if err != nil { + _ = c.client.Close() return err } - s.connected = true + c.connected = true return nil } -func (s *session) getHostWithPort() string { - host := s.endpoint.Host - if strings.Index(s.endpoint.Host, ":") == -1 { +func (c *command) getHostWithPort() string { + host := c.endpoint.Host + if strings.Index(c.endpoint.Host, ":") == -1 { host += ":22" } return host } -func (s *session) setAuthFromEndpoint() error { +func (c *command) setAuthFromEndpoint() error { var u string - if info := s.endpoint.User; info != nil { + if info := c.endpoint.User; info != nil { u = info.Username() } var err error - s.auth, err = NewSSHAgentAuth(u) + c.auth, err = NewSSHAgentAuth(u) return err } -func (s *session) openSSHSession() error { - var err error - s.session, err = s.client.NewSession() - if err != nil { - return fmt.Errorf("cannot open SSH session: %s", err) - } - - s.stdin, err = s.session.StdinPipe() - if err != nil { - return fmt.Errorf("cannot pipe remote stdin: %s", err) - } - - s.stdout, err = s.session.StdoutPipe() - if err != nil { - return fmt.Errorf("cannot pipe remote stdout: %s", err) - } - - s.stderr, err = s.session.StderrPipe() - if err != nil { - return fmt.Errorf("cannot pipe remote stderr: %s", err) - } - - return nil -} - -func (s *session) runCommand(cmd string) chan error { - done := make(chan error) - go func() { - done <- s.session.Run(cmd) - }() - - return done -} - -const ( - githubRepoNotFoundErr = "ERROR: Repository not found." - bitbucketRepoNotFoundErr = "conq: repository does not exist." -) - -func isRepoNotFoundError(s string) bool { - if strings.HasPrefix(s, githubRepoNotFoundErr) { - return true - } - - if strings.HasPrefix(s, bitbucketRepoNotFoundErr) { - return true - } +func endpointToCommand(cmd string, ep transport.Endpoint) string { + directory := ep.Path + directory = directory[1:] - return false + return fmt.Sprintf("%s '%s'", cmd, directory) } |