main
go 86 lines 1.62 KB
Raw
1 package utils
2
3 import (
4 "encoding/json"
5 "os"
6 "path/filepath"
7 "strings"
8 )
9
10 func EnsureParentDir(path string) error {
11 dir := filepath.Dir(strings.TrimSpace(path))
12 if dir == "" || dir == "." {
13 return nil
14 }
15 return os.MkdirAll(dir, 0o700)
16 }
17
18 func FileExists(path string) bool {
19 path = strings.TrimSpace(path)
20 if path == "" {
21 return false
22 }
23 _, err := os.Stat(path)
24 return err == nil
25 }
26
27 func WriteFileAtomic(path string, data []byte, mode os.FileMode) error {
28 path = strings.TrimSpace(path)
29 dir := filepath.Dir(path)
30 if dir == "" {
31 dir = "."
32 }
33 tmp, err := os.CreateTemp(dir, ".tmp-*")
34 if err != nil {
35 return err
36 }
37 tmpName := tmp.Name()
38 defer func() { _ = os.Remove(tmpName) }()
39
40 if _, err := tmp.Write(data); err != nil {
41 _ = tmp.Close()
42 return err
43 }
44 if err := tmp.Chmod(mode); err != nil {
45 _ = tmp.Close()
46 return err
47 }
48 if err := tmp.Close(); err != nil {
49 return err
50 }
51 if err := os.Rename(tmpName, path); err != nil {
52 return err
53 }
54 return os.Chmod(path, mode)
55 }
56
57 func ReadJSONFile(path string, out any) error {
58 raw, err := os.ReadFile(strings.TrimSpace(path))
59 if err != nil {
60 return err
61 }
62 return json.Unmarshal(raw, out)
63 }
64
65 func ReadJSONFileIfExists(path string, out any) (bool, error) {
66 err := ReadJSONFile(path, out)
67 switch {
68 case err == nil:
69 return true, nil
70 case os.IsNotExist(err):
71 return false, nil
72 default:
73 return false, err
74 }
75 }
76
77 func WriteJSONFile(path string, payload any, mode os.FileMode) error {
78 data, err := json.MarshalIndent(payload, "", " ")
79 if err != nil {
80 return err
81 }
82 if err := EnsureParentDir(path); err != nil {
83 return err
84 }
85 return WriteFileAtomic(path, data, mode)
86 }