This repository has been archived by the owner on Sep 11, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 540
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from alcortesm/file-client
Adds external protocol insertion for the clients and protocol selection based on the scheme
- Loading branch information
Showing
7 changed files
with
180 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,69 @@ | ||
// 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 ( | ||
"fmt" | ||
"net/url" | ||
|
||
"gopkg.in/src-d/go-git.v2/clients/common" | ||
"gopkg.in/src-d/go-git.v2/clients/http" | ||
"gopkg.in/src-d/go-git.v2/clients/ssh" | ||
) | ||
|
||
func NewGitUploadPackService() common.GitUploadPackService { | ||
return http.NewGitUploadPackService() | ||
// 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 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) | ||
} | ||
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
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) } | ||
|
||
type SuiteCommon struct{} | ||
|
||
var _ = Suite(&SuiteCommon{}) | ||
|
||
func (s *SuiteCommon) TestNewGitUploadPackService(c *C) { | ||
var tests = [...]struct { | ||
input string | ||
err bool | ||
expected string | ||
}{ | ||
{"://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"}, | ||
} | ||
|
||
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(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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters