diff --git a/context.go b/context.go index 921f642..e003cba 100644 --- a/context.go +++ b/context.go @@ -14,8 +14,7 @@ import ( // Context corresponds to the current link in the chain and provides methods // that enable plugins to inject new files into the chain. type Context struct { - goldsmith *Goldsmith - + chain *chainState plugin Plugin filtersExt filterStack @@ -86,8 +85,8 @@ func (self *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 (self *Context) DispatchAndCacheFile(outputFile *File, inputFiles ...*File) { - if self.goldsmith.state.cache != nil { - self.goldsmith.state.cache.storeFile(self, outputFile, inputFiles) + if self.chain.cache != nil { + self.chain.cache.storeFile(self, outputFile, inputFiles) } self.DispatchFile(outputFile) @@ -98,8 +97,8 @@ func (self *Context) DispatchAndCacheFile(outputFile *File, inputFiles ...*File) // will return nil if the desired file is not found in the cache. func (self *Context) RetrieveCachedFile(outputPath string, inputFiles ...*File) *File { var outputFile *File - if self.goldsmith.state.cache != nil { - outputFile, _ = self.goldsmith.state.cache.retrieveFile(self, outputPath, inputFiles) + if self.chain.cache != nil { + outputFile, _ = self.chain.cache.retrieveFile(self, outputPath, inputFiles) } return outputFile @@ -125,7 +124,7 @@ func (self *Context) step() { if initializer, ok := self.plugin.(Initializer); ok { if err := initializer.Initialize(self); err != nil { - self.goldsmith.fault(self.plugin.Name(), nil, err) + self.chain.fault(self.plugin.Name(), nil, err) return } } @@ -146,10 +145,10 @@ func (self *Context) step() { for inputFile := range self.filesIn { if processor != nil && self.filtersInt.accept(inputFile) && self.filtersExt.accept(inputFile) { if _, err := inputFile.Seek(0, io.SeekStart); err != nil { - self.goldsmith.fault("core", inputFile, err) + self.chain.fault("core", inputFile, err) } if err := processor.Process(self, inputFile); err != nil { - self.goldsmith.fault(self.plugin.Name(), inputFile, err) + self.chain.fault(self.plugin.Name(), inputFile, err) } } else { self.DispatchFile(inputFile) @@ -163,7 +162,7 @@ func (self *Context) step() { if finalizer, ok := self.plugin.(Finalizer); ok { if err := finalizer.Finalize(self); err != nil { - self.goldsmith.fault(self.plugin.Name(), nil, err) + self.chain.fault(self.plugin.Name(), nil, err) } } } diff --git a/goldsmith.go b/goldsmith.go index cfde059..429fa0e 100644 --- a/goldsmith.go +++ b/goldsmith.go @@ -6,6 +6,82 @@ import ( "sync" ) +// Goldsmith chainable context. +type Goldsmith struct { + chain *chainState +} + +// Begin starts a chain, reading the files located in the source directory as input. +func (self *Goldsmith) Begin(sourceDir string) *Goldsmith { + self.chain = new(chainState) + self.Chain(&fileImporter{sourceDir: sourceDir}) + return self +} + +// Cache enables caching in cacheDir for the remainder of the chain. +func (self *Goldsmith) Cache(cacheDir string) *Goldsmith { + self.chain.cache = &cache{cacheDir} + return self +} + +// Clean enables or disables removal of leftover files in the target directory. +func (self *Goldsmith) Clean(clean bool) *Goldsmith { + self.chain.clean = clean + return self +} + +// Chain links a plugin instance into the chain. +func (self *Goldsmith) Chain(plugin Plugin) *Goldsmith { + context := &Context{ + chain: self.chain, + plugin: plugin, + filtersExt: append(filterStack(nil), self.chain.filters...), + index: self.chain.index, + filesOut: make(chan *File), + } + + if len(self.chain.contexts) > 0 { + context.filesIn = self.chain.contexts[len(self.chain.contexts)-1].filesOut + } + + self.chain.contexts = append(self.chain.contexts, context) + self.chain.index++ + + return self +} + +// FilterPush pushes a filter instance on the chain's filter stack. +func (self *Goldsmith) FilterPush(filter Filter) *Goldsmith { + self.chain.filters.push(filter, self.chain.index) + self.chain.index++ + return self +} + +// FilterPop pops a filter instance from the chain's filter stack. +func (self *Goldsmith) FilterPop() *Goldsmith { + self.chain.filters.pop() + self.chain.index++ + return self +} + +// End stops a chain, writing all recieved files to targetDir as output. +func (self *Goldsmith) End(targetDir string) []error { + self.Chain(&fileExporter{targetDir: targetDir, clean: self.chain.clean}) + for _, context := range self.chain.contexts { + go context.step() + } + + context := self.chain.contexts[len(self.chain.contexts)-1] + for range context.filesOut { + + } + + errors := self.chain.errors + self.chain = nil + + return errors +} + type chainState struct { contexts []*Context @@ -18,85 +94,9 @@ type chainState struct { mutex sync.Mutex } -// Goldsmith chainable context. -type Goldsmith struct { - state *chainState -} - -// Begin starts a chain, reading the files located in the source directory as input. -func (self *Goldsmith) Begin(sourceDir string) *Goldsmith { - self.state = new(chainState) - self.Chain(&fileImporter{sourceDir: sourceDir}) - return self -} - -// Cache enables caching in cacheDir for the remainder of the chain. -func (self *Goldsmith) Cache(cacheDir string) *Goldsmith { - self.state.cache = &cache{cacheDir} - return self -} - -// Clean enables or disables removal of leftover files in the target directory. -func (self *Goldsmith) Clean(clean bool) *Goldsmith { - self.state.clean = clean - return self -} - -// Chain links a plugin instance into the chain. -func (self *Goldsmith) Chain(plugin Plugin) *Goldsmith { - context := &Context{ - goldsmith: self, - plugin: plugin, - filtersExt: append(filterStack(nil), self.state.filters...), - index: self.state.index, - filesOut: make(chan *File), - } - - if len(self.state.contexts) > 0 { - context.filesIn = self.state.contexts[len(self.state.contexts)-1].filesOut - } - - self.state.contexts = append(self.state.contexts, context) - self.state.index++ - - return self -} - -// FilterPush pushes a filter instance on the chain's filter stack. -func (self *Goldsmith) FilterPush(filter Filter) *Goldsmith { - self.state.filters.push(filter, self.state.index) - self.state.index++ - return self -} - -// FilterPop pops a filter instance from the chain's filter stack. -func (self *Goldsmith) FilterPop() *Goldsmith { - self.state.filters.pop() - self.state.index++ - return self -} - -// End stops a chain, writing all recieved files to targetDir as output. -func (self *Goldsmith) End(targetDir string) []error { - self.Chain(&fileExporter{targetDir: targetDir, clean: self.state.clean}) - for _, context := range self.state.contexts { - go context.step() - } - - context := self.state.contexts[len(self.state.contexts)-1] - for range context.filesOut { - - } - - errors := self.state.errors - self.state = nil - - return errors -} - -func (self *Goldsmith) fault(name string, file *File, err error) { - self.state.mutex.Lock() - defer self.state.mutex.Unlock() +func (self *chainState) fault(name string, file *File, err error) { + self.mutex.Lock() + defer self.mutex.Unlock() var faultError error if file == nil { @@ -105,5 +105,5 @@ func (self *Goldsmith) fault(name string, file *File, err error) { faultError = fmt.Errorf("[%s@%v]: %w", name, file, err) } - self.state.errors = append(self.state.errors, faultError) + self.errors = append(self.errors, faultError) }