Skip to content

Write the GUI text and CSV exports atomically - #127

Merged
amrali-eg merged 3 commits into
masterfrom
fix/gui-export-atomic
Sep 19, 2026
Merged

amrali-eg merged 3 commits into
masterfrom
fix/gui-export-atomic

Conversation

@amrali-eg

@amrali-eg amrali-eg commented Sep 19, 2026

Copy link
Copy Markdown
Owner

Summary

  • The GUI text-list and CSV exports opened the chosen file directly with new StreamWriter(path, false, encoding), which truncates an existing report before the new one is complete. A failed write showed the warning, but the previous report was already gone.
  • Both exports now write through MainForm.WriteExportFile, which uses AtomicArtifactFile.Write: the report is staged in a temporary file and installed only when complete. Save dialog, encodings, BOM policy, row scope and menu labels are unchanged.

Behaviour decisions

  • Read-only destination: refused. The atomic install would clear the read-only flag and replace the file; a direct write failed. WriteExportFile returns "is read-only" and leaves the file and its flag alone.
  • Link destination: refused. The atomic install would swap a link for a regular file; a direct write went through it. WriteExportFile returns "is a link" and writes nothing. Conversion already refuses reparse points.
  • A fault of an argument or invalid-operation kind raised inside the write callback is now reported as a failed export (the atomic writer's catch is wider than the old one).

Testability

  • The text export's encoding and line format moved into MainForm.TextExportEncoding and MainForm.WriteTextExport, which the handler and the tests both use, so the tests no longer duplicate the handler and compare exact bytes.

Ledger

BL-24 claimed all saved report types used the atomic writer. Its note now records this GUI gap, why it is folded into BL-24, and that GuiExportWriteTests never ran against the original code (the method they call did not exist); with the direct write re-created behind the same method, the mid-write failure tests fail.

Verification

  • GuiExportWriteTests (12): exact bytes for new and replaced reports (TXT and CSV), the line format, a write that fails part way leaves the previous bytes and no staging file, a failed new report leaves nothing, a held-open report, a missing folder, a read-only report, a linked destination.
  • Mutation-tested, each caught: read-only refusal off, link refusal off, direct write restored, BOM removed, line format changed.
  • Full suite 929/929, 0 warnings. Backlog checker passes.

Limits

  • The SaveFileDialog around the write is not exercised. WriteExportFile is the step both handlers call.
  • The link case uses a junction, which carries the same reparse-point attribute as a file symlink; no file symlink was created.
  • No live GUI run and no real disk-full fault was injected.

🤖 Generated with Claude Code

amrali-eg and others added 3 commits September 20, 2026 01:34
Both exports opened the chosen file directly, which truncates an existing
report before the new one is complete. If the write then failed, the warning
appeared but the previous report was already gone. The CLI reports, journals,
plans and settings already used AtomicArtifactFile; these two paths did not.

The exports now write through WriteExportFile, which stages the report in a
temporary file and installs it only when it is complete. The save dialog,
encodings, BOM policy and row scope are unchanged.

The new tests fail a mid-write error against the old behaviour, leaving the
previous report untouched and no staging file behind. BL-24 now records that
its "all saved files" claim missed these two exports.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The atomic install would clear a read-only flag or swap a link for a regular
file, where the previous direct write failed or wrote through. WriteExportFile
now refuses both with a message, so exports keep that protection.

The text export's encoding and line format move into internal members that the
handler and the tests both use, so the tests no longer duplicate them and now
compare exact bytes. New cases cover a missing folder, a read-only report and a
link. BL-24's note is reworded: it says why it is folded into BL-24 and that
the tests never ran against the original code, only against the direct write
re-created behind the same method.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@amrali-eg
amrali-eg merged commit faf8a54 into master Sep 19, 2026
3 checks passed
@amrali-eg
amrali-eg deleted the fix/gui-export-atomic branch September 19, 2026 23:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant