111 lines
1.9 KiB
Go
111 lines
1.9 KiB
Go
|
package mex
|
||
|
|
||
|
import (
|
||
|
"io"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
"sync"
|
||
|
)
|
||
|
|
||
|
func copyFile(targetPath, sourcePath string) error {
|
||
|
sourceFile, err := os.Open(sourcePath)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
defer sourceFile.Close()
|
||
|
|
||
|
targetFile, err := os.Create(targetPath)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
defer targetFile.Close()
|
||
|
|
||
|
if _, err := io.Copy(targetFile, sourceFile); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func stripExt(path string) string {
|
||
|
name := filepath.Base(path)
|
||
|
return name[:len(name)-len(filepath.Ext(name))]
|
||
|
}
|
||
|
|
||
|
type TempDirAllocator struct {
|
||
|
mutex sync.Mutex
|
||
|
dirs []string
|
||
|
}
|
||
|
|
||
|
func (self *TempDirAllocator) TempDir() (string, error) {
|
||
|
dir, err := os.MkdirTemp("", "mex_")
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
self.mutex.Lock()
|
||
|
defer self.mutex.Unlock()
|
||
|
self.dirs = append(self.dirs, dir)
|
||
|
|
||
|
return dir, nil
|
||
|
}
|
||
|
|
||
|
func (self *TempDirAllocator) Cleanup() {
|
||
|
for _, dir := range self.dirs {
|
||
|
os.RemoveAll(dir)
|
||
|
}
|
||
|
|
||
|
self.mutex.Lock()
|
||
|
defer self.mutex.Unlock()
|
||
|
self.dirs = nil
|
||
|
}
|
||
|
|
||
|
type Node struct {
|
||
|
Name string
|
||
|
Path string
|
||
|
Info os.FileInfo
|
||
|
Children []*Node
|
||
|
}
|
||
|
|
||
|
func Walk(path string, allocator *TempDirAllocator) (*Node, error) {
|
||
|
info, err := os.Stat(path)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
currNode := &Node{
|
||
|
Name: filepath.Base(path),
|
||
|
Path: path,
|
||
|
Info: info,
|
||
|
}
|
||
|
|
||
|
if info.IsDir() {
|
||
|
entries, err := os.ReadDir(path)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
for _, entry := range entries {
|
||
|
child, err := Walk(filepath.Join(path, entry.Name()), allocator)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
currNode.Children = append(currNode.Children, child)
|
||
|
}
|
||
|
} else {
|
||
|
if contentDir, err := Decompress(path, allocator); err == nil {
|
||
|
archName := currNode.Name
|
||
|
if currNode, err = Walk(contentDir, allocator); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
currNode.Name = archName
|
||
|
} else if err != UnsupportedArchiveFormatError {
|
||
|
return nil, err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return currNode, nil
|
||
|
}
|