terraform/builtin/providers/archive/zip_archiver.go

137 lines
2.4 KiB
Go

package archive
import (
"archive/zip"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sort"
)
type ZipArchiver struct {
filepath string
filewriter *os.File
writer *zip.Writer
}
func NewZipArchiver(filepath string) Archiver {
return &ZipArchiver{
filepath: filepath,
}
}
func (a *ZipArchiver) ArchiveContent(content []byte, infilename string) error {
if err := a.open(); err != nil {
return err
}
defer a.close()
f, err := a.writer.Create(infilename)
if err != nil {
return err
}
_, err = f.Write(content)
return err
}
func (a *ZipArchiver) ArchiveFile(infilename string) error {
fi, err := assertValidFile(infilename)
if err != nil {
return err
}
content, err := ioutil.ReadFile(infilename)
if err != nil {
return err
}
return a.ArchiveContent(content, fi.Name())
}
func (a *ZipArchiver) ArchiveDir(indirname string) error {
_, err := assertValidDir(indirname)
if err != nil {
return err
}
if err := a.open(); err != nil {
return err
}
defer a.close()
return filepath.Walk(indirname, func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}
if err != nil {
return err
}
relname, err := filepath.Rel(indirname, path)
if err != nil {
return fmt.Errorf("error relativizing file for archival: %s", err)
}
f, err := a.writer.Create(relname)
if err != nil {
return fmt.Errorf("error creating file inside archive: %s", err)
}
content, err := ioutil.ReadFile(path)
if err != nil {
return fmt.Errorf("error reading file for archival: %s", err)
}
_, err = f.Write(content)
return err
})
}
func (a *ZipArchiver) ArchiveMultiple(content map[string][]byte) error {
if err := a.open(); err != nil {
return err
}
defer a.close()
// Ensure files are processed in the same order so hashes don't change
keys := make([]string, len(content))
i := 0
for k := range content {
keys[i] = k
i++
}
sort.Strings(keys)
for _, filename := range keys {
f, err := a.writer.Create(filename)
if err != nil {
return err
}
_, err = f.Write(content[filename])
if err != nil {
return err
}
}
return nil
}
func (a *ZipArchiver) open() error {
f, err := os.Create(a.filepath)
if err != nil {
return err
}
a.filewriter = f
a.writer = zip.NewWriter(f)
return nil
}
func (a *ZipArchiver) close() {
if a.writer != nil {
a.writer.Close()
a.writer = nil
}
if a.filewriter != nil {
a.filewriter.Close()
a.filewriter = nil
}
}