From d50161181583f7767038de58eff8ee204de7646d Mon Sep 17 00:00:00 2001 From: Jeremy Stribling Date: Thu, 2 Nov 2017 16:30:51 -0700 Subject: 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. --- storage/filesystem/internal/dotgit/dotgit.go | 30 +++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'storage/filesystem/internal/dotgit') 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 } -- cgit