diff options
Diffstat (limited to 'pkg/index')
| -rw-r--r-- | pkg/index/filters.go | 40 | ||||
| -rw-r--r-- | pkg/index/filters_test.go | 30 | ||||
| -rw-r--r-- | pkg/index/index.go | 32 | ||||
| -rw-r--r-- | pkg/index/index_test.go | 53 |
4 files changed, 82 insertions, 73 deletions
diff --git a/pkg/index/filters.go b/pkg/index/filters.go index 44b12cf..a60a629 100644 --- a/pkg/index/filters.go +++ b/pkg/index/filters.go @@ -15,7 +15,7 @@ import ( type DocFilter struct { Name string - Filter func(infoPath, io.ReadSeeker) bool + Filter func(InfoPath, io.ReadSeeker) bool } const FilterHelp string = ` @@ -77,8 +77,8 @@ func ParseFilter(s string) (DocFilter, error) { func NewExtensionFilter(ext string) DocFilter { return DocFilter{ ext + " Filter", - func(ip infoPath, _ io.ReadSeeker) bool { - return filepath.Ext(ip.path) == ext + func(ip InfoPath, _ io.ReadSeeker) bool { + return filepath.Ext(ip.Path) == ext }, } } @@ -86,8 +86,8 @@ func NewExtensionFilter(ext string) DocFilter { func NewMaxFilesizeFilter(size int64) DocFilter { return DocFilter{ fmt.Sprintf("Max Size Filter %d", size), - func(ip infoPath, _ io.ReadSeeker) bool { - return ip.info.Size() <= size + func(ip InfoPath, _ io.ReadSeeker) bool { + return ip.Info.Size() <= size }, } } @@ -95,8 +95,8 @@ func NewMaxFilesizeFilter(size int64) DocFilter { func NewExcludeFilenameFilter(excluded []string) DocFilter { return DocFilter{ "Excluded Filename filter", - func(ip infoPath, _ io.ReadSeeker) bool { - filename := filepath.Base(ip.path) + func(ip InfoPath, _ io.ReadSeeker) bool { + filename := filepath.Base(ip.Path) return !slices.Contains(excluded, filename) }, } @@ -105,8 +105,8 @@ func NewExcludeFilenameFilter(excluded []string) DocFilter { func NewIncludeFilenameFilter(included []string) DocFilter { return DocFilter{ "Included Filename filter", - func(ip infoPath, _ io.ReadSeeker) bool { - filename := filepath.Base(ip.path) + func(ip InfoPath, _ io.ReadSeeker) bool { + filename := filepath.Base(ip.Path) return slices.Contains(included, filename) }, } @@ -116,8 +116,8 @@ func NewIncludeFilenameFilter(included []string) DocFilter { func NewExcludeParentFilter(badParent string) DocFilter { return DocFilter{ "Excluded Parent Directory filter: " + badParent, - func(ip infoPath, _ io.ReadSeeker) bool { - return !slices.Contains(strings.Split(ip.path, string(os.PathSeparator)), badParent) + func(ip InfoPath, _ io.ReadSeeker) bool { + return !slices.Contains(strings.Split(ip.Path, string(os.PathSeparator)), badParent) }, } } @@ -130,8 +130,8 @@ func NewIncludeRegexFilter(pattern string) (DocFilter, error) { return DocFilter{ "Included Regex Filter: " + pattern, - func(ip infoPath, _ io.ReadSeeker) bool { - return re.MatchString(ip.path) + func(ip InfoPath, _ io.ReadSeeker) bool { + return re.MatchString(ip.Path) }, }, nil } @@ -143,23 +143,21 @@ func NewExcludeRegexFilter(pattern string) (DocFilter, error) { return DocFilter{ "Excluded Regex Filter: " + pattern, - func(ip infoPath, _ io.ReadSeeker) bool { - return !re.MatchString(ip.path) + func(ip InfoPath, _ io.ReadSeeker) bool { + return !re.MatchString(ip.Path) }, }, nil } var YamlHeaderFilter = DocFilter{ "YAML Header Filter", - yamlHeaderFilterFunc, -} - -func yamlHeaderFilterFunc(_ infoPath, r io.ReadSeeker) bool { - return yamlHeaderPos(r) > 0 + func(_ InfoPath, rs io.ReadSeeker) bool { + return YamlHeaderPos(rs) > 0 + }, } // Position of the end of a yaml header, negative -func yamlHeaderPos(r io.ReadSeeker) int64 { +func YamlHeaderPos(r io.ReadSeeker) int64 { const bufSize = 4096 buf := make([]byte, bufSize) diff --git a/pkg/index/filters_test.go b/pkg/index/filters_test.go index f46874c..bedf5e9 100644 --- a/pkg/index/filters_test.go +++ b/pkg/index/filters_test.go @@ -1,10 +1,12 @@ -package index +package index_test import ( "bytes" "io" "os" "testing" + + "github.com/jpappel/atlas/pkg/index" ) func noYamlHeader() io.ReadSeeker { @@ -27,7 +29,7 @@ func trailingYamlHeader() io.ReadSeeker { return bytes.NewReader(buf) } -func extensionless(t *testing.T) infoPath { +func extensionless(t *testing.T) index.InfoPath { root := t.TempDir() path := root + "/" + "afile" f, err := os.Create(path) @@ -45,10 +47,10 @@ func extensionless(t *testing.T) infoPath { t.Fatal(err) } - return infoPath{path, info} + return index.InfoPath{path, info} } -func markdownExtension(t *testing.T) infoPath { +func markdownExtension(t *testing.T) index.InfoPath { root := t.TempDir() path := root + "/" + "a.md" f, err := os.Create(path) @@ -62,23 +64,23 @@ func markdownExtension(t *testing.T) infoPath { t.Fatal(err) } - return infoPath{path, info} + return index.InfoPath{path, info} } -func parentDirectory(t *testing.T) infoPath { +func parentDirectory(t *testing.T) index.InfoPath { root := t.TempDir() dir := root + "/parent" path := dir + "/a" - return infoPath{path: path} + return index.InfoPath{Path: path} } -func grandparentDirectory(t *testing.T) infoPath { +func grandparentDirectory(t *testing.T) index.InfoPath { root := t.TempDir() dir := root + "/grandparent/parent" path := dir + "/a" - return infoPath{path: path} + return index.InfoPath{Path: path} } func TestYamlHeaderFilter(t *testing.T) { @@ -94,7 +96,7 @@ func TestYamlHeaderFilter(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := yamlHeaderFilterFunc(infoPath{}, tt.r) + got := index.YamlHeaderPos(tt.r) > 0 if got != tt.want { t.Errorf("YamlHeaderFilter() = %v, want %v", got, tt.want) } @@ -105,7 +107,7 @@ func TestYamlHeaderFilter(t *testing.T) { func TestExtensionFilter(t *testing.T) { tests := []struct { name string - infoGen func(*testing.T) infoPath + infoGen func(*testing.T) index.InfoPath ext string want bool }{ @@ -116,7 +118,7 @@ func TestExtensionFilter(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - docFilter := NewExtensionFilter(tt.ext) + docFilter := index.NewExtensionFilter(tt.ext) ip := tt.infoGen(t) got := docFilter.Filter(ip, nil) @@ -130,7 +132,7 @@ func TestExtensionFilter(t *testing.T) { func TestExcludeParentFilter(t *testing.T) { tests := []struct { name string - infoGen func(*testing.T) infoPath + infoGen func(*testing.T) index.InfoPath parent string want bool }{ @@ -152,7 +154,7 @@ func TestExcludeParentFilter(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - docFilter := NewExcludeParentFilter(tt.parent) + docFilter := index.NewExcludeParentFilter(tt.parent) ip := tt.infoGen(t) got := docFilter.Filter(ip, nil) diff --git a/pkg/index/index.go b/pkg/index/index.go index 419607c..a35b670 100644 --- a/pkg/index/index.go +++ b/pkg/index/index.go @@ -36,9 +36,9 @@ type ParseOpts struct { IgnoreMetaError bool } -type infoPath struct { - path string - info os.FileInfo +type InfoPath struct { + Path string + Info os.FileInfo } type Index struct { @@ -191,12 +191,12 @@ func (doc Document) Equal(other Document) bool { return true } -func visit(file infoPath, visitQueue chan<- infoPath, filterQueue chan<- infoPath, wg *sync.WaitGroup) { +func visit(file InfoPath, visitQueue chan<- InfoPath, filterQueue chan<- InfoPath, wg *sync.WaitGroup) { // TODO: check if symlink, and handle appropriately // TODO: extract error out of function - if file.info.IsDir() { - entries, err := os.ReadDir(file.path) + if file.Info.IsDir() { + entries, err := os.ReadDir(file.Path) if err != nil { panic(err) } @@ -209,17 +209,17 @@ func visit(file infoPath, visitQueue chan<- infoPath, filterQueue chan<- infoPat } // PERF: prevents deadlock but introduces an additional goroutine overhead per file go func(path string) { - visitQueue <- infoPath{path: path, info: entryInfo} - }(file.path + "/" + entry.Name()) + visitQueue <- InfoPath{Path: path, Info: entryInfo} + }(file.Path + "/" + entry.Name()) } - } else if file.info.Mode().IsRegular() { + } else if file.Info.Mode().IsRegular() { filterQueue <- file } wg.Done() } -func workerTraverse(wg *sync.WaitGroup, visitQueue chan infoPath, filterQueue chan<- infoPath) { +func workerTraverse(wg *sync.WaitGroup, visitQueue chan InfoPath, filterQueue chan<- InfoPath) { for work := range visitQueue { visit(work, visitQueue, filterQueue, wg) } @@ -236,8 +236,8 @@ func (idx Index) Traverse(numWorkers uint) []string { panic(err) } - jobs := make(chan infoPath, numWorkers) - filterQueue := make(chan infoPath, numWorkers) + jobs := make(chan InfoPath, numWorkers) + filterQueue := make(chan InfoPath, numWorkers) activeJobs := &sync.WaitGroup{} @@ -248,7 +248,7 @@ func (idx Index) Traverse(numWorkers uint) []string { // init send activeJobs.Add(1) - jobs <- infoPath{path: idx.Root, info: rootInfo} + jobs <- InfoPath{Path: idx.Root, Info: rootInfo} // close jobs queue go func() { @@ -259,7 +259,7 @@ func (idx Index) Traverse(numWorkers uint) []string { // gather for doc := range filterQueue { - docs = append(docs, doc.path) + docs = append(docs, doc.Path) } return docs @@ -278,7 +278,7 @@ func (idx Index) FilterOne(path string) bool { defer f.Close() for _, docFilter := range idx.Filters { - if !docFilter.Filter(infoPath{string(path), info}, f) { + if !docFilter.Filter(InfoPath{string(path), info}, f) { return false } if _, err := f.Seek(0, io.SeekStart); err != nil { @@ -340,7 +340,7 @@ func ParseDoc(path string, opts ParseOpts) (*Document, error) { } doc.FileTime = info.ModTime() - pos := yamlHeaderPos(f) + pos := YamlHeaderPos(f) f.Seek(0, io.SeekStart) if pos < 0 { return nil, fmt.Errorf("Can't find YAML header in %s", path) diff --git a/pkg/index/index_test.go b/pkg/index/index_test.go index 3f9b900..0a3239d 100644 --- a/pkg/index/index_test.go +++ b/pkg/index/index_test.go @@ -1,4 +1,4 @@ -package index +package index_test import ( "errors" @@ -7,16 +7,18 @@ import ( "slices" "testing" "time" + + "github.com/jpappel/atlas/pkg/index" ) -var indexCases map[string]func(t *testing.T) Index +var indexCases map[string]func(t *testing.T) index.Index func init() { - indexCases = make(map[string]func(t *testing.T) Index) + indexCases = make(map[string]func(t *testing.T) index.Index) - indexCases["single file"] = func(t *testing.T) Index { + indexCases["single file"] = func(t *testing.T) index.Index { root := t.TempDir() - index := Index{Root: root, Filters: []DocFilter{NewExtensionFilter(".md")}} + index := index.Index{Root: root, Filters: []index.DocFilter{index.NewExtensionFilter(".md")}} f, err := os.Create(root + "/a_file.md") if err != nil { @@ -27,16 +29,16 @@ func init() { return index } - indexCases["large file"] = func(t *testing.T) Index { + indexCases["large file"] = func(t *testing.T) index.Index { root := t.TempDir() - index := Index{Root: root} + index := index.Index{Root: root} return index } - indexCases["worker saturation"] = func(t *testing.T) Index { + indexCases["worker saturation"] = func(t *testing.T) index.Index { root := t.TempDir() - index := Index{Root: root} + index := index.Index{Root: root} permission := os.FileMode(0o777) for _, dirName := range []string{"a", "b", "c", "d", "e", "f"} { @@ -61,7 +63,7 @@ func init() { func TestIndex_Traverse(t *testing.T) { tests := []struct { name string - indexCase func(t *testing.T) Index + indexCase func(t *testing.T) index.Index numWorkers uint want []string }{ @@ -104,7 +106,7 @@ func TestIndex_Filter(t *testing.T) { tests := []struct { name string paths []string - indexCase func(t *testing.T) Index + indexCase func(t *testing.T) index.Index numWorkers uint want []string }{ @@ -154,7 +156,8 @@ func TestIndex_ParseOne(t *testing.T) { tests := []struct { name string pathMaker func(t *testing.T) string - want *Document + parseOpts index.ParseOpts + want *index.Document wantErr error }{ { @@ -166,7 +169,8 @@ func TestIndex_ParseOne(t *testing.T) { f.WriteString("---\ntitle: A title\n---\n") return path }, - &Document{Title: "A title"}, + index.ParseOpts{}, + &index.Document{Title: "A title"}, nil, }, { @@ -184,7 +188,8 @@ func TestIndex_ParseOne(t *testing.T) { return path }, - &Document{Tags: []string{"a", "b", "c"}}, + index.ParseOpts{}, + &index.Document{Tags: []string{"a", "b", "c"}}, nil, }, { @@ -197,7 +202,8 @@ func TestIndex_ParseOne(t *testing.T) { return path }, - &Document{Date: time.Date(2025, time.May, 1, 0, 0, 0, 0, time.UTC)}, + index.ParseOpts{}, + &index.Document{Date: time.Date(2025, time.May, 1, 0, 0, 0, 0, time.UTC)}, nil, }, { @@ -210,7 +216,8 @@ func TestIndex_ParseOne(t *testing.T) { return path }, - &Document{Authors: []string{"Rob Pike"}}, + index.ParseOpts{}, + &index.Document{Authors: []string{"Rob Pike"}}, nil, }, { @@ -223,7 +230,8 @@ func TestIndex_ParseOne(t *testing.T) { return path }, - &Document{Authors: []string{"Robert Griesemer", "Rob Pike", "Ken Thompson"}}, + index.ParseOpts{}, + &index.Document{Authors: []string{"Robert Griesemer", "Rob Pike", "Ken Thompson"}}, nil, }, { @@ -238,7 +246,8 @@ func TestIndex_ParseOne(t *testing.T) { return path }, - &Document{OtherMeta: "unknownKey: value\n"}, + index.ParseOpts{ParseMeta: true}, + &index.Document{OtherMeta: "unknownKey: value\n"}, nil, }, { @@ -253,8 +262,9 @@ func TestIndex_ParseOne(t *testing.T) { return path }, - &Document{}, - ErrHeaderParse, + index.ParseOpts{}, + &index.Document{}, + index.ErrHeaderParse, }, } for _, tt := range tests { @@ -262,8 +272,7 @@ func TestIndex_ParseOne(t *testing.T) { path := tt.pathMaker(t) tt.want.Path = path - // TODO: add ParseOpts as test param - got, gotErr := ParseDoc(path, ParseOpts{ParseMeta: true}) + got, gotErr := index.ParseDoc(path, tt.parseOpts) if !errors.Is(gotErr, tt.wantErr) { t.Errorf("Recieved unexpected error: want %v got %v", tt.wantErr, gotErr) |
