This commit is contained in:
Alex Yatskov 2015-11-02 17:11:11 +09:00
parent a6b0c84934
commit 57769c218c
2 changed files with 46 additions and 28 deletions

View File

@ -33,38 +33,39 @@ import (
) )
type stage struct { type stage struct {
input, output chan File input, output chan *File
} }
type goldsmith struct { type goldsmith struct {
srcDir, dstDir string
stages []stage stages []stage
files chan File files chan *File
err error err error
} }
func New(src string) Goldsmith { func New(srcDir, dstDir string) Goldsmith {
gs := new(goldsmith) gs := &goldsmith{srcDir: srcDir, dstDir: dstDir}
gs.scan(src) gs.scan()
return gs return gs
} }
func (gs *goldsmith) scan(srcDir string) { func (gs *goldsmith) scan() {
matches, err := doublestar.Glob(filepath.Join(srcDir, "**")) matches, err := doublestar.Glob(filepath.Join(gs.srcDir, "**"))
if err != nil { if err != nil {
gs.err = err gs.err = err
return return
} }
s := stage{nil, make(chan File, len(matches))} s := stage{nil, make(chan *File, len(matches))}
defer close(s.output) defer close(s.output)
for _, match := range matches { for _, match := range matches {
relPath, err := filepath.Rel(srcDir, match) relPath, err := filepath.Rel(gs.srcDir, match)
if err != nil { if err != nil {
panic(err) panic(err)
} }
file := File{ file := &File{
Path: relPath, Path: relPath,
Meta: make(map[string]interface{}), Meta: make(map[string]interface{}),
Buff: new(bytes.Buffer), Buff: new(bytes.Buffer),
@ -83,7 +84,11 @@ func (gs *goldsmith) scan(srcDir string) {
} }
func (gs *goldsmith) makeStage() stage { func (gs *goldsmith) makeStage() stage {
s := stage{gs.stages[len(gs.stages)-1].output, make(chan File)} s := stage{
gs.stages[len(gs.stages)-1].output,
make(chan *File),
}
gs.stages = append(gs.stages, s) gs.stages = append(gs.stages, s)
return s return s
} }
@ -94,12 +99,12 @@ func (gs *goldsmith) chainSingle(s stage, cs ChainerSingle, globs []string) {
var wg sync.WaitGroup var wg sync.WaitGroup
for file := range s.input { for file := range s.input {
wg.Add(1) wg.Add(1)
go func(f File) { go func(f *File) {
defer wg.Done() defer wg.Done()
if skipFile(&f, globs) { if skipFile(f, globs) {
s.output <- f s.output <- f
} else { } else {
s.output <- cs.ChainSingle(f) s.output <- cs.ChainSingle(gs, f)
} }
}(file) }(file)
} }
@ -108,13 +113,13 @@ func (gs *goldsmith) chainSingle(s stage, cs ChainerSingle, globs []string) {
} }
func (gs *goldsmith) chainMultiple(s stage, cm ChainerMultiple, globs []string) { func (gs *goldsmith) chainMultiple(s stage, cm ChainerMultiple, globs []string) {
filtered := make(chan File) filtered := make(chan *File)
defer close(filtered) defer close(filtered)
go cm.ChainMultiple(filtered, s.output) go cm.ChainMultiple(gs, filtered, s.output)
for file := range s.input { for file := range s.input {
if skipFile(&file, globs) { if skipFile(file, globs) {
s.output <- file s.output <- file
} else { } else {
filtered <- file filtered <- file
@ -122,7 +127,15 @@ func (gs *goldsmith) chainMultiple(s stage, cm ChainerMultiple, globs []string)
} }
} }
func (gs *goldsmith) Chain(ctx Context) Goldsmith { func (gs *goldsmith) SrcDir() string {
return gs.srcDir
}
func (gs *goldsmith) DstDir() string {
return gs.dstDir
}
func (gs *goldsmith) Chain(ctx Config) Goldsmith {
if gs.err != nil { if gs.err != nil {
return gs return gs
} }
@ -139,13 +152,13 @@ func (gs *goldsmith) Chain(ctx Context) Goldsmith {
return gs return gs
} }
func (gs *goldsmith) Complete(dstDir string) ([]File, error) { func (gs *goldsmith) Complete() ([]*File, error) {
s := gs.stages[len(gs.stages)-1] s := gs.stages[len(gs.stages)-1]
var files []File var files []*File
for file := range s.output { for file := range s.output {
if file.Err == nil { if file.Err == nil {
absPath := filepath.Join(dstDir, file.Path) absPath := filepath.Join(gs.dstDir, file.Path)
if file.Err = os.MkdirAll(path.Dir(absPath), 0755); file.Err != nil { if file.Err = os.MkdirAll(path.Dir(absPath), 0755); file.Err != nil {
continue continue
} }

View File

@ -25,16 +25,16 @@ package goldsmith
import "bytes" import "bytes"
type Goldsmith interface { type Goldsmith interface {
Chain(ctx Context) Goldsmith Chain(cfg Config) Goldsmith
Complete(dstDir string) ([]File, error) Complete() ([]*File, error)
} }
type ChainerSingle interface { type ChainerSingle interface {
ChainSingle(file File) File ChainSingle(ctx Context, file *File) *File
} }
type ChainerMultiple interface { type ChainerMultiple interface {
ChainMultiple(input, output chan File) ChainMultiple(ctx Context, input, output chan *File)
} }
type File struct { type File struct {
@ -44,7 +44,12 @@ type File struct {
Err error Err error
} }
type Context struct { type Context interface {
SrcDir() string
DstDir() string
}
type Config struct {
Chainer interface{} Chainer interface{}
Globs []string Globs []string
Err error Err error