feat: allow expanding and remove archive after download

This commit is contained in:
David Allen 2025-08-29 11:04:16 -06:00
parent c2d5be5eed
commit e5c1b59bc1
Signed by: towk
GPG key ID: 0430CDBE22619155
2 changed files with 223 additions and 19 deletions

View file

@ -6,6 +6,7 @@ import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
makeshift "git.towk2.me/towk/makeshift/pkg"
@ -32,7 +33,85 @@ func Create(filenames []string, buf io.Writer, hooks []makeshift.Hook) error {
return nil
}
func Expand(path string) error {
func Expand(tarname, xpath string) error {
tarfile, err := os.Open(tarname)
if err != nil {
return err
}
defer tarfile.Close()
// absPath, err := filepath.Abs(xpath)
// if err != nil {
// return err
// }
tr := tar.NewReader(tarfile)
if strings.HasSuffix(tarname, ".gz") {
gz, err := gzip.NewReader(tarfile)
if err != nil {
return fmt.Errorf("failed to create new gzip reader: %v", err)
}
defer gz.Close()
tr = tar.NewReader(gz)
}
// untar each segment
for {
header, err := tr.Next()
if err == io.EOF {
break
}
if err != nil {
return fmt.Errorf("failed to get next tar header: %v", err)
}
// determine proper file path info
var (
fileinfo = header.FileInfo()
filename = header.Name
file *os.File
abspath string
dirpath string
)
// absFileName := filepath.Join(absPath, filename) // if a dir, create it, then go to next segment
if fileinfo.Mode().IsDir() {
if err := os.MkdirAll(filename, 0o755); err != nil {
return fmt.Errorf("failed to make directory '%s': %v", filename, err)
}
continue
}
dirpath = filepath.Dir(filename)
if err = os.MkdirAll(dirpath, 0o777); err != nil {
return fmt.Errorf("failed to make directory '%s': %v", err)
}
// create new file with original file mode
abspath, err = filepath.Abs(filename)
if err != nil {
return fmt.Errorf("failed to get absolute path: %v", err)
}
file, err = os.OpenFile(
abspath,
os.O_RDWR|os.O_CREATE|os.O_TRUNC,
fileinfo.Mode().Perm(),
)
if err != nil {
return fmt.Errorf("failed to open file: %v", err)
}
// fmt.Printf("x %s\n", filename)
// copy the contents to the new file
n, err := io.Copy(file, tr)
if err != nil {
return fmt.Errorf("failed to copy file: %v", err)
}
if err = file.Close(); err != nil {
return fmt.Errorf("failed to close file: %v", err)
}
if n != fileinfo.Size() {
return fmt.Errorf("wrote %d, want %d", n, fileinfo.Size())
}
}
return nil
}