aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMáximo Cuadros <mcuadros@gmail.com>2016-08-15 21:43:33 +0200
committerMáximo Cuadros <mcuadros@gmail.com>2016-08-15 21:43:33 +0200
commited2e3b299e03e4bfd4c37bf5232e9fde05c0600d (patch)
treea4ecca997e4528b643758ddaa1dedfa4546369cd
parent4c6e65190f48f0a7558718d239ffb23ee59580ac (diff)
downloadgo-git-ed2e3b299e03e4bfd4c37bf5232e9fde05c0600d.tar.gz
Repository.Pull, PoC
-rw-r--r--options.go52
-rw-r--r--remote.go4
-rw-r--r--repository.go68
3 files changed, 119 insertions, 5 deletions
diff --git a/options.go b/options.go
index 2aebbc7..0c1fefb 100644
--- a/options.go
+++ b/options.go
@@ -1,6 +1,8 @@
package git
import (
+ "errors"
+
"gopkg.in/src-d/go-git.v3/clients/common"
"gopkg.in/src-d/go-git.v4/core"
)
@@ -10,6 +12,11 @@ const (
DefaultRemoteName = "origin"
)
+var (
+ ErrMissingURL = errors.New("URL field is required")
+ ErrMissingReferences = errors.New("references cannot be empty")
+)
+
// RepositoryCloneOptions describe how a clone should be perform
type RepositoryCloneOptions struct {
// The (possibly remote) repository URL to clone from
@@ -26,7 +33,12 @@ type RepositoryCloneOptions struct {
Depth int
}
-func (o *RepositoryCloneOptions) Default() {
+// Validate validate the fields and set the default values
+func (o *RepositoryCloneOptions) Validate() error {
+ if o.URL == "" {
+ return ErrMissingURL
+ }
+
if o.RemoteName == "" {
o.RemoteName = DefaultRemoteName
}
@@ -34,12 +46,50 @@ func (o *RepositoryCloneOptions) Default() {
if o.ReferenceName == "" {
o.ReferenceName = core.HEAD
}
+
+ return nil
+}
+
+// RepositoryPullOptions describe how a pull should be perform
+type RepositoryPullOptions struct {
+ // Name of the remote to be pulled
+ RemoteName string
+ // Remote branch to clone
+ ReferenceName core.ReferenceName
+ // Fetch only ReferenceName if true
+ SingleBranch bool
+ // Limit fetching to the specified number of commits
+ Depth int
+}
+
+// Validate validate the fields and set the default values
+func (o *RepositoryPullOptions) Validate() error {
+ if o.RemoteName == "" {
+ o.RemoteName = DefaultRemoteName
+ }
+
+ if o.ReferenceName == "" {
+ o.ReferenceName = core.HEAD
+ }
+
+ return nil
}
// RemoteFetchOptions describe how a fetch should be perform
type RemoteFetchOptions struct {
// Remote branchs to fetch
References []*core.Reference
+ // Local references present on the local storage
+ LocalReferences []*core.Reference
// Limit fetching to the specified number of commits
Depth int
}
+
+// Validate validate the fields and set the default values
+func (o *RemoteFetchOptions) Validate() error {
+ if len(o.References) == 0 {
+ return ErrMissingReferences
+ }
+
+ return nil
+}
diff --git a/remote.go b/remote.go
index ce74af4..7e25ef7 100644
--- a/remote.go
+++ b/remote.go
@@ -80,6 +80,10 @@ func (r *Remote) Capabilities() *common.Capabilities {
// Fetch returns a reader using the request
func (r *Remote) Fetch(s core.ObjectStorage, o *RemoteFetchOptions) (err error) {
+ if err := o.Validate(); err != nil {
+ return err
+ }
+
req := &common.GitUploadPackRequest{}
req.Depth = o.Depth
diff --git a/repository.go b/repository.go
index b17bbea..e9aa55a 100644
--- a/repository.go
+++ b/repository.go
@@ -12,15 +12,14 @@ import (
)
var (
- // ErrObjectNotFound object not found
ErrObjectNotFound = errors.New("object not found")
+ ErrUnknownRemote = errors.New("unknown remote")
)
// Repository giturl string, auth common.AuthMethod repository struct
type Repository struct {
Remotes map[string]*Remote
-
- s core.Storage
+ s core.Storage
}
// NewMemoryRepository creates a new repository, backed by a memory.Storage
@@ -45,7 +44,9 @@ func NewRepository(s core.Storage) (*Repository, error) {
// Clone clones a remote repository
func (r *Repository) Clone(o *RepositoryCloneOptions) error {
- o.Default()
+ if err := o.Validate(); err != nil {
+ return err
+ }
remote, err := r.createRemote(o.RemoteName, o.URL, o.Auth)
if err != nil {
@@ -194,6 +195,65 @@ func (r *Repository) createRemoteReference(remote *Remote, ref *core.Reference)
return r.s.ReferenceStorage().Set(n)
}
+// Pull incorporates changes from a remote repository into the current branch
+func (r *Repository) Pull(o *RepositoryPullOptions) error {
+ if err := o.Validate(); err != nil {
+ return err
+ }
+
+ remote, ok := r.Remotes[o.RemoteName]
+ if !ok {
+ return ErrUnknownRemote
+ }
+
+ head, err := remote.Ref(o.ReferenceName, true)
+ if err != nil {
+ return err
+ }
+
+ refs, err := r.getLocalReferences()
+ if err != nil {
+ return err
+ }
+
+ err = remote.Fetch(r.s.ObjectStorage(), &RemoteFetchOptions{
+ References: []*core.Reference{head},
+ LocalReferences: refs,
+ Depth: o.Depth,
+ })
+
+ if err != nil {
+ return err
+ }
+
+ return r.createLocalReferences(head)
+}
+
+func (r *Repository) getLocalReferences() ([]*core.Reference, error) {
+ var refs []*core.Reference
+ i := r.Refs()
+ defer i.Close()
+
+ for {
+ ref, err := i.Next()
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+
+ return nil, err
+ }
+
+ if ref.Type() == core.SymbolicReference {
+ continue
+ }
+
+ refs = append(refs, ref)
+ }
+
+ return refs, nil
+}
+
// Commit return the commit with the given hash
func (r *Repository) Commit(h core.Hash) (*Commit, error) {
obj, err := r.s.ObjectStorage().Get(h)