diff options
author | Jeremy Stribling <strib@alum.mit.edu> | 2017-11-29 17:10:43 -0800 |
---|---|---|
committer | Jeremy Stribling <strib@alum.mit.edu> | 2017-11-29 17:12:45 -0800 |
commit | 5a6cc4e0996d1dd6c66d46ced92dee26c3121628 (patch) | |
tree | 4c8a389b4cdc4dec5278b956b2a363a1f7d7eeac /storage | |
parent | c2e6b5dcf8ff1cb6b61f4a165e526af209c6c185 (diff) | |
download | go-git-5a6cc4e0996d1dd6c66d46ced92dee26c3121628.tar.gz |
dotgit: open+lock packed-refs file until it doesn't change
Windows doesn't like it when we re-open a file we already have locked.
Diffstat (limited to 'storage')
-rw-r--r-- | storage/filesystem/internal/dotgit/dotgit.go | 64 |
1 files changed, 46 insertions, 18 deletions
diff --git a/storage/filesystem/internal/dotgit/dotgit.go b/storage/filesystem/internal/dotgit/dotgit.go index cd4f517..3a12385 100644 --- a/storage/filesystem/internal/dotgit/dotgit.go +++ b/storage/filesystem/internal/dotgit/dotgit.go @@ -460,32 +460,60 @@ func (d *DotGit) addRefsFromPackedRefs(refs *[]*plumbing.Reference, seen map[plu return nil } -func (d *DotGit) rewritePackedRefsWithoutRef(name plumbing.ReferenceName) (err error) { - f, err := d.fs.Open(packedRefsPath) - if err != nil { - if os.IsNotExist(err) { - return nil +func (d *DotGit) openAndLockPackedRefs() (pr billy.File, err error) { + var f billy.File + defer func() { + if err != nil && f != nil { + ioutil.CheckClose(f, &err) } + }() - return err - } - defer ioutil.CheckClose(f, &err) + // Keep trying to open and lock the file until we're sure the file + // didn't change between the open and the lock. + for { + f, err = d.fs.Open(packedRefsPath) + if err != nil { + if os.IsNotExist(err) { + return nil, nil + } - err = f.Lock() - if err != nil { - return err - } + return nil, err + } + fi, err := d.fs.Stat(packedRefsPath) + if err != nil { + return nil, err + } + mtime := fi.ModTime() - // Re-open the file after locking, since it could have been - // renamed over by a new file during the Lock process. - pr, err := d.fs.Open(packedRefsPath) - if err != nil { - if os.IsNotExist(err) { - return nil + err = f.Lock() + if err != nil { + return nil, err + } + + fi, err = d.fs.Stat(packedRefsPath) + if err != nil { + return nil, err + } + if mtime == fi.ModTime() { + break } + // The file has changed since we opened it. Close and retry. + err = f.Close() + if err != nil { + return nil, err + } + } + return f, nil +} +func (d *DotGit) rewritePackedRefsWithoutRef(name plumbing.ReferenceName) (err error) { + pr, err := d.openAndLockPackedRefs() + if err != nil { return err } + if pr == nil { + return nil + } doClosePR := true defer func() { if doClosePR { |