@@ -460,32 +460,60 @@ func (d *DotGit) addRefsFromPackedRefs(refs *[]*plumbing.Reference, seen map[plu
460460 return nil
461461}
462462
463- func (d * DotGit ) rewritePackedRefsWithoutRef ( name plumbing. ReferenceName ) (err error ) {
464- f , err := d . fs . Open ( packedRefsPath )
465- if err != nil {
466- if os . IsNotExist ( err ) {
467- return nil
463+ func (d * DotGit ) openAndLockPackedRefs ( ) (pr billy. File , err error ) {
464+ var f billy. File
465+ defer func () {
466+ if err != nil && f != nil {
467+ ioutil . CheckClose ( f , & err )
468468 }
469+ }()
469470
470- return err
471- }
472- defer ioutil .CheckClose (f , & err )
471+ // Keep trying to open and lock the file until we're sure the file
472+ // didn't change between the open and the lock.
473+ for {
474+ f , err = d .fs .Open (packedRefsPath )
475+ if err != nil {
476+ if os .IsNotExist (err ) {
477+ return nil , nil
478+ }
473479
474- err = f .Lock ()
475- if err != nil {
476- return err
477- }
480+ return nil , err
481+ }
482+ fi , err := d .fs .Stat (packedRefsPath )
483+ if err != nil {
484+ return nil , err
485+ }
486+ mtime := fi .ModTime ()
478487
479- // Re-open the file after locking, since it could have been
480- // renamed over by a new file during the Lock process.
481- pr , err := d .fs .Open (packedRefsPath )
482- if err != nil {
483- if os .IsNotExist (err ) {
484- return nil
488+ err = f .Lock ()
489+ if err != nil {
490+ return nil , err
491+ }
492+
493+ fi , err = d .fs .Stat (packedRefsPath )
494+ if err != nil {
495+ return nil , err
496+ }
497+ if mtime == fi .ModTime () {
498+ break
485499 }
500+ // The file has changed since we opened it. Close and retry.
501+ err = f .Close ()
502+ if err != nil {
503+ return nil , err
504+ }
505+ }
506+ return f , nil
507+ }
486508
509+ func (d * DotGit ) rewritePackedRefsWithoutRef (name plumbing.ReferenceName ) (err error ) {
510+ pr , err := d .openAndLockPackedRefs ()
511+ if err != nil {
487512 return err
488513 }
514+ if pr == nil {
515+ return nil
516+ }
489517 doClosePR := true
490518 defer func () {
491519 if doClosePR {
0 commit comments