@@ -134,7 +134,7 @@ func (r *Remote) Push(o *PushOptions) (err error) {
134
134
return rs .Error ()
135
135
}
136
136
137
- func (r * Remote ) fetch (o * FetchOptions ) (refs storer.ReferenceStorer , err error ) {
137
+ func (r * Remote ) fetch (o * FetchOptions ) (storer.ReferenceStorer , error ) {
138
138
if o .RemoteName == "" {
139
139
o .RemoteName = r .c .Name
140
140
}
@@ -169,7 +169,12 @@ func (r *Remote) fetch(o *FetchOptions) (refs storer.ReferenceStorer, err error)
169
169
return nil , err
170
170
}
171
171
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 )
173
178
if len (req .Wants ) > 0 {
174
179
req .Haves , err = getHaves (r .s )
175
180
if err != nil {
@@ -181,14 +186,15 @@ func (r *Remote) fetch(o *FetchOptions) (refs storer.ReferenceStorer, err error)
181
186
}
182
187
}
183
188
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 {
186
191
return nil , err
187
192
}
188
193
189
- if len ( req . Wants ) == 0 {
190
- return remoteRefs , err
194
+ if ! updated {
195
+ return remoteRefs , NoErrAlreadyUpToDate
191
196
}
197
+
192
198
return remoteRefs , nil
193
199
}
194
200
@@ -372,56 +378,52 @@ func getHaves(localRefs storer.ReferenceStorer) ([]plumbing.Hash, error) {
372
378
return haves , nil
373
379
}
374
380
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 ) {
386
385
iter , err := remoteRefs .IterReferences ()
387
386
if err != nil {
388
387
return nil , err
389
388
}
390
389
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 {
393
392
if ! config .MatchAny (spec , ref .Name ()) {
394
- if ! ref .IsTag () || ! wantTags {
393
+ if ! ref .IsTag () || tags != AllTags {
395
394
return nil
396
395
}
397
396
}
398
397
399
398
if ref .Type () == plumbing .SymbolicReference {
400
- ref , err = storer .ResolveReference (remoteRefs , ref .Name ())
399
+ target , err : = storer .ResolveReference (remoteRefs , ref .Name ())
401
400
if err != nil {
402
401
return err
403
402
}
403
+
404
+ ref = plumbing .NewHashReference (ref .Name (), target .Hash ())
404
405
}
405
406
406
407
if ref .Type () != plumbing .HashReference {
407
408
return nil
408
409
}
409
410
410
- hash := ref .Hash ()
411
+ return refs .SetReference (ref )
412
+ })
413
+ }
411
414
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 ())
413
420
if err != nil {
414
- return err
421
+ return nil , err
415
422
}
416
423
417
424
if ! exists {
418
425
wants [hash ] = true
419
426
}
420
-
421
- return nil
422
- })
423
- if err != nil {
424
- return nil , err
425
427
}
426
428
427
429
var result []plumbing.Hash
@@ -503,6 +505,19 @@ func (r *Remote) newUploadPackRequest(o *FetchOptions,
503
505
}
504
506
}
505
507
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
+
506
521
return req , nil
507
522
}
508
523
@@ -524,10 +539,17 @@ func buildSidebandIfSupported(l *capability.List, reader io.Reader, p sideband.P
524
539
return d
525
540
}
526
541
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
529
547
for _ , spec := range specs {
530
- for _ , ref := range refs {
548
+ if ! spec .IsWildcard () {
549
+ isWildcard = false
550
+ }
551
+
552
+ for _ , ref := range fetchedRefs {
531
553
if ! spec .Match (ref .Name ()) {
532
554
continue
533
555
}
@@ -536,33 +558,36 @@ func (r *Remote) updateLocalReferenceStorage(specs []config.RefSpec, refs memory
536
558
continue
537
559
}
538
560
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
543
566
}
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 {
549
569
updated = true
550
570
}
551
571
}
552
572
}
553
573
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
556
581
}
557
582
558
- if ! updated {
559
- return NoErrAlreadyUpToDate
583
+ if tagUpdated {
584
+ updated = true
560
585
}
561
- return nil
586
+
587
+ return
562
588
}
563
589
564
- func (r * Remote ) buildFetchedTags (refs memory.ReferenceStorage ) error {
565
- updated := false
590
+ func (r * Remote ) buildFetchedTags (refs memory.ReferenceStorage ) (updated bool , err error ) {
566
591
for _ , ref := range refs {
567
592
if ! ref .IsTag () {
568
593
continue
@@ -574,18 +599,20 @@ func (r *Remote) buildFetchedTags(refs memory.ReferenceStorage) error {
574
599
}
575
600
576
601
if err != nil {
577
- return err
602
+ return false , err
578
603
}
579
604
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
582
612
}
583
- updated = true
584
- }
585
- if ! updated {
586
- return NoErrAlreadyUpToDate
587
613
}
588
- return nil
614
+
615
+ return
589
616
}
590
617
591
618
func objectsToPush (commands []* packp.Command ) ([]plumbing.Hash , error ) {
0 commit comments