Add builder for file locator

Signed-off-by: Evan Lezar <elezar@nvidia.com>
This commit is contained in:
Evan Lezar 2023-11-21 16:55:26 +01:00
parent 039d7fd324
commit 64f554ef41

View File

@ -31,49 +31,55 @@ var ErrNotFound = errors.New("not found")
// file can be used to locate file (or file-like elements) at a specified set of // file can be used to locate file (or file-like elements) at a specified set of
// prefixes. The validity of a file is determined by a filter function. // prefixes. The validity of a file is determined by a filter function.
type file struct { type file struct {
logger logger.Interface builder
root string prefixes []string
prefixes []string
filter func(string) error
count int
isOptional bool
} }
// Option defines a function for passing options to the NewFileLocator() call // builder defines the builder for a file locator.
type Option func(*file) type builder struct {
logger logger.Interface
root string
searchPaths []string
filter func(string) error
count int
isOptional bool
}
// Option defines a function for passing builder to the NewFileLocator() call
type Option func(*builder)
// WithRoot sets the root for the file locator // WithRoot sets the root for the file locator
func WithRoot(root string) Option { func WithRoot(root string) Option {
return func(f *file) { return func(f *builder) {
f.root = root f.root = root
} }
} }
// WithLogger sets the logger for the file locator // WithLogger sets the logger for the file locator
func WithLogger(logger logger.Interface) Option { func WithLogger(logger logger.Interface) Option {
return func(f *file) { return func(f *builder) {
f.logger = logger f.logger = logger
} }
} }
// WithSearchPaths sets the search paths for the file locator. // WithSearchPaths sets the search paths for the file locator.
func WithSearchPaths(paths ...string) Option { func WithSearchPaths(paths ...string) Option {
return func(f *file) { return func(f *builder) {
f.prefixes = paths f.searchPaths = paths
} }
} }
// WithFilter sets the filter for the file locator // WithFilter sets the filter for the file locator
// The filter is called for each candidate file and candidates that return nil are considered. // The filter is called for each candidate file and candidates that return nil are considered.
func WithFilter(assert func(string) error) Option { func WithFilter(assert func(string) error) Option {
return func(f *file) { return func(f *builder) {
f.filter = assert f.filter = assert
} }
} }
// WithCount sets the maximum number of candidates to discover // WithCount sets the maximum number of candidates to discover
func WithCount(count int) Option { func WithCount(count int) Option {
return func(f *file) { return func(f *builder) {
f.count = count f.count = count
} }
} }
@ -81,32 +87,42 @@ func WithCount(count int) Option {
// WithOptional sets the optional flag for the file locator // WithOptional sets the optional flag for the file locator
// If the optional flag is set, the locator will not return an error if the file is not found. // If the optional flag is set, the locator will not return an error if the file is not found.
func WithOptional(optional bool) Option { func WithOptional(optional bool) Option {
return func(f *file) { return func(f *builder) {
f.isOptional = optional f.isOptional = optional
} }
} }
// NewFileLocator creates a Locator that can be used to find files with the specified options. func newBuilder(opts ...Option) *builder {
o := &builder{}
for _, opt := range opts {
opt(o)
}
if o.logger == nil {
o.logger = logger.New()
}
if o.filter == nil {
o.filter = assertFile
}
return o
}
func (o builder) build() *file {
f := file{
builder: o,
// Since the `Locate` implementations rely on the root already being specified we update
// the prefixes to include the root.
prefixes: getSearchPrefixes(o.root, o.searchPaths...),
}
return &f
}
// NewFileLocator creates a Locator that can be used to find files with the specified builder.
func NewFileLocator(opts ...Option) Locator { func NewFileLocator(opts ...Option) Locator {
return newFileLocator(opts...) return newFileLocator(opts...)
} }
func newFileLocator(opts ...Option) *file { func newFileLocator(opts ...Option) *file {
f := &file{} return newBuilder(opts...).build()
for _, opt := range opts {
opt(f)
}
if f.logger == nil {
f.logger = logger.New()
}
if f.filter == nil {
f.filter = assertFile
}
// Since the `Locate` implementations rely on the root already being specified we update
// the prefixes to include the root.
f.prefixes = getSearchPrefixes(f.root, f.prefixes...)
return f
} }
// getSearchPrefixes generates a list of unique paths to be searched by a file locator. // getSearchPrefixes generates a list of unique paths to be searched by a file locator.