@@ -47,7 +47,7 @@ func (r *Remote) String() string {
4747
4848// Fetch fetches references from the remote to the local repository.
4949// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
50- // no changes to be fetched, or an error.
50+ // no changes to be fetched and no local references to update , or an error.
5151func (r * Remote ) Fetch (o * FetchOptions ) error {
5252 _ , err := r .fetch (o )
5353 return err
@@ -156,24 +156,26 @@ func (r *Remote) fetch(o *FetchOptions) (refs storer.ReferenceStorer, err error)
156156 }
157157
158158 req .Wants , err = getWants (o .RefSpecs , r .s , remoteRefs )
159- if len (req .Wants ) == 0 {
160- return remoteRefs , NoErrAlreadyUpToDate
161- }
159+ if len (req .Wants ) > 0 {
160+ req .Haves , err = getHaves (r .s )
161+ if err != nil {
162+ return nil , err
163+ }
162164
163- req . Haves , err = getHaves ( r . s )
164- if err != nil {
165- return nil , err
165+ if err := r . fetchPack ( o , s , req ); err != nil {
166+ return nil , err
167+ }
166168 }
167169
168- if err := r .fetchPack (o , s , req ); err != nil {
170+ err = r .updateLocalReferenceStorage (o .RefSpecs , remoteRefs )
171+ if err != nil && err != NoErrAlreadyUpToDate {
169172 return nil , err
170173 }
171174
172- if err := r . updateLocalReferenceStorage ( o . RefSpecs , remoteRefs ); err != nil {
173- return nil , err
175+ if len ( req . Wants ) == 0 {
176+ return remoteRefs , err
174177 }
175-
176- return remoteRefs , err
178+ return remoteRefs , nil
177179}
178180
179181func newUploadPackSession (url string , auth transport.AuthMethod ) (transport.UploadPackSession , error ) {
@@ -473,6 +475,7 @@ func buildSidebandIfSupported(l *capability.List, reader io.Reader, p sideband.P
473475}
474476
475477func (r * Remote ) updateLocalReferenceStorage (specs []config.RefSpec , refs memory.ReferenceStorage ) error {
478+ updated := false
476479 for _ , spec := range specs {
477480 for _ , ref := range refs {
478481 if ! spec .Match (ref .Name ()) {
@@ -484,38 +487,55 @@ func (r *Remote) updateLocalReferenceStorage(specs []config.RefSpec, refs memory
484487 }
485488
486489 name := spec .Dst (ref .Name ())
487- n := plumbing . NewHashReference ( name , ref . Hash () )
488- if err := r . s . SetReference ( n ); err != nil {
490+ sref , err := r . s . Reference ( name )
491+ if err != nil && err != plumbing . ErrReferenceNotFound {
489492 return err
490493 }
494+ if err == plumbing .ErrReferenceNotFound || sref .Hash () != ref .Hash () {
495+ n := plumbing .NewHashReference (name , ref .Hash ())
496+ if err := r .s .SetReference (n ); err != nil {
497+ return err
498+ }
499+ updated = true
500+ }
491501 }
492502 }
493503
494- return r .buildFetchedTags (refs )
495- }
496-
497- func (r * Remote ) buildFetchedTags (refs storer.ReferenceStorer ) error {
498- iter , err := refs .IterReferences ()
499- if err != nil {
504+ if err := r .buildFetchedTags (refs ); err != nil {
500505 return err
501506 }
502507
503- return iter .ForEach (func (ref * plumbing.Reference ) error {
508+ if ! updated {
509+ return NoErrAlreadyUpToDate
510+ }
511+ return nil
512+ }
513+
514+ func (r * Remote ) buildFetchedTags (refs memory.ReferenceStorage ) error {
515+ updated := false
516+ for _ , ref := range refs {
504517 if ! ref .IsTag () {
505- return nil
518+ continue
506519 }
507520
508521 _ , err := r .s .EncodedObject (plumbing .AnyObject , ref .Hash ())
509522 if err == plumbing .ErrObjectNotFound {
510- return nil
523+ continue
511524 }
512525
513526 if err != nil {
514527 return err
515528 }
516529
517- return r .s .SetReference (ref )
518- })
530+ if err = r .s .SetReference (ref ); err != nil {
531+ return err
532+ }
533+ updated = true
534+ }
535+ if ! updated {
536+ return NoErrAlreadyUpToDate
537+ }
538+ return nil
519539}
520540
521541func objectsToPush (commands []* packp.Command ) ([]plumbing.Hash , error ) {
0 commit comments