mirror of
https://github.com/pocketbase/pocketbase.git
synced 2024-11-25 01:16:21 +02:00
94 lines
1.8 KiB
Go
94 lines
1.8 KiB
Go
package archive
|
|
|
|
import (
|
|
"archive/zip"
|
|
"compress/flate"
|
|
"io"
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// Create creates a new zip archive from src dir content and saves it in dest path.
|
|
//
|
|
// You can specify skipPaths to skip/ignore certain directories and files (relative to src)
|
|
// preventing adding them in the final archive.
|
|
func Create(src string, dest string, skipPaths ...string) error {
|
|
if err := os.MkdirAll(filepath.Dir(dest), os.ModePerm); err != nil {
|
|
return err
|
|
}
|
|
|
|
zf, err := os.Create(dest)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer zf.Close()
|
|
|
|
zw := zip.NewWriter(zf)
|
|
defer zw.Close()
|
|
|
|
// register a custom Deflate compressor
|
|
zw.RegisterCompressor(zip.Deflate, func(out io.Writer) (io.WriteCloser, error) {
|
|
return flate.NewWriter(out, flate.BestSpeed)
|
|
})
|
|
|
|
if err := zipAddFS(zw, os.DirFS(src), skipPaths...); err != nil {
|
|
// try to cleanup at least the created zip file
|
|
os.Remove(dest)
|
|
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// note remove after similar method is added in the std lib (https://github.com/golang/go/issues/54898)
|
|
func zipAddFS(w *zip.Writer, fsys fs.FS, skipPaths ...string) error {
|
|
return fs.WalkDir(fsys, ".", func(name string, d fs.DirEntry, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if d.IsDir() {
|
|
return nil
|
|
}
|
|
|
|
// skip
|
|
for _, ignore := range skipPaths {
|
|
if ignore == name ||
|
|
strings.HasPrefix(filepath.Clean(name)+string(os.PathSeparator), filepath.Clean(ignore)+string(os.PathSeparator)) {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
info, err := d.Info()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
h, err := zip.FileInfoHeader(info)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
h.Name = name
|
|
h.Method = zip.Deflate
|
|
|
|
fw, err := w.CreateHeader(h)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
f, err := fsys.Open(name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer f.Close()
|
|
|
|
_, err = io.Copy(fw, f)
|
|
|
|
return err
|
|
})
|
|
}
|