diff --git a/context.go b/context.go index 3d260ea..0d9e3b4 100644 --- a/context.go +++ b/context.go @@ -65,7 +65,10 @@ func (context *Context) DispatchFile(file *File) { // dependencies on any input files that are needed to generate it, and then // passes it to the next link in the chain. func (context *Context) DispatchAndCacheFile(outputFile *File, inputFiles ...*File) { - context.goldsmith.storeFile(context, outputFile, inputFiles) + if context.goldsmith.fileCache != nil { + context.goldsmith.fileCache.storeFile(context, outputFile, inputFiles) + } + context.outputFiles <- outputFile } @@ -73,7 +76,12 @@ func (context *Context) DispatchAndCacheFile(outputFile *File, inputFiles ...*Fi // output path and any input files that are needed to generate it. The function // will return nil if the desired file is not found in the cache. func (context *Context) RetrieveCachedFile(outputPath string, inputFiles ...*File) *File { - return context.goldsmith.retrieveFile(context, outputPath, inputFiles) + var outputFile *File + if context.goldsmith.fileCache != nil { + outputFile, _ = context.goldsmith.fileCache.retrieveFile(context, outputPath, inputFiles) + } + + return outputFile } // Specify internal filter(s) that exclude files from being processed. diff --git a/goldsmith.go b/goldsmith.go index bad1dca..e8edd15 100644 --- a/goldsmith.go +++ b/goldsmith.go @@ -5,8 +5,6 @@ import ( "fmt" "hash" "hash/crc32" - "os" - "path/filepath" "sync" ) @@ -18,7 +16,6 @@ type Goldsmith struct { contexts []*Context contextHasher hash.Hash32 - fileRefs map[string]bool fileCache *cache filters filterStack @@ -33,10 +30,9 @@ func Begin(sourceDir string) *Goldsmith { goldsmith := &Goldsmith{ sourceDir: sourceDir, contextHasher: crc32.NewIEEE(), - fileRefs: make(map[string]bool), } - goldsmith.Chain(new(loader)) + goldsmith.Chain(&loader{}) return goldsmith } @@ -89,66 +85,18 @@ func (goldsmith *Goldsmith) FilterPop() *Goldsmith { func (goldsmith *Goldsmith) End(targetDir string) []error { goldsmith.targetDir = targetDir + goldsmith.Chain(&saver{ + clean: goldsmith.clean, + tokens: make(map[string]bool), + }) + for _, context := range goldsmith.contexts { go context.step() } - context := goldsmith.contexts[len(goldsmith.contexts)-1] - for file := range context.outputFiles { - if goldsmith.filters.accept(file) { - goldsmith.exportFile(file) - } - } - - if goldsmith.clean { - goldsmith.removeUnreferencedFiles() - } - return goldsmith.errors } -func (goldsmith *Goldsmith) retrieveFile(context *Context, outputPath string, inputFiles []*File) *File { - if goldsmith.fileCache != nil { - outputFile, _ := goldsmith.fileCache.retrieveFile(context, outputPath, inputFiles) - return outputFile - } - - return nil -} - -func (goldsmith *Goldsmith) storeFile(context *Context, outputFile *File, inputFiles []*File) { - if goldsmith.fileCache != nil { - goldsmith.fileCache.storeFile(context, outputFile, inputFiles) - } - -} - -func (goldsmith *Goldsmith) removeUnreferencedFiles() { - infos := make(chan fileInfo) - go scanDir(goldsmith.targetDir, infos) - - for info := range infos { - if info.path != goldsmith.targetDir { - relPath, _ := filepath.Rel(goldsmith.targetDir, info.path) - if contained, _ := goldsmith.fileRefs[relPath]; !contained { - os.RemoveAll(info.path) - } - } - } -} - -func (goldsmith *Goldsmith) exportFile(file *File) error { - if err := file.export(goldsmith.targetDir); err != nil { - return err - } - - for pathSeg := cleanPath(file.sourcePath); pathSeg != "."; pathSeg = filepath.Dir(pathSeg) { - goldsmith.fileRefs[pathSeg] = true - } - - return nil -} - func (goldsmith *Goldsmith) fault(name string, file *File, err error) { goldsmith.mutex.Lock() defer goldsmith.mutex.Unlock() diff --git a/loader.go b/loader.go index 478a399..d469237 100644 --- a/loader.go +++ b/loader.go @@ -2,9 +2,7 @@ package goldsmith import "path/filepath" -type loader struct { - Initializer -} +type loader struct{} func (*loader) Name() string { return "loader" diff --git a/saver.go b/saver.go new file mode 100644 index 0000000..2d7d4ac --- /dev/null +++ b/saver.go @@ -0,0 +1,49 @@ +package goldsmith + +import ( + "os" + "path/filepath" + "sync" +) + +type saver struct { + clean bool + + tokens map[string]bool + mutex sync.Mutex +} + +func (*saver) Name() string { + return "saver" +} + +func (saver *saver) Process(context *Context, file *File) error { + saver.mutex.Lock() + defer saver.mutex.Unlock() + + for token := cleanPath(file.sourcePath); token != "."; token = filepath.Dir(token) { + saver.tokens[token] = true + } + + return file.export(context.goldsmith.targetDir) +} + +func (saver *saver) Finalize(context *Context) error { + if !saver.clean { + return nil + } + + infos := make(chan fileInfo) + go scanDir(context.goldsmith.targetDir, infos) + + for info := range infos { + if info.path != context.goldsmith.targetDir { + relPath, _ := filepath.Rel(context.goldsmith.targetDir, info.path) + if contained, _ := saver.tokens[relPath]; !contained { + os.RemoveAll(info.path) + } + } + } + + return nil +}