From a42a5961861f638fef3b49685fc6df2eea38fa0d Mon Sep 17 00:00:00 2001 From: Jeff Halter <868228+jhalter@users.noreply.github.com> Date: Wed, 8 Jul 2026 09:11:10 -0700 Subject: Decouple FileStore from *os.File for object-store backends The FileStore interface returned concrete *os.File from Open/Create/ OpenFile, which no non-filesystem backend (e.g. S3/R2) can produce, and many file-library hot paths bypassed the interface entirely with direct os.* / filepath.Walk calls. Widen the interface to return io.ReadCloser / io.WriteCloser and add ReadDir, ReadLink, and Walk so directory traversal no longer escapes the abstraction. Route every file-library call site (fork writers, upload/ download handlers, GetFileNameList, CalcTotalSize/CalcItemCount, the set- file-info folder rename) through the injected FileStore, and add a WithFileStore option. OSFileStore keeps byte-identical behavior. DownloadHandler now nil-guards the optional resource-fork reader instead of relying on *os.File's nil-receiver tolerance, so a backend returning an untyped-nil reader does not panic. --- hotline/files_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'hotline/files_test.go') diff --git a/hotline/files_test.go b/hotline/files_test.go index 3d9846f..44902d3 100644 --- a/hotline/files_test.go +++ b/hotline/files_test.go @@ -76,7 +76,7 @@ func TestCalcTotalSize(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := CalcTotalSize(tt.args.filePath) + got, err := CalcTotalSize(&OSFileStore{}, tt.args.filePath) if (err != nil) != tt.wantErr { t.Errorf("CalcTotalSize() error = %v, wantErr %v", err, tt.wantErr) return @@ -160,7 +160,7 @@ func TestCalcItemCount(t *testing.T) { } // Calculate item count - result, err := CalcItemCount(tempDir) + result, err := CalcItemCount(&OSFileStore{}, tempDir) if err != nil { t.Fatalf("CalcItemCount returned an error: %v", err) } @@ -201,7 +201,7 @@ func TestGetFileNameList_Encoding(t *testing.T) { } t.Run("macintosh encoder converts UTF-8 to Mac Roman", func(t *testing.T) { - fields, err := GetFileNameList(tempDir, nil, charmap.Macintosh.NewEncoder(), slog.Default()) + fields, err := GetFileNameList(&OSFileStore{}, tempDir, nil, charmap.Macintosh.NewEncoder(), slog.Default()) assert.NoError(t, err) assert.Len(t, fields, 1) @@ -211,7 +211,7 @@ func TestGetFileNameList_Encoding(t *testing.T) { }) t.Run("nop encoder passes UTF-8 through unchanged", func(t *testing.T) { - fields, err := GetFileNameList(tempDir, nil, encoding.Nop.NewEncoder(), slog.Default()) + fields, err := GetFileNameList(&OSFileStore{}, tempDir, nil, encoding.Nop.NewEncoder(), slog.Default()) assert.NoError(t, err) assert.Len(t, fields, 1) -- cgit