-
Notifications
You must be signed in to change notification settings - Fork 0
/
config.go
122 lines (104 loc) · 2.18 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package util
import (
"errors"
"fmt"
"io/fs"
"os"
"path"
"path/filepath"
"reflect"
"strings"
"github.com/abibby/salusa/slices"
"gopkg.in/yaml.v3"
)
type Package struct {
Dir string `yaml:"dir"`
Pkg string `yaml:"package"`
Import string `yaml:"import"`
}
type Config struct {
Root string `yaml:"-"`
Module string `yaml:"module"`
Model *Package `yaml:"model"`
Migration *Package `yaml:"migration"`
}
var ErrNotFound = errors.New("file not found")
const configFileName = "spice.yml"
func defaultConfig() *Config {
return &Config{
Model: &Package{Dir: "app/models"},
Migration: &Package{Dir: "migrations"},
}
}
func LoadConfig(from string) (*Config, error) {
root, err := FileDir(from, configFileName)
if err != nil {
return nil, err
}
pkgRoot, err := FileDir(from, "go.mod")
if err != nil {
return nil, err
}
pkg, err := PkgInfo(pkgRoot, root)
if err != nil {
return nil, err
}
b, err := os.ReadFile(path.Join(root, configFileName))
if err != nil {
return nil, err
}
c := defaultConfig()
err = yaml.Unmarshal(b, c)
if err != nil {
return nil, err
}
c.prep(root, pkg)
return c, nil
}
func (c *Config) prep(root string, pkgInfo *PackageInfo) {
c.Root = root
v := reflect.ValueOf(c).Elem()
for i := 0; i < v.NumField(); i++ {
pkg, ok := v.Field(i).Interface().(*Package)
if !ok {
continue
}
pkg.Dir = path.Join(root, pkg.Dir)
if pkg.Pkg == "" {
pkg.Pkg = path.Base(pkg.Dir)
}
if pkg.Import == "" {
imp, ok := strings.CutPrefix(pkg.Dir, root)
if ok {
pkg.Import = path.Join(pkgInfo.SpicePackage, imp)
}
}
}
}
func FileDir(from, file string) (string, error) {
cwd, err := filepath.Abs(from)
if err != nil {
return "", err
}
current := cwd
name := ""
relPackage := ""
for {
files, err := os.ReadDir(current)
if err != nil {
return "", err
}
_, ok := slices.Find(files, func(f fs.DirEntry) bool {
return f.Name() == file
})
if ok {
return current, nil
}
if current == "/" {
return "", fmt.Errorf("no file %s: %w", file, ErrNotFound)
}
current = strings.TrimSuffix(current, "/")
current, name = path.Split(current)
relPackage = path.Join(name, relPackage)
}
}