mex/arch.go

100 lines
2.0 KiB
Go
Raw Normal View History

2023-10-23 03:57:43 +00:00
package mex
import (
"errors"
"fmt"
"log"
"os/exec"
"path/filepath"
"strings"
)
var (
UnsupportedArchiveFormatError = errors.New("unsupported archive format")
RequiredToolNotInstalled = errors.New("required tool not installed")
)
var (
archExt = ".cbz"
rarToolNames = []string{"unrar"}
zipToolNames = []string{"7za", "7z"}
)
func findToolByName(names ...string) (string, error) {
for _, name := range names {
if path, err := exec.LookPath(name); err == nil {
return path, nil
}
}
return "", RequiredToolNotInstalled
}
func Compress(archPath, contentDir string) error {
if filepath.Ext(archPath) != archExt {
archPath += archExt
}
toolPath, err := findToolByName(zipToolNames...)
if err != nil {
return RequiredToolNotInstalled
}
toolCmd := exec.Command(
toolPath,
"a", archPath,
contentDir+string(filepath.Separator)+"*",
)
log.Printf("compressing %s...", archPath)
if err := toolCmd.Run(); err != nil {
return errors.Join(fmt.Errorf("compression of %s failed", archPath), err)
}
return nil
}
func Decompress(archPath string, allocator *TempDirAllocator) (string, error) {
archPathAbs, err := filepath.Abs(archPath)
if err != nil {
return "", err
}
var (
toolNames []string
toolArgs []string
)
switch strings.ToLower(filepath.Ext(archPathAbs)) {
case ".rar", ".cbr":
toolNames = rarToolNames
toolArgs = []string{"x", archPathAbs}
case ".zip", ".cbz", ".7z":
toolNames = zipToolNames
toolArgs = []string{"x", archPathAbs}
default:
return "", UnsupportedArchiveFormatError
}
toolPath, err := findToolByName(toolNames...)
if err != nil {
return "", err
}
contentDir, err := allocator.TempDir()
if err != nil {
return "", err
}
toolCmd := exec.Command(toolPath, toolArgs...)
toolCmd.Dir = contentDir
log.Printf("decompressing %s...", archPath)
if err := toolCmd.Run(); err != nil {
return "", errors.Join(fmt.Errorf("decompression of %s failed", archPath), err)
}
return contentDir, nil
}