From 55593e14ee2a4225d1db1058da9d8d1f663225b6 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Tue, 14 Apr 2026 11:19:50 +0300 Subject: refactor: use fs.FS for aggregate and DB import (ask v3) Decouple Aggregator and ImportFromDir from direct os.Open by routing through io/fs: NewAggregatorFS, ImportFromFS, recordsdir.ListNonEmptyFilesFS. NewAggregator and ImportFromDir wrap os.DirFS for backward compatibility. Add fstest.MapFS tests for recordsdir, aggregate, and ImportFromFS. Made-with: Cursor --- internal/recordsdir/recordsdir.go | 45 +++++++++++++++++++++++++++++----- internal/recordsdir/recordsdir_test.go | 16 ++++++++++++ 2 files changed, 55 insertions(+), 6 deletions(-) (limited to 'internal/recordsdir') diff --git a/internal/recordsdir/recordsdir.go b/internal/recordsdir/recordsdir.go index 9f3ce5b..94f7f0e 100644 --- a/internal/recordsdir/recordsdir.go +++ b/internal/recordsdir/recordsdir.go @@ -1,7 +1,9 @@ package recordsdir import ( + "io/fs" "os" + "path" "path/filepath" "strings" ) @@ -19,22 +21,53 @@ func HostFromFileName(name string) string { return host } -func ListNonEmptyFiles(dir string) ([]Entry, error) { - entries, err := os.ReadDir(dir) +func listRecordsFileNames(fsys fs.FS, root string) ([]string, error) { + entries, err := fs.ReadDir(fsys, root) if err != nil { return nil, err } - var out []Entry + var names []string for _, e := range entries { if e.IsDir() || !strings.HasSuffix(e.Name(), ".records") { continue } - path := filepath.Join(dir, e.Name()) - info, err := os.Stat(path) + rel := path.Join(root, e.Name()) + info, err := fs.Stat(fsys, rel) if err != nil || info.Size() == 0 { continue } - out = append(out, Entry{Path: path, Host: HostFromFileName(e.Name())}) + names = append(names, e.Name()) + } + return names, nil +} + +// ListNonEmptyFilesFS returns non-empty .records files under root within fsys. +func ListNonEmptyFilesFS(fsys fs.FS, root string) ([]Entry, error) { + names, err := listRecordsFileNames(fsys, root) + if err != nil { + return nil, err + } + var out []Entry + for _, name := range names { + out = append(out, Entry{ + Path: path.Join(root, name), + Host: HostFromFileName(name), + }) + } + return out, nil +} + +func ListNonEmptyFiles(dir string) ([]Entry, error) { + names, err := listRecordsFileNames(os.DirFS(dir), ".") + if err != nil { + return nil, err + } + var out []Entry + for _, name := range names { + out = append(out, Entry{ + Path: filepath.Join(dir, name), + Host: HostFromFileName(name), + }) } return out, nil } diff --git a/internal/recordsdir/recordsdir_test.go b/internal/recordsdir/recordsdir_test.go index bee8d67..5e72d9d 100644 --- a/internal/recordsdir/recordsdir_test.go +++ b/internal/recordsdir/recordsdir_test.go @@ -4,6 +4,7 @@ import ( "os" "path/filepath" "testing" + "testing/fstest" ) func TestHostFromFileName(t *testing.T) { @@ -56,3 +57,18 @@ func TestListNonEmptyFiles_ReadError(t *testing.T) { t.Fatal("expected error") } } + +func TestListNonEmptyFilesFS_MapFS(t *testing.T) { + m := fstest.MapFS{ + "skip.txt": &fstest.MapFile{Data: []byte("x"), Mode: 0o644}, + "empty.records": &fstest.MapFile{Data: nil, Mode: 0o644}, + "h1.records": &fstest.MapFile{Data: []byte("line\n"), Mode: 0o644}, + } + entries, err := ListNonEmptyFilesFS(m, ".") + if err != nil { + t.Fatal(err) + } + if len(entries) != 1 || entries[0].Host != "h1" || entries[0].Path != "h1.records" { + t.Fatalf("got %#v", entries) + } +} -- cgit v1.2.3