fix(02): write fixtures exclusively and only on successful flush (WR-01)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -49,6 +49,15 @@ func ParseFlow(raw []byte) (Flow, error) {
|
||||
|
||||
// SaveFlow writes a validated flow atomically, syncing before rename.
|
||||
func SaveFlow(path string, flow Flow) error {
|
||||
return saveFlow(path, flow, false)
|
||||
}
|
||||
|
||||
// SaveFlowExclusive writes a validated flow and fails if path already exists.
|
||||
func SaveFlowExclusive(path string, flow Flow) error {
|
||||
return saveFlow(path, flow, true)
|
||||
}
|
||||
|
||||
func saveFlow(path string, flow Flow, exclusive bool) error {
|
||||
if err := validateFlow(flow); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -62,6 +71,30 @@ func SaveFlow(path string, flow Flow) error {
|
||||
return fmt.Errorf("tide: create fixture dir: %w", err)
|
||||
}
|
||||
}
|
||||
if exclusive {
|
||||
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0o644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("tide: create fixture: %w", err)
|
||||
}
|
||||
ok := false
|
||||
defer func() {
|
||||
_ = f.Close()
|
||||
if !ok {
|
||||
_ = os.Remove(path)
|
||||
}
|
||||
}()
|
||||
if _, err := f.Write(raw); err != nil {
|
||||
return fmt.Errorf("tide: write fixture: %w", err)
|
||||
}
|
||||
if err := f.Sync(); err != nil {
|
||||
return fmt.Errorf("tide: sync fixture: %w", err)
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
return fmt.Errorf("tide: close fixture: %w", err)
|
||||
}
|
||||
ok = true
|
||||
return nil
|
||||
}
|
||||
tmp, err := os.CreateTemp(dir, ".tide-*.tmp")
|
||||
if err != nil {
|
||||
return fmt.Errorf("tide: create temp fixture: %w", err)
|
||||
|
||||
Reference in New Issue
Block a user