Skip to content

Commit

Permalink
Move file system archive code into backup package
Browse files Browse the repository at this point in the history
  • Loading branch information
tom-f committed Jun 24, 2017
1 parent f4c5d79 commit 30dea40
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 84 deletions.
91 changes: 7 additions & 84 deletions system/admin/upload/backup.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package upload

import (
"archive/tar"
"compress/gzip"
"context"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"time"

"github.com/ponzu-cms/ponzu/system/backup"
)

// Backup creates an archive of a project's uploads and writes it
Expand All @@ -18,105 +18,28 @@ func Backup(ctx context.Context, res http.ResponseWriter) error {
ts := time.Now().Unix()
filename := fmt.Sprintf("uploads-%d.bak.tar.gz", ts)
tmp := os.TempDir()
backup := filepath.Join(tmp, filename)
bk := filepath.Join(tmp, filename)

// create uploads-{stamp}.bak.tar.gz
f, err := os.Create(backup)
f, err := os.Create(bk)
if err != nil {
return err
}

// loop through directory and gzip files
// add all to uploads.bak.tar.gz tarball
gz := gzip.NewWriter(f)
tarball := tar.NewWriter(gz)

errChan := make(chan error, 1)
walkFn := func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}

hdr, err := tar.FileInfoHeader(info, "")
if err != nil {
return err
}

hdr.Name = path

err = tarball.WriteHeader(hdr)
if err != nil {
return err
}

if !info.IsDir() {
src, err := os.Open(path)
if err != nil {
return err
}
defer src.Close()

_, err = io.Copy(tarball, src)
if err != nil {
return err
}

err = tarball.Flush()
if err != nil {
return err
}

err = gz.Flush()
if err != nil {
return err
}
}

return nil
}

// stop processing if we get a cancellation signal
err = filepath.Walk("uploads", func(path string, info os.FileInfo, err error) error {
go func() { errChan <- walkFn(path, info, err) }()
err = backup.ArchiveFS(ctx, "uploads", f)

select {
case <-ctx.Done():
if err := ctx.Err(); err != nil {
return err
}
case err := <-errChan:
if err != nil {
return err
}
}

return nil
})
if err != nil {
fmt.Println(err)
return err
}

err = gz.Close()
if err != nil {
return err
}
err = tarball.Close()
if err != nil {
return err
}
err = f.Close()
if err != nil {
return err
}

// write data to response
data, err := os.Open(backup)
data, err := os.Open(bk)
if err != nil {
return err
}
defer data.Close()
defer os.Remove(backup)
defer os.Remove(bk)

disposition := `attachment; filename=%s`
info, err := data.Stat()
Expand Down
95 changes: 95 additions & 0 deletions system/backup/archive.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package backup

import (
"archive/tar"
"compress/gzip"
"context"
"fmt"
"io"
"os"
"path/filepath"
)

// ArchiveFS walks the filesystem starting from basedir writing files encountered
// tarred and gzipped to the provided writer
func ArchiveFS(ctx context.Context, basedir string, w io.Writer) error {
gz := gzip.NewWriter(w)
tarball := tar.NewWriter(gz)

errChan := make(chan error, 1)
walkFn := func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}

hdr, err := tar.FileInfoHeader(info, "")
if err != nil {
return err
}

hdr.Name = path

err = tarball.WriteHeader(hdr)
if err != nil {
return err
}

if !info.IsDir() {
src, err := os.Open(path)
if err != nil {
return err
}
defer src.Close()

_, err = io.Copy(tarball, src)
if err != nil {
return err
}

err = tarball.Flush()
if err != nil {
return err
}

err = gz.Flush()
if err != nil {
return err
}
}

return nil
}

// stop processing if we get a cancellation signal
err := filepath.Walk(basedir, func(path string, info os.FileInfo, err error) error {
go func() { errChan <- walkFn(path, info, err) }()

select {
case <-ctx.Done():
if err := ctx.Err(); err != nil {
return err
}
case err := <-errChan:
if err != nil {
return err
}
}

return nil
})
if err != nil {
fmt.Println(err)
return err
}

err = gz.Close()
if err != nil {
return err
}
err = tarball.Close()
if err != nil {
return err
}

return nil
}

0 comments on commit 30dea40

Please sign in to comment.