mirror of
https://github.com/rclone/rclone.git
synced 2025-11-23 21:44:49 +02:00
74 lines
1.6 KiB
Go
74 lines
1.6 KiB
Go
|
|
package vfs
|
||
|
|
|
||
|
|
import (
|
||
|
|
"archive/zip"
|
||
|
|
"context"
|
||
|
|
"fmt"
|
||
|
|
"io"
|
||
|
|
"os"
|
||
|
|
|
||
|
|
"github.com/rclone/rclone/fs"
|
||
|
|
)
|
||
|
|
|
||
|
|
// CreateZip creates a zip file from a vfs.Dir writing it to w
|
||
|
|
func CreateZip(ctx context.Context, dir *Dir, w io.Writer) (err error) {
|
||
|
|
zipWriter := zip.NewWriter(w)
|
||
|
|
defer fs.CheckClose(zipWriter, &err)
|
||
|
|
var walk func(dir *Dir, root string) error
|
||
|
|
walk = func(dir *Dir, root string) error {
|
||
|
|
nodes, err := dir.ReadDirAll()
|
||
|
|
if err != nil {
|
||
|
|
return fmt.Errorf("create zip directory read: %w", err)
|
||
|
|
}
|
||
|
|
for _, node := range nodes {
|
||
|
|
switch e := node.(type) {
|
||
|
|
case *File:
|
||
|
|
in, err := e.Open(os.O_RDONLY)
|
||
|
|
if err != nil {
|
||
|
|
return fmt.Errorf("create zip open file: %w", err)
|
||
|
|
}
|
||
|
|
header := &zip.FileHeader{
|
||
|
|
Name: root + e.Name(),
|
||
|
|
Method: zip.Deflate,
|
||
|
|
Modified: e.ModTime(),
|
||
|
|
}
|
||
|
|
fileWriter, err := zipWriter.CreateHeader(header)
|
||
|
|
if err != nil {
|
||
|
|
fs.CheckClose(in, &err)
|
||
|
|
return fmt.Errorf("create zip file header: %w", err)
|
||
|
|
}
|
||
|
|
_, err = io.Copy(fileWriter, in)
|
||
|
|
if err != nil {
|
||
|
|
fs.CheckClose(in, &err)
|
||
|
|
return fmt.Errorf("create zip copy: %w", err)
|
||
|
|
}
|
||
|
|
fs.CheckClose(in, &err)
|
||
|
|
case *Dir:
|
||
|
|
name := root + e.Path()
|
||
|
|
if name != "" && name[len(name)-1] != '/' {
|
||
|
|
name += "/"
|
||
|
|
}
|
||
|
|
header := &zip.FileHeader{
|
||
|
|
Name: name,
|
||
|
|
Method: zip.Store,
|
||
|
|
Modified: e.ModTime(),
|
||
|
|
}
|
||
|
|
_, err := zipWriter.CreateHeader(header)
|
||
|
|
if err != nil {
|
||
|
|
return fmt.Errorf("create zip directory header: %w", err)
|
||
|
|
}
|
||
|
|
err = walk(e, name)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
err = walk(dir, "")
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|