From c8c4a69045f75e0a6dce601387bc2ff49f7c1e84 Mon Sep 17 00:00:00 2001 From: Alberto Cortés Date: Thu, 17 Dec 2015 18:01:38 +0100 Subject: Add install protocols capabilities to GitUploadPackService --- clients/common.go | 60 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 11 deletions(-) (limited to 'clients/common.go') 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 } -- cgit