Some checks are pending
Docs Deploy / build_and_deploy (push) Waiting to run
Generate Docs / cli (push) Waiting to run
Generate Config Doc / cli (push) Waiting to run
Go formatting / go-formatting (push) Waiting to run
Check links / markdown-link-check (push) Waiting to run
Integration / pre-test (push) Waiting to run
Integration / test on (push) Blocked by required conditions
Integration / status (push) Blocked by required conditions
Lint / Lint Go code (push) Waiting to run
Test / test (ubuntu-latest) (push) Waiting to run
122 lines
2.6 KiB
Go
122 lines
2.6 KiB
Go
package archive
|
|
|
|
import (
|
|
"archive/tar"
|
|
"compress/gzip"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/ignite/cli/v29/ignite/pkg/errors"
|
|
)
|
|
|
|
// CreateArchive creates a tar.gz archive from a list of files.
|
|
func CreateArchive(dir string, buf io.Writer) 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()
|
|
|
|
return filepath.WalkDir(dir, func(path string, _ os.DirEntry, _ error) error {
|
|
return addToArchive(tw, path)
|
|
})
|
|
}
|
|
|
|
func addToArchive(tw *tar.Writer, filename string) error {
|
|
// Open the file which will be written into the archive
|
|
file, err := os.Open(filename)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
|
|
// Get FileInfo about our file providing file size, mode, etc.
|
|
info, err := file.Stat()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Create a tar Header from the FileInfo data
|
|
if info.IsDir() {
|
|
hdr, err := tar.FileInfoHeader(info, info.Name())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
hdr.Name = filename
|
|
if err := tw.WriteHeader(hdr); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
header, err := tar.FileInfoHeader(info, info.Name())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Use full path as name (FileInfoHeader only takes the basename)
|
|
// If we don't do this the directory structure would
|
|
// not be preserved
|
|
// 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
|
|
}
|
|
|
|
_, err = io.Copy(tw, file)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ExtractArchive extracts a tar.gz archive to the specified directory.
|
|
func ExtractArchive(outDir string, gzipStream io.Reader) error {
|
|
uncompressedStream, err := gzip.NewReader(gzipStream)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
tarReader := tar.NewReader(uncompressedStream)
|
|
|
|
for {
|
|
header, err := tarReader.Next()
|
|
if err == io.EOF {
|
|
break
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
|
|
targetPath := filepath.Join(outDir, header.Name) //nolint:gosec // We trust the tar file
|
|
|
|
switch header.Typeflag {
|
|
case tar.TypeDir:
|
|
if err := os.MkdirAll(targetPath, 0o755); err != nil {
|
|
return err
|
|
}
|
|
case tar.TypeReg:
|
|
outFile, err := os.Create(targetPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if _, err := io.Copy(outFile, tarReader); err != nil { //nolint:gosec // We trust the tar file
|
|
return err
|
|
}
|
|
outFile.Close()
|
|
|
|
default:
|
|
return errors.Errorf("unknown type: %s in %s", string(header.Typeflag), header.Name)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|