Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 5578008

Browse files
committed
Repository.Clone and Remote.Fetch remote, local branches and client: correct header read
1 parent e2cef9f commit 5578008

File tree

13 files changed

+323
-84
lines changed

13 files changed

+323
-84
lines changed

clients/common/common.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ func (r *GitUploadPackInfo) Bytes() []byte {
287287
type GitUploadPackRequest struct {
288288
Wants []core.Hash
289289
Haves []core.Hash
290+
Depth int
290291
}
291292

292293
func (r *GitUploadPackRequest) Want(h ...core.Hash) {
@@ -312,6 +313,10 @@ func (r *GitUploadPackRequest) Reader() *strings.Reader {
312313
e.AddLine(fmt.Sprintf("have %s", have))
313314
}
314315

316+
if r.Depth != 0 {
317+
e.AddLine(fmt.Sprintf("deepen %d", r.Depth))
318+
}
319+
315320
e.AddFlush()
316321
e.AddLine("done")
317322

clients/http/git_upload_pack.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,28 @@ func (s *GitUploadPackService) Fetch(r *common.GitUploadPackRequest) (io.ReadClo
6666
return nil, err
6767
}
6868

69-
h := make([]byte, 8)
70-
if _, err := res.Body.Read(h); err != nil {
71-
return nil, core.NewUnexpectedError(err)
69+
if err := s.discardResponseInfo(res.Body); err != nil {
70+
return nil, err
7271
}
7372

7473
return res.Body, nil
7574
}
7675

76+
func (s *GitUploadPackService) discardResponseInfo(r io.Reader) error {
77+
decoder := pktline.NewDecoder(r)
78+
for {
79+
line, err := decoder.ReadLine()
80+
if err != nil {
81+
break
82+
}
83+
84+
if line == "NAK\n" {
85+
break
86+
}
87+
}
88+
89+
return nil
90+
}
7791
func (s *GitUploadPackService) doRequest(method, url string, content *strings.Reader) (*http.Response, error) {
7892
var body io.Reader
7993
if content != nil {

clients/http/git_upload_pack_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,19 @@ func (s *RemoteSuite) TestFetch(c *C) {
7373
c.Assert(err, IsNil)
7474
c.Assert(b, HasLen, 85374)
7575
}
76+
77+
func (s *RemoteSuite) TestFetchMulti(c *C) {
78+
r := NewGitUploadPackService(s.Endpoint)
79+
c.Assert(r.Connect(), IsNil)
80+
81+
req := &common.GitUploadPackRequest{}
82+
req.Want(core.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"))
83+
req.Want(core.NewHash("e8d3ffab552895c19b9fcf7aa264d277cde33881"))
84+
85+
reader, err := r.Fetch(req)
86+
c.Assert(err, IsNil)
87+
88+
b, err := ioutil.ReadAll(reader)
89+
c.Assert(err, IsNil)
90+
c.Assert(len(b), HasLen, 85585)
91+
}

common_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,15 @@ func (p *MockGitUploadPackService) Info() (*common.GitUploadPackInfo, error) {
4848
c.Decode("6ecf0ef2c2dffb796033e5a02219af86ec6584e5 HEADmulti_ack thin-pack side-band side-band-64k ofs-delta shallow no-progress include-tag multi_ack_detailed no-done symref=HEAD:refs/heads/master agent=git/2:2.4.8~dbussink-fix-enterprise-tokens-compilation-1167-gc7006cf")
4949

5050
ref := core.ReferenceName("refs/heads/master")
51+
branch := core.ReferenceName("refs/heads/branch")
5152
tag := core.ReferenceName("refs/tags/v1.0.0")
5253
return &common.GitUploadPackInfo{
5354
Capabilities: c,
5455
Refs: map[core.ReferenceName]*core.Reference{
5556
core.HEAD: core.NewSymbolicReference(core.HEAD, ref),
5657
ref: core.NewHashReference(ref, h),
5758
tag: core.NewHashReference(tag, h),
59+
branch: core.NewHashReference(branch, core.NewHash("e8d3ffab552895c19b9fcf7aa264d277cde33881")),
5860
},
5961
}, nil
6062
}

core/reference.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ func (r *Reference) Target() ReferenceName {
114114

115115
// IsBranch check if a reference is a branch
116116
func (r *Reference) IsBranch() bool {
117-
return strings.HasPrefix(string(r.n), refHeadPrefix)
117+
return strings.HasPrefix(string(r.n), refHeadPrefix) || r.n == HEAD
118118
}
119119

120120
// IsNote check if a reference is a note

examples/basic/main.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,18 @@ func main() {
1616
panic(err)
1717
}
1818

19-
if err = r.Clone(&git.CloneOptions{URL: url}); err != nil {
19+
if err = r.Clone(&git.RepositoryCloneOptions{URL: url, Depth: 1, SingleBranch: false}); err != nil {
2020
panic(err)
2121
}
2222

2323
iter, err := r.Commits()
2424
if err != nil {
2525
panic(err)
2626
}
27+
2728
defer iter.Close()
2829

30+
var count = 0
2931
for {
3032
//the commits are not shorted in any special order
3133
commit, err := iter.Next()
@@ -37,6 +39,9 @@ func main() {
3739
panic(err)
3840
}
3941

42+
count++
4043
fmt.Println(commit)
4144
}
45+
46+
fmt.Println("total commits:", count)
4247
}

formats/pktline/decoder.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func (d *Decoder) ReadLine() (string, error) {
3232

3333
func (d *Decoder) readLine() (string, error) {
3434
raw := make([]byte, HeaderLength)
35-
if _, err := d.r.Read(raw); err != nil {
35+
if _, err := io.ReadFull(d.r, raw); err != nil {
3636
return "", err
3737
}
3838

objects_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func (s *ObjectsSuite) SetUpTest(c *C) {
2323
s.r, err = NewMemoryRepository()
2424
c.Assert(err, IsNil)
2525

26-
err = s.r.Clone(&CloneOptions{URL: RepositoryFixture})
26+
err = s.r.Clone(&RepositoryCloneOptions{URL: RepositoryFixture})
2727
c.Assert(err, IsNil)
2828
}
2929

options.go

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,41 @@ import (
55
"gopkg.in/src-d/go-git.v4/core"
66
)
77

8-
// CloneOptions describe how a clone should be perform
9-
type CloneOptions struct {
8+
const (
9+
// DefaultRemoteName name of the default Remote, just like git command
10+
DefaultRemoteName = "origin"
11+
)
12+
13+
// RepositoryCloneOptions describe how a clone should be perform
14+
type RepositoryCloneOptions struct {
1015
// The (possibly remote) repository URL to clone from
1116
URL string
1217
// Auth credentials, if required, to uses with the remote repository
1318
Auth common.AuthMethod
14-
// Remote branch to fetch
19+
// Name of the remote to be added, by default `origin`
20+
RemoteName string
21+
// Remote branch to clone
1522
ReferenceName core.ReferenceName
23+
// Fetch only ReferenceName if true
24+
SingleBranch bool
25+
// Limit fetching to the specified number of commits
26+
Depth int
1627
}
1728

18-
func (o *CloneOptions) Default() {
19-
if o.ReferenceName == "" {
20-
o.ReferenceName = core.HEAD
29+
func (o *RepositoryCloneOptions) Default() {
30+
if o.RemoteName == "" {
31+
o.RemoteName = DefaultRemoteName
2132
}
22-
}
2333

24-
// FetchOptions describe how a fetch should be perform
25-
type FetchOptions struct {
26-
// Remote branch to fetch
27-
ReferenceName core.ReferenceName
28-
}
29-
30-
func (o *FetchOptions) Default() {
3134
if o.ReferenceName == "" {
3235
o.ReferenceName = core.HEAD
3336
}
3437
}
38+
39+
// RemoteFetchOptions describe how a fetch should be perform
40+
type RemoteFetchOptions struct {
41+
// Remote branchs to fetch
42+
References []*core.Reference
43+
// Limit fetching to the specified number of commits
44+
Depth int
45+
}

remote.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
// Remote represents a connection to a remote repository
1111
type Remote struct {
12+
Name string
1213
Endpoint common.Endpoint
1314
Auth common.AuthMethod
1415

@@ -17,13 +18,13 @@ type Remote struct {
1718
}
1819

1920
// NewRemote returns a new Remote, using as client http.DefaultClient
20-
func NewRemote(url string) (*Remote, error) {
21-
return NewAuthenticatedRemote(url, nil)
21+
func NewRemote(name, url string) (*Remote, error) {
22+
return NewAuthenticatedRemote(name, url, nil)
2223
}
2324

2425
// NewAuthenticatedRemote returns a new Remote using the given AuthMethod, using as
2526
// client http.DefaultClient
26-
func NewAuthenticatedRemote(url string, auth common.AuthMethod) (*Remote, error) {
27+
func NewAuthenticatedRemote(name, url string, auth common.AuthMethod) (*Remote, error) {
2728
endpoint, err := common.NewEndpoint(url)
2829
if err != nil {
2930
return nil, err
@@ -36,6 +37,7 @@ func NewAuthenticatedRemote(url string, auth common.AuthMethod) (*Remote, error)
3637

3738
return &Remote{
3839
Endpoint: endpoint,
40+
Name: name,
3941
Auth: auth,
4042
upSrv: upSrv,
4143
}, nil
@@ -77,16 +79,17 @@ func (r *Remote) Capabilities() *common.Capabilities {
7779
}
7880

7981
// Fetch returns a reader using the request
80-
func (r *Remote) Fetch(s core.ObjectStorage, o *FetchOptions) (err error) {
81-
o.Default()
82+
func (r *Remote) Fetch(s core.ObjectStorage, o *RemoteFetchOptions) (err error) {
83+
req := &common.GitUploadPackRequest{}
84+
req.Depth = o.Depth
8285

83-
ref, err := r.Ref(o.ReferenceName, true)
84-
if err != nil {
85-
return err
86-
}
86+
for _, ref := range o.References {
87+
if ref.Type() != core.HashReference {
88+
continue
89+
}
8790

88-
req := &common.GitUploadPackRequest{}
89-
req.Want(ref.Hash())
91+
req.Want(ref.Hash())
92+
}
9093

9194
reader, err := r.upSrv.Fetch(req)
9295
if err != nil {

remote_test.go

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,39 +15,41 @@ type RemoteSuite struct {
1515
var _ = Suite(&RemoteSuite{})
1616

1717
func (s *RemoteSuite) TestNewRemote(c *C) {
18-
r, err := NewRemote(RepositoryFixture)
18+
r, err := NewRemote("foo", RepositoryFixture)
1919
c.Assert(err, IsNil)
20+
c.Assert(r.Name, Equals, "foo")
2021
c.Assert(r.Endpoint.String(), Equals, RepositoryFixture)
2122
}
2223

2324
func (s *RemoteSuite) TestNewRemoteInvalidEndpoint(c *C) {
24-
r, err := NewRemote("qux")
25+
r, err := NewRemote("foo", "qux")
2526
c.Assert(err, NotNil)
2627
c.Assert(r, IsNil)
2728
}
2829

2930
func (s *RemoteSuite) TestNewRemoteInvalidSchemaEndpoint(c *C) {
30-
r, err := NewRemote("qux://foo")
31+
r, err := NewRemote("foo", "qux://foo")
3132
c.Assert(err, NotNil)
3233
c.Assert(r, IsNil)
3334
}
3435

3536
func (s *RemoteSuite) TestNewAuthenticatedRemote(c *C) {
3637
a := &http.BasicAuth{}
37-
r, err := NewAuthenticatedRemote(RepositoryFixture, a)
38+
r, err := NewAuthenticatedRemote("foo", RepositoryFixture, a)
3839
c.Assert(err, IsNil)
40+
c.Assert(r.Name, Equals, "foo")
3941
c.Assert(r.Endpoint.String(), Equals, RepositoryFixture)
4042
c.Assert(r.Auth, Equals, a)
4143
}
4244

4345
func (s *RemoteSuite) TestConnect(c *C) {
44-
r, err := NewRemote(RepositoryFixture)
46+
r, err := NewRemote("foo", RepositoryFixture)
4547
c.Assert(err, IsNil)
4648
c.Assert(r.Connect(), IsNil)
4749
}
4850

4951
func (s *RemoteSuite) TestInfo(c *C) {
50-
r, err := NewRemote(RepositoryFixture)
52+
r, err := NewRemote("foo", RepositoryFixture)
5153
c.Assert(err, IsNil)
5254
c.Assert(r.Info(), IsNil)
5355
c.Assert(r.Connect(), IsNil)
@@ -56,7 +58,7 @@ func (s *RemoteSuite) TestInfo(c *C) {
5658
}
5759

5860
func (s *RemoteSuite) TestDefaultBranch(c *C) {
59-
r, err := NewRemote(RepositoryFixture)
61+
r, err := NewRemote("foo", RepositoryFixture)
6062
r.upSrv = &MockGitUploadPackService{}
6163

6264
c.Assert(err, IsNil)
@@ -65,7 +67,7 @@ func (s *RemoteSuite) TestDefaultBranch(c *C) {
6567
}
6668

6769
func (s *RemoteSuite) TestCapabilities(c *C) {
68-
r, err := NewRemote(RepositoryFixture)
70+
r, err := NewRemote("foo", RepositoryFixture)
6971
r.upSrv = &MockGitUploadPackService{}
7072

7173
c.Assert(err, IsNil)
@@ -74,38 +76,27 @@ func (s *RemoteSuite) TestCapabilities(c *C) {
7476
}
7577

7678
func (s *RemoteSuite) TestFetch(c *C) {
77-
r, err := NewRemote(RepositoryFixture)
79+
r, err := NewRemote("foo", RepositoryFixture)
7880
r.upSrv = &MockGitUploadPackService{}
7981

8082
c.Assert(err, IsNil)
8183
c.Assert(r.Connect(), IsNil)
8284

8385
sto := memory.NewObjectStorage()
84-
err = r.Fetch(sto, &FetchOptions{
85-
ReferenceName: core.HEAD,
86+
err = r.Fetch(sto, &RemoteFetchOptions{
87+
References: []*core.Reference{
88+
core.NewReferenceFromStrings(
89+
"refs/heads/master", "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
90+
),
91+
},
8692
})
8793

8894
c.Assert(err, IsNil)
8995
c.Assert(sto.Objects, HasLen, 28)
9096
}
9197

92-
func (s *RemoteSuite) TestFetchInvalidBranch(c *C) {
93-
r, err := NewRemote(RepositoryFixture)
94-
r.upSrv = &MockGitUploadPackService{}
95-
96-
c.Assert(err, IsNil)
97-
c.Assert(r.Connect(), IsNil)
98-
99-
sto := memory.NewObjectStorage()
100-
err = r.Fetch(sto, &FetchOptions{
101-
ReferenceName: core.ReferenceName("qux"),
102-
})
103-
104-
c.Assert(err, NotNil)
105-
}
106-
10798
func (s *RemoteSuite) TestHead(c *C) {
108-
r, err := NewRemote(RepositoryFixture)
99+
r, err := NewRemote("foo", RepositoryFixture)
109100
r.upSrv = &MockGitUploadPackService{}
110101
c.Assert(err, IsNil)
111102

@@ -115,7 +106,7 @@ func (s *RemoteSuite) TestHead(c *C) {
115106
}
116107

117108
func (s *RemoteSuite) TestRef(c *C) {
118-
r, err := NewRemote(RepositoryFixture)
109+
r, err := NewRemote("foo", RepositoryFixture)
119110
r.upSrv = &MockGitUploadPackService{}
120111
c.Assert(err, IsNil)
121112

@@ -132,7 +123,7 @@ func (s *RemoteSuite) TestRef(c *C) {
132123
}
133124

134125
func (s *RemoteSuite) TestRefs(c *C) {
135-
r, err := NewRemote(RepositoryFixture)
126+
r, err := NewRemote("foo", RepositoryFixture)
136127
r.upSrv = &MockGitUploadPackService{}
137128
c.Assert(err, IsNil)
138129

0 commit comments

Comments
 (0)