diff options
author | Jeremy Stribling <strib@alum.mit.edu> | 2017-11-02 16:30:51 -0700 |
---|---|---|
committer | Jeremy Stribling <strib@alum.mit.edu> | 2017-11-29 10:37:30 -0800 |
commit | d50161181583f7767038de58eff8ee204de7646d (patch) | |
tree | 108ce8becf34ffafdce7b3bb82100ef55fe0188d /storage/filesystem | |
parent | 3447303ce76caa3a22e9f510fa00e73f5143267e (diff) | |
download | go-git-d50161181583f7767038de58eff8ee204de7646d.tar.gz |
dotgit: during rewriting, re-open packed-refs after locking
The file could have been completely replaced while waiting for the
lock, so we need to re-open, otherwise we might be reading a stale
file that has already been deleted/overwritten.
Diffstat (limited to 'storage/filesystem')
-rw-r--r-- | storage/filesystem/internal/dotgit/dotgit.go | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/storage/filesystem/internal/dotgit/dotgit.go b/storage/filesystem/internal/dotgit/dotgit.go index 330f9d5..8b1df3d 100644 --- a/storage/filesystem/internal/dotgit/dotgit.go +++ b/storage/filesystem/internal/dotgit/dotgit.go @@ -421,18 +421,30 @@ func (d *DotGit) rewritePackedRefsWithoutRef(name plumbing.ReferenceName) (err e return err } - doCloseF := true - defer func() { - if doCloseF { - ioutil.CheckClose(f, &err) - } - }() + defer ioutil.CheckClose(f, &err) err = f.Lock() if err != nil { return err } + // 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 + } + + return err + } + doClosePR := true + defer func() { + if doClosePR { + ioutil.CheckClose(pr, &err) + } + }() + // Creating the temp file in the same directory as the target file // improves our chances for rename operation to be atomic. tmp, err := d.fs.TempFile("", tmpPackedRefsPrefix) @@ -446,7 +458,7 @@ func (d *DotGit) rewritePackedRefsWithoutRef(name plumbing.ReferenceName) (err e } }() - s := bufio.NewScanner(f) + s := bufio.NewScanner(pr) found := false for s.Scan() { line := s.Text() @@ -479,8 +491,8 @@ func (d *DotGit) rewritePackedRefsWithoutRef(name plumbing.ReferenceName) (err e return d.fs.Remove(tmp.Name()) } - doCloseF = false - if err := f.Close(); err != nil { + doClosePR = false + if err := pr.Close(); err != nil { return err } |