aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clients/common/common.go2
-rw-r--r--clients/common_test.go2
-rw-r--r--clients/http/common.go7
-rw-r--r--clients/http/git_upload_pack.go31
-rw-r--r--clients/http/git_upload_pack_test.go21
-rw-r--r--clients/ssh/auth_method.go10
-rw-r--r--clients/ssh/git_upload_pack.go96
-rw-r--r--clients/ssh/git_upload_pack_test.go4
-rw-r--r--common_test.go3
9 files changed, 115 insertions, 61 deletions
diff --git a/clients/common/common.go b/clients/common/common.go
index 0d0026b..b5e6152 100644
--- a/clients/common/common.go
+++ b/clients/common/common.go
@@ -26,7 +26,7 @@ const GitUploadPackServiceName = "git-upload-pack"
type GitUploadPackService interface {
Connect() error
- ConnectWithAuth(AuthMethod) error
+ SetAuth(AuthMethod) error
Info() (*GitUploadPackInfo, error)
Fetch(*GitUploadPackRequest) (io.ReadCloser, error)
Disconnect() error
diff --git a/clients/common_test.go b/clients/common_test.go
index 0381f63..59fc300 100644
--- a/clients/common_test.go
+++ b/clients/common_test.go
@@ -64,7 +64,7 @@ func (s *dummyProtocolService) Connect() error {
return nil
}
-func (s *dummyProtocolService) ConnectWithAuth(auth common.AuthMethod) error {
+func (s *dummyProtocolService) SetAuth(auth common.AuthMethod) error {
return nil
}
diff --git a/clients/http/common.go b/clients/http/common.go
index 703208b..483308a 100644
--- a/clients/http/common.go
+++ b/clients/http/common.go
@@ -9,15 +9,18 @@ import (
"gopkg.in/src-d/go-git.v4/core"
)
+// HTTPAuthMethod concrete implementation of common.AuthMethod for HTTP services
type HTTPAuthMethod interface {
common.AuthMethod
setAuth(r *http.Request)
}
+// BasicAuth represent a HTTP basic auth
type BasicAuth struct {
username, password string
}
+// NewBasicAuth returns a BasicAuth base on the given user and password
func NewBasicAuth(username, password string) *BasicAuth {
return &BasicAuth{username, password}
}
@@ -26,6 +29,7 @@ func (a *BasicAuth) setAuth(r *http.Request) {
r.SetBasicAuth(a.username, a.password)
}
+// Name name of the auth
func (a *BasicAuth) Name() string {
return "http-basic-auth"
}
@@ -39,10 +43,12 @@ func (a *BasicAuth) String() string {
return fmt.Sprintf("%s - %s:%s", a.Name(), a.username, masked)
}
+// HTTPError a dedicated error to return errors bases on status codes
type HTTPError struct {
Response *http.Response
}
+// NewHTTPError returns a new HTTPError based on a http response
func NewHTTPError(r *http.Response) error {
if r.StatusCode >= 200 && r.StatusCode < 300 {
return nil
@@ -59,6 +65,7 @@ func NewHTTPError(r *http.Response) error {
return core.NewUnexpectedError(err)
}
+// StatusCode returns the status code of the response
func (e *HTTPError) StatusCode() int {
return e.Response.StatusCode
}
diff --git a/clients/http/git_upload_pack.go b/clients/http/git_upload_pack.go
index bca4534..888d279 100644
--- a/clients/http/git_upload_pack.go
+++ b/clients/http/git_upload_pack.go
@@ -12,24 +12,47 @@ import (
"gopkg.in/src-d/go-git.v4/formats/pktline"
)
+// GitUploadPackService git-upoad-pack service over HTTP
type GitUploadPackService struct {
client *http.Client
endpoint common.Endpoint
auth HTTPAuthMethod
}
+// NewGitUploadPackService connects to a git-upload-pack service over HTTP, the
+// auth is extracted from the URL, or can be provided using the SetAuth method
func NewGitUploadPackService(endpoint common.Endpoint) common.GitUploadPackService {
- return &GitUploadPackService{
+ s := &GitUploadPackService{
client: http.DefaultClient,
endpoint: endpoint,
}
+
+ s.setBasicAuthFromEndpoint()
+ return s
}
+// Connect has not any effect, is here just for meet the interface
func (s *GitUploadPackService) Connect() error {
return nil
}
-func (s *GitUploadPackService) ConnectWithAuth(auth common.AuthMethod) error {
+func (s *GitUploadPackService) setBasicAuthFromEndpoint() {
+ info := s.endpoint.User
+ if info == nil {
+ return
+ }
+
+ p, ok := info.Password()
+ if !ok {
+ return
+ }
+
+ u := info.Username()
+ s.auth = NewBasicAuth(u, p)
+}
+
+// SetAuth sets the AuthMethod
+func (s *GitUploadPackService) SetAuth(auth common.AuthMethod) error {
httpAuth, ok := auth.(HTTPAuthMethod)
if !ok {
return common.ErrInvalidAuthMethod
@@ -39,6 +62,7 @@ func (s *GitUploadPackService) ConnectWithAuth(auth common.AuthMethod) error {
return nil
}
+// Info returns the references info and capabilities from the service
func (s *GitUploadPackService) Info() (*common.GitUploadPackInfo, error) {
url := fmt.Sprintf(
"%s/info/refs?service=%s",
@@ -56,6 +80,7 @@ func (s *GitUploadPackService) Info() (*common.GitUploadPackInfo, error) {
return i, i.Decode(pktline.NewDecoder(res.Body))
}
+// Fetch request and returns a reader to a packfile
func (s *GitUploadPackService) Fetch(r *common.GitUploadPackRequest) (io.ReadCloser, error) {
url := fmt.Sprintf(
"%s/%s",
@@ -98,6 +123,7 @@ func (s *GitUploadPackService) discardResponseInfo(r io.Reader) error {
return nil
}
+
func (s *GitUploadPackService) doRequest(method, url string, content *strings.Reader) (*http.Response, error) {
var body io.Reader
if content != nil {
@@ -145,6 +171,7 @@ func (s *GitUploadPackService) applyAuthToRequest(req *http.Request) {
s.auth.setAuth(req)
}
+// Disconnect do nothing
func (s *GitUploadPackService) Disconnect() (err error) {
return nil
}
diff --git a/clients/http/git_upload_pack_test.go b/clients/http/git_upload_pack_test.go
index e344a49..579419f 100644
--- a/clients/http/git_upload_pack_test.go
+++ b/clients/http/git_upload_pack_test.go
@@ -16,19 +16,30 @@ var _ = Suite(&RemoteSuite{})
func (s *RemoteSuite) SetUpSuite(c *C) {
var err error
- s.Endpoint, err = common.NewEndpoint("https://github.com/tyba/git-fixture")
+ s.Endpoint, err = common.NewEndpoint("https://github.com/git-fixtures/basic")
c.Assert(err, IsNil)
}
+func (s *RemoteSuite) TestNewGitUploadPackServiceAuth(c *C) {
+ e, err := common.NewEndpoint("https://foo:bar@github.com/git-fixtures/basic")
+ c.Assert(err, IsNil)
+
+ r := NewGitUploadPackService(e)
+ auth := r.(*GitUploadPackService).auth
+
+ c.Assert(auth.String(), Equals, "http-basic-auth - foo:*******")
+}
+
func (s *RemoteSuite) TestConnect(c *C) {
r := NewGitUploadPackService(s.Endpoint)
c.Assert(r.Connect(), IsNil)
}
-func (s *RemoteSuite) TestConnectWithAuth(c *C) {
+func (s *RemoteSuite) TestSetAuth(c *C) {
auth := &BasicAuth{}
r := NewGitUploadPackService(s.Endpoint)
- c.Assert(r.ConnectWithAuth(auth), IsNil)
+ r.SetAuth(auth)
+ c.Assert(auth, Equals, r.(*GitUploadPackService).auth)
}
type mockAuth struct{}
@@ -36,9 +47,9 @@ type mockAuth struct{}
func (*mockAuth) Name() string { return "" }
func (*mockAuth) String() string { return "" }
-func (s *RemoteSuite) TestConnectWithAuthWrongType(c *C) {
+func (s *RemoteSuite) TestSetAuthWrongType(c *C) {
r := NewGitUploadPackService(s.Endpoint)
- c.Assert(r.ConnectWithAuth(&mockAuth{}), Equals, common.ErrInvalidAuthMethod)
+ c.Assert(r.SetAuth(&mockAuth{}), Equals, common.ErrInvalidAuthMethod)
}
func (s *RemoteSuite) TestInfoEmpty(c *C) {
diff --git a/clients/ssh/auth_method.go b/clients/ssh/auth_method.go
index e55283e..1ce45ef 100644
--- a/clients/ssh/auth_method.go
+++ b/clients/ssh/auth_method.go
@@ -138,16 +138,22 @@ func (a *PublicKeysCallback) clientConfig() *ssh.ClientConfig {
}
}
+const DefaultSSHUsername = "git"
+
// Opens a pipe with the ssh agent and uses the pipe
// as the implementer of the public key callback function.
-func NewSSHAgentAuth() (*PublicKeysCallback, error) {
+func NewSSHAgentAuth(user string) (*PublicKeysCallback, error) {
+ if user == "" {
+ user = DefaultSSHUsername
+ }
+
pipe, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK"))
if err != nil {
return nil, err
}
return &PublicKeysCallback{
- User: "git",
+ User: user,
Callback: agent.NewClient(pipe).Signers,
}, nil
}
diff --git a/clients/ssh/git_upload_pack.go b/clients/ssh/git_upload_pack.go
index eb5926e..d83aadb 100644
--- a/clients/ssh/git_upload_pack.go
+++ b/clients/ssh/git_upload_pack.go
@@ -1,6 +1,4 @@
// Package ssh implements a ssh client for go-git.
-//
-// The Connect() method is not allowed in ssh, use ConnectWithAuth() instead.
package ssh
import (
@@ -10,13 +8,12 @@ import (
"fmt"
"io"
"io/ioutil"
- "net/url"
+ "strings"
"gopkg.in/src-d/go-git.v4/clients/common"
"gopkg.in/src-d/go-git.v4/formats/pktline"
"golang.org/x/crypto/ssh"
- "gopkg.in/sourcegraph/go-vcsurl.v1"
)
// New errors introduced by this package.
@@ -32,79 +29,79 @@ var (
// GitUploadPackService holds the service information.
// The zero value is safe to use.
-// TODO: remove NewGitUploadPackService().
type GitUploadPackService struct {
connected bool
endpoint common.Endpoint
- vcs *vcsurl.RepoInfo
client *ssh.Client
auth AuthMethod
}
-// NewGitUploadPackService initialises a GitUploadPackService.
+// NewGitUploadPackService initialises a GitUploadPackService,
func NewGitUploadPackService(endpoint common.Endpoint) common.GitUploadPackService {
return &GitUploadPackService{endpoint: endpoint}
}
-// Connect cannot be used with SSH clients and always return
-// ErrAuthRequired. Use ConnectWithAuth instead.
+// 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 *GitUploadPackService) Connect() error {
- auth, err := NewSSHAgentAuth()
- if err != nil {
- return err
- }
-
- return s.ConnectWithAuth(auth)
-}
-
-// ConnectWithAuth connects to ep using SSH. Authentication is handled
-// by auth.
-func (s *GitUploadPackService) ConnectWithAuth(auth common.AuthMethod) (err error) {
if s.connected {
return ErrAlreadyConnected
}
- s.vcs, err = vcsurl.Parse(s.endpoint.String())
- if err != nil {
+ if err := s.setAuthFromEndpoint(); err != nil {
return err
}
- url, err := vcsToURL(s.vcs)
+ var err error
+ s.client, err = ssh.Dial("tcp", s.getHostWithPort(), s.auth.clientConfig())
if err != nil {
- return
+ return err
}
- var ok bool
- s.auth, ok = auth.(AuthMethod)
- if !ok {
- return ErrInvalidAuthMethod
+ s.connected = true
+ return nil
+}
+
+func (s *GitUploadPackService) getHostWithPort() string {
+ host := s.endpoint.Host
+ if strings.Index(s.endpoint.Host, ":") == -1 {
+ host += ":22"
}
- s.client, err = ssh.Dial("tcp", url.Host, s.auth.clientConfig())
+ return host
+}
+
+func (s *GitUploadPackService) setAuthFromEndpoint() error {
+ var u string
+ if info := s.endpoint.User; info != nil {
+ u = info.Username()
+ }
+
+ var err error
+ s.auth, err = NewSSHAgentAuth(u)
if err != nil {
return err
}
- s.connected = true
- return
+ return nil
}
-func vcsToURL(vcs *vcsurl.RepoInfo) (u *url.URL, err error) {
- if vcs.VCS != vcsurl.Git {
- return nil, ErrUnsupportedVCS
- }
- if vcs.RepoHost != vcsurl.GitHub {
- return nil, ErrUnsupportedRepo
+// SetAuth sets the AuthMethod
+func (s *GitUploadPackService) SetAuth(auth common.AuthMethod) error {
+ var ok bool
+ s.auth, ok = auth.(AuthMethod)
+ if !ok {
+ return ErrInvalidAuthMethod
}
- s := "ssh://git@" + string(vcs.RepoHost) + ":22/" + vcs.FullName
- u, err = url.Parse(s)
- return
+
+ return nil
}
-// Info returns the GitUploadPackInfo of the repository.
-// The client must be connected with the repository (using
-// the ConnectWithAuth() method) before using this
-// method.
+// Info returns the GitUploadPackInfo of the repository. The client must be
+// connected with the repository (using the ConnectWithAuth() method) before
+// using this method.
func (s *GitUploadPackService) Info() (i *common.GitUploadPackInfo, err error) {
if !s.connected {
return nil, ErrNotConnected
@@ -120,7 +117,7 @@ func (s *GitUploadPackService) Info() (i *common.GitUploadPackInfo, err error) {
_ = session.Close()
}()
- out, err := session.Output("git-upload-pack " + s.vcs.FullName + ".git")
+ out, err := session.Output(s.getCommand())
if err != nil {
return nil, err
}
@@ -169,7 +166,7 @@ func (s *GitUploadPackService) Fetch(r *common.GitUploadPackRequest) (rc io.Read
return nil, err
}
- if err := session.Start("git-upload-pack " + s.vcs.FullName + ".git"); err != nil {
+ if err := session.Start(s.getCommand()); err != nil {
return nil, err
}
@@ -209,3 +206,10 @@ func (s *GitUploadPackService) Fetch(r *common.GitUploadPackRequest) (rc io.Read
buf := bytes.NewBuffer(data)
return ioutil.NopCloser(buf), nil
}
+
+func (s *GitUploadPackService) getCommand() string {
+ directory := s.endpoint.Path
+ directory = directory[1:len(directory)]
+
+ return fmt.Sprintf("git-upload-pack %s", directory)
+}
diff --git a/clients/ssh/git_upload_pack_test.go b/clients/ssh/git_upload_pack_test.go
index b26276d..0785af5 100644
--- a/clients/ssh/git_upload_pack_test.go
+++ b/clients/ssh/git_upload_pack_test.go
@@ -32,9 +32,9 @@ type mockAuth struct{}
func (*mockAuth) Name() string { return "" }
func (*mockAuth) String() string { return "" }
-func (s *RemoteSuite) TestConnectWithAuthWrongType(c *C) {
+func (s *RemoteSuite) TestSetAuthWrongType(c *C) {
r := NewGitUploadPackService(s.Endpoint)
- c.Assert(r.ConnectWithAuth(&mockAuth{}), Equals, ErrInvalidAuthMethod)
+ c.Assert(r.SetAuth(&mockAuth{}), Equals, ErrInvalidAuthMethod)
}
func (s *RemoteSuite) TestAlreadyConnected(c *C) {
diff --git a/common_test.go b/common_test.go
index e02e9d6..42b3310 100644
--- a/common_test.go
+++ b/common_test.go
@@ -45,8 +45,7 @@ func (p *MockGitUploadPackService) Connect() error {
return nil
}
-func (p *MockGitUploadPackService) ConnectWithAuth(auth common.AuthMethod) error {
- p.connected = true
+func (p *MockGitUploadPackService) SetAuth(auth common.AuthMethod) error {
p.auth = auth
return nil
}