aboutsummaryrefslogtreecommitdiffstats
path: root/storage
diff options
context:
space:
mode:
authorMáximo Cuadros <mcuadros@gmail.com>2016-11-28 10:31:06 +0100
committerGitHub <noreply@github.com>2016-11-28 10:31:06 +0100
commitd541d40da1f11bdfbd80dc65b191d129c028ea0c (patch)
tree62cf8c907cc61021e59372fa52c67b0ebb35d51b /storage
parent68893edf9ddc3de181431f1552e3b773cb66f080 (diff)
downloadgo-git-d541d40da1f11bdfbd80dc65b191d129c028ea0c.tar.gz
storage: filesystem, clean close when the packfile is not used (#140)
Diffstat (limited to 'storage')
-rw-r--r--storage/filesystem/internal/dotgit/writers.go58
-rw-r--r--storage/filesystem/internal/dotgit/writers_test.go21
2 files changed, 65 insertions, 14 deletions
diff --git a/storage/filesystem/internal/dotgit/writers.go b/storage/filesystem/internal/dotgit/writers.go
index d3d3b43..8e22a39 100644
--- a/storage/filesystem/internal/dotgit/writers.go
+++ b/storage/filesystem/internal/dotgit/writers.go
@@ -12,6 +12,12 @@ import (
"gopkg.in/src-d/go-git.v4/utils/fs"
)
+// PackWriter is a io.Writer that generates the packfile index simultaneously,
+// a packfile.Decoder is used with a file reader to read the file being written
+// this operation is synchronized with the write operations.
+// The packfile is written in a temp file, when Close is called this file
+// is renamed/moved (depends on the Filesystem implementation) to the final
+// location, if the PackWriter is not used, nothing is written
type PackWriter struct {
Notify func(h plumbing.Hash, i idxfile.Idxfile)
@@ -72,34 +78,58 @@ func (w *PackWriter) buildIndex() {
w.result <- err
}
-func (w *PackWriter) Write(p []byte) (n int, err error) {
+// waitBuildIndex waits until buildIndex function finishes, this can terminate
+// with a packfile.ErrEmptyPackfile, this means that nothing was written so we
+// ignore the error
+func (w *PackWriter) waitBuildIndex() error {
+ err := <-w.result
+ if err == packfile.ErrEmptyPackfile {
+ return nil
+ }
+
+ return err
+}
+
+func (w *PackWriter) Write(p []byte) (int, error) {
return w.synced.Write(p)
}
+// Close closes all the file descriptors and save the final packfile, if nothing
+// was written, the tempfiles are deleted without writing a packfile.
func (w *PackWriter) Close() error {
defer func() {
+ if w.Notify != nil {
+ w.Notify(w.checksum, w.index)
+ }
+
close(w.result)
}()
- pipe := []func() error{
- w.synced.Close,
- func() error { return <-w.result },
- w.fr.Close,
- w.fw.Close,
- w.save,
+ if err := w.synced.Close(); err != nil {
+ return err
}
- for _, f := range pipe {
- if err := f(); err != nil {
- return err
- }
+ if err := w.waitBuildIndex(); err != nil {
+ return err
}
- if w.Notify != nil {
- w.Notify(w.checksum, w.index)
+ if err := w.fr.Close(); err != nil {
+ return err
}
- return nil
+ if err := w.fw.Close(); err != nil {
+ return err
+ }
+
+ if len(w.index.Entries) == 0 {
+ return w.clean()
+ }
+
+ return w.save()
+}
+
+func (w *PackWriter) clean() error {
+ return w.fs.Remove(w.fw.Filename())
}
func (w *PackWriter) save() error {
diff --git a/storage/filesystem/internal/dotgit/writers_test.go b/storage/filesystem/internal/dotgit/writers_test.go
index 23d3a0e..c66613a 100644
--- a/storage/filesystem/internal/dotgit/writers_test.go
+++ b/storage/filesystem/internal/dotgit/writers_test.go
@@ -44,6 +44,27 @@ func (s *SuiteDotGit) TestNewObjectPack(c *C) {
c.Assert(stat.Size(), Equals, int64(1940))
}
+func (s *SuiteDotGit) TestNewObjectPackUnused(c *C) {
+ dir, err := ioutil.TempDir("", "example")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ defer os.RemoveAll(dir)
+
+ fs := osfs.New(dir)
+ dot := New(fs)
+
+ w, err := dot.NewObjectPack()
+ c.Assert(err, IsNil)
+
+ c.Assert(w.Close(), IsNil)
+
+ info, err := fs.ReadDir("objects/pack")
+ c.Assert(err, IsNil)
+ c.Assert(info, HasLen, 0)
+}
+
func (s *SuiteDotGit) TestSyncedReader(c *C) {
tmpw, err := ioutil.TempFile("", "example")
c.Assert(err, IsNil)