97 lines
1.7 KiB
Go
97 lines
1.7 KiB
Go
package archive
|
|
|
|
import (
|
|
"archive/tar"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"io/fs"
|
|
"path/filepath"
|
|
|
|
"code.icb4dc0.de/buildr/buildr/internal/ignore"
|
|
)
|
|
|
|
var ErrEmptyArchive = errors.New("no files were added to the archive")
|
|
|
|
type Tar struct {
|
|
Ignorer *ignore.Ignorer
|
|
root *archiveNode
|
|
}
|
|
|
|
func (t *Tar) Write(writer io.Writer) error {
|
|
if t.root == nil {
|
|
return ErrEmptyArchive
|
|
}
|
|
tarWriter := tar.NewWriter(writer)
|
|
|
|
if err := t.root.writeToTar(tarWriter, t.Ignorer, ""); err != nil {
|
|
return err
|
|
}
|
|
|
|
return tarWriter.Close()
|
|
}
|
|
|
|
func (t *Tar) Remove(path string) bool {
|
|
if t.root == nil {
|
|
return false
|
|
}
|
|
|
|
return t.root.remove(path)
|
|
}
|
|
|
|
func (t *Tar) Add(srcPath, destPath string) error {
|
|
if t.root == nil {
|
|
t.root = newNode()
|
|
}
|
|
|
|
info, err := t.Ignorer.Stat(srcPath)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get file information for %s: %w", srcPath, err)
|
|
}
|
|
|
|
if info.IsDir() {
|
|
return t.addDir(srcPath, destPath)
|
|
}
|
|
|
|
t.addFile(srcPath, destPath)
|
|
return nil
|
|
}
|
|
|
|
func (t *Tar) addFile(srcPath, destPath string) {
|
|
if t.root == nil {
|
|
t.root = newNode()
|
|
}
|
|
|
|
t.root.addFile(srcPath, destPath)
|
|
}
|
|
|
|
func (t *Tar) addDir(srcPath, destPath string) error {
|
|
if t.root == nil {
|
|
t.root = newNode()
|
|
}
|
|
|
|
err := t.Ignorer.WalkDir(srcPath, func(path string, d fs.DirEntry, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
relativeToSource, err := filepath.Rel(srcPath, path)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to determine relative path for %s: %w", path, err)
|
|
}
|
|
|
|
if d.IsDir() {
|
|
t.root.addDir(filepath.Join(destPath, relativeToSource))
|
|
} else {
|
|
t.root.addFile(path, filepath.Join(destPath, relativeToSource))
|
|
}
|
|
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to add dir %s recursively: %w", srcPath, err)
|
|
}
|
|
|
|
return nil
|
|
}
|