pkg/testutil/bldr/files_builder.go (91 lines of code) (raw):
package bldr
import (
"io/fs"
"math/rand"
"os"
"path"
"path/filepath"
"strconv"
"testing"
"github.com/stretchr/testify/require"
)
type FilesBuilder struct {
dirs map[string]os.FileMode
symlinks map[string]string
files map[string]FileData
t *testing.T
baseDir string
}
type FileData struct {
data []byte
perm os.FileMode
}
func Files(t *testing.T) *FilesBuilder {
return &FilesBuilder{
dirs: make(map[string]os.FileMode),
files: make(map[string]FileData),
symlinks: make(map[string]string),
t: t,
baseDir: t.TempDir(),
}
}
func (b *FilesBuilder) WithShortBaseDir() *FilesBuilder {
b.baseDir = filepath.Join(os.TempDir(), strconv.FormatUint(rand.Uint64(), 10))
err := os.MkdirAll(b.baseDir, 0777)
require.NoError(b.t, err)
b.t.Cleanup(func() { _ = os.RemoveAll(b.baseDir) })
return b
}
func (b *FilesBuilder) WriteDir(dir string) *FilesBuilder {
b.dirs[filepath.Join(b.baseDir, dir)] = 0755
return b
}
func (b *FilesBuilder) TouchFile(path string) *FilesBuilder {
return b.WriteFile(path, "")
}
func (b *FilesBuilder) WriteFile(path string, data any) *FilesBuilder {
return b.WriteFileWithPerms(path, data, 0644)
}
func (b *FilesBuilder) WriteFileWithPerms(path string, data any, perm os.FileMode) *FilesBuilder {
var contents []byte
switch v := data.(type) {
case []byte:
contents = v
case string:
contents = []byte(v)
default:
b.t.Fatalf("data must be of type []byte or string, got %T", v)
}
b.files[filepath.Join(b.baseDir, path)] = FileData{data: contents, perm: perm}
return b
}
func (b *FilesBuilder) WriteSymlink(from string, to string) *FilesBuilder {
b.symlinks[filepath.Join(b.baseDir, from)] = filepath.Join(b.baseDir, to)
return b
}
func (b *FilesBuilder) Build() string {
for dir, perm := range b.dirs {
err := os.MkdirAll(dir, perm)
require.NoError(b.t, err)
}
for filePath, fileData := range b.files {
dir, _ := path.Split(filePath)
err := os.MkdirAll(dir, 0755)
require.NoError(b.t, err)
err = os.WriteFile(filePath, fileData.data, fileData.perm)
require.NoError(b.t, err)
}
for from, to := range b.symlinks {
err := os.Symlink(to, from)
require.NoError(b.t, err)
}
return b.baseDir
}
func (b *FilesBuilder) BuildFS() fs.FS {
dir := b.Build()
return os.DirFS(dir)
}
func (b *FilesBuilder) BuildPath(path string) string {
dir := b.Build()
return filepath.Join(dir, path)
}