diff options
author | Máximo Cuadros <mcuadros@gmail.com> | 2018-12-10 23:46:47 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-10 23:46:47 +0100 |
commit | 94ddfeb46ae98274afb8089f2bedfe48ee90b3b9 (patch) | |
tree | af8c16b7cba5afdb192a7e5b9b967e0f12db2227 /storage/filesystem/dotgit/dotgit_setref.go | |
parent | 443abf89696c62d46e0c3e567c8ba380ff974d0d (diff) | |
parent | 681855bf2cccd9afa85f50fa0e2ae9e05b54d3b5 (diff) | |
download | go-git-94ddfeb46ae98274afb8089f2bedfe48ee90b3b9.tar.gz |
Merge pull request #1036 from jfontan/fix/capabilities-setref
storage/dotgit: use fs capabilities in setRef
Diffstat (limited to 'storage/filesystem/dotgit/dotgit_setref.go')
-rw-r--r-- | storage/filesystem/dotgit/dotgit_setref.go | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/storage/filesystem/dotgit/dotgit_setref.go b/storage/filesystem/dotgit/dotgit_setref.go index d27c1a3..9da2f31 100644 --- a/storage/filesystem/dotgit/dotgit_setref.go +++ b/storage/filesystem/dotgit/dotgit_setref.go @@ -1,15 +1,24 @@ -// +build !norwfs - package dotgit import ( + "fmt" "os" "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/utils/ioutil" + + "gopkg.in/src-d/go-billy.v4" ) func (d *DotGit) setRef(fileName, content string, old *plumbing.Reference) (err error) { + if billy.CapabilityCheck(d.fs, billy.ReadAndWriteCapability) { + return d.setRefRwfs(fileName, content, old) + } + + return d.setRefNorwfs(fileName, content, old) +} + +func (d *DotGit) setRefRwfs(fileName, content string, old *plumbing.Reference) (err error) { // If we are not checking an old ref, just truncate the file. mode := os.O_RDWR | os.O_CREATE if old == nil { @@ -41,3 +50,41 @@ func (d *DotGit) setRef(fileName, content string, old *plumbing.Reference) (err _, err = f.Write([]byte(content)) return err } + +// There are some filesystems that don't support opening files in RDWD mode. +// In these filesystems the standard SetRef function can not be used as it +// reads the reference file to check that it's not modified before updating it. +// +// This version of the function writes the reference without extra checks +// making it compatible with these simple filesystems. This is usually not +// a problem as they should be accessed by only one process at a time. +func (d *DotGit) setRefNorwfs(fileName, content string, old *plumbing.Reference) error { + _, err := d.fs.Stat(fileName) + if err == nil && old != nil { + fRead, err := d.fs.Open(fileName) + if err != nil { + return err + } + + ref, err := d.readReferenceFrom(fRead, old.Name().String()) + fRead.Close() + + if err != nil { + return err + } + + if ref.Hash() != old.Hash() { + return fmt.Errorf("reference has changed concurrently") + } + } + + f, err := d.fs.Create(fileName) + if err != nil { + return err + } + + defer f.Close() + + _, err = f.Write([]byte(content)) + return err +} |