github.com/hattya/nazuna@v0.7.1-0.20240331055452-55e14c275c1c/util.go (about) 1 // 2 // nazuna :: util.go 3 // 4 // Copyright (c) 2013-2022 Akinori Hattori <hattya@gmail.com> 5 // 6 // SPDX-License-Identifier: MIT 7 // 8 9 package nazuna 10 11 import ( 12 "encoding/json" 13 "fmt" 14 "io" 15 "net/http" 16 "os" 17 "path/filepath" 18 "reflect" 19 "sort" 20 "strings" 21 "unicode/utf8" 22 ) 23 24 func IsDir(path string) bool { 25 fi, err := os.Stat(path) 26 return err == nil && fi.IsDir() 27 } 28 29 func IsEmptyDir(path string) bool { 30 f, err := os.Open(path) 31 if err != nil { 32 return true 33 } 34 defer f.Close() 35 _, err = f.Readdir(1) 36 return err == io.EOF 37 } 38 39 func SplitPath(path string) (string, string) { 40 dir, name := filepath.Split(path) 41 dir = strings.TrimRightFunc(dir, func(r rune) bool { 42 return r < utf8.RuneSelf && os.IsPathSeparator(uint8(r)) 43 }) 44 return dir, name 45 } 46 47 func sortKeys(i interface{}) []string { 48 v := reflect.Indirect(reflect.ValueOf(i)) 49 if v.Kind() != reflect.Map { 50 return nil 51 } 52 keys := v.MapKeys() 53 if len(keys) == 0 || keys[0].Kind() != reflect.String { 54 return nil 55 } 56 list := make(sort.StringSlice, len(keys)) 57 for i, k := range keys { 58 list[i] = k.String() 59 } 60 list.Sort() 61 return list 62 } 63 64 func marshal(repo *Repository, path string, v interface{}) error { 65 rel, err := filepath.Rel(repo.root, path) 66 if err != nil { 67 return err 68 } 69 data, err := json.MarshalIndent(v, "", " ") 70 if err != nil { 71 return fmt.Errorf("%v: %v", rel, err) 72 } 73 if err := os.WriteFile(path, append(data, '\n'), 0o666); err != nil { 74 return fmt.Errorf("cannot write '%v'", rel) 75 } 76 return nil 77 } 78 79 func unmarshal(repo *Repository, path string, v interface{}) error { 80 rel, err := filepath.Rel(repo.root, path) 81 if err != nil { 82 return err 83 } 84 if _, err := os.Stat(path); err == nil { 85 data, err := os.ReadFile(path) 86 if err != nil { 87 return fmt.Errorf("cannot read '%v'", rel) 88 } 89 if err := json.Unmarshal(data, v); err != nil { 90 return fmt.Errorf("%v: %v", rel, err) 91 } 92 } 93 return nil 94 } 95 96 func httpGet(uri string) ([]byte, error) { 97 resp, err := http.Get(uri) 98 if err != nil { 99 return nil, err 100 } 101 defer resp.Body.Close() 102 if resp.StatusCode != 200 { 103 return nil, fmt.Errorf("%v: %v", uri, resp.Status) 104 } 105 data, err := io.ReadAll(resp.Body) 106 if err != nil { 107 return nil, err 108 } 109 return data, nil 110 }