diff options
author | Steve Manuel <nilslice@gmail.com> | 2017-06-26 16:56:39 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-26 16:56:39 -0700 |
commit | e2aeabb21ffae9446d13e43a2feed0002241bb1d (patch) | |
tree | f434af0cca05efedb7aeb8c9c874d58ef39eb859 /system/backup/archive.go | |
parent | 9105d78ee74858d561f7a60e36f28ed994529452 (diff) | |
parent | 629725aa84c8c0cf66eb1683107aabd6e20928eb (diff) |
Merge pull request #172 from ponzu-cms/ponzu-dev
[core] Add search index backup routine
Diffstat (limited to 'system/backup/archive.go')
-rw-r--r-- | system/backup/archive.go | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/system/backup/archive.go b/system/backup/archive.go new file mode 100644 index 0000000..0a8b964 --- /dev/null +++ b/system/backup/archive.go @@ -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 +} |