🎉 Initial commit, all commands basically working
Signed-off-by: Lukas Bachschwell <lukas@lbsfilm.at>
This commit is contained in:
153
compression/compression.go
Normal file
153
compression/compression.go
Normal file
@ -0,0 +1,153 @@
|
||||
package compression
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
log "github.com/s00500/env_logger"
|
||||
)
|
||||
|
||||
func isSymlink(fi os.FileInfo) bool {
|
||||
return fi.Mode()&os.ModeSymlink != 0
|
||||
}
|
||||
|
||||
func Compress(inputPath, outputPath string) error {
|
||||
var file *os.File
|
||||
var err error
|
||||
var writer *gzip.Writer
|
||||
|
||||
if file, err = os.OpenFile(outputPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
if writer, err = gzip.NewWriterLevel(file, gzip.BestCompression); err != nil {
|
||||
return err
|
||||
}
|
||||
defer writer.Close()
|
||||
|
||||
tw := tar.NewWriter(writer)
|
||||
defer tw.Close()
|
||||
|
||||
err = filepath.Walk(inputPath, func(file string, fi os.FileInfo, err error) error {
|
||||
log.Should(err)
|
||||
if inputPath == file {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Skip some strange systemfiles
|
||||
if strings.Contains(file, ".DS_Store") || strings.Contains(file, ".Trash") || strings.Contains(file, "._") {
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Trace("Compressing ", inputPath, " : Got: ", file)
|
||||
// generate tar header
|
||||
header, err := tar.FileInfoHeader(fi, file)
|
||||
// set to numeric only
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if isSymlink(fi) {
|
||||
linkTarget, err := os.Readlink(file)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: readlink: %v", fi.Name(), err)
|
||||
}
|
||||
header, err = tar.FileInfoHeader(fi, filepath.ToSlash(linkTarget))
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: making header: %v", fi.Name(), err)
|
||||
}
|
||||
}
|
||||
|
||||
header.Name = "./" + strings.TrimPrefix(filepath.ToSlash(file), filepath.ToSlash(inputPath)+"/")
|
||||
|
||||
header.Uname = ""
|
||||
header.Gname = ""
|
||||
|
||||
// write header
|
||||
if err := tw.WriteHeader(header); err != nil {
|
||||
return err
|
||||
}
|
||||
// if not a dir, write file content
|
||||
if !fi.IsDir() && !isSymlink(fi) {
|
||||
data, err := os.Open(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := io.Copy(tw, data); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func ExtractTarGz(gzipStream io.Reader, extractDir string) error {
|
||||
uncompressedStream, err := gzip.NewReader(gzipStream)
|
||||
if err != nil {
|
||||
return fmt.Errorf("extractTarGz: NewReader failed: %w", err)
|
||||
}
|
||||
|
||||
tarReader := tar.NewReader(uncompressedStream)
|
||||
|
||||
for {
|
||||
header, err := tarReader.Next()
|
||||
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("extractTarGz: Next() failed: %w", err)
|
||||
}
|
||||
|
||||
switch header.Typeflag {
|
||||
case tar.TypeDir:
|
||||
//log.Info("DIr!", header.Name)
|
||||
if err := os.Mkdir(filepath.Join(extractDir, header.Name), 0755); err != nil {
|
||||
return fmt.Errorf("extractTarGz: Mkdir() failed: %w", err)
|
||||
}
|
||||
case tar.TypeReg:
|
||||
//log.Info("File!", header.Name)
|
||||
if err := os.MkdirAll(filepath.Join(extractDir, filepath.Dir(header.Name)), 0755); err != nil {
|
||||
return fmt.Errorf("extractTarGz: File Mkdir() failed: %w", err)
|
||||
}
|
||||
outFile, err := os.OpenFile(filepath.Join(extractDir, header.Name), os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))
|
||||
if err != nil {
|
||||
return fmt.Errorf("extractTarGz: OpenFile() failed: %w", err)
|
||||
}
|
||||
if _, err := io.Copy(outFile, tarReader); err != nil {
|
||||
return fmt.Errorf("extractTarGz: Copy() failed: %w", err)
|
||||
}
|
||||
outFile.Close()
|
||||
case tar.TypeSymlink:
|
||||
if err := os.MkdirAll(filepath.Join(extractDir, filepath.Dir(header.Name)), 0755); err != nil {
|
||||
return fmt.Errorf("extractTarGz: File Mkdir() failed: %w", err)
|
||||
}
|
||||
if err := os.Symlink(header.Linkname, filepath.Join(extractDir, header.Name)); err != nil {
|
||||
log.Errorf("failed writing symbolic link: %s", err)
|
||||
//return fmt.Errorf("failed writing symbolic link: %s", err)
|
||||
}
|
||||
//log.Infof("Skip symlink in: %b in %s",
|
||||
// header.Typeflag,
|
||||
// header.Name)
|
||||
default:
|
||||
return fmt.Errorf("extractTarGz: uknown type: %d in %s",
|
||||
header.Typeflag,
|
||||
header.Name)
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Exists(name string) bool {
|
||||
_, err := os.Stat(name)
|
||||
return !os.IsNotExist(err)
|
||||
}
|
Reference in New Issue
Block a user