aboutsummaryrefslogtreecommitdiffstats
path: root/remote.go
diff options
context:
space:
mode:
authorMáximo Cuadros <mcuadros@gmail.com>2016-08-19 17:42:13 +0200
committerMáximo Cuadros <mcuadros@gmail.com>2016-08-19 17:42:13 +0200
commit1d56b98d9b02e20f7feea542c75746eab34fad63 (patch)
tree006e8c3ac5e40353032109a5259bb28c37751996 /remote.go
parentb1d116c59f7656dc8d5ff7294ba8f8a82c51bfd1 (diff)
downloadgo-git-1d56b98d9b02e20f7feea542c75746eab34fad63.tar.gz
Remote.Fetch base on RefSpec, improvement of the responsabilities separation
Diffstat (limited to 'remote.go')
-rw-r--r--remote.go100
1 files changed, 91 insertions, 9 deletions
diff --git a/remote.go b/remote.go
index 7e25ef7..9b07223 100644
--- a/remote.go
+++ b/remote.go
@@ -1,14 +1,19 @@
package git
import (
+ "io"
+
"gopkg.in/src-d/go-git.v4/clients"
"gopkg.in/src-d/go-git.v4/clients/common"
+ "gopkg.in/src-d/go-git.v4/config"
"gopkg.in/src-d/go-git.v4/core"
"gopkg.in/src-d/go-git.v4/formats/packfile"
)
// Remote represents a connection to a remote repository
type Remote struct {
+ config *config.RemoteConfig
+
Name string
Endpoint common.Endpoint
Auth common.AuthMethod
@@ -79,20 +84,19 @@ func (r *Remote) Capabilities() *common.Capabilities {
}
// Fetch returns a reader using the request
-func (r *Remote) Fetch(s core.ObjectStorage, o *RemoteFetchOptions) (err error) {
+func (r *Remote) Fetch(s core.Storage, o *RemoteFetchOptions) (err error) {
if err := o.Validate(); err != nil {
return err
}
- req := &common.GitUploadPackRequest{}
- req.Depth = o.Depth
-
- for _, ref := range o.References {
- if ref.Type() != core.HashReference {
- continue
- }
+ refs, err := r.getWantedReferences(o.RefSpec)
+ if err != nil {
+ return err
+ }
- req.Want(ref.Hash())
+ req, err := r.buildRequest(s.ReferenceStorage(), o, refs)
+ if err != nil {
+ return err
}
reader, err := r.upSrv.Fetch(req)
@@ -101,12 +105,85 @@ func (r *Remote) Fetch(s core.ObjectStorage, o *RemoteFetchOptions) (err error)
}
defer checkClose(reader, &err)
+ if err := r.updateObjectStorage(s.ObjectStorage(), reader); err != nil {
+ return err
+ }
+
+ return r.updateLocalReferenceStorage(s.ReferenceStorage(), o.RefSpec, refs)
+}
+
+func (r *Remote) getWantedReferences(spec config.RefSpec) ([]*core.Reference, error) {
+ var refs []*core.Reference
+
+ return refs, r.Refs().ForEach(func(r *core.Reference) error {
+ if r.Type() != core.HashReference {
+ return nil
+ }
+
+ if spec.Match(r.Name()) {
+ refs = append(refs, r)
+ }
+
+ return nil
+ })
+}
+
+func (r *Remote) buildRequest(
+ s core.ReferenceStorage, o *RemoteFetchOptions, refs []*core.Reference,
+) (*common.GitUploadPackRequest, error) {
+ req := &common.GitUploadPackRequest{}
+ req.Depth = o.Depth
+
+ for _, ref := range refs {
+ req.Want(ref.Hash())
+ }
+
+ i, err := s.Iter()
+ if err != nil {
+ return nil, err
+ }
+
+ err = i.ForEach(func(ref *core.Reference) error {
+ if ref.Type() != core.HashReference {
+ return nil
+ }
+
+ req.Have(ref.Hash())
+ return nil
+ })
+
+ return req, err
+}
+
+func (r *Remote) updateObjectStorage(s core.ObjectStorage, reader io.Reader) error {
stream := packfile.NewStream(reader)
d := packfile.NewDecoder(stream)
return d.Decode(s)
}
+func (r *Remote) updateLocalReferenceStorage(
+ local core.ReferenceStorage, spec config.RefSpec, refs []*core.Reference,
+) error {
+ for _, ref := range refs {
+ if !spec.Match(ref.Name()) {
+ continue
+ }
+
+ if ref.Type() != core.HashReference {
+ continue
+ }
+
+ name := spec.Dst(ref.Name())
+ n := core.NewHashReference(name, ref.Hash())
+ if err := local.Set(n); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
// Head returns the Reference of the HEAD
func (r *Remote) Head() *core.Reference {
return r.upInfo.Head()
@@ -126,3 +203,8 @@ func (r *Remote) Refs() core.ReferenceIter {
i, _ := r.upInfo.Refs.Iter()
return i
}
+
+func (r *Remote) Disconnect() error {
+ r.upInfo = nil
+ return r.upSrv.Disconnect()
+}