Skip to content

Commit 9a4e2cf

Browse files
committed
Add configurable http client factory (fixes src-d#120)
* new http client factory ready to install/override default http(s) * mv GitUploadPackServiceFactory to clients.common pkg * rename http.HTTPError to http.Err * rename http.HTTPAuthMethod to http.AuthMethod * general improvements: - update install link in readme to v4 (example are already pointing v4) - fix indentation in package doc (styling for godoc.org) - use http.Status constants instead of integers - close leaked response body - rm named returns which stutter in doc - fix one format string - rm unnecessary if checks - documentation fixes
1 parent f49096e commit 9a4e2cf

File tree

10 files changed

+100
-77
lines changed

10 files changed

+100
-77
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Installation
3030
The recommended way to install *go-git* is:
3131

3232
```
33-
go get -u gopkg.in/src-d/go-git.v3/...
33+
go get -u gopkg.in/src-d/go-git.v4/...
3434
```
3535

3636

doc.go

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,32 @@
66
// extensions.
77
//
88
// Small example extracting the commits from a repository:
9-
// func ExampleBasic_printCommits() {
10-
// r := git.NewMemoryRepository()
11-
// o := &git.CloneOptions{
12-
// URL: "https://github.com/src-d/go-git",
13-
// }
14-
// if err := r.Clone(o); err != nil {
15-
// panic(err)
16-
// }
179
//
18-
// iter, err := r.Commits()
19-
// if err != nil {
20-
// panic(err)
21-
// }
22-
// defer iter.Close()
10+
// func ExampleBasic_printCommits() {
11+
// r := git.NewMemoryRepository()
12+
// o := &git.CloneOptions{
13+
// URL: "https://github.com/src-d/go-git",
14+
// }
15+
// if err := r.Clone(o); err != nil {
16+
// panic(err)
17+
// }
2318
//
24-
// for {
25-
// commit, err := iter.Next()
26-
// if err != nil {
27-
// if err == io.EOF {
28-
// break
29-
// }
30-
// panic(err)
31-
// }
19+
// iter, err := r.Commits()
20+
// if err != nil {
21+
// panic(err)
22+
// }
23+
// defer iter.Close()
3224
//
33-
// fmt.Println(commit)
34-
// }
35-
// }
25+
// for {
26+
// commit, err := iter.Next()
27+
// if err != nil {
28+
// if err == io.EOF {
29+
// break
30+
// }
31+
// panic(err)
32+
// }
33+
//
34+
// fmt.Println(commit)
35+
// }
36+
// }
3637
package git // import "gopkg.in/src-d/go-git.v4"

plumbing/client/common.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Package clients includes the implementation for diferent transport protocols
1+
// Package clients includes the implementation for different transport protocols
22
//
33
// go-git needs the packfile and the refs of the repo. The
44
// `NewGitUploadPackService` function returns an object that allows to
@@ -21,17 +21,15 @@ import (
2121
"gopkg.in/src-d/go-git.v4/plumbing/client/ssh"
2222
)
2323

24-
type GitUploadPackServiceFactory func(common.Endpoint) common.GitUploadPackService
25-
2624
// Protocols are the protocols supported by default.
27-
var Protocols = map[string]GitUploadPackServiceFactory{
25+
var Protocols = map[string]common.GitUploadPackServiceFactory{
2826
"http": http.NewGitUploadPackService,
2927
"https": http.NewGitUploadPackService,
3028
"ssh": ssh.NewGitUploadPackService,
3129
}
3230

3331
// InstallProtocol adds or modifies an existing protocol.
34-
func InstallProtocol(scheme string, f GitUploadPackServiceFactory) {
32+
func InstallProtocol(scheme string, f common.GitUploadPackServiceFactory) {
3533
Protocols[scheme] = f
3634
}
3735

plumbing/client/common/common.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ type GitUploadPackService interface {
3636
Disconnect() error
3737
}
3838

39+
// GitUploadPackServiceFactory is capable of instantiating GitUploadPackService with given endpoint
40+
type GitUploadPackServiceFactory func(Endpoint) GitUploadPackService
41+
3942
type AuthMethod interface {
4043
Name() string
4144
String() string

plumbing/client/http/common.go

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import (
99
"gopkg.in/src-d/go-git.v4/plumbing/client/common"
1010
)
1111

12-
// HTTPAuthMethod concrete implementation of common.AuthMethod for HTTP services
13-
type HTTPAuthMethod interface {
12+
// AuthMethod is concrete implementation of common.AuthMethod for HTTP services
13+
type AuthMethod interface {
1414
common.AuthMethod
1515
setAuth(r *http.Request)
1616
}
@@ -29,7 +29,7 @@ func (a *BasicAuth) setAuth(r *http.Request) {
2929
r.SetBasicAuth(a.username, a.password)
3030
}
3131

32-
// Name name of the auth
32+
// Name is name of the auth
3333
func (a *BasicAuth) Name() string {
3434
return "http-basic-auth"
3535
}
@@ -43,34 +43,33 @@ func (a *BasicAuth) String() string {
4343
return fmt.Sprintf("%s - %s:%s", a.Name(), a.username, masked)
4444
}
4545

46-
// HTTPError a dedicated error to return errors bases on status codes
47-
type HTTPError struct {
46+
// Err is a dedicated error to return errors based on status code
47+
type Err struct {
4848
Response *http.Response
4949
}
5050

51-
// NewHTTPError returns a new HTTPError based on a http response
52-
func NewHTTPError(r *http.Response) error {
53-
if r.StatusCode >= 200 && r.StatusCode < 300 {
51+
// NewErr returns a new Err based on a http response
52+
func NewErr(r *http.Response) error {
53+
if r.StatusCode >= http.StatusOK && r.StatusCode < http.StatusMultipleChoices {
5454
return nil
5555
}
5656

5757
switch r.StatusCode {
58-
case 401:
58+
case http.StatusUnauthorized:
5959
return common.ErrAuthorizationRequired
60-
case 404:
60+
case http.StatusNotFound:
6161
return common.ErrRepositoryNotFound
6262
}
6363

64-
err := &HTTPError{r}
65-
return plumbing.NewUnexpectedError(err)
64+
return plumbing.NewUnexpectedError(&Err{r})
6665
}
6766

6867
// StatusCode returns the status code of the response
69-
func (e *HTTPError) StatusCode() int {
68+
func (e *Err) StatusCode() int {
7069
return e.Response.StatusCode
7170
}
7271

73-
func (e *HTTPError) Error() string {
72+
func (e *Err) Error() string {
7473
return fmt.Sprintf("unexpected requesting %q status code: %d",
7574
e.Response.Request.URL, e.Response.StatusCode,
7675
)

plumbing/client/http/common_test.go

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,22 @@ func (s *SuiteCommon) TestNewBasicAuth(c *C) {
2020
c.Assert(a.String(), Equals, "http-basic-auth - foo:*******")
2121
}
2222

23-
func (s *SuiteCommon) TestNewHTTPError200(c *C) {
24-
res := &http.Response{StatusCode: 200}
25-
res.StatusCode = 200
26-
err := NewHTTPError(res)
23+
func (s *SuiteCommon) TestNewErrOK(c *C) {
24+
res := &http.Response{StatusCode: http.StatusOK}
25+
err := NewErr(res)
2726
c.Assert(err, IsNil)
2827
}
2928

30-
func (s *SuiteCommon) TestNewHTTPError401(c *C) {
31-
s.testNewHTTPError(c, 401, "authorization required")
29+
func (s *SuiteCommon) TestNewErrUnauthorized(c *C) {
30+
s.testNewHTTPError(c, http.StatusUnauthorized, "authorization required")
3231
}
3332

34-
func (s *SuiteCommon) TestNewHTTPError404(c *C) {
35-
s.testNewHTTPError(c, 404, "repository not found")
33+
func (s *SuiteCommon) TestNewErrNotFound(c *C) {
34+
s.testNewHTTPError(c, http.StatusNotFound, "repository not found")
3635
}
3736

3837
func (s *SuiteCommon) TestNewHTTPError40x(c *C) {
39-
s.testNewHTTPError(c, 402, "unexpected client error.*")
38+
s.testNewHTTPError(c, http.StatusPaymentRequired, "unexpected client error.*")
4039
}
4140

4241
func (s *SuiteCommon) testNewHTTPError(c *C, code int, msg string) {
@@ -46,7 +45,7 @@ func (s *SuiteCommon) testNewHTTPError(c *C, code int, msg string) {
4645
Request: req,
4746
}
4847

49-
err := NewHTTPError(res)
48+
err := NewErr(res)
5049
c.Assert(err, NotNil)
5150
c.Assert(err, ErrorMatches, msg)
5251
}

plumbing/client/http/git_upload_pack.go

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,41 @@ import (
1313
"gopkg.in/src-d/go-git.v4/plumbing/format/packp/pktline"
1414
)
1515

16-
// GitUploadPackService git-upoad-pack service over HTTP
16+
// GitUploadPackService git-upload-pack service over HTTP
1717
type GitUploadPackService struct {
1818
client *http.Client
1919
endpoint common.Endpoint
20-
auth HTTPAuthMethod
20+
auth AuthMethod
2121
}
2222

2323
// NewGitUploadPackService connects to a git-upload-pack service over HTTP, the
2424
// auth is extracted from the URL, or can be provided using the SetAuth method
2525
func NewGitUploadPackService(endpoint common.Endpoint) common.GitUploadPackService {
26+
return newGitUploadPackService(endpoint, http.DefaultClient)
27+
}
28+
29+
// NewGitUploadPackServiceFactory creates a http client factory with a customizable client
30+
// See `InstallProtocol` to install and override default http client.
31+
// Unless a properly initialized client is given, it will fall back into `http.DefaultClient`.
32+
func NewGitUploadPackServiceFactory(client *http.Client) common.GitUploadPackServiceFactory {
33+
return func(endpoint common.Endpoint) common.GitUploadPackService {
34+
return newGitUploadPackService(endpoint, client)
35+
}
36+
}
37+
38+
func newGitUploadPackService(endpoint common.Endpoint, client *http.Client) common.GitUploadPackService {
39+
if client == nil {
40+
client = http.DefaultClient
41+
}
2642
s := &GitUploadPackService{
27-
client: http.DefaultClient,
43+
client: client,
2844
endpoint: endpoint,
2945
}
30-
3146
s.setBasicAuthFromEndpoint()
3247
return s
3348
}
3449

35-
// Connect has not any effect, is here just for meet the interface
50+
// Connect has not any effect, is here to satisfy interface
3651
func (s *GitUploadPackService) Connect() error {
3752
return nil
3853
}
@@ -54,7 +69,7 @@ func (s *GitUploadPackService) setBasicAuthFromEndpoint() {
5469

5570
// SetAuth sets the AuthMethod
5671
func (s *GitUploadPackService) SetAuth(auth common.AuthMethod) error {
57-
httpAuth, ok := auth.(HTTPAuthMethod)
72+
httpAuth, ok := auth.(AuthMethod)
5873
if !ok {
5974
return common.ErrInvalidAuthMethod
6075
}
@@ -139,7 +154,8 @@ func (s *GitUploadPackService) doRequest(method, url string, content *strings.Re
139154
return nil, plumbing.NewUnexpectedError(err)
140155
}
141156

142-
if err := NewHTTPError(res); err != nil {
157+
if err := NewErr(res); err != nil {
158+
_ = res.Body.Close()
143159
return nil, err
144160
}
145161

@@ -168,7 +184,7 @@ func (s *GitUploadPackService) applyAuthToRequest(req *http.Request) {
168184
}
169185

170186
// Disconnect do nothing
171-
func (s *GitUploadPackService) Disconnect() (err error) {
187+
func (s *GitUploadPackService) Disconnect() error {
172188
return nil
173189
}
174190

plumbing/client/http/git_upload_pack_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package http
22

33
import (
4+
"crypto/tls"
45
"io/ioutil"
6+
"net/http"
57

68
. "gopkg.in/check.v1"
79
"gopkg.in/src-d/go-git.v4/plumbing"
@@ -30,6 +32,18 @@ func (s *RemoteSuite) TestNewGitUploadPackServiceAuth(c *C) {
3032
c.Assert(auth.String(), Equals, "http-basic-auth - foo:*******")
3133
}
3234

35+
func (s *RemoteSuite) TestNewGitUploadPackServiceFactory(c *C) {
36+
e, err := common.NewEndpoint("https://foo:[email protected]/git-fixtures/basic")
37+
c.Assert(err, IsNil)
38+
39+
roundTripper := &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}
40+
client := &http.Client{Transport: roundTripper}
41+
r := NewGitUploadPackServiceFactory(client)(e).(*GitUploadPackService)
42+
43+
c.Assert(r.auth.String(), Equals, "http-basic-auth - foo:*******")
44+
c.Assert(r.client.Transport, Equals, roundTripper)
45+
}
46+
3347
func (s *RemoteSuite) TestConnect(c *C) {
3448
r := NewGitUploadPackService(s.Endpoint)
3549
c.Assert(r.Connect(), IsNil)

plumbing/client/ssh/git_upload_pack.go

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,7 @@ func (s *GitUploadPackService) setAuthFromEndpoint() error {
8484

8585
var err error
8686
s.auth, err = NewSSHAgentAuth(u)
87-
if err != nil {
88-
return err
89-
}
90-
91-
return nil
87+
return err
9288
}
9389

9490
// SetAuth sets the AuthMethod
@@ -105,7 +101,7 @@ func (s *GitUploadPackService) SetAuth(auth common.AuthMethod) error {
105101
// Info returns the GitUploadPackInfo of the repository. The client must be
106102
// connected with the repository (using the ConnectWithAuth() method) before
107103
// using this method.
108-
func (s *GitUploadPackService) Info() (i *common.GitUploadPackInfo, err error) {
104+
func (s *GitUploadPackService) Info() (*common.GitUploadPackInfo, error) {
109105
if !s.connected {
110106
return nil, ErrNotConnected
111107
}
@@ -125,12 +121,12 @@ func (s *GitUploadPackService) Info() (i *common.GitUploadPackInfo, err error) {
125121
return nil, err
126122
}
127123

128-
i = common.NewGitUploadPackInfo()
124+
i := common.NewGitUploadPackInfo()
129125
return i, i.Decode(bytes.NewReader(out))
130126
}
131127

132128
// Disconnect the SSH client.
133-
func (s *GitUploadPackService) Disconnect() (err error) {
129+
func (s *GitUploadPackService) Disconnect() error {
134130
if !s.connected {
135131
return ErrNotConnected
136132
}
@@ -142,7 +138,7 @@ func (s *GitUploadPackService) Disconnect() (err error) {
142138
// SSH session on a connected GitUploadPackService, sends the given
143139
// upload request to the server and returns a reader for the received
144140
// packfile. Closing the returned reader will close the SSH session.
145-
func (s *GitUploadPackService) Fetch(req *common.GitUploadPackRequest) (rc io.ReadCloser, err error) {
141+
func (s *GitUploadPackService) Fetch(req *common.GitUploadPackRequest) (io.ReadCloser, error) {
146142
if !s.connected {
147143
return nil, ErrNotConnected
148144
}
@@ -243,7 +239,7 @@ func sendHaves(w io.Writer, req *common.GitUploadPackRequest) error {
243239
e := pktline.NewEncoder(w)
244240
for _, have := range req.Haves {
245241
if err := e.Encodef("have %s\n", have); err != nil {
246-
return fmt.Errorf("sending haves for %q: err ", have, err)
242+
return fmt.Errorf("sending haves for %q: %s", have, err)
247243
}
248244
}
249245

remote.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,8 @@ func (r *Remote) connectUploadPackService() error {
6060

6161
func (r *Remote) retrieveUpInfo() error {
6262
var err error
63-
if r.upInfo, err = r.upSrv.Info(); err != nil {
64-
return err
65-
}
66-
67-
return nil
63+
r.upInfo, err = r.upSrv.Info()
64+
return err
6865
}
6966

7067
// Info returns the git-upload-pack info

0 commit comments

Comments
 (0)