WIP
This commit is contained in:
parent
394982f9e9
commit
37539daaf6
103
goldsmith.go
103
goldsmith.go
@ -29,19 +29,15 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
FileFlagStatic = 1 << iota
|
|
||||||
)
|
|
||||||
|
|
||||||
type stage struct {
|
type stage struct {
|
||||||
input, output chan *File
|
input, output chan *File
|
||||||
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
type goldsmith struct {
|
type goldsmith struct {
|
||||||
srcDir, dstDir string
|
srcDir, dstDir string
|
||||||
stages []stage
|
stages []*stage
|
||||||
refs map[string]bool
|
refs map[string]bool
|
||||||
err error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(srcDir, dstDir string) Goldsmith {
|
func New(srcDir, dstDir string) Goldsmith {
|
||||||
@ -50,21 +46,21 @@ func New(srcDir, dstDir string) Goldsmith {
|
|||||||
return gs
|
return gs
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFile(path string) *File {
|
func (gs *goldsmith) NewFile(path string) *File {
|
||||||
return &File{
|
return &File{
|
||||||
Path: cleanPath(path),
|
Path: cleanPath(path),
|
||||||
Meta: make(map[string]interface{}),
|
Meta: make(map[string]interface{}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFileStatic(path string) *File {
|
func (gs *goldsmith) NewFileStatic(path string) *File {
|
||||||
file := NewFile(path)
|
file := gs.NewFile(path)
|
||||||
file.Type = FileStatic
|
file.Type = FileStatic
|
||||||
return file
|
return file
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFileRef(path string) *File {
|
func (gs *goldsmith) NewFileRef(path string) *File {
|
||||||
file := NewFile(path)
|
file := gs.NewFile(path)
|
||||||
file.Type = FileReference
|
file.Type = FileReference
|
||||||
return file
|
return file
|
||||||
}
|
}
|
||||||
@ -84,7 +80,7 @@ func (gs *goldsmith) queueFiles() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
file := NewFile(relPath)
|
file := gs.NewFile(relPath)
|
||||||
|
|
||||||
var f *os.File
|
var f *os.File
|
||||||
if f, file.Err = os.Open(path); file.Err == nil {
|
if f, file.Err = os.Open(path); file.Err == nil {
|
||||||
@ -160,8 +156,8 @@ func (gs *goldsmith) exportFile(file *File) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gs *goldsmith) makeStage() stage {
|
func (gs *goldsmith) makeStage() *stage {
|
||||||
s := stage{output: make(chan *File)}
|
s := &stage{output: make(chan *File)}
|
||||||
if len(gs.stages) > 0 {
|
if len(gs.stages) > 0 {
|
||||||
s.input = gs.stages[len(gs.stages)-1].output
|
s.input = gs.stages[len(gs.stages)-1].output
|
||||||
}
|
}
|
||||||
@ -170,43 +166,36 @@ func (gs *goldsmith) makeStage() stage {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gs *goldsmith) chain(s stage, c Chainer) {
|
func (gs *goldsmith) chain(s *stage, p Plugin) {
|
||||||
var (
|
defer close(s.output)
|
||||||
wg sync.WaitGroup
|
|
||||||
output = make(chan *File)
|
|
||||||
input = make(chan *File)
|
|
||||||
)
|
|
||||||
|
|
||||||
wg.Add(1)
|
if init, ok := p.(Initializer); ok {
|
||||||
go func() {
|
if s.err = init.Initialize(gs); s.err != nil {
|
||||||
for file := range output {
|
return
|
||||||
s.output <- file
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Done()
|
if proc, ok := p.(Processor); ok {
|
||||||
}()
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
wg.Add(1)
|
|
||||||
go func() {
|
|
||||||
a, _ := c.(Accepter)
|
|
||||||
for file := range s.input {
|
for file := range s.input {
|
||||||
if file.Type == FileNormal && (a == nil || a.Accept(file)) {
|
go func(f *File) {
|
||||||
input <- file
|
defer wg.Done()
|
||||||
} else {
|
if proc.Process(gs, f) {
|
||||||
s.output <- file
|
s.output <- f
|
||||||
}
|
}
|
||||||
|
}(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
close(input)
|
|
||||||
wg.Done()
|
|
||||||
}()
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
c.Chain(gs, input, output)
|
|
||||||
|
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
close(s.output)
|
} else {
|
||||||
}()
|
for file := range s.input {
|
||||||
|
s.output <- file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if fin, ok := p.(Finalizer); ok {
|
||||||
|
s.err = fin.Finalize(gs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gs *goldsmith) refFile(path string) {
|
func (gs *goldsmith) refFile(path string) {
|
||||||
@ -234,42 +223,34 @@ func (gs *goldsmith) DstDir() string {
|
|||||||
return gs.dstDir
|
return gs.dstDir
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gs *goldsmith) Chain(c Chainer, err error) Goldsmith {
|
func (gs *goldsmith) Chain(p Plugin) Goldsmith {
|
||||||
if gs.err != nil {
|
go gs.chain(gs.makeStage(), p)
|
||||||
return gs
|
|
||||||
}
|
|
||||||
|
|
||||||
if gs.err = err; gs.err == nil {
|
|
||||||
gs.chain(gs.makeStage(), c)
|
|
||||||
}
|
|
||||||
|
|
||||||
return gs
|
return gs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gs *goldsmith) Complete() ([]*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 gs.err == nil {
|
|
||||||
gs.exportFile(file)
|
gs.exportFile(file)
|
||||||
}
|
|
||||||
|
|
||||||
file.Buff.Reset()
|
file.Buff.Reset()
|
||||||
files = append(files, file)
|
files = append(files, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
if gs.err == nil {
|
|
||||||
gs.cleanupFiles()
|
gs.cleanupFiles()
|
||||||
}
|
|
||||||
|
|
||||||
err := gs.err
|
var errs []error
|
||||||
|
for _, s := range gs.stages {
|
||||||
|
if s.err != nil {
|
||||||
|
errs = append(errs, s.err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gs.stages = nil
|
gs.stages = nil
|
||||||
gs.refs = nil
|
gs.refs = nil
|
||||||
gs.err = nil
|
|
||||||
|
|
||||||
return files, err
|
return files, errs
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanPath(path string) string {
|
func cleanPath(path string) string {
|
||||||
|
26
types.go
26
types.go
@ -25,18 +25,28 @@ package goldsmith
|
|||||||
import "bytes"
|
import "bytes"
|
||||||
|
|
||||||
type Goldsmith interface {
|
type Goldsmith interface {
|
||||||
Chain(c Chainer, err error) Goldsmith
|
Chain(p Plugin, err error) Goldsmith
|
||||||
Complete() ([]*File, error)
|
Complete() ([]*File, []error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Plugin interface{}
|
||||||
|
|
||||||
|
type Initializer interface {
|
||||||
|
Initialize(ctx Context) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type Finalizer interface {
|
||||||
|
Finalize(ctx Context) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type Processor interface {
|
||||||
|
Process(ctx Context, file *File) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Chainer interface {
|
type Chainer interface {
|
||||||
Chain(ctx Context, input, output chan *File)
|
Chain(ctx Context, input, output chan *File)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Accepter interface {
|
|
||||||
Accept(file *File) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type FileType int
|
type FileType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -56,4 +66,8 @@ type File struct {
|
|||||||
type Context interface {
|
type Context interface {
|
||||||
SrcDir() string
|
SrcDir() string
|
||||||
DstDir() string
|
DstDir() string
|
||||||
|
|
||||||
|
NewFile(path string) *File
|
||||||
|
NewFileStatic(path string) *File
|
||||||
|
NewFileRef(path string) *File
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user