From 64f554ef419485b4bcb6de1471a7bf98f9c087ca Mon Sep 17 00:00:00 2001 From: Evan Lezar Date: Tue, 21 Nov 2023 16:55:26 +0100 Subject: [PATCH] Add builder for file locator Signed-off-by: Evan Lezar --- internal/lookup/file.go | 78 +++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/internal/lookup/file.go b/internal/lookup/file.go index 20a1f164..636ac315 100644 --- a/internal/lookup/file.go +++ b/internal/lookup/file.go @@ -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 // prefixes. The validity of a file is determined by a filter function. type file struct { - logger logger.Interface - root string - prefixes []string - filter func(string) error - count int - isOptional bool + builder + prefixes []string } -// Option defines a function for passing options to the NewFileLocator() call -type Option func(*file) +// builder defines the builder for a file locator. +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 func WithRoot(root string) Option { - return func(f *file) { + return func(f *builder) { f.root = root } } // WithLogger sets the logger for the file locator func WithLogger(logger logger.Interface) Option { - return func(f *file) { + return func(f *builder) { f.logger = logger } } // WithSearchPaths sets the search paths for the file locator. func WithSearchPaths(paths ...string) Option { - return func(f *file) { - f.prefixes = paths + return func(f *builder) { + f.searchPaths = paths } } // WithFilter sets the filter for the file locator // The filter is called for each candidate file and candidates that return nil are considered. func WithFilter(assert func(string) error) Option { - return func(f *file) { + return func(f *builder) { f.filter = assert } } // WithCount sets the maximum number of candidates to discover func WithCount(count int) Option { - return func(f *file) { + return func(f *builder) { f.count = count } } @@ -81,32 +87,42 @@ func WithCount(count int) Option { // 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. func WithOptional(optional bool) Option { - return func(f *file) { + return func(f *builder) { 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 { return newFileLocator(opts...) } func newFileLocator(opts ...Option) *file { - f := &file{} - 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 + return newBuilder(opts...).build() } // getSearchPrefixes generates a list of unique paths to be searched by a file locator.