From 0446725ea8a25400d5c95206242913d4429e0b5e Mon Sep 17 00:00:00 2001 From: plastikfan Date: Thu, 16 Nov 2023 21:33:54 +0000 Subject: [PATCH] feat(nav): implement directory sampling (#369) feat(nav): implement file sampler (#369) feat(nav): implement folder sampler (#369) feat(nav): implement universal sampler (#369) ref(nav): remove redundant order field from directory entries (#369) ref(nav): remove frivolous factories (#369) ref(nav): tidy up xi18n/i18n imports (#369) --- internal/helpers/test-utilities.go | 12 +++++-- internal/log/new-logger.go | 4 +-- xfs/nav/directory-entries.go | 54 ++++++++++++++-------------- xfs/nav/error-handlers.go | 6 ++-- xfs/nav/helpers_test.go | 7 ++-- xfs/nav/marshal-state.go | 4 +-- xfs/nav/navigation-agent.go | 34 ++++++++---------- xfs/nav/navigation-listener.go | 4 +-- xfs/nav/navigation-session.go | 4 +-- xfs/nav/navigator-files.go | 32 +++++++++-------- xfs/nav/navigator-folders.go | 17 ++++----- xfs/nav/navigator-universal.go | 36 ++++++++++--------- xfs/nav/new-filter.go | 6 ++-- xfs/nav/new-marshaller.go | 4 +-- xfs/nav/new-navigator.go | 14 ++++---- xfs/nav/new-resume.go | 4 +-- xfs/nav/resume-strategy-spawn.go | 13 +++---- xfs/nav/traverse-defs.go | 2 +- xfs/nav/traverse-sample_test.go | 57 ++++++++++++++++++++++++------ xfs/nav/traverse-samplers.go | 36 ++++++++++++------- 20 files changed, 200 insertions(+), 150 deletions(-) diff --git a/internal/helpers/test-utilities.go b/internal/helpers/test-utilities.go index 7be25c5..460480c 100644 --- a/internal/helpers/test-utilities.go +++ b/internal/helpers/test-utilities.go @@ -7,7 +7,7 @@ import ( "runtime" "strings" - xi18n "github.com/snivilised/extendio/i18n" + "github.com/snivilised/extendio/i18n" "github.com/snivilised/extendio/xfs/nav" ) @@ -24,6 +24,12 @@ func Reason(name string) string { return fmt.Sprintf("❌ for item named: '%v'", name) } +func BecauseQuantity(name string, expected, actual int) string { + return fmt.Sprintf("❌ incorrect no of items for: '%v', expected: '%v', actual: '%v'", + name, expected, actual, + ) +} + func JoinCwd(segments ...string) string { if current, err := os.Getwd(); err == nil { parent, _ := filepath.Split(current) @@ -98,8 +104,8 @@ type DummyCreator struct { Invoked bool } -func (dc *DummyCreator) Create(_ *xi18n.LanguageInfo, _ string) (*xi18n.Localizer, error) { +func (dc *DummyCreator) Create(_ *i18n.LanguageInfo, _ string) (*i18n.Localizer, error) { dc.Invoked = true - return &xi18n.Localizer{}, nil + return &i18n.Localizer{}, nil } diff --git a/internal/log/new-logger.go b/internal/log/new-logger.go index 4f3f78d..1b0c42a 100644 --- a/internal/log/new-logger.go +++ b/internal/log/new-logger.go @@ -7,14 +7,14 @@ import ( "go.uber.org/zap" "go.uber.org/zap/zapcore" - xi18n "github.com/snivilised/extendio/i18n" + "github.com/snivilised/extendio/i18n" ) func NewLogger(info *LoggerInfo) Ref { return utils.NewRoProp(lo.TernaryF(info.Enabled, func() Logger { if info.Path == "" { - panic(xi18n.NewInvalidConfigEntryError(info.Path, "Store/Logging/Path")) + panic(i18n.NewInvalidConfigEntryError(info.Path, "Store/Logging/Path")) } ws := zapcore.AddSync(&lumberjack.Logger{ Filename: info.Path, diff --git a/xfs/nav/directory-entries.go b/xfs/nav/directory-entries.go index 70bd938..36e8bc1 100644 --- a/xfs/nav/directory-entries.go +++ b/xfs/nav/directory-entries.go @@ -1,11 +1,10 @@ package nav import ( - "fmt" "io/fs" "github.com/samber/lo" - xi18n "github.com/snivilised/extendio/i18n" + "github.com/snivilised/extendio/i18n" ) // DirectoryEntryOrderEnum determines what order a directories @@ -20,18 +19,14 @@ const ( DirectoryEntryOrderFilesFirstEn ) -type directoryEntriesFactory struct{} - -type directoryEntriesFactoryParams struct { +type newDirectoryEntriesParams struct { o *TraverseOptions - order DirectoryEntryOrderEnum entries []fs.DirEntry } -func (directoryEntriesFactory) new(params *directoryEntriesFactoryParams) *DirectoryEntries { +func newDirectoryEntries(params *newDirectoryEntriesParams) *DirectoryEntries { instance := DirectoryEntries{ Options: params.o, - Order: params.order, } instance.arrange(params.entries) @@ -39,17 +34,29 @@ func (directoryEntriesFactory) new(params *directoryEntriesFactoryParams) *Direc return &instance } -// DirectoryEntries +// DirectoryEntries represents the contents of a directory's contents and +// handles sorting order which by default is different between various +// operating systems. This abstraction removes the differences in sorting +// behaviour on different platforms. type DirectoryEntries struct { Options *TraverseOptions - Order DirectoryEntryOrderEnum Folders []fs.DirEntry Files []fs.DirEntry } -func (e *DirectoryEntries) Sample() *DirectoryEntries { - fmt.Println("❌❌❌ DirectoryEntries.Sample NOT-IMPLEMENTED") - return e +// All returns the contents of a directory respecting the directory sorting +// order defined in the traversal options. +func (e *DirectoryEntries) All() []fs.DirEntry { + result := []fs.DirEntry{} + + switch e.Options.Store.Behaviours.Sort.DirectoryEntryOrder { + case DirectoryEntryOrderFoldersFirstEn: + result = append(e.Folders, e.Files...) //nolint:gocritic // no alternative known + case DirectoryEntryOrderFilesFirstEn: + result = append(e.Files, e.Folders...) //nolint:gocritic // no alternative known + } + + return result } func (e *DirectoryEntries) arrange(entries []fs.DirEntry) { @@ -69,21 +76,16 @@ func (e *DirectoryEntries) arrange(entries []fs.DirEntry) { } } -func (e *DirectoryEntries) all() []fs.DirEntry { - result := []fs.DirEntry{} - - switch e.Order { - case DirectoryEntryOrderFoldersFirstEn: - result = append(e.Folders, e.Files...) //nolint:gocritic // no alternative known - case DirectoryEntryOrderFilesFirstEn: - result = append(e.Files, e.Folders...) //nolint:gocritic // no alternative known +func (e *DirectoryEntries) sort(entries []fs.DirEntry) { + if err := e.Options.Hooks.Sort(entries); err != nil { + panic(i18n.NewSortFnFailedError()) } - - return result } -func (e *DirectoryEntries) sort(entries []fs.DirEntry) { - if err := e.Options.Hooks.Sort(entries); err != nil { - panic(xi18n.NewSortFnFailedError()) +func newEmptyDirectoryEntries(o *TraverseOptions) *DirectoryEntries { + return &DirectoryEntries{ + Options: o, + Files: []fs.DirEntry{}, + Folders: []fs.DirEntry{}, } } diff --git a/xfs/nav/error-handlers.go b/xfs/nav/error-handlers.go index f67ccc8..a8a6f18 100644 --- a/xfs/nav/error-handlers.go +++ b/xfs/nav/error-handlers.go @@ -5,7 +5,7 @@ import ( "os" "github.com/samber/lo" - xi18n "github.com/snivilised/extendio/i18n" + "github.com/snivilised/extendio/i18n" ) type fileSystemErrorParams struct { @@ -26,10 +26,10 @@ type notifyCallbackErrorHandler struct { func (h *notifyCallbackErrorHandler) accept(params *fileSystemErrorParams) error { err := lo.TernaryF(os.IsNotExist(params.err), func() error { - return xi18n.NewPathNotFoundError("Traverse Item", params.path) + return i18n.NewPathNotFoundError("Traverse Item", params.path) }, func() error { - return xi18n.NewThirdPartyErr(params.err) + return i18n.NewThirdPartyErr(params.err) }, ) diff --git a/xfs/nav/helpers_test.go b/xfs/nav/helpers_test.go index c91b7b4..01abac2 100644 --- a/xfs/nav/helpers_test.go +++ b/xfs/nav/helpers_test.go @@ -54,9 +54,10 @@ type skipTE struct { type sampleTE struct { naviTE - filter *filterTE - noOf nav.SampleNoOf - useLastFn bool + filter *filterTE + noOf nav.SampleNoOf + useLastFn bool + expectedNoOf directoryQuantities } type listenTE struct { diff --git a/xfs/nav/marshal-state.go b/xfs/nav/marshal-state.go index b430ef7..23b5191 100644 --- a/xfs/nav/marshal-state.go +++ b/xfs/nav/marshal-state.go @@ -4,7 +4,7 @@ import ( "encoding/json" "os" - xi18n "github.com/snivilised/extendio/i18n" + "github.com/snivilised/extendio/i18n" ) type stateMarshallerJSON struct { @@ -48,7 +48,7 @@ func (m *stateMarshallerJSON) unmarshal(path string) error { func (m *stateMarshallerJSON) validate() { if m.o.Callback.Fn == nil { - panic(xi18n.NewMissingCallbackError()) + panic(i18n.NewMissingCallbackError()) } } diff --git a/xfs/nav/navigation-agent.go b/xfs/nav/navigation-agent.go index 8f141fd..43c66c5 100644 --- a/xfs/nav/navigation-agent.go +++ b/xfs/nav/navigation-agent.go @@ -5,19 +5,17 @@ import ( "io/fs" "path/filepath" - xi18n "github.com/snivilised/extendio/i18n" + "github.com/snivilised/extendio/i18n" "github.com/snivilised/extendio/xfs/utils" ) -type agentFactory struct{} -type agentFactoryParams struct { - doInvoke bool - o *TraverseOptions - deFactory directoryEntriesFactory - handler fileSystemErrorHandler +type newAgentParams struct { + doInvoke bool + o *TraverseOptions + handler fileSystemErrorHandler } -func (agentFactory) new(params *agentFactoryParams) *navigationAgent { +func newAgent(params *newAgentParams) *navigationAgent { instance := navigationAgent{ doInvoke: utils.NewRoProp(params.doInvoke), o: params.o, @@ -76,7 +74,6 @@ func (a *navigationAgent) top(params *agentTopParams) (*TraverseResult, error) { func (a *navigationAgent) read( path string, - order DirectoryEntryOrderEnum, ) (*DirectoryEntries, error) { // this method was spun out from notify, as there needs to be a separation // between these pieces of functionality to support 'extension'; ie we @@ -84,11 +81,8 @@ func (a *navigationAgent) read( // created for the extension. // entries, err := a.o.Hooks.ReadDirectory(path) - - deFactory := directoryEntriesFactory{} - de := deFactory.new(&directoryEntriesFactoryParams{ + de := newDirectoryEntries(&newDirectoryEntriesParams{ o: a.o, - order: order, entries: entries, }) @@ -96,10 +90,10 @@ func (a *navigationAgent) read( } type agentNotifyParams struct { - frame *navigationFrame - item *TraverseItem - entries []fs.DirEntry - readErr error + frame *navigationFrame + item *TraverseItem + contents []fs.DirEntry + readErr error } func (a *navigationAgent) notify(params *agentNotifyParams) (SkipTraversal, error) { @@ -108,7 +102,7 @@ func (a *navigationAgent) notify(params *agentNotifyParams) (SkipTraversal, erro if params.readErr != nil { if a.doInvoke.Get() { item2 := params.item.clone() - item2.Error = xi18n.NewThirdPartyErr(params.readErr) + item2.Error = i18n.NewThirdPartyErr(params.readErr) // Second call, to report ReadDir error // @@ -117,10 +111,10 @@ func (a *navigationAgent) notify(params *agentNotifyParams) (SkipTraversal, erro params.readErr = nil } - return SkipTraversalAllEn, xi18n.NewThirdPartyErr(params.readErr) + return SkipTraversalAllEn, i18n.NewThirdPartyErr(params.readErr) } } else { - return SkipTraversalAllEn, xi18n.NewThirdPartyErr(params.readErr) + return SkipTraversalAllEn, i18n.NewThirdPartyErr(params.readErr) } } diff --git a/xfs/nav/navigation-listener.go b/xfs/nav/navigation-listener.go index 8d1b325..6f52ebd 100644 --- a/xfs/nav/navigation-listener.go +++ b/xfs/nav/navigation-listener.go @@ -2,7 +2,7 @@ package nav import ( "github.com/snivilised/extendio/collections" - xi18n "github.com/snivilised/extendio/i18n" + "github.com/snivilised/extendio/i18n" ) // ListenHandler @@ -141,7 +141,7 @@ func (l *navigationListener) makeStates(params *listenStatesParams) { ListenRetired: &LabelledTraverseCallback{ Label: "ListenRetired decorator", Fn: func(_ *TraverseItem) error { - return xi18n.NewTerminateTraverseError() + return i18n.NewTerminateTraverseError() }, }, } diff --git a/xfs/nav/navigation-session.go b/xfs/nav/navigation-session.go index 8073674..5896674 100644 --- a/xfs/nav/navigation-session.go +++ b/xfs/nav/navigation-session.go @@ -4,7 +4,7 @@ import ( "errors" "time" - xi18n "github.com/snivilised/extendio/i18n" + "github.com/snivilised/extendio/i18n" ) type Session interface { @@ -125,7 +125,7 @@ func (s *Resume) init() { }) if err != nil { - panic(xi18n.NewFailedToResumeFromFileError(s.RestorePath, err)) + panic(i18n.NewFailedToResumeFromFileError(s.RestorePath, err)) } } diff --git a/xfs/nav/navigator-files.go b/xfs/nav/navigator-files.go index 7823348..ef4b733 100644 --- a/xfs/nav/navigator-files.go +++ b/xfs/nav/navigator-files.go @@ -1,5 +1,7 @@ package nav +import "io/fs" + type filesNavigator struct { navigator } @@ -33,16 +35,14 @@ func (n *filesNavigator) traverse(params *traverseParams) (*TraverseItem, error) } var ( - entries *DirectoryEntries - readErr error - isDir = params.item.IsDir() + entries *DirectoryEntries + contents []fs.DirEntry + readErr error + isDir = params.item.IsDir() ) if isDir { - entries, readErr = n.agent.read( - params.item.Path, - n.o.Store.Behaviours.Sort.DirectoryEntryOrder, - ) + entries, readErr = n.agent.read(params.item.Path) // Files and Folders need to be sorted independently to preserve the navigation order // stipulated by .Behaviours.Sort.DirectoryEntryOrder @@ -50,7 +50,7 @@ func (n *filesNavigator) traverse(params *traverseParams) (*TraverseItem, error) entries.sort(entries.Files) entries.sort(entries.Folders) } else { - entries = &DirectoryEntries{} + entries = newEmptyDirectoryEntries(n.o) } if !isDir { @@ -61,15 +61,17 @@ func (n *filesNavigator) traverse(params *traverseParams) (*TraverseItem, error) return nil, params.frame.proxy(params.item, nil) } - // sample here + if n.o.isSamplingActive() { + n.o.Sampler.Fn(entries) + } - sorted := entries.all() + contents = entries.All() if skip, err := n.agent.notify(&agentNotifyParams{ - frame: params.frame, - item: params.item, - entries: sorted, - readErr: readErr, + frame: params.frame, + item: params.item, + contents: contents, + readErr: readErr, }); skip == SkipTraversalAllEn || err != nil { return nil, err } else if skip == SkipTraversalDirEn { @@ -78,7 +80,7 @@ func (n *filesNavigator) traverse(params *traverseParams) (*TraverseItem, error) return n.agent.traverse(&agentTraverseParams{ impl: n, - contents: sorted, + contents: contents, parent: params.item, frame: params.frame, }) diff --git a/xfs/nav/navigator-folders.go b/xfs/nav/navigator-folders.go index a309139..f1d690d 100644 --- a/xfs/nav/navigator-folders.go +++ b/xfs/nav/navigator-folders.go @@ -40,9 +40,7 @@ func (n *foldersNavigator) traverse(params *traverseParams) (*TraverseItem, erro // n.o.Store.Behaviours.Sort.DirectoryEntryOrder, as we're only interested in // folders and therefore force to use DirectoryEntryOrderFoldersFirstEn instead // - entries, readErr := n.agent.read(params.item.Path, - DirectoryEntryOrderFoldersFirstEn, - ) + entries, readErr := n.agent.read(params.item.Path) folders := entries.Folders entries.sort(folders) // !!!! @@ -73,17 +71,20 @@ func (n *foldersNavigator) traverse(params *traverseParams) (*TraverseItem, erro n.o.Hooks.Extend(navi, entries) - // sample here + if n.o.isSamplingActive() { + n.o.Sampler.Fn(entries) + folders = entries.Folders + } if le := params.frame.proxy(params.item, compoundCounts); le != nil { return nil, le } if skip, err := n.agent.notify(&agentNotifyParams{ - frame: params.frame, - item: params.item, - entries: folders, - readErr: readErr, + frame: params.frame, + item: params.item, + contents: folders, + readErr: readErr, }); skip == SkipTraversalAllEn { return nil, err } diff --git a/xfs/nav/navigator-universal.go b/xfs/nav/navigator-universal.go index 2f429c1..5ef5ac8 100644 --- a/xfs/nav/navigator-universal.go +++ b/xfs/nav/navigator-universal.go @@ -1,5 +1,7 @@ package nav +import "io/fs" + type universalNavigator struct { navigator } @@ -29,40 +31,42 @@ func (n *universalNavigator) traverse(params *traverseParams) (*TraverseItem, er n.descend(navi) var ( - entries *DirectoryEntries - readErr error - isDir = params.item.IsDir() + entries *DirectoryEntries + contents []fs.DirEntry + readErr error + isDir = params.item.IsDir() ) if isDir { - entries, readErr = n.agent.read( - params.item.Path, - n.o.Store.Behaviours.Sort.DirectoryEntryOrder, - ) + entries, readErr = n.agent.read(params.item.Path) // Files and Folders need to be sorted independently to preserve the navigation order // stipulated by .Behaviours.Sort.DirectoryEntryOrder // entries.sort(entries.Files) entries.sort(entries.Folders) + + contents = entries.All() + + if n.o.isSamplingActive() { + n.o.Sampler.Fn(entries) + contents = entries.All() + } } else { - entries = &DirectoryEntries{} + entries = newEmptyDirectoryEntries(n.o) } - sorted := entries.all() n.o.Hooks.Extend(navi, entries) - // sample here - if le := params.frame.proxy(params.item, nil); le != nil { return nil, le } if skip, err := n.agent.notify(&agentNotifyParams{ - frame: params.frame, - item: params.item, - entries: sorted, - readErr: readErr, + frame: params.frame, + item: params.item, + contents: contents, + readErr: readErr, }); skip == SkipTraversalAllEn { return nil, err } else if skip == SkipTraversalDirEn { @@ -71,7 +75,7 @@ func (n *universalNavigator) traverse(params *traverseParams) (*TraverseItem, er return n.agent.traverse(&agentTraverseParams{ impl: n, - contents: sorted, + contents: contents, parent: params.item, frame: params.frame, }) diff --git a/xfs/nav/new-filter.go b/xfs/nav/new-filter.go index 3e9d8dc..f819d6f 100644 --- a/xfs/nav/new-filter.go +++ b/xfs/nav/new-filter.go @@ -3,7 +3,7 @@ package nav import ( "fmt" - xi18n "github.com/snivilised/extendio/i18n" + "github.com/snivilised/extendio/i18n" "github.com/snivilised/extendio/xfs/utils" ) @@ -46,7 +46,7 @@ func newNodeFilter(def *FilterDef) TraverseFilter { case FilterTypeCustomEn: if utils.IsNil(def.Custom) { - panic(xi18n.NewMissingCustomFilterDefinitionError("Options/Store/FilterDefs/Node/Custom")) + panic(i18n.NewMissingCustomFilterDefinitionError("Options/Store/FilterDefs/Node/Custom")) } filter = def.Custom @@ -85,7 +85,7 @@ func newCompoundFilter(def *CompoundFilterDef) CompoundTraverseFilter { case FilterTypeCustomEn: if utils.IsNil(def.Custom) { - panic(xi18n.NewMissingCustomFilterDefinitionError("Options/Store/FilterDefs/Children/Custom")) + panic(i18n.NewMissingCustomFilterDefinitionError("Options/Store/FilterDefs/Children/Custom")) } filter = def.Custom diff --git a/xfs/nav/new-marshaller.go b/xfs/nav/new-marshaller.go index edbdee1..6d42f87 100644 --- a/xfs/nav/new-marshaller.go +++ b/xfs/nav/new-marshaller.go @@ -3,7 +3,7 @@ package nav import ( "fmt" - xi18n "github.com/snivilised/extendio/i18n" + "github.com/snivilised/extendio/i18n" ) type marshallerFactory struct{} @@ -12,7 +12,7 @@ func (m *marshallerFactory) new(o *TraverseOptions, state *persistState) stateMa var marshaller stateMarshaller if o.Persist.Format != PersistInJSONEn { - panic(xi18n.NewUnknownMarshalFormatError( + panic(i18n.NewUnknownMarshalFormatError( fmt.Sprintf("%v", o.Persist.Format), "Options/Persist/Format", )) } diff --git a/xfs/nav/new-navigator.go b/xfs/nav/new-navigator.go index b92a5c4..06a5124 100644 --- a/xfs/nav/new-navigator.go +++ b/xfs/nav/new-navigator.go @@ -4,7 +4,7 @@ import ( "github.com/snivilised/extendio/internal/log" "github.com/snivilised/extendio/xfs/utils" - xi18n "github.com/snivilised/extendio/i18n" + "github.com/snivilised/extendio/i18n" ) type navigatorFactory struct{} @@ -28,7 +28,7 @@ func (f navigatorFactory) fromOptionsFn(fn ...TraverseOptionFn) TraverseNavigato o := composeTraverseOptions(fn...) if o.Callback.Fn == nil { - panic(xi18n.NewMissingCallbackError()) + panic(i18n.NewMissingCallbackError()) } return f.new(o) @@ -48,12 +48,10 @@ func (f navigatorImplFactory) new(o *TraverseOptions) navigatorImpl { var impl navigatorImpl doInvoke := o.Store.Subscription != SubscribeFiles - deFactory := directoryEntriesFactory{} - agent := agentFactory{}.new(&agentFactoryParams{ - o: o, - doInvoke: doInvoke, - deFactory: deFactory, - handler: ¬ifyCallbackErrorHandler{}, + agent := newAgent(&newAgentParams{ + o: o, + doInvoke: doInvoke, + handler: ¬ifyCallbackErrorHandler{}, }) logger := f.makeLogger(o) diff --git a/xfs/nav/new-resume.go b/xfs/nav/new-resume.go index dce9ee1..d79aca4 100644 --- a/xfs/nav/new-resume.go +++ b/xfs/nav/new-resume.go @@ -3,7 +3,7 @@ package nav import ( "fmt" - xi18n "github.com/snivilised/extendio/i18n" + "github.com/snivilised/extendio/i18n" ) type resumerFactory struct{} @@ -80,7 +80,7 @@ func (f strategyFactory) new(params *createStrategyParams) resumeStrategy { } default: - panic(xi18n.NewInvalidResumeStrategyError(fmt.Sprintf("%v", params.strategyEn))) + panic(i18n.NewInvalidResumeStrategyError(fmt.Sprintf("%v", params.strategyEn))) } return strategy diff --git a/xfs/nav/resume-strategy-spawn.go b/xfs/nav/resume-strategy-spawn.go index 35b453b..5e11623 100644 --- a/xfs/nav/resume-strategy-spawn.go +++ b/xfs/nav/resume-strategy-spawn.go @@ -8,7 +8,7 @@ import ( "github.com/snivilised/extendio/internal/log" "github.com/snivilised/extendio/xfs/utils" - xi18n "github.com/snivilised/extendio/i18n" + "github.com/snivilised/extendio/i18n" ) const ( @@ -66,7 +66,7 @@ func (s *spawnStrategy) conclude(conclusion *concludeInfo) (*TraverseResult, err compoundResult, err := s.seed(&seedParams{ frame: s.nc.frame, parent: parent, - entries: following.siblings.all(), + entries: following.siblings.All(), conclusion: conclusion, }) @@ -128,7 +128,7 @@ func (s *spawnStrategy) following(params *followingParams) *shard { entries, err := s.o.Hooks.ReadDirectory(params.parent) if err != nil { - panic(xi18n.NewFailedToReadDirectoryContentsError(params.parent, err)) + panic(i18n.NewFailedToReadDirectoryContentsError(params.parent, err)) } groups := lo.GroupBy(entries, func(item fs.DirEntry) bool { @@ -138,12 +138,9 @@ func (s *spawnStrategy) following(params *followingParams) *shard { return item.Name() > params.anchor }) siblings := groups[followingSiblings] - - deFactory := directoryEntriesFactory{} - de := deFactory.new( - &directoryEntriesFactoryParams{ + de := newDirectoryEntries( + &newDirectoryEntriesParams{ o: s.o, - order: params.order, entries: siblings, }, ) diff --git a/xfs/nav/traverse-defs.go b/xfs/nav/traverse-defs.go index 5a0f919..9fd6b98 100644 --- a/xfs/nav/traverse-defs.go +++ b/xfs/nav/traverse-defs.go @@ -190,4 +190,4 @@ const ( ) // SampleCallback -type SampleCallback func(entries *DirectoryEntries) *DirectoryEntries +type SampleCallback func(entries *DirectoryEntries) diff --git a/xfs/nav/traverse-sample_test.go b/xfs/nav/traverse-sample_test.go index 820c9fa..a27b417 100644 --- a/xfs/nav/traverse-sample_test.go +++ b/xfs/nav/traverse-sample_test.go @@ -37,7 +37,7 @@ import ( ---> 🌊 UNIVERSAL//CONTAINS-FOLDERS-CALLBACK: (depth:9999) '/Users/plastikfan/dev/github/snivilised/extendio/Test/data/MUSICO/RETRO-WAVE/Electric Youth/Innerworld/vinyl-info.innerworld.txt' */ -var _ = XDescribe("Traverse With Sample", Ordered, func() { +var _ = Describe("Traverse With Sample", Ordered, func() { var root string BeforeAll(func() { @@ -92,12 +92,26 @@ var _ = XDescribe("Traverse With Sample", Ordered, func() { providedOptions.Store.FilterDefs = filterDefs } - _, _ = nav.New().Primary(&nav.Prime{ + result, _ := nav.New().Primary(&nav.Prime{ Path: path, ProvidedOptions: providedOptions, }).Run() - Expect(1) + files := result.Metrics.Count(nav.MetricNoFilesInvokedEn) + folders := result.Metrics.Count(nav.MetricNoFoldersInvokedEn) + GinkgoWriter.Printf("===> files: '%v', folders: '%v'\n", files, folders) + + if entry.expectedNoOf.folders > 0 { + Expect(folders).To(BeEquivalentTo(entry.expectedNoOf.folders), + helpers.BecauseQuantity(entry.message, int(entry.expectedNoOf.folders), int(folders)), + ) + } + + if entry.expectedNoOf.files > 0 { + Expect(files).To(BeEquivalentTo(entry.expectedNoOf.files), + helpers.BecauseQuantity(entry.message, int(entry.expectedNoOf.files), int(files)), + ) + } }, func(entry *sampleTE) string { return fmt.Sprintf("🧪 ===> given: '%v', should: '%v'", entry.message, entry.should) @@ -105,19 +119,23 @@ var _ = XDescribe("Traverse With Sample", Ordered, func() { Entry(nil, &sampleTE{ naviTE: naviTE{ - message: "universal: default (top), with 2 files", + message: "universal: default (first), with 2 files", should: "invoke for at most 2 files per directory", subscription: nav.SubscribeAny, prohibited: []string{"cover.night-drive.jpg"}, }, noOf: nav.SampleNoOf{ - Files: 2, + Files: 2, + Folders: 2, + }, + expectedNoOf: directoryQuantities{ + files: 6, }, }), Entry(nil, &sampleTE{ naviTE: naviTE{ - message: "universal: default (top), with 2 folders", + message: "universal: default (first), with 2 folders", should: "invoke for at most 2 folders per directory", subscription: nav.SubscribeAny, prohibited: []string{"Electric Youth"}, @@ -125,11 +143,15 @@ var _ = XDescribe("Traverse With Sample", Ordered, func() { noOf: nav.SampleNoOf{ Folders: 2, }, + expectedNoOf: directoryQuantities{ + files: 11, + folders: 6, + }, }), Entry(nil, &sampleTE{ naviTE: naviTE{ - message: "universal: default (top), with 2 files and 2 folders", + message: "universal: default (first), with 2 files and 2 folders", should: "invoke for at most 2 files and 2 folders per directory", subscription: nav.SubscribeAny, prohibited: []string{"cover.night-drive.jpg", "Electric Youth"}, @@ -138,11 +160,15 @@ var _ = XDescribe("Traverse With Sample", Ordered, func() { Files: 2, Folders: 2, }, + expectedNoOf: directoryQuantities{ + files: 6, + folders: 6, + }, }), Entry(nil, &sampleTE{ naviTE: naviTE{ - message: "folders: default (top), with 2 folders", + message: "folders: default (first), with 2 folders", should: "invoke for at most 2 folders per directory", subscription: nav.SubscribeFolders, prohibited: []string{"Electric Youth"}, @@ -150,6 +176,9 @@ var _ = XDescribe("Traverse With Sample", Ordered, func() { noOf: nav.SampleNoOf{ Folders: 2, }, + expectedNoOf: directoryQuantities{ + folders: 6, + }, }), Entry(nil, &sampleTE{ @@ -169,14 +198,17 @@ var _ = XDescribe("Traverse With Sample", Ordered, func() { Entry(nil, &sampleTE{ naviTE: naviTE{ - message: "files: default (top), with 2 files", + message: "files: default (first), with 2 files", should: "invoke for at most 2 files per directory", - subscription: nav.SubscribeFolders, + subscription: nav.SubscribeFiles, prohibited: []string{"cover.night-drive.jpg"}, }, noOf: nav.SampleNoOf{ Files: 2, }, + expectedNoOf: directoryQuantities{ + files: 8, + }, }), Entry(nil, &sampleTE{ @@ -188,7 +220,10 @@ var _ = XDescribe("Traverse With Sample", Ordered, func() { }, useLastFn: true, noOf: nav.SampleNoOf{ - Folders: 1, + Files: 1, + }, + expectedNoOf: directoryQuantities{ + files: 4, }, }), diff --git a/xfs/nav/traverse-samplers.go b/xfs/nav/traverse-samplers.go index 79baac6..29ae5e5 100644 --- a/xfs/nav/traverse-samplers.go +++ b/xfs/nav/traverse-samplers.go @@ -9,7 +9,9 @@ import ( type subSetFn func(entries []fs.DirEntry, n int) []fs.DirEntry func firstSampler(entries []fs.DirEntry, n int) []fs.DirEntry { - return entries[:len(entries)-(min(n, len(entries)))] + result := entries[:(min(n, len(entries)))] + + return result } func lastSampler(entries []fs.DirEntry, n int) []fs.DirEntry { @@ -17,32 +19,40 @@ func lastSampler(entries []fs.DirEntry, n int) []fs.DirEntry { } func getSubSetSampler(noOf *SampleNoOf, fn subSetFn) SampleCallback { - return func(entries *DirectoryEntries) *DirectoryEntries { + return func(entries *DirectoryEntries) { o := entries.Options - clone := entries.Sample() switch o.Store.Subscription { case SubscribeAny: - clone.Folders = lo.Ternary(noOf.Folders > 0, - fn(entries.Folders, int(noOf.Folders)), - entries.Folders, + entries.Folders = lo.TernaryF(noOf.Folders > 0, + func() []fs.DirEntry { + return fn(entries.Folders, int(noOf.Folders)) + }, + func() []fs.DirEntry { + return entries.Folders + }, ) - clone.Files = lo.Ternary(noOf.Files > 0, - fn(entries.Files, int(noOf.Files)), - entries.Files, + entries.Files = lo.TernaryF(noOf.Files > 0, + func() []fs.DirEntry { + return fn(entries.Files, int(noOf.Files)) + }, + func() []fs.DirEntry { + return entries.Files + }, ) case SubscribeFolders: + entries.Folders = fn(entries.Folders, int(noOf.Folders)) + case SubscribeFoldersWithFiles: - clone.Folders = fn(entries.Folders, int(noOf.Folders)) + entries.Folders = fn(entries.Folders, int(noOf.Folders)) + case SubscribeFiles: - clone.Files = fn(entries.Files, int(noOf.Files)) + entries.Files = fn(entries.Files, int(noOf.Files)) default: } - - return clone } }