makeshift/internal/archive/archive.go

103 lines
2 KiB
Go

package archive
import (
"archive/tar"
"compress/gzip"
"io"
"os"
"strings"
makeshift "git.towk2.me/towk/makeshift/pkg"
)
func Create(filenames []string, buf io.Writer, hooks []makeshift.Hook) error {
// Create new Writers for gzip and tar
// These writers are chained. Writing to the tar writer will
// write to the gzip writer which in turn will write to
// the "buf" writer
gw := gzip.NewWriter(buf)
defer gw.Close()
tw := tar.NewWriter(gw)
defer tw.Close()
// Iterate over files and add them to the tar archive
for _, filename := range filenames {
err := addToArchive(tw, filename, hooks)
if err != nil {
return err
}
}
return nil
}
func Expand(path string) error {
return nil
}
func addToArchive(tw *tar.Writer, filename string, hooks []makeshift.Hook) error {
var (
hook makeshift.Hook
file *os.File
data any
err error
)
// open file to write to archive
file, err = os.Open(filename)
if err != nil {
return err
}
defer file.Close()
// run pre-hooks to modify the contents of the file
// before archiving using plugins
for _, hook := range hooks {
err = hook.Run()
if err != nil {
return err
}
}
// get FileInfo for file size, mode, etc.
info, err := file.Stat()
if err != nil {
return err
}
// skip file if it's a directory
if info.IsDir() {
return nil
}
// create a tar Header from the FileInfo data
header, err := tar.FileInfoHeader(info, info.Name())
if err != nil {
return err
}
// use full path as name (FileInfoHeader only takes the basename) to
// preserve directory structure
// see for more info: https://golang.org/src/archive/tar/common.go?#L626
header.Name = filename
// Write file header to the tar archive
err = tw.WriteHeader(header)
if err != nil {
return err
}
// take the contents from the last hook and update files
hook = hooks[len(hooks)-1]
data, err = hook.Data.Get("out")
if err != nil {
return err
}
// copy file content to tar archive
_, err = io.Copy(tw, strings.NewReader(data.(string)))
if err != nil {
return err
}
return nil
}