@@ -47,7 +47,7 @@ func (r *Remote) String() string {
47
47
48
48
// Fetch fetches references from the remote to the local repository.
49
49
// 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.
51
51
func (r * Remote ) Fetch (o * FetchOptions ) error {
52
52
_ , err := r .fetch (o )
53
53
return err
@@ -156,24 +156,26 @@ func (r *Remote) fetch(o *FetchOptions) (refs storer.ReferenceStorer, err error)
156
156
}
157
157
158
158
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
+ }
162
164
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
+ }
166
168
}
167
169
168
- if err := r .fetchPack (o , s , req ); err != nil {
170
+ err = r .updateLocalReferenceStorage (o .RefSpecs , remoteRefs )
171
+ if err != nil && err != NoErrAlreadyUpToDate {
169
172
return nil , err
170
173
}
171
174
172
- if err := r . updateLocalReferenceStorage ( o . RefSpecs , remoteRefs ); err != nil {
173
- return nil , err
175
+ if len ( req . Wants ) == 0 {
176
+ return remoteRefs , err
174
177
}
175
-
176
- return remoteRefs , err
178
+ return remoteRefs , nil
177
179
}
178
180
179
181
func newUploadPackSession (url string , auth transport.AuthMethod ) (transport.UploadPackSession , error ) {
@@ -473,6 +475,7 @@ func buildSidebandIfSupported(l *capability.List, reader io.Reader, p sideband.P
473
475
}
474
476
475
477
func (r * Remote ) updateLocalReferenceStorage (specs []config.RefSpec , refs memory.ReferenceStorage ) error {
478
+ updated := false
476
479
for _ , spec := range specs {
477
480
for _ , ref := range refs {
478
481
if ! spec .Match (ref .Name ()) {
@@ -484,38 +487,55 @@ func (r *Remote) updateLocalReferenceStorage(specs []config.RefSpec, refs memory
484
487
}
485
488
486
489
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 {
489
492
return err
490
493
}
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
+ }
491
501
}
492
502
}
493
503
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 {
500
505
return err
501
506
}
502
507
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 {
504
517
if ! ref .IsTag () {
505
- return nil
518
+ continue
506
519
}
507
520
508
521
_ , err := r .s .EncodedObject (plumbing .AnyObject , ref .Hash ())
509
522
if err == plumbing .ErrObjectNotFound {
510
- return nil
523
+ continue
511
524
}
512
525
513
526
if err != nil {
514
527
return err
515
528
}
516
529
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
519
539
}
520
540
521
541
func objectsToPush (commands []* packp.Command ) ([]plumbing.Hash , error ) {
0 commit comments