49 lines
1.3 KiB
Go
49 lines
1.3 KiB
Go
// Package fileutil provides narrow filesystem helpers for durable artifacts.
|
|
package fileutil
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
func WriteFileAtomic(path string, data []byte) error {
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
return fmt.Errorf("create directory %q: %w", filepath.Dir(path), err)
|
|
}
|
|
tmp, err := os.CreateTemp(filepath.Dir(path), "."+filepath.Base(path)+".*.tmp")
|
|
if err != nil {
|
|
return fmt.Errorf("create temporary file for %q: %w", path, err)
|
|
}
|
|
tmpName := tmp.Name()
|
|
defer os.Remove(tmpName)
|
|
if _, err := tmp.Write(data); err != nil {
|
|
tmp.Close()
|
|
return fmt.Errorf("write temporary file for %q: %w", path, err)
|
|
}
|
|
if err := tmp.Close(); err != nil {
|
|
return fmt.Errorf("close temporary file for %q: %w", path, err)
|
|
}
|
|
if err := os.Rename(tmpName, path); err != nil {
|
|
return fmt.Errorf("save %q: %w", path, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func WriteJSONAtomic(path string, value any) error {
|
|
data, err := json.MarshalIndent(value, "", " ")
|
|
if err != nil {
|
|
return fmt.Errorf("marshal %q: %w", path, err)
|
|
}
|
|
return WriteFileAtomic(path, data)
|
|
}
|
|
|
|
func CopyFileAtomic(source string, target string) error {
|
|
data, err := os.ReadFile(source)
|
|
if err != nil {
|
|
return fmt.Errorf("read %q: %w", source, err)
|
|
}
|
|
return WriteFileAtomic(target, data)
|
|
}
|