Filter publication record names before sorting directory results

This commit is contained in:
2026-11-02 22:36:35 +00:00
parent 781341a0ba
commit 3b8bacf114
3 changed files with 62 additions and 7 deletions

View File

@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"sort"
@@ -40,16 +41,10 @@ func ListAttempts(ctx context.Context, repositoryDir, override string) (Attempts
if err := ctx.Err(); err != nil {
return result, &RecoveryError{Kind: "canceled", cause: err}
}
entries, err := os.ReadDir(directory)
paths, err := recordPaths(ctx, directory)
if err != nil {
return result, recoveryFailure(ctx, "storage_enumeration", fmt.Errorf("enumerate records in %q: %w", directory, err))
}
paths := make([]string, 0, len(entries))
for _, entry := range entries {
if !entry.IsDir() && strings.HasSuffix(entry.Name(), ".json") {
paths = append(paths, filepath.Join(directory, entry.Name()))
}
}
sort.Strings(paths)
for _, path := range paths {
if err := ctx.Err(); err != nil {
@@ -73,6 +68,33 @@ func ListAttempts(ctx context.Context, repositoryDir, override string) (Attempts
return result, nil
}
// recordPaths filters unsorted batches, retaining only selected record names.
func recordPaths(ctx context.Context, directory string) ([]string, error) {
file, err := os.Open(directory)
if err != nil {
return nil, err
}
defer file.Close()
var paths []string
for {
if err := ctx.Err(); err != nil {
return paths, err
}
entries, err := file.ReadDir(128)
for _, entry := range entries {
if !entry.IsDir() && strings.HasSuffix(entry.Name(), ".json") {
paths = append(paths, filepath.Join(directory, entry.Name()))
}
}
if errors.Is(err, io.EOF) {
return paths, nil
}
if err != nil {
return paths, err
}
}
}
func recordDirectoryFor(ctx context.Context, repositoryDir, override string) (string, error) {
if filepath.IsAbs(override) {
return filepath.Clean(override), nil

View File

@@ -371,6 +371,34 @@ func TestListAttemptsReturnsReadableRecordsAndDiagnosticsInPathOrder(t *testing.
}
}
func TestListAttemptsFiltersMixedDirectoryAcrossBatches(t *testing.T) {
directory := t.TempDir()
for i := range 400 {
if err := os.WriteFile(filepath.Join(directory, fmt.Sprintf("unrelated-%04d.txt", i)), []byte("not a record"), 0600); err != nil {
t.Fatal(err)
}
}
if err := os.Mkdir(filepath.Join(directory, "directory.json"), 0700); err != nil {
t.Fatal(err)
}
names := []string{"z.json", "b.json", "a.json"}
for _, name := range names {
if err := os.WriteFile(filepath.Join(directory, name), []byte(`{"format_version":1,"evidence":{"tag":"v1.2.3"}}`), 0600); err != nil {
t.Fatal(err)
}
}
listed, err := ListAttempts(t.Context(), "", directory)
if err != nil || len(listed.Diagnostics) != 0 || len(listed.Attempts) != len(names) {
t.Fatalf("filtered result = %#v, %v", listed, err)
}
sort.Strings(names)
for i, name := range names {
if listed.Attempts[i].RecordPath != filepath.Join(directory, name) {
t.Fatalf("incorrect path order: %#v", listed.Attempts)
}
}
}
func TestListAttemptsDistinguishesEmptyMissingAndCanceledStorage(t *testing.T) {
empty := t.TempDir()
listed, err := ListAttempts(t.Context(), "", empty)