aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlberto Cortés <alberto@sourced.tech>2015-12-17 18:01:38 +0100
committerAlberto Cortés <alberto@sourced.tech>2015-12-17 18:01:38 +0100
commitc8c4a69045f75e0a6dce601387bc2ff49f7c1e84 (patch)
tree1331275bfd4714a18ec9b3fa12ca31c80416c671
parentbf98b6096fd1e813ebadbb1f71d4b2d4e48bdb4b (diff)
downloadgo-git-c8c4a69045f75e0a6dce601387bc2ff49f7c1e84.tar.gz
Add install protocols capabilities to GitUploadPackService
-rw-r--r--clients/common.go60
-rw-r--r--clients/common_test.go62
-rw-r--r--clients/file/git_upload_pack.go29
-rw-r--r--clients/http/git_upload_pack.go3
-rw-r--r--clients/http/git_upload_pack_test.go12
-rw-r--r--clients/ssh/git_upload_pack.go3
-rw-r--r--clients/ssh/git_upload_pack_test.go32
-rw-r--r--remote.go6
8 files changed, 136 insertions, 71 deletions
diff --git a/clients/common.go b/clients/common.go
index b2e906d..ce36dd1 100644
--- a/clients/common.go
+++ b/clients/common.go
@@ -1,3 +1,14 @@
+// Go-git needs the packfile and the refs of the repo. The
+// `NewGitUploadPackService` function returns an object that allows to
+// download them.
+//
+// Go-git supports HTTP and SSH (see `KnownProtocols`) for downloading
+// the packfile and the refs, but you can also install your own
+// protocols (see `InstallProtocol` below).
+//
+// Each protocol has its own implementation of
+// `NewGitUploadPackService`, but you should generally not use them
+// directly, use this package's `NewGitUploadPackService` instead.
package clients
import (
@@ -5,27 +16,54 @@ import (
"net/url"
"gopkg.in/src-d/go-git.v2/clients/common"
- "gopkg.in/src-d/go-git.v2/clients/file"
"gopkg.in/src-d/go-git.v2/clients/http"
"gopkg.in/src-d/go-git.v2/clients/ssh"
)
+// ServiceFromURLFunc defines a service returning function for a given
+// URL.
+type ServiceFromURLFunc func(url string) common.GitUploadPackService
+
+// DefaultProtocols are the protocols supported by default.
+// Wrapping is needed because you can not cast a function that
+// returns an implementation of an interface to a function that
+// returns the interface.
+var DefaultProtocols = map[string]ServiceFromURLFunc{
+ "http": func(s string) common.GitUploadPackService { return http.NewGitUploadPackService(s) },
+ "https": func(s string) common.GitUploadPackService { return http.NewGitUploadPackService(s) },
+ "ssh": func(s string) common.GitUploadPackService { return ssh.NewGitUploadPackService(s) },
+}
+
+// KnownProtocols holds the current set of known protocols. Initially
+// it gets its contents from `DefaultProtocols`. See `InstallProtocol`
+// below to add or modify this variable.
+var KnownProtocols = make(map[string]ServiceFromURLFunc, len(DefaultProtocols))
+
+func init() {
+ for k, v := range DefaultProtocols {
+ KnownProtocols[k] = v
+ }
+}
+
// NewGitUploadPackService returns the appropiate upload pack service
-// among of the set of supported protocols: HTTP, SSH or file.
-// TODO: should this get a scheme as an argument instead of an URL?
+// among of the set of known protocols: HTTP, SSH. See `InstallProtocol`
+// to add or modify protocols.
func NewGitUploadPackService(repoURL string) (common.GitUploadPackService, error) {
u, err := url.Parse(repoURL)
if err != nil {
return nil, fmt.Errorf("invalid url %q", repoURL)
}
- switch u.Scheme {
- case "http", "https":
- return http.NewGitUploadPackService(), nil
- case "ssh":
- return ssh.NewGitUploadPackService(), nil
- case "file":
- return file.NewGitUploadPackService(), nil
- default:
+ srvFn, ok := KnownProtocols[u.Scheme]
+ if !ok {
return nil, fmt.Errorf("unsupported scheme %q", u.Scheme)
}
+ return srvFn(repoURL), nil
+}
+
+// InstallProtocol adds or modifies an existing protocol.
+func InstallProtocol(scheme string, serviceFn ServiceFromURLFunc) {
+ if serviceFn == nil {
+ panic("nil service")
+ }
+ KnownProtocols[scheme] = serviceFn
}
diff --git a/clients/common_test.go b/clients/common_test.go
index f8bcbd3..ff9ca32 100644
--- a/clients/common_test.go
+++ b/clients/common_test.go
@@ -2,9 +2,11 @@ package clients
import (
"fmt"
+ "io"
"testing"
. "gopkg.in/check.v1"
+ "gopkg.in/src-d/go-git.v2/clients/common"
)
func Test(t *testing.T) { TestingT(t) }
@@ -19,20 +21,68 @@ func (s *SuiteCommon) TestNewGitUploadPackService(c *C) {
err bool
expected string
}{
- {"ht/ml://example.com", true, "<nil>"},
- {"", true, "<nil>"},
- {"-", true, "<nil>"},
- {"!@", true, "<nil>"},
+ {"://example.com", true, "<nil>"},
{"badscheme://github.com/src-d/go-git", true, "<nil>"},
{"http://github.com/src-d/go-git", false, "*http.GitUploadPackService"},
{"https://github.com/src-d/go-git", false, "*http.GitUploadPackService"},
{"ssh://github.com/src-d/go-git", false, "*ssh.GitUploadPackService"},
- {"file://github.com/src-d/go-git", false, "*file.GitUploadPackService"},
}
for i, t := range tests {
output, err := NewGitUploadPackService(t.input)
c.Assert(err != nil, Equals, t.err, Commentf("%d) %q: wrong error value", i, t.input))
- c.Assert(fmt.Sprintf("%T", output), Equals, t.expected, Commentf("%d) %q: wrong type", i, t.input))
+ c.Assert(typeAsString(output), Equals, t.expected, Commentf("%d) %q: wrong type", i, t.input))
}
}
+
+type dummyProtocolService struct{}
+
+func newDummyProtocolService(url string) common.GitUploadPackService {
+ return &dummyProtocolService{}
+}
+
+func (s *dummyProtocolService) Connect(url common.Endpoint) error {
+ return nil
+}
+
+func (s *dummyProtocolService) ConnectWithAuth(url common.Endpoint, auth common.AuthMethod) error {
+ return nil
+}
+
+func (s *dummyProtocolService) Info() (*common.GitUploadPackInfo, error) {
+ return nil, nil
+}
+
+func (s *dummyProtocolService) Fetch(r *common.GitUploadPackRequest) (io.ReadCloser, error) {
+ return nil, nil
+}
+
+func (s *SuiteCommon) TestInstallProtocol(c *C) {
+ var tests = [...]struct {
+ scheme string
+ serviceFn ServiceFromURLFunc
+ panic bool
+ }{
+ {"panic", nil, true},
+ {"newscheme", newDummyProtocolService, false},
+ {"http", newDummyProtocolService, false},
+ }
+
+ for i, t := range tests {
+ if t.panic {
+ fmt.Println(t.serviceFn == nil)
+ c.Assert(func() { InstallProtocol(t.scheme, t.serviceFn) }, PanicMatches, `nil service`)
+ continue
+ }
+ InstallProtocol(t.scheme, t.serviceFn)
+ c.Assert(typeAsString(KnownProtocols[t.scheme]), Equals, typeAsString(t.serviceFn), Commentf("%d) wrong service", i))
+ // reset to default protocols after installing
+ if v, ok := DefaultProtocols[t.scheme]; ok {
+ InstallProtocol(t.scheme, v)
+ }
+ }
+}
+
+func typeAsString(v interface{}) string {
+ return fmt.Sprintf("%T", v)
+}
diff --git a/clients/file/git_upload_pack.go b/clients/file/git_upload_pack.go
deleted file mode 100644
index 34ee958..0000000
--- a/clients/file/git_upload_pack.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package file
-
-import (
- "io"
-
- "gopkg.in/src-d/go-git.v2/clients/common"
-)
-
-type GitUploadPackService struct{}
-
-func NewGitUploadPackService() *GitUploadPackService {
- return &GitUploadPackService{}
-}
-
-func (s *GitUploadPackService) Connect(url common.Endpoint) error {
- return nil
-}
-
-func (s *GitUploadPackService) ConnectWithAuth(url common.Endpoint, auth common.AuthMethod) error {
- return nil
-}
-
-func (s *GitUploadPackService) Info() (*common.GitUploadPackInfo, error) {
- return nil, nil
-}
-
-func (s *GitUploadPackService) Fetch(r *common.GitUploadPackRequest) (io.ReadCloser, error) {
- return nil, nil
-}
diff --git a/clients/http/git_upload_pack.go b/clients/http/git_upload_pack.go
index 2d38d42..4b06c72 100644
--- a/clients/http/git_upload_pack.go
+++ b/clients/http/git_upload_pack.go
@@ -18,7 +18,8 @@ type GitUploadPackService struct {
auth HTTPAuthMethod
}
-func NewGitUploadPackService() *GitUploadPackService {
+func NewGitUploadPackService(url string) *GitUploadPackService {
+ // url ignored
return &GitUploadPackService{
Client: http.DefaultClient,
}
diff --git a/clients/http/git_upload_pack_test.go b/clients/http/git_upload_pack_test.go
index f9ec424..b479155 100644
--- a/clients/http/git_upload_pack_test.go
+++ b/clients/http/git_upload_pack_test.go
@@ -15,13 +15,13 @@ var _ = Suite(&SuiteRemote{})
const RepositoryFixture = "https://github.com/tyba/git-fixture"
func (s *SuiteRemote) TestConnect(c *C) {
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(RepositoryFixture)
c.Assert(r.Connect(RepositoryFixture), IsNil)
}
func (s *SuiteRemote) TestConnectWithAuth(c *C) {
auth := &BasicAuth{}
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(RepositoryFixture)
c.Assert(r.ConnectWithAuth(RepositoryFixture, auth), IsNil)
c.Assert(r.auth, Equals, auth)
}
@@ -32,12 +32,12 @@ func (*mockAuth) Name() string { return "" }
func (*mockAuth) String() string { return "" }
func (s *SuiteRemote) TestConnectWithAuthWrongType(c *C) {
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(RepositoryFixture)
c.Assert(r.ConnectWithAuth(RepositoryFixture, &mockAuth{}), Equals, InvalidAuthMethodErr)
}
func (s *SuiteRemote) TestDefaultBranch(c *C) {
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(RepositoryFixture)
c.Assert(r.Connect(RepositoryFixture), IsNil)
info, err := r.Info()
@@ -46,7 +46,7 @@ func (s *SuiteRemote) TestDefaultBranch(c *C) {
}
func (s *SuiteRemote) TestCapabilities(c *C) {
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(RepositoryFixture)
c.Assert(r.Connect(RepositoryFixture), IsNil)
info, err := r.Info()
@@ -55,7 +55,7 @@ func (s *SuiteRemote) TestCapabilities(c *C) {
}
func (s *SuiteRemote) TestFetch(c *C) {
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(RepositoryFixture)
c.Assert(r.Connect(RepositoryFixture), IsNil)
req := &common.GitUploadPackRequest{}
diff --git a/clients/ssh/git_upload_pack.go b/clients/ssh/git_upload_pack.go
index 09cb5ab..4a4021d 100644
--- a/clients/ssh/git_upload_pack.go
+++ b/clients/ssh/git_upload_pack.go
@@ -42,7 +42,8 @@ type GitUploadPackService struct {
// NewGitUploadPackService initialises a GitUploadPackService.
// TODO: remove this, as the struct is zero-value safe.
-func NewGitUploadPackService() *GitUploadPackService {
+func NewGitUploadPackService(url string) *GitUploadPackService {
+ // url ignored
return &GitUploadPackService{}
}
diff --git a/clients/ssh/git_upload_pack_test.go b/clients/ssh/git_upload_pack_test.go
index 66ac306..8626b50 100644
--- a/clients/ssh/git_upload_pack_test.go
+++ b/clients/ssh/git_upload_pack_test.go
@@ -25,7 +25,7 @@ const (
)
func (s *SuiteRemote) TestConnect(c *C) {
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(fixRepo)
c.Assert(r.Connect(fixRepo), Equals, ErrAuthRequired)
}
@@ -62,7 +62,7 @@ func (s *SuiteRemote) TestConnectWithPublicKeysCallback(c *C) {
c.Assert(err, IsNil)
defer func() { c.Assert(agent.close(), IsNil) }()
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(fixRepo)
c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
defer func() { c.Assert(r.Disconnect(), IsNil) }()
c.Assert(r.connected, Equals, true)
@@ -70,17 +70,17 @@ func (s *SuiteRemote) TestConnectWithPublicKeysCallback(c *C) {
}
func (s *SuiteRemote) TestConnectBadVcs(c *C) {
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(fixRepoBadVcs)
c.Assert(r.ConnectWithAuth(fixRepoBadVcs, nil), ErrorMatches, fmt.Sprintf(".*%s.*", fixRepoBadVcs))
}
func (s *SuiteRemote) TestConnectNonGit(c *C) {
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(fixRepoNonGit)
c.Assert(r.ConnectWithAuth(fixRepoNonGit, nil), Equals, ErrUnsupportedVCS)
}
func (s *SuiteRemote) TestConnectNonGithub(c *C) {
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(fixGitRepoNonGithub)
c.Assert(r.ConnectWithAuth(fixGitRepoNonGithub, nil), Equals, ErrUnsupportedRepo)
}
@@ -92,7 +92,7 @@ func (*mockAuth) Name() string { return "" }
func (*mockAuth) String() string { return "" }
func (s *SuiteRemote) TestConnectWithAuthWrongType(c *C) {
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(fixRepo)
c.Assert(r.ConnectWithAuth(fixRepo, &mockAuth{}), Equals, ErrInvalidAuthMethod)
c.Assert(r.connected, Equals, false)
}
@@ -102,7 +102,7 @@ func (s *SuiteRemote) TestAlreadyConnected(c *C) {
c.Assert(err, IsNil)
defer func() { c.Assert(agent.close(), IsNil) }()
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(fixRepo)
c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
defer func() { c.Assert(r.Disconnect(), IsNil) }()
c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), Equals, ErrAlreadyConnected)
@@ -114,14 +114,14 @@ func (s *SuiteRemote) TestDisconnect(c *C) {
c.Assert(err, IsNil)
defer func() { c.Assert(agent.close(), IsNil) }()
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(fixRepo)
c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
c.Assert(r.Disconnect(), IsNil)
c.Assert(r.connected, Equals, false)
}
func (s *SuiteRemote) TestDisconnectedWhenNonConnected(c *C) {
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService("Dear Twinkle")
c.Assert(r.Disconnect(), Equals, ErrNotConnected)
}
@@ -130,7 +130,7 @@ func (s *SuiteRemote) TestAlreadyDisconnected(c *C) {
c.Assert(err, IsNil)
defer func() { c.Assert(agent.close(), IsNil) }()
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(fixRepo)
c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
c.Assert(r.Disconnect(), IsNil)
c.Assert(r.Disconnect(), Equals, ErrNotConnected)
@@ -142,7 +142,7 @@ func (s *SuiteRemote) TestServeralConnections(c *C) {
c.Assert(err, IsNil)
defer func() { c.Assert(agent.close(), IsNil) }()
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(fixRepo)
c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
c.Assert(r.Disconnect(), IsNil)
@@ -158,7 +158,7 @@ func (s *SuiteRemote) TestServeralConnections(c *C) {
}
func (s *SuiteRemote) TestInfoNotConnected(c *C) {
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(fixRepo)
_, err := r.Info()
c.Assert(err, Equals, ErrNotConnected)
}
@@ -168,7 +168,7 @@ func (s *SuiteRemote) TestDefaultBranch(c *C) {
c.Assert(err, IsNil)
defer func() { c.Assert(agent.close(), IsNil) }()
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(fixRepo)
c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
defer func() { c.Assert(r.Disconnect(), IsNil) }()
@@ -182,7 +182,7 @@ func (s *SuiteRemote) TestCapabilities(c *C) {
c.Assert(err, IsNil)
defer func() { c.Assert(agent.close(), IsNil) }()
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(fixRepo)
c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
defer func() { c.Assert(r.Disconnect(), IsNil) }()
@@ -192,7 +192,7 @@ func (s *SuiteRemote) TestCapabilities(c *C) {
}
func (s *SuiteRemote) TestFetchNotConnected(c *C) {
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService("foo bar")
pr := &common.GitUploadPackRequest{}
pr.Want(core.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"))
_, err := r.Fetch(pr)
@@ -204,7 +204,7 @@ func (s *SuiteRemote) TestFetch(c *C) {
c.Assert(err, IsNil)
defer func() { c.Assert(agent.close(), IsNil) }()
- r := NewGitUploadPackService()
+ r := NewGitUploadPackService(fixRepo)
c.Assert(r.ConnectWithAuth(fixRepo, agent.auth), IsNil)
defer func() { c.Assert(r.Disconnect(), IsNil) }()
diff --git a/remote.go b/remote.go
index e28a3b0..685b8a8 100644
--- a/remote.go
+++ b/remote.go
@@ -30,10 +30,14 @@ func NewAuthenticatedRemote(url string, auth common.AuthMethod) (*Remote, error)
return nil, err
}
+ upSrv, err := clients.NewGitUploadPackService(url)
+ if err != nil {
+ return nil, err
+ }
return &Remote{
Endpoint: end,
Auth: auth,
- upSrv: clients.NewGitUploadPackService(),
+ upSrv: upSrv,
}, nil
}