aboutsummaryrefslogtreecommitdiffstats
path: root/storage/filesystem/dotgit/dotgit_rewrite_packed_refs.go
diff options
context:
space:
mode:
authorMáximo Cuadros <mcuadros@gmail.com>2018-07-06 11:28:18 +0200
committerGitHub <noreply@github.com>2018-07-06 11:28:18 +0200
commit8ad72db0b7e1c03d9fad343890e469d5c3ed757b (patch)
tree16f8efddca3778a35947a4a6306f7ba96c194e31 /storage/filesystem/dotgit/dotgit_rewrite_packed_refs.go
parentfcfd239c49baee9195f7b8234f46288a29c3951c (diff)
parentda5d474fb43dffd1b28cd5662b3a5bf7e446cd5c (diff)
downloadgo-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.go81
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
+}