buildr/internal/archive/tar.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
}