This commit is contained in:
Alex Yatskov 2023-12-10 09:41:50 -08:00
parent e4eacea3dd
commit f0259bcbe9
7 changed files with 118 additions and 118 deletions

View File

@ -8,6 +8,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
"strings"
) )
type cache struct { type cache struct {
@ -72,7 +73,9 @@ func (self *cache) buildCachePath(context *Context, outputPath string, inputFile
hasher := crc32.NewIEEE() hasher := crc32.NewIEEE()
hasher.Write([]byte(outputPath)) hasher.Write([]byte(outputPath))
sort.Sort(filesByPath(inputFiles)) sort.Slice(inputFiles, func(i, j int) bool {
return strings.Compare(inputFiles[i].Path(), inputFiles[j].Path()) < 0
})
for _, inputFile := range inputFiles { for _, inputFile := range inputFiles {
modTimeBuff := make([]byte, 8) modTimeBuff := make([]byte, 8)

69
file_exporter.go Normal file
View File

@ -0,0 +1,69 @@
package goldsmith
import (
"os"
"path/filepath"
)
type fileExporter struct {
targetDir string
clean bool
tokens map[string]bool
}
func (*fileExporter) Name() string {
return "exporter"
}
func (self *fileExporter) Initialize(context *Context) error {
self.tokens = make(map[string]bool)
context.Threads(1)
return nil
}
func (self *fileExporter) Process(context *Context, file *File) error {
slicePath := func(path string) string {
if filepath.IsAbs(path) {
var err error
if path, err = filepath.Rel("/", path); err != nil {
panic(err)
}
}
return filepath.Clean(path)
}
for token := slicePath(file.relPath); token != "."; token = filepath.Dir(token) {
self.tokens[token] = true
}
return file.export(self.targetDir)
}
func (self *fileExporter) Finalize(context *Context) error {
if !self.clean {
return nil
}
infoChan := make(chan fileInfo)
go scanDir(self.targetDir, infoChan)
for info := range infoChan {
if info.path == self.targetDir {
continue
}
relPath, err := filepath.Rel(self.targetDir, info.path)
if err != nil {
panic(err)
}
if tokenized, _ := self.tokens[relPath]; !tokenized {
if err := os.RemoveAll(info.path); err != nil {
return err
}
}
}
return nil
}

38
file_importer.go Normal file
View File

@ -0,0 +1,38 @@
package goldsmith
import (
"path/filepath"
)
type fileImporter struct {
sourceDir string
}
func (*fileImporter) Name() string {
return "importer"
}
func (self *fileImporter) Initialize(context *Context) error {
infoChan := make(chan fileInfo)
go scanDir(self.sourceDir, infoChan)
for info := range infoChan {
if info.IsDir() {
continue
}
relPath, err := filepath.Rel(self.sourceDir, info.path)
if err != nil {
panic(err)
}
file, err := context.CreateFileFromAsset(relPath, info.path)
if err != nil {
return err
}
context.DispatchFile(file)
}
return nil
}

View File

@ -3,45 +3,19 @@ package goldsmith
import ( import (
"os" "os"
"path/filepath" "path/filepath"
"strings"
) )
type filesByPath []*File
func (self filesByPath) Len() int {
return len(self)
}
func (self filesByPath) Swap(i, j int) {
self[i], self[j] = self[j], self[i]
}
func (self filesByPath) Less(i, j int) bool {
return strings.Compare(self[i].Path(), self[j].Path()) < 0
}
type fileInfo struct { type fileInfo struct {
os.FileInfo os.FileInfo
path string path string
} }
func cleanPath(path string) string { func scanDir(dir string, infoChan chan fileInfo) {
if filepath.IsAbs(path) { defer close(infoChan)
var err error
if path, err = filepath.Rel("/", path); err != nil {
panic(err)
}
}
return filepath.Clean(path) filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
}
func scanDir(rootDir string, infos chan fileInfo) {
defer close(infos)
filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
if err == nil { if err == nil {
infos <- fileInfo{FileInfo: info, path: path} infoChan <- fileInfo{FileInfo: info, path: path}
} }
return err return err

View File

@ -8,9 +8,6 @@ import (
// Goldsmith chainable context. // Goldsmith chainable context.
type Goldsmith struct { type Goldsmith struct {
sourceDir string
targetDir string
contexts []*Context contexts []*Context
cache *cache cache *cache
@ -24,8 +21,8 @@ type Goldsmith struct {
// Begin starts a chain, reading the files located in the source directory as input. // Begin starts a chain, reading the files located in the source directory as input.
func Begin(sourceDir string) *Goldsmith { func Begin(sourceDir string) *Goldsmith {
goldsmith := &Goldsmith{sourceDir: sourceDir} goldsmith := new(Goldsmith)
goldsmith.Chain(&loader{}) goldsmith.Chain(&fileImporter{sourceDir: sourceDir})
return goldsmith return goldsmith
} }
@ -77,9 +74,7 @@ func (self *Goldsmith) FilterPop() *Goldsmith {
// End stops a chain, writing all recieved files to targetDir as output. // End stops a chain, writing all recieved files to targetDir as output.
func (self *Goldsmith) End(targetDir string) []error { func (self *Goldsmith) End(targetDir string) []error {
self.targetDir = targetDir self.Chain(&fileExporter{targetDir: targetDir, clean: self.clean})
self.Chain(&saver{clean: self.clean})
for _, context := range self.contexts { for _, context := range self.contexts {
go context.step() go context.step()
} }

View File

@ -1,30 +0,0 @@
package goldsmith
import "path/filepath"
type loader struct{}
func (*loader) Name() string {
return "loader"
}
func (*loader) Initialize(context *Context) error {
scannedInfo := make(chan fileInfo)
go scanDir(context.goldsmith.sourceDir, scannedInfo)
for info := range scannedInfo {
if info.IsDir() {
continue
}
relPath, _ := filepath.Rel(context.goldsmith.sourceDir, info.path)
file, err := context.CreateFileFromAsset(relPath, info.path)
if err != nil {
return err
}
context.DispatchFile(file)
}
return nil
}

View File

@ -1,49 +0,0 @@
package goldsmith
import (
"os"
"path/filepath"
)
type saver struct {
clean bool
tokens map[string]bool
}
func (*saver) Name() string {
return "saver"
}
func (self *saver) Initialize(context *Context) error {
self.tokens = make(map[string]bool)
context.Threads(1)
return nil
}
func (self *saver) Process(context *Context, file *File) error {
for token := cleanPath(file.relPath); token != "."; token = filepath.Dir(token) {
self.tokens[token] = true
}
return file.export(context.goldsmith.targetDir)
}
func (self *saver) Finalize(context *Context) error {
if !self.clean {
return nil
}
scannedInfo := make(chan fileInfo)
go scanDir(context.goldsmith.targetDir, scannedInfo)
for info := range scannedInfo {
if info.path != context.goldsmith.targetDir {
relPath, _ := filepath.Rel(context.goldsmith.targetDir, info.path)
if contained, _ := self.tokens[relPath]; !contained {
os.RemoveAll(info.path)
}
}
}
return nil
}