aboutsummaryrefslogtreecommitdiffstats
path: root/remote.go
diff options
context:
space:
mode:
authorMáximo Cuadros <mcuadros@gmail.com>2017-07-17 09:33:58 +0200
committerMáximo Cuadros <mcuadros@gmail.com>2017-07-17 09:33:58 +0200
commitcbdb2584da59ec068e0d21e3e61028e54d1726fc (patch)
treed26557fbf9e01e704794f38de9b5a3fe67b830b8 /remote.go
parent6b3a6df29920d39b8308924b3b84178226b56224 (diff)
downloadgo-git-cbdb2584da59ec068e0d21e3e61028e54d1726fc.tar.gz
remote: fetch, correct behaviour on tags
Diffstat (limited to 'remote.go')
-rw-r--r--remote.go139
1 files changed, 83 insertions, 56 deletions
diff --git a/remote.go b/remote.go
index 7ebb843..b2c5d1c 100644
--- a/remote.go
+++ b/remote.go
@@ -134,7 +134,7 @@ func (r *Remote) Push(o *PushOptions) (err error) {
return rs.Error()
}
-func (r *Remote) fetch(o *FetchOptions) (refs storer.ReferenceStorer, err error) {
+func (r *Remote) fetch(o *FetchOptions) (storer.ReferenceStorer, error) {
if o.RemoteName == "" {
o.RemoteName = r.c.Name
}
@@ -169,7 +169,12 @@ func (r *Remote) fetch(o *FetchOptions) (refs storer.ReferenceStorer, err error)
return nil, err
}
- req.Wants, err = getWants(o.RefSpecs, r.s, remoteRefs)
+ refs, err := calculateRefs(o.RefSpecs, remoteRefs, o.Tags)
+ if err != nil {
+ return nil, err
+ }
+
+ req.Wants, err = getWants(r.s, refs)
if len(req.Wants) > 0 {
req.Haves, err = getHaves(r.s)
if err != nil {
@@ -181,14 +186,15 @@ func (r *Remote) fetch(o *FetchOptions) (refs storer.ReferenceStorer, err error)
}
}
- err = r.updateLocalReferenceStorage(o.RefSpecs, remoteRefs)
- if err != nil && err != NoErrAlreadyUpToDate {
+ updated, err := r.updateLocalReferenceStorage(o.RefSpecs, refs, remoteRefs)
+ if err != nil {
return nil, err
}
- if len(req.Wants) == 0 {
- return remoteRefs, err
+ if !updated {
+ return remoteRefs, NoErrAlreadyUpToDate
}
+
return remoteRefs, nil
}
@@ -372,56 +378,52 @@ func getHaves(localRefs storer.ReferenceStorer) ([]plumbing.Hash, error) {
return haves, nil
}
-func getWants(
- spec []config.RefSpec, localStorer storage.Storer, remoteRefs storer.ReferenceStorer,
-) ([]plumbing.Hash, error) {
- wantTags := true
- for _, s := range spec {
- if !s.IsWildcard() {
- wantTags = false
- break
- }
- }
-
+func calculateRefs(spec []config.RefSpec,
+ remoteRefs storer.ReferenceStorer,
+ tags TagFetchMode,
+) (memory.ReferenceStorage, error) {
iter, err := remoteRefs.IterReferences()
if err != nil {
return nil, err
}
- wants := map[plumbing.Hash]bool{}
- err = iter.ForEach(func(ref *plumbing.Reference) error {
+ refs := make(memory.ReferenceStorage, 0)
+ return refs, iter.ForEach(func(ref *plumbing.Reference) error {
if !config.MatchAny(spec, ref.Name()) {
- if !ref.IsTag() || !wantTags {
+ if !ref.IsTag() || tags != AllTags {
return nil
}
}
if ref.Type() == plumbing.SymbolicReference {
- ref, err = storer.ResolveReference(remoteRefs, ref.Name())
+ target, err := storer.ResolveReference(remoteRefs, ref.Name())
if err != nil {
return err
}
+
+ ref = plumbing.NewHashReference(ref.Name(), target.Hash())
}
if ref.Type() != plumbing.HashReference {
return nil
}
- hash := ref.Hash()
+ return refs.SetReference(ref)
+ })
+}
- exists, err := objectExists(localStorer, hash)
+func getWants(localStorer storage.Storer, refs memory.ReferenceStorage) ([]plumbing.Hash, error) {
+ wants := map[plumbing.Hash]bool{}
+ for _, ref := range refs {
+ hash := ref.Hash()
+ exists, err := objectExists(localStorer, ref.Hash())
if err != nil {
- return err
+ return nil, err
}
if !exists {
wants[hash] = true
}
-
- return nil
- })
- if err != nil {
- return nil, err
}
var result []plumbing.Hash
@@ -503,6 +505,19 @@ func (r *Remote) newUploadPackRequest(o *FetchOptions,
}
}
+ isWildcard := true
+ for _, s := range o.RefSpecs {
+ if !s.IsWildcard() {
+ isWildcard = false
+ }
+ }
+
+ if isWildcard && o.Tags == TagFollowing && ar.Capabilities.Supports(capability.IncludeTag) {
+ if err := req.Capabilities.Set(capability.IncludeTag); err != nil {
+ return nil, err
+ }
+ }
+
return req, nil
}
@@ -524,10 +539,17 @@ func buildSidebandIfSupported(l *capability.List, reader io.Reader, p sideband.P
return d
}
-func (r *Remote) updateLocalReferenceStorage(specs []config.RefSpec, refs memory.ReferenceStorage) error {
- updated := false
+func (r *Remote) updateLocalReferenceStorage(
+ specs []config.RefSpec,
+ fetchedRefs, remoteRefs memory.ReferenceStorage,
+) (updated bool, err error) {
+ isWildcard := true
for _, spec := range specs {
- for _, ref := range refs {
+ if !spec.IsWildcard() {
+ isWildcard = false
+ }
+
+ for _, ref := range fetchedRefs {
if !spec.Match(ref.Name()) {
continue
}
@@ -536,33 +558,36 @@ func (r *Remote) updateLocalReferenceStorage(specs []config.RefSpec, refs memory
continue
}
- name := spec.Dst(ref.Name())
- sref, err := r.s.Reference(name)
- if err != nil && err != plumbing.ErrReferenceNotFound {
- return err
+ new := plumbing.NewHashReference(spec.Dst(ref.Name()), ref.Hash())
+
+ refUpdated, err := updateReferenceStorerIfNeeded(r.s, new)
+ if err != nil {
+ return updated, err
}
- if err == plumbing.ErrReferenceNotFound || sref.Hash() != ref.Hash() {
- n := plumbing.NewHashReference(name, ref.Hash())
- if err := r.s.SetReference(n); err != nil {
- return err
- }
+
+ if refUpdated {
updated = true
}
}
}
- if err := r.buildFetchedTags(refs); err != nil {
- return err
+ tags := fetchedRefs
+ if isWildcard {
+ tags = remoteRefs
+ }
+ tagUpdated, err := r.buildFetchedTags(tags)
+ if err != nil {
+ return updated, err
}
- if !updated {
- return NoErrAlreadyUpToDate
+ if tagUpdated {
+ updated = true
}
- return nil
+
+ return
}
-func (r *Remote) buildFetchedTags(refs memory.ReferenceStorage) error {
- updated := false
+func (r *Remote) buildFetchedTags(refs memory.ReferenceStorage) (updated bool, err error) {
for _, ref := range refs {
if !ref.IsTag() {
continue
@@ -574,18 +599,20 @@ func (r *Remote) buildFetchedTags(refs memory.ReferenceStorage) error {
}
if err != nil {
- return err
+ return false, err
}
- if err = r.s.SetReference(ref); err != nil {
- return err
+ refUpdated, err := updateReferenceStorerIfNeeded(r.s, ref)
+ if err != nil {
+ return updated, err
+ }
+
+ if refUpdated {
+ updated = true
}
- updated = true
- }
- if !updated {
- return NoErrAlreadyUpToDate
}
- return nil
+
+ return
}
func objectsToPush(commands []*packp.Command) ([]plumbing.Hash, error) {