diff options
| author | Paul Buetow <paul@buetow.org> | 2026-04-10 09:48:07 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-04-10 09:48:07 +0300 |
| commit | 4ff456a6111d8553893308a84e9f0e992d4809bf (patch) | |
| tree | ddde0aa190b8dcbf6eb6649a82db732f0cdfd6a7 | |
| parent | c8e10b6c5ab26d8bd34c288a7ce91c320862b58e (diff) | |
processor: return error when markdown pre-scan cannot read .md
claimedByMarkdown now wraps os.ReadFile failures instead of skipping,
so Run fails fast and avoids wrong image claim state. Add regression
test using an unreadable markdown file (Unix).
Made-with: Cursor
| -rw-r--r-- | internal/processor/markdown_test.go | 35 | ||||
| -rw-r--r-- | internal/processor/processor.go | 11 |
2 files changed, 42 insertions, 4 deletions
diff --git a/internal/processor/markdown_test.go b/internal/processor/markdown_test.go index a17b704..2445b53 100644 --- a/internal/processor/markdown_test.go +++ b/internal/processor/markdown_test.go @@ -3,7 +3,10 @@ package processor import ( "os" "path/filepath" + "runtime" "testing" + + "codeberg.org/snonux/snonux/internal/config" ) func TestFindLocalImages(t *testing.T) { @@ -88,3 +91,35 @@ func TestFindLocalImages(t *testing.T) { }) } } + +func TestRun_UnreadableMarkdownPreScanFails(t *testing.T) { + t.Parallel() + if runtime.GOOS == "windows" { + t.Skip("chmod does not reliably deny read for owned files on Windows") + } + + base := t.TempDir() + inputDir := filepath.Join(base, "inbox") + outputDir := filepath.Join(base, "out") + if err := os.MkdirAll(inputDir, 0o755); err != nil { + t.Fatal(err) + } + if err := os.MkdirAll(outputDir, 0o755); err != nil { + t.Fatal(err) + } + + mdPath := filepath.Join(inputDir, "note.md") + if err := os.WriteFile(mdPath, []byte("# x\n"), 0o644); err != nil { + t.Fatal(err) + } + if err := os.Chmod(mdPath, 0); err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = os.Chmod(mdPath, 0o644) }) + + cfg := &config.Config{InputDir: inputDir, OutputDir: outputDir} + _, err := Run(cfg) + if err == nil { + t.Fatal("Run: expected error when markdown pre-scan cannot read a .md file") + } +} diff --git a/internal/processor/processor.go b/internal/processor/processor.go index 2e2d626..b6fa40b 100644 --- a/internal/processor/processor.go +++ b/internal/processor/processor.go @@ -33,7 +33,10 @@ func Run(cfg *config.Config) (int, error) { // Pre-scan markdown files to discover which image filenames they claim. // Claimed images are excluded from independent processing. - claimed := claimedByMarkdown(entries, cfg.InputDir) + claimed, err := claimedByMarkdown(entries, cfg.InputDir) + if err != nil { + return 0, err + } count := 0 @@ -59,7 +62,7 @@ func Run(cfg *config.Config) (int, error) { // claimedByMarkdown scans all .md entries in inputDir and returns a set of // image filenames that are referenced within those markdown files. // Those images should be embedded in the markdown post, not processed alone. -func claimedByMarkdown(entries []os.DirEntry, inputDir string) map[string]bool { +func claimedByMarkdown(entries []os.DirEntry, inputDir string) (map[string]bool, error) { claimed := make(map[string]bool) for _, entry := range entries { @@ -70,7 +73,7 @@ func claimedByMarkdown(entries []os.DirEntry, inputDir string) map[string]bool { mdPath := filepath.Join(inputDir, entry.Name()) data, err := os.ReadFile(mdPath) if err != nil { - continue + return nil, fmt.Errorf("read markdown for image claims %s: %w", entry.Name(), err) } for _, imgName := range findLocalImages(string(data), inputDir) { @@ -78,7 +81,7 @@ func claimedByMarkdown(entries []os.DirEntry, inputDir string) map[string]bool { } } - return claimed + return claimed, nil } // processFile processes a single input file into a new post directory. |
