Switch to new interfaces

This commit is contained in:
Alex Yatskov 2021-04-11 19:13:59 -07:00
parent a197b40f61
commit 4ff3c32c4b
7 changed files with 55 additions and 60 deletions

View File

@ -1,4 +1,4 @@
Copyright 2015-2019 Alex Yatskov Copyright 2015-2021 Alex Yatskov
Permission is hereby granted, free of charge, to any person obtaining a copy of 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 this software and associated documentation files (the "Software"), to deal in

View File

@ -75,7 +75,7 @@ func (cache *cache) buildCachePath(context *Context, outputPath string, inputFil
hasher.Write(uintBuff) hasher.Write(uintBuff)
hasher.Write([]byte(outputPath)) hasher.Write([]byte(outputPath))
sort.Sort(FilesByPath(inputFiles)) sort.Sort(filesByPath(inputFiles))
for _, inputFile := range inputFiles { for _, inputFile := range inputFiles {
fileHash, err := inputFile.hash() fileHash, err := inputFile.hash()
if err != nil { if err != nil {

View File

@ -17,7 +17,9 @@ type Context struct {
plugin Plugin plugin Plugin
hash uint32 hash uint32
fileFilters []Filter filtersExternal filterStack
filtersInternal filterStack
inputFiles chan *File inputFiles chan *File
outputFiles chan *File outputFiles chan *File
} }
@ -74,14 +76,17 @@ func (context *Context) RetrieveCachedFile(outputPath string, inputFiles ...*Fil
return context.goldsmith.retrieveFile(context, outputPath, inputFiles) return context.goldsmith.retrieveFile(context, outputPath, inputFiles)
} }
// Specify internal filter(s) that exclude files from being processed.
func (context *Context) Filter(filters ...Filter) *Context {
context.filtersInternal = filters
return context
}
func (context *Context) step() { func (context *Context) step() {
defer close(context.outputFiles) defer close(context.outputFiles)
var err error
var filter Filter
if initializer, ok := context.plugin.(Initializer); ok { if initializer, ok := context.plugin.(Initializer); ok {
filter, err = initializer.Initialize(context) if err := initializer.Initialize(context); err != nil {
if err != nil {
context.goldsmith.fault(context.plugin.Name(), nil, err) context.goldsmith.fault(context.plugin.Name(), nil, err)
return return
} }
@ -96,26 +101,7 @@ func (context *Context) step() {
go func() { go func() {
defer wg.Done() defer wg.Done()
for inputFile := range context.inputFiles { for inputFile := range context.inputFiles {
var fileFilters []Filter if processor != nil && context.filtersInternal.accept(inputFile) && context.filtersExternal.accept(inputFile) {
fileFilters = append(fileFilters, context.fileFilters...)
if filter != nil {
fileFilters = append(fileFilters, filter)
}
var accept bool
if processor != nil {
for _, fileFilter := range fileFilters {
if accept, err = fileFilter.Accept(inputFile); err != nil {
context.goldsmith.fault(fileFilter.Name(), inputFile, err)
return
}
if !accept {
break
}
}
}
if accept {
if _, err := inputFile.Seek(0, os.SEEK_SET); err != nil { if _, err := inputFile.Seek(0, os.SEEK_SET); err != nil {
context.goldsmith.fault("core", inputFile, err) context.goldsmith.fault("core", inputFile, err)
} }

33
file.go
View File

@ -186,17 +186,17 @@ func (file *File) hash() (uint32, error) {
return file.hashValue, nil return file.hashValue, nil
} }
type FilesByPath []*File type filesByPath []*File
func (file FilesByPath) Len() int { func (file filesByPath) Len() int {
return len(file) return len(file)
} }
func (file FilesByPath) Swap(i, j int) { func (file filesByPath) Swap(i, j int) {
file[i], file[j] = file[j], file[i] file[i], file[j] = file[j], file[i]
} }
func (file FilesByPath) Less(i, j int) bool { func (file filesByPath) Less(i, j int) bool {
return strings.Compare(file[i].Path(), file[j].Path()) < 0 return strings.Compare(file[i].Path(), file[j].Path()) < 0
} }
@ -227,3 +227,28 @@ func scanDir(rootDir string, infos chan fileInfo) {
return err return err
}) })
} }
type filterStack []Filter
func (filters *filterStack) accept(file *File) bool {
for _, filter := range *filters {
if !filter.Accept(file) {
return false
}
}
return true
}
func (filters *filterStack) push(filter Filter) {
*filters = append(*filters, filter)
}
func (filters *filterStack) pop() {
count := len(*filters)
if count == 0 {
panic("attempted to pop empty filter stack")
}
*filters = (*filters)[:count-1]
}

View File

@ -19,9 +19,9 @@ type Goldsmith struct {
contextHasher hash.Hash32 contextHasher hash.Hash32
fileRefs map[string]bool fileRefs map[string]bool
fileFilters []Filter
fileCache *cache fileCache *cache
filters filterStack
clean bool clean bool
errors []error errors []error
@ -63,7 +63,7 @@ func (goldsmith *Goldsmith) Chain(plugin Plugin) *Goldsmith {
outputFiles: make(chan *File), outputFiles: make(chan *File),
} }
context.fileFilters = append(context.fileFilters, goldsmith.fileFilters...) context.filtersExternal = append(context.filtersExternal, goldsmith.filters...)
if len(goldsmith.contexts) > 0 { if len(goldsmith.contexts) > 0 {
context.inputFiles = goldsmith.contexts[len(goldsmith.contexts)-1].outputFiles context.inputFiles = goldsmith.contexts[len(goldsmith.contexts)-1].outputFiles
@ -75,18 +75,13 @@ func (goldsmith *Goldsmith) Chain(plugin Plugin) *Goldsmith {
// FilterPush pushes a filter instance on the chain's filter stack. // FilterPush pushes a filter instance on the chain's filter stack.
func (goldsmith *Goldsmith) FilterPush(filter Filter) *Goldsmith { func (goldsmith *Goldsmith) FilterPush(filter Filter) *Goldsmith {
goldsmith.fileFilters = append(goldsmith.fileFilters, filter) goldsmith.filters.push(filter)
return goldsmith return goldsmith
} }
// FilterPop pops a filter instance from the chain's filter stack. // FilterPop pops a filter instance from the chain's filter stack.
func (goldsmith *Goldsmith) FilterPop() *Goldsmith { func (goldsmith *Goldsmith) FilterPop() *Goldsmith {
count := len(goldsmith.fileFilters) goldsmith.filters.pop()
if count == 0 {
panic("attempted to pop empty filter stack")
}
goldsmith.fileFilters = goldsmith.fileFilters[:count-1]
return goldsmith return goldsmith
} }
@ -99,22 +94,11 @@ func (goldsmith *Goldsmith) End(targetDir string) []error {
} }
context := goldsmith.contexts[len(goldsmith.contexts)-1] context := goldsmith.contexts[len(goldsmith.contexts)-1]
export:
for file := range context.outputFiles { for file := range context.outputFiles {
for _, fileFilter := range goldsmith.fileFilters { if goldsmith.filters.accept(file) {
accept, err := fileFilter.Accept(file)
if err != nil {
goldsmith.fault(fileFilter.Name(), file, err)
continue export
}
if !accept {
continue export
}
}
goldsmith.exportFile(file) goldsmith.exportFile(file)
} }
}
if goldsmith.clean { if goldsmith.clean {
goldsmith.removeUnreferencedFiles() goldsmith.removeUnreferencedFiles()

View File

@ -9,7 +9,7 @@ type Plugin interface {
// Initializer is used to optionally initialize a plugin and to specify a // Initializer is used to optionally initialize a plugin and to specify a
// filter to be used for determining which files will be processed. // filter to be used for determining which files will be processed.
type Initializer interface { type Initializer interface {
Initialize(context *Context) (Filter, error) Initialize(context *Context) error
} }
// Processor allows for optional processing of files passing through a plugin. // Processor allows for optional processing of files passing through a plugin.
@ -26,5 +26,5 @@ type Finalizer interface {
// Filter is used to determine which files should continue in the chain. // Filter is used to determine which files should continue in the chain.
type Filter interface { type Filter interface {
Name() string Name() string
Accept(file *File) (bool, error) Accept(file *File) bool
} }

View File

@ -10,7 +10,7 @@ func (*loader) Name() string {
return "loader" return "loader"
} }
func (*loader) Initialize(ctx *Context) (Filter, error) { func (*loader) Initialize(ctx *Context) error {
infos := make(chan fileInfo) infos := make(chan fileInfo)
go scanDir(ctx.goldsmith.sourceDir, infos) go scanDir(ctx.goldsmith.sourceDir, infos)
@ -32,5 +32,5 @@ func (*loader) Initialize(ctx *Context) (Filter, error) {
ctx.DispatchFile(file) ctx.DispatchFile(file)
} }
return nil, nil return nil
} }