package ioutil import ( "crypto/sha256" "encoding/json" "fmt" "os" ) func CommitData(path string, data []byte) error { return os.WriteFile(path, data, 0644) // FIXME: use safefile package for atomic file writes } func ReadData(path string) ([]byte, error) { return os.ReadFile(path) } func CommitJSON(path string, obj any) error { b, err := json.MarshalIndent(obj, "", " ") if err != nil { return err } return CommitData(path, b) } func ReadJSON(path string, obj any) error { b, err := os.ReadFile(path) if err != nil { return fmt.Errorf("%s: %v", path, err) } return json.Unmarshal(b, obj) } func CreateDirectories(paths []string) error { for _, path := range paths { if err := os.Mkdir(path, 0755); err != nil { return err } } return nil } func DirectoriesExist(paths []string) error { for _, path := range paths { info, err := os.Stat(path) if os.IsNotExist(err) { return fmt.Errorf("directory does not exist: %s", path) } if err != nil { return err } if !info.IsDir() { return fmt.Errorf("%s: is not a directory", path) } } return nil } func CopyHashes(hashes [][sha256.Size]byte) (ret [][sha256.Size]byte) { for _, hash := range hashes { var dst [sha256.Size]byte copy(dst[:], hash[:]) ret = append(ret, dst) } return } func SliceHashes(hashes [][sha256.Size]byte) (ret [][]byte) { for _, hash := range hashes { dst := hash ret = append(ret, dst[:]) } return } // UnsliceHashes panics unless all hashes are 32 bytes func UnsliceHashes(hashes [][]byte) (ret [][sha256.Size]byte) { for _, hash := range hashes { if got, want := len(hash), sha256.Size; got != want { panic(fmt.Sprintf("bug: invalid hash: size %d", got)) } var dst [sha256.Size]byte copy(dst[:], hash) ret = append(ret, dst) } return }