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

Commit 86a411c

Browse files
committed
Repository.Pull, PoC
1 parent cfe4f12 commit 86a411c

File tree

3 files changed

+119
-5
lines changed

3 files changed

+119
-5
lines changed

options.go

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package git
22

33
import (
4+
"errors"
5+
46
"gopkg.in/src-d/go-git.v3/clients/common"
57
"gopkg.in/src-d/go-git.v4/core"
68
)
@@ -10,6 +12,11 @@ const (
1012
DefaultRemoteName = "origin"
1113
)
1214

15+
var (
16+
ErrMissingURL = errors.New("URL field is required")
17+
ErrMissingReferences = errors.New("references cannot be empty")
18+
)
19+
1320
// RepositoryCloneOptions describe how a clone should be perform
1421
type RepositoryCloneOptions struct {
1522
// The (possibly remote) repository URL to clone from
@@ -26,20 +33,63 @@ type RepositoryCloneOptions struct {
2633
Depth int
2734
}
2835

29-
func (o *RepositoryCloneOptions) Default() {
36+
// Validate validate the fields and set the default values
37+
func (o *RepositoryCloneOptions) Validate() error {
38+
if o.URL == "" {
39+
return ErrMissingURL
40+
}
41+
3042
if o.RemoteName == "" {
3143
o.RemoteName = DefaultRemoteName
3244
}
3345

3446
if o.ReferenceName == "" {
3547
o.ReferenceName = core.HEAD
3648
}
49+
50+
return nil
51+
}
52+
53+
// RepositoryPullOptions describe how a pull should be perform
54+
type RepositoryPullOptions struct {
55+
// Name of the remote to be pulled
56+
RemoteName string
57+
// Remote branch to clone
58+
ReferenceName core.ReferenceName
59+
// Fetch only ReferenceName if true
60+
SingleBranch bool
61+
// Limit fetching to the specified number of commits
62+
Depth int
63+
}
64+
65+
// Validate validate the fields and set the default values
66+
func (o *RepositoryPullOptions) Validate() error {
67+
if o.RemoteName == "" {
68+
o.RemoteName = DefaultRemoteName
69+
}
70+
71+
if o.ReferenceName == "" {
72+
o.ReferenceName = core.HEAD
73+
}
74+
75+
return nil
3776
}
3877

3978
// RemoteFetchOptions describe how a fetch should be perform
4079
type RemoteFetchOptions struct {
4180
// Remote branchs to fetch
4281
References []*core.Reference
82+
// Local references present on the local storage
83+
LocalReferences []*core.Reference
4384
// Limit fetching to the specified number of commits
4485
Depth int
4586
}
87+
88+
// Validate validate the fields and set the default values
89+
func (o *RemoteFetchOptions) Validate() error {
90+
if len(o.References) == 0 {
91+
return ErrMissingReferences
92+
}
93+
94+
return nil
95+
}

remote.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ func (r *Remote) Capabilities() *common.Capabilities {
8080

8181
// Fetch returns a reader using the request
8282
func (r *Remote) Fetch(s core.ObjectStorage, o *RemoteFetchOptions) (err error) {
83+
if err := o.Validate(); err != nil {
84+
return err
85+
}
86+
8387
req := &common.GitUploadPackRequest{}
8488
req.Depth = o.Depth
8589

repository.go

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,14 @@ import (
1212
)
1313

1414
var (
15-
// ErrObjectNotFound object not found
1615
ErrObjectNotFound = errors.New("object not found")
16+
ErrUnknownRemote = errors.New("unknown remote")
1717
)
1818

1919
// Repository giturl string, auth common.AuthMethod repository struct
2020
type Repository struct {
2121
Remotes map[string]*Remote
22-
23-
s core.Storage
22+
s core.Storage
2423
}
2524

2625
// NewMemoryRepository creates a new repository, backed by a memory.Storage
@@ -45,7 +44,9 @@ func NewRepository(s core.Storage) (*Repository, error) {
4544

4645
// Clone clones a remote repository
4746
func (r *Repository) Clone(o *RepositoryCloneOptions) error {
48-
o.Default()
47+
if err := o.Validate(); err != nil {
48+
return err
49+
}
4950

5051
remote, err := r.createRemote(o.RemoteName, o.URL, o.Auth)
5152
if err != nil {
@@ -194,6 +195,65 @@ func (r *Repository) createRemoteReference(remote *Remote, ref *core.Reference)
194195
return r.s.ReferenceStorage().Set(n)
195196
}
196197

198+
// Pull incorporates changes from a remote repository into the current branch
199+
func (r *Repository) Pull(o *RepositoryPullOptions) error {
200+
if err := o.Validate(); err != nil {
201+
return err
202+
}
203+
204+
remote, ok := r.Remotes[o.RemoteName]
205+
if !ok {
206+
return ErrUnknownRemote
207+
}
208+
209+
head, err := remote.Ref(o.ReferenceName, true)
210+
if err != nil {
211+
return err
212+
}
213+
214+
refs, err := r.getLocalReferences()
215+
if err != nil {
216+
return err
217+
}
218+
219+
err = remote.Fetch(r.s.ObjectStorage(), &RemoteFetchOptions{
220+
References: []*core.Reference{head},
221+
LocalReferences: refs,
222+
Depth: o.Depth,
223+
})
224+
225+
if err != nil {
226+
return err
227+
}
228+
229+
return r.createLocalReferences(head)
230+
}
231+
232+
func (r *Repository) getLocalReferences() ([]*core.Reference, error) {
233+
var refs []*core.Reference
234+
i := r.Refs()
235+
defer i.Close()
236+
237+
for {
238+
ref, err := i.Next()
239+
if err != nil {
240+
if err == io.EOF {
241+
break
242+
}
243+
244+
return nil, err
245+
}
246+
247+
if ref.Type() == core.SymbolicReference {
248+
continue
249+
}
250+
251+
refs = append(refs, ref)
252+
}
253+
254+
return refs, nil
255+
}
256+
197257
// Commit return the commit with the given hash
198258
func (r *Repository) Commit(h core.Hash) (*Commit, error) {
199259
obj, err := r.s.ObjectStorage().Get(h)

0 commit comments

Comments
 (0)