/
config.go
148 lines (132 loc) · 3.89 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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package core
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sort"
"strings"
"github.com/olekukonko/tablewriter"
"github.com/mitchellh/go-homedir"
"github.com/mritd/mmh/common"
)
const (
// EnvConfigDirName The MMH_CONFIG_DIR env specifies the dir where the mmh config file is stored
EnvConfigDirName = "MMH_CONFIG_DIR"
ConfigNameFile = ".current"
BasicConfigName = "basic.yaml"
)
var (
Configs ConfigList
configDir string
basicConfig Config
currentConfig Config
currentConfigName string
currentConfigPath string
basicConfigPath string
)
// LoadConfig is responsible for loading config files and serializing them to memory objects
func LoadConfig() {
// get user home dir
home, err := homedir.Dir()
common.CheckAndExit(err)
// load config dir from env
configDir = os.Getenv(EnvConfigDirName)
if configDir != "" {
// config dir path only support absolute path or start with homedir(~)
if !filepath.IsAbs(configDir) && !strings.HasPrefix(configDir, "~") {
common.Exit("the config dir path must be a absolute path or start with homedir(~)", 1)
}
// convert config dir path with homedir(~) prefix to absolute path
if strings.HasPrefix(configDir, "~") {
configDir = strings.Replace(configDir, "~", home, 1)
}
} else {
// default to $HOME/.mmh
configDir = filepath.Join(home, ".mmh")
}
// check config dir if it not exist
f, err := os.Lstat(configDir)
if err != nil {
if os.IsNotExist(err) {
initConfig(configDir)
} else {
common.Exit(err.Error(), 1)
}
} else {
// check config dir is symlink. filepath Walk does not follow symbolic links
if f.Mode()&os.ModeSymlink != 0 {
configDir, err = os.Readlink(configDir)
if os.IsNotExist(err) {
initConfig(configDir)
} else {
common.Exit(err.Error(), 1)
}
}
}
// get current config
bs, err := ioutil.ReadFile(filepath.Join(configDir, ConfigNameFile))
if err != nil || len(bs) < 1 {
fmt.Println("failed to get current config, use default config(default.yaml)")
currentConfigName = "default.yaml"
} else {
currentConfigName = string(bs)
}
// load current config
currentConfigPath = filepath.Join(configDir, currentConfigName)
common.PrintErr(currentConfig.LoadFrom(currentConfigPath))
// load basic config if it exist
basicConfigPath = filepath.Join(configDir, BasicConfigName)
if _, err = os.Stat(basicConfigPath); err == nil {
common.PrintErr(basicConfig.LoadFrom(basicConfigPath))
}
// load all config info
_ = filepath.Walk(configDir, func(path string, f os.FileInfo, err error) error {
if !common.CheckErr(err) {
return nil
}
if f.IsDir() || !strings.HasSuffix(f.Name(), ".yaml") {
return nil
}
Configs = append(Configs, ConfigInfo{
Name: strings.TrimSuffix(f.Name(), ".yaml"),
Path: path,
IsCurrent: path == currentConfigPath,
})
return nil
})
sort.Sort(Configs)
}
// SetConfig set which config file to use, and writes the config file name into
// the file storage; the config file must exist or the operation fails
func SetConfig(name string) {
// check config name exist
var exist bool
for _, c := range Configs {
if c.Name == name {
exist = true
}
}
if !exist {
common.Exit(fmt.Sprintf("config [%s] not exist", name), 1)
}
// write to file
common.CheckAndExit(ioutil.WriteFile(filepath.Join(configDir, ConfigNameFile), []byte(name+".yaml"), 0644))
}
func ListConfigs() {
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Name", "Path"})
for _, c := range Configs {
table.Append([]string{c.Name, c.Path})
}
table.Render()
}
// initConfig init the example config
func initConfig(dir string) {
// create config dir
common.CheckAndExit(os.MkdirAll(dir, 0755))
// create basic config file
common.CheckAndExit(ConfigExample().WriteTo(filepath.Join(dir, BasicConfigName)))
// set current config to default
common.CheckAndExit(ioutil.WriteFile(filepath.Join(dir, ConfigNameFile), []byte(BasicConfigName), 0644))
}