diff options
author | Máximo Cuadros <mcuadros@gmail.com> | 2018-07-06 11:28:18 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-06 11:28:18 +0200 |
commit | 8ad72db0b7e1c03d9fad343890e469d5c3ed757b (patch) | |
tree | 16f8efddca3778a35947a4a6306f7ba96c194e31 /storage/filesystem/dotgit/dotgit_rewrite_packed_refs.go | |
parent | fcfd239c49baee9195f7b8234f46288a29c3951c (diff) | |
parent | da5d474fb43dffd1b28cd5662b3a5bf7e446cd5c (diff) | |
download | go-git-8ad72db0b7e1c03d9fad343890e469d5c3ed757b.tar.gz |
Merge pull request #864 from smola/no-norwfs
storage/filesystem: avoid norwfs build flag
Diffstat (limited to 'storage/filesystem/dotgit/dotgit_rewrite_packed_refs.go')
-rw-r--r-- | storage/filesystem/dotgit/dotgit_rewrite_packed_refs.go | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/storage/filesystem/dotgit/dotgit_rewrite_packed_refs.go b/storage/filesystem/dotgit/dotgit_rewrite_packed_refs.go new file mode 100644 index 0000000..7f1c02c --- /dev/null +++ b/storage/filesystem/dotgit/dotgit_rewrite_packed_refs.go @@ -0,0 +1,81 @@ +package dotgit + +import ( + "io" + "os" + "runtime" + + "gopkg.in/src-d/go-billy.v4" + "gopkg.in/src-d/go-git.v4/utils/ioutil" +) + +func (d *DotGit) openAndLockPackedRefsMode() int { + if billy.CapabilityCheck(d.fs, billy.ReadAndWriteCapability) { + return os.O_RDWR + } + + return os.O_RDONLY +} + +func (d *DotGit) rewritePackedRefsWhileLocked( + tmp billy.File, pr billy.File) error { + // Try plain rename. If we aren't using the bare Windows filesystem as the + // storage layer, we might be able to get away with a rename over a locked + // file. + err := d.fs.Rename(tmp.Name(), pr.Name()) + if err == nil { + return nil + } + + // If we are in a filesystem that does not support rename (e.g. sivafs) + // a full copy is done. + if err == billy.ErrNotSupported { + return d.copyNewFile(tmp, pr) + } + + if runtime.GOOS != "windows" { + return err + } + + // Otherwise, Windows doesn't let us rename over a locked file, so + // we have to do a straight copy. Unfortunately this could result + // in a partially-written file if the process fails before the + // copy completes. + return d.copyToExistingFile(tmp, pr) +} + +func (d *DotGit) copyToExistingFile(tmp, pr billy.File) error { + _, err := pr.Seek(0, io.SeekStart) + if err != nil { + return err + } + err = pr.Truncate(0) + if err != nil { + return err + } + _, err = tmp.Seek(0, io.SeekStart) + if err != nil { + return err + } + _, err = io.Copy(pr, tmp) + + return err +} + +func (d *DotGit) copyNewFile(tmp billy.File, pr billy.File) (err error) { + prWrite, err := d.fs.Create(pr.Name()) + if err != nil { + return err + } + + defer ioutil.CheckClose(prWrite, &err) + + _, err = tmp.Seek(0, io.SeekStart) + if err != nil { + return err + } + + _, err = io.Copy(prWrite, tmp) + + return err +} |