diff options
author | Máximo Cuadros <mcuadros@gmail.com> | 2016-08-19 17:42:13 +0200 |
---|---|---|
committer | Máximo Cuadros <mcuadros@gmail.com> | 2016-08-19 17:42:13 +0200 |
commit | 1d56b98d9b02e20f7feea542c75746eab34fad63 (patch) | |
tree | 006e8c3ac5e40353032109a5259bb28c37751996 /remote.go | |
parent | b1d116c59f7656dc8d5ff7294ba8f8a82c51bfd1 (diff) | |
download | go-git-1d56b98d9b02e20f7feea542c75746eab34fad63.tar.gz |
Remote.Fetch base on RefSpec, improvement of the responsabilities separation
Diffstat (limited to 'remote.go')
-rw-r--r-- | remote.go | 100 |
1 files changed, 91 insertions, 9 deletions
@@ -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() +} |