54 lines
1.0 KiB
Go
54 lines
1.0 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
func atomicWriteJSON(path string, value any, mode os.FileMode) error {
|
|
if path == "" {
|
|
return nil
|
|
}
|
|
dir := filepath.Dir(path)
|
|
if err := os.MkdirAll(dir, 0o700); err != nil {
|
|
return err
|
|
}
|
|
data, err := json.MarshalIndent(value, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
temp, err := os.CreateTemp(dir, ".gh-threads-*")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
name := temp.Name()
|
|
defer os.Remove(name)
|
|
if err := temp.Chmod(mode); err != nil {
|
|
_ = temp.Close()
|
|
return err
|
|
}
|
|
if _, err := temp.Write(data); err != nil {
|
|
_ = temp.Close()
|
|
return err
|
|
}
|
|
if err := temp.Sync(); err != nil {
|
|
_ = temp.Close()
|
|
return err
|
|
}
|
|
if err := temp.Close(); err != nil {
|
|
return err
|
|
}
|
|
if err := os.Rename(name, path); err != nil {
|
|
return err
|
|
}
|
|
if directory, err := os.Open(dir); err == nil {
|
|
defer directory.Close()
|
|
if syncErr := directory.Sync(); syncErr != nil && !errors.Is(syncErr, os.ErrInvalid) {
|
|
return syncErr
|
|
}
|
|
}
|
|
return nil
|
|
}
|