@@ -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
591618func objectsToPush (commands []* packp.Command ) ([]plumbing.Hash , error ) {
0 commit comments