aboutsummaryrefslogtreecommitdiffstats
path: root/storage/filesystem/internal/dotgit/writers.go
diff options
context:
space:
mode:
Diffstat (limited to 'storage/filesystem/internal/dotgit/writers.go')
-rw-r--r--storage/filesystem/internal/dotgit/writers.go58
1 files changed, 44 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 {