From d541d40da1f11bdfbd80dc65b191d129c028ea0c Mon Sep 17 00:00:00 2001 From: Máximo Cuadros Date: Mon, 28 Nov 2016 10:31:06 +0100 Subject: storage: filesystem, clean close when the packfile is not used (#140) --- storage/filesystem/internal/dotgit/writers.go | 58 ++++++++++++++++++++------- 1 file changed, 44 insertions(+), 14 deletions(-) (limited to 'storage/filesystem/internal/dotgit/writers.go') 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 { -- cgit