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

Commit cbdb258

Browse files
committed
remote: fetch, correct behaviour on tags
1 parent 6b3a6df commit cbdb258

File tree

3 files changed

+205
-109
lines changed

3 files changed

+205
-109
lines changed

options.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,18 @@ func (o *PullOptions) Validate() error {
103103
return nil
104104
}
105105

106+
type TagFetchMode int
107+
108+
var (
109+
// TagFollowing any tag that points into the histories being fetched is also
110+
// fetched. TagFollowing requires a server with `include-tag` capability
111+
// in order to fetch the annotated tags objects.
112+
TagFollowing TagFetchMode = 0
113+
// AllTags fetch all tags from the remote (i.e., fetch remote tags
114+
// refs/tags/* into local tags with the same name)
115+
AllTags TagFetchMode = 1
116+
)
117+
106118
// FetchOptions describes how a fetch should be performed
107119
type FetchOptions struct {
108120
// Name of the remote to fetch from. Defaults to origin.
@@ -117,6 +129,9 @@ type FetchOptions struct {
117129
// stored, if nil nothing is stored and the capability (if supported)
118130
// no-progress, is sent to the server to avoid send this information.
119131
Progress sideband.Progress
132+
// Tags describe how the tags will be fetched from the remote repository,
133+
// by default is TagFollowing.
134+
Tags TagFetchMode
120135
}
121136

122137
// Validate validates the fields and sets the default values.

remote.go

Lines changed: 83 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ func (r *Remote) Push(o *PushOptions) (err error) {
134134
return rs.Error()
135135
}
136136

137-
func (r *Remote) fetch(o *FetchOptions) (refs storer.ReferenceStorer, err error) {
137+
func (r *Remote) fetch(o *FetchOptions) (storer.ReferenceStorer, error) {
138138
if o.RemoteName == "" {
139139
o.RemoteName = r.c.Name
140140
}
@@ -169,7 +169,12 @@ func (r *Remote) fetch(o *FetchOptions) (refs storer.ReferenceStorer, err error)
169169
return nil, err
170170
}
171171

172-
req.Wants, err = getWants(o.RefSpecs, r.s, remoteRefs)
172+
refs, err := calculateRefs(o.RefSpecs, remoteRefs, o.Tags)
173+
if err != nil {
174+
return nil, err
175+
}
176+
177+
req.Wants, err = getWants(r.s, refs)
173178
if len(req.Wants) > 0 {
174179
req.Haves, err = getHaves(r.s)
175180
if err != nil {
@@ -181,14 +186,15 @@ func (r *Remote) fetch(o *FetchOptions) (refs storer.ReferenceStorer, err error)
181186
}
182187
}
183188

184-
err = r.updateLocalReferenceStorage(o.RefSpecs, remoteRefs)
185-
if err != nil && err != NoErrAlreadyUpToDate {
189+
updated, err := r.updateLocalReferenceStorage(o.RefSpecs, refs, remoteRefs)
190+
if err != nil {
186191
return nil, err
187192
}
188193

189-
if len(req.Wants) == 0 {
190-
return remoteRefs, err
194+
if !updated {
195+
return remoteRefs, NoErrAlreadyUpToDate
191196
}
197+
192198
return remoteRefs, nil
193199
}
194200

@@ -372,56 +378,52 @@ func getHaves(localRefs storer.ReferenceStorer) ([]plumbing.Hash, error) {
372378
return haves, nil
373379
}
374380

375-
func getWants(
376-
spec []config.RefSpec, localStorer storage.Storer, remoteRefs storer.ReferenceStorer,
377-
) ([]plumbing.Hash, error) {
378-
wantTags := true
379-
for _, s := range spec {
380-
if !s.IsWildcard() {
381-
wantTags = false
382-
break
383-
}
384-
}
385-
381+
func calculateRefs(spec []config.RefSpec,
382+
remoteRefs storer.ReferenceStorer,
383+
tags TagFetchMode,
384+
) (memory.ReferenceStorage, error) {
386385
iter, err := remoteRefs.IterReferences()
387386
if err != nil {
388387
return nil, err
389388
}
390389

391-
wants := map[plumbing.Hash]bool{}
392-
err = iter.ForEach(func(ref *plumbing.Reference) error {
390+
refs := make(memory.ReferenceStorage, 0)
391+
return refs, iter.ForEach(func(ref *plumbing.Reference) error {
393392
if !config.MatchAny(spec, ref.Name()) {
394-
if !ref.IsTag() || !wantTags {
393+
if !ref.IsTag() || tags != AllTags {
395394
return nil
396395
}
397396
}
398397

399398
if ref.Type() == plumbing.SymbolicReference {
400-
ref, err = storer.ResolveReference(remoteRefs, ref.Name())
399+
target, err := storer.ResolveReference(remoteRefs, ref.Name())
401400
if err != nil {
402401
return err
403402
}
403+
404+
ref = plumbing.NewHashReference(ref.Name(), target.Hash())
404405
}
405406

406407
if ref.Type() != plumbing.HashReference {
407408
return nil
408409
}
409410

410-
hash := ref.Hash()
411+
return refs.SetReference(ref)
412+
})
413+
}
411414

412-
exists, err := objectExists(localStorer, hash)
415+
func getWants(localStorer storage.Storer, refs memory.ReferenceStorage) ([]plumbing.Hash, error) {
416+
wants := map[plumbing.Hash]bool{}
417+
for _, ref := range refs {
418+
hash := ref.Hash()
419+
exists, err := objectExists(localStorer, ref.Hash())
413420
if err != nil {
414-
return err
421+
return nil, err
415422
}
416423

417424
if !exists {
418425
wants[hash] = true
419426
}
420-
421-
return nil
422-
})
423-
if err != nil {
424-
return nil, err
425427
}
426428

427429
var result []plumbing.Hash
@@ -503,6 +505,19 @@ func (r *Remote) newUploadPackRequest(o *FetchOptions,
503505
}
504506
}
505507

508+
isWildcard := true
509+
for _, s := range o.RefSpecs {
510+
if !s.IsWildcard() {
511+
isWildcard = false
512+
}
513+
}
514+
515+
if isWildcard && o.Tags == TagFollowing && ar.Capabilities.Supports(capability.IncludeTag) {
516+
if err := req.Capabilities.Set(capability.IncludeTag); err != nil {
517+
return nil, err
518+
}
519+
}
520+
506521
return req, nil
507522
}
508523

@@ -524,10 +539,17 @@ func buildSidebandIfSupported(l *capability.List, reader io.Reader, p sideband.P
524539
return d
525540
}
526541

527-
func (r *Remote) updateLocalReferenceStorage(specs []config.RefSpec, refs memory.ReferenceStorage) error {
528-
updated := false
542+
func (r *Remote) updateLocalReferenceStorage(
543+
specs []config.RefSpec,
544+
fetchedRefs, remoteRefs memory.ReferenceStorage,
545+
) (updated bool, err error) {
546+
isWildcard := true
529547
for _, spec := range specs {
530-
for _, ref := range refs {
548+
if !spec.IsWildcard() {
549+
isWildcard = false
550+
}
551+
552+
for _, ref := range fetchedRefs {
531553
if !spec.Match(ref.Name()) {
532554
continue
533555
}
@@ -536,33 +558,36 @@ func (r *Remote) updateLocalReferenceStorage(specs []config.RefSpec, refs memory
536558
continue
537559
}
538560

539-
name := spec.Dst(ref.Name())
540-
sref, err := r.s.Reference(name)
541-
if err != nil && err != plumbing.ErrReferenceNotFound {
542-
return err
561+
new := plumbing.NewHashReference(spec.Dst(ref.Name()), ref.Hash())
562+
563+
refUpdated, err := updateReferenceStorerIfNeeded(r.s, new)
564+
if err != nil {
565+
return updated, err
543566
}
544-
if err == plumbing.ErrReferenceNotFound || sref.Hash() != ref.Hash() {
545-
n := plumbing.NewHashReference(name, ref.Hash())
546-
if err := r.s.SetReference(n); err != nil {
547-
return err
548-
}
567+
568+
if refUpdated {
549569
updated = true
550570
}
551571
}
552572
}
553573

554-
if err := r.buildFetchedTags(refs); err != nil {
555-
return err
574+
tags := fetchedRefs
575+
if isWildcard {
576+
tags = remoteRefs
577+
}
578+
tagUpdated, err := r.buildFetchedTags(tags)
579+
if err != nil {
580+
return updated, err
556581
}
557582

558-
if !updated {
559-
return NoErrAlreadyUpToDate
583+
if tagUpdated {
584+
updated = true
560585
}
561-
return nil
586+
587+
return
562588
}
563589

564-
func (r *Remote) buildFetchedTags(refs memory.ReferenceStorage) error {
565-
updated := false
590+
func (r *Remote) buildFetchedTags(refs memory.ReferenceStorage) (updated bool, err error) {
566591
for _, ref := range refs {
567592
if !ref.IsTag() {
568593
continue
@@ -574,18 +599,20 @@ func (r *Remote) buildFetchedTags(refs memory.ReferenceStorage) error {
574599
}
575600

576601
if err != nil {
577-
return err
602+
return false, err
578603
}
579604

580-
if err = r.s.SetReference(ref); err != nil {
581-
return err
605+
refUpdated, err := updateReferenceStorerIfNeeded(r.s, ref)
606+
if err != nil {
607+
return updated, err
608+
}
609+
610+
if refUpdated {
611+
updated = true
582612
}
583-
updated = true
584-
}
585-
if !updated {
586-
return NoErrAlreadyUpToDate
587613
}
588-
return nil
614+
615+
return
589616
}
590617

591618
func objectsToPush(commands []*packp.Command) ([]plumbing.Hash, error) {

0 commit comments

Comments
 (0)