diff --git a/context.go b/context.go index 0e8bd3c..f85eec5 100644 --- a/context.go +++ b/context.go @@ -30,26 +30,17 @@ import ( type context struct { gs *goldsmith + plug Plugin input, output chan *file } -func newContext(gs *goldsmith) *context { - ctx := &context{gs: gs, output: make(chan *file)} - if len(gs.contexts) > 0 { - ctx.input = gs.contexts[len(gs.contexts)-1].output - } - - gs.contexts = append(gs.contexts, ctx) - return ctx -} - -func (ctx *context) chain(p Plugin) { +func (ctx *context) chain() { defer close(ctx.output) - init, _ := p.(Initializer) - accept, _ := p.(Accepter) - proc, _ := p.(Processor) - fin, _ := p.(Finalizer) + init, _ := ctx.plug.(Initializer) + accept, _ := ctx.plug.(Accepter) + proc, _ := ctx.plug.(Processor) + fin, _ := ctx.plug.(Finalizer) if init != nil { if err := init.Initialize(ctx); err != nil { @@ -58,26 +49,28 @@ func (ctx *context) chain(p Plugin) { } } - var wg sync.WaitGroup - for i := 0; i < runtime.NumCPU(); i++ { - wg.Add(1) - go func() { - defer wg.Done() - for f := range ctx.input { - if proc == nil || accept != nil && !accept.Accept(ctx, f) { - ctx.output <- f - } else { - if _, err := f.Seek(0, os.SEEK_SET); err != nil { - ctx.gs.fault(f, err) - } - if err := proc.Process(ctx, f); err != nil { - ctx.gs.fault(f, err) + if ctx.input != nil { + var wg sync.WaitGroup + for i := 0; i < runtime.NumCPU(); i++ { + wg.Add(1) + go func() { + defer wg.Done() + for f := range ctx.input { + if proc == nil || accept != nil && !accept.Accept(ctx, f) { + ctx.output <- f + } else { + if _, err := f.Seek(0, os.SEEK_SET); err != nil { + ctx.gs.fault(f, err) + } + if err := proc.Process(ctx, f); err != nil { + ctx.gs.fault(f, err) + } } } - } - }() + }() + } + wg.Wait() } - wg.Wait() if fin != nil { if err := fin.Finalize(ctx); err != nil { diff --git a/goldsmith.go b/goldsmith.go index b744a37..6af2130 100644 --- a/goldsmith.go +++ b/goldsmith.go @@ -39,24 +39,14 @@ type goldsmith struct { errorMtx sync.Mutex } -func (gs *goldsmith) queueFiles() { - files := make(chan string) - go scanDir(gs.srcDir, files, nil) +func (gs *goldsmith) pushContext(plug Plugin) *context { + ctx := &context{gs: gs, plug: plug, output: make(chan *file)} + if len(gs.contexts) > 0 { + ctx.input = gs.contexts[len(gs.contexts)-1].output + } - ctx := newContext(gs) - - go func() { - defer close(ctx.output) - for path := range files { - relPath, err := filepath.Rel(gs.srcDir, path) - if err != nil { - panic(err) - } - - f := NewFileFromAsset(relPath, path) - ctx.DispatchFile(f) - } - }() + gs.contexts = append(gs.contexts, ctx) + return ctx } func (gs *goldsmith) cleanupFiles() { @@ -139,12 +129,17 @@ func (gs *goldsmith) fault(f *file, err error) { // func (gs *goldsmith) Chain(p Plugin) Goldsmith { - ctx := newContext(gs) - go ctx.chain(p) + gs.pushContext(p) return gs } -func (gs *goldsmith) Complete() []error { +func (gs *goldsmith) End(dstDir string) []error { + gs.dstDir = dstDir + + for _, ctx := range gs.contexts { + go ctx.chain() + } + ctx := gs.contexts[len(gs.contexts)-1] for f := range ctx.output { gs.exportFile(f) diff --git a/loader.go b/loader.go new file mode 100644 index 0000000..cbf0204 --- /dev/null +++ b/loader.go @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 Alex Yatskov + * Author: Alex Yatskov + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package goldsmith + +import "path/filepath" + +type loader struct{} + +func (*loader) Initialize(ctx Context) error { + files := make(chan string) + go scanDir(ctx.SrcDir(), files, nil) + + for path := range files { + relPath, err := filepath.Rel(ctx.SrcDir(), path) + if err != nil { + return err + } + + f := NewFileFromAsset(relPath, path) + ctx.DispatchFile(f) + } + + return nil +} diff --git a/types.go b/types.go index 2451a9a..7d702c2 100644 --- a/types.go +++ b/types.go @@ -29,17 +29,12 @@ import ( type Goldsmith interface { Chain(p Plugin) Goldsmith - Complete() []error + End(dstDir string) []error } -func New(srcDir, dstDir string) Goldsmith { - gs := &goldsmith{ - srcDir: srcDir, - dstDir: dstDir, - refs: make(map[string]bool), - } - - gs.queueFiles() +func Begin(srcDir string) Goldsmith { + gs := &goldsmith{srcDir: srcDir, refs: make(map[string]bool)} + gs.Chain(new(loader)) return gs }