@@ -178,7 +178,7 @@ func (r *Repository) Clone(o *CloneOptions) error {
178178 return err
179179 }
180180
181- if err := r .createReferences (c .Fetch , o .ReferenceName , head ); err != nil {
181+ if _ , err := r .updateReferences (c .Fetch , o .ReferenceName , head ); err != nil {
182182 return err
183183 }
184184
@@ -239,31 +239,42 @@ func (r *Repository) updateRemoteConfig(remote *Remote, o *CloneOptions,
239239 return r .s .SetConfig (cfg )
240240}
241241
242- func (r * Repository ) createReferences (spec []config.RefSpec ,
243- headName plumbing.ReferenceName , resolvedHead * plumbing.Reference ) error {
242+ func (r * Repository ) updateReferences (spec []config.RefSpec ,
243+ headName plumbing.ReferenceName , resolvedHead * plumbing.Reference ) ( updated bool , err error ) {
244244
245245 if ! resolvedHead .IsBranch () {
246246 // Detached HEAD mode
247247 head := plumbing .NewHashReference (plumbing .HEAD , resolvedHead .Hash ())
248- return r .s . SetReference ( head )
248+ return updateReferenceStorerIfNeeded ( r .s , head )
249249 }
250250
251- // Create local reference for the resolved head
252- if err := r .s .SetReference (resolvedHead ); err != nil {
253- return err
251+ refs := []* plumbing.Reference {
252+ // Create local reference for the resolved head
253+ resolvedHead ,
254+ // Create local symbolic HEAD
255+ plumbing .NewSymbolicReference (plumbing .HEAD , resolvedHead .Name ()),
254256 }
255257
256- // Create local symbolic HEAD
257- head := plumbing .NewSymbolicReference (plumbing .HEAD , resolvedHead .Name ())
258- if err := r .s .SetReference (head ); err != nil {
259- return err
258+ refs = append (refs , r .calculateRemoteHeadReference (spec , resolvedHead )... )
259+
260+ for _ , ref := range refs {
261+ u , err := updateReferenceStorerIfNeeded (r .s , ref )
262+ if err != nil {
263+ return updated , err
264+ }
265+
266+ if u {
267+ updated = true
268+ }
260269 }
261270
262- return r . createRemoteHeadReference ( spec , resolvedHead )
271+ return
263272}
264273
265- func (r * Repository ) createRemoteHeadReference (spec []config.RefSpec ,
266- resolvedHead * plumbing.Reference ) error {
274+ func (r * Repository ) calculateRemoteHeadReference (spec []config.RefSpec ,
275+ resolvedHead * plumbing.Reference ) []* plumbing.Reference {
276+
277+ var refs []* plumbing.Reference
267278
268279 // Create resolved HEAD reference with remote prefix if it does not
269280 // exist. This is needed when using single branch and HEAD.
@@ -276,20 +287,31 @@ func (r *Repository) createRemoteHeadReference(spec []config.RefSpec,
276287 name = rs .Dst (name )
277288 _ , err := r .s .Reference (name )
278289 if err == plumbing .ErrReferenceNotFound {
279- ref := plumbing .NewHashReference (name , resolvedHead .Hash ())
280- if err := r .s .SetReference (ref ); err != nil {
281- return err
282- }
283-
284- continue
290+ refs = append (refs , plumbing .NewHashReference (name , resolvedHead .Hash ()))
285291 }
292+ }
286293
287- if err != nil {
288- return err
294+ return refs
295+ }
296+
297+ func updateReferenceStorerIfNeeded (
298+ s storer.ReferenceStorer , r * plumbing.Reference ) (updated bool , err error ) {
299+
300+ p , err := s .Reference (r .Name ())
301+ if err != nil && err != plumbing .ErrReferenceNotFound {
302+ return false , err
303+ }
304+
305+ // we use the string method to compare references, is the easiest way
306+ if err == plumbing .ErrReferenceNotFound || r .String () != p .String () {
307+ if err := s .SetReference (r ); err != nil {
308+ return false , err
289309 }
310+
311+ return true , nil
290312 }
291313
292- return nil
314+ return false , nil
293315}
294316
295317// IsEmpty returns true if the repository is empty
@@ -322,7 +344,11 @@ func (r *Repository) Pull(o *PullOptions) error {
322344 remoteRefs , err := remote .fetch (& FetchOptions {
323345 Depth : o .Depth ,
324346 })
325- if err != nil {
347+
348+ updated := true
349+ if err == NoErrAlreadyUpToDate {
350+ updated = false
351+ } else if err != nil {
326352 return err
327353 }
328354
@@ -331,7 +357,20 @@ func (r *Repository) Pull(o *PullOptions) error {
331357 return err
332358 }
333359
334- return r .createReferences (remote .c .Fetch , o .ReferenceName , head )
360+ refsUpdated , err := r .updateReferences (remote .c .Fetch , o .ReferenceName , head )
361+ if err != nil {
362+ return err
363+ }
364+
365+ if refsUpdated {
366+ updated = refsUpdated
367+ }
368+
369+ if ! updated {
370+ return NoErrAlreadyUpToDate
371+ }
372+
373+ return nil
335374}
336375
337376// Fetch fetches changes from a remote repository.
0 commit comments