-
Notifications
You must be signed in to change notification settings - Fork 6
/
config.go
144 lines (121 loc) · 2.93 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
package rfm
import (
"path/filepath"
"os"
"sync"
"github.com/mitchellh/go-homedir"
"github.com/pelletier/go-toml"
)
const (
// ConfigFileName is the name of config file
ConfigFileName = "rfm.toml"
// DefaultDevice is the name of the default device
DefaultDevice = "default"
// DefaultPort is to be used if the user did not pass a port
DefaultPort = 80
// DefaultPassword is used if the user did not pass a password
DefaultPassword = "reprap"
)
type device struct {
Domain string
Port uint64
Password string
Excludes map[string]Excludes
}
// Config holds the configuration sets
type Config struct {
// Devices is only exported for marshalling/unmarshalling. Use GetDevice(string) instead
Devices map[string]device
}
var conf = &Config{}
var mu sync.Mutex
var load sync.Once
// GetDevice returns a pointer to the config for the given device name.
// Even though Config.Devices is exported this is the preferred way
// to fetch a device
func GetDevice(deviceName string) *device {
loadConfigs()
d, ok := conf.Devices[deviceName]
if !ok {
return nil
}
if d.Excludes == nil {
d.Excludes = make(map[string]Excludes)
}
return &d
}
// LoadConfigs tries to read the config file and returns
// either its contents or an empty config and in case of
// an error also an error instance
func loadConfigs() (*Config, error) {
var err error
load.Do(func() {
mu.Lock()
defer mu.Unlock()
// Get the user's home dir
var h string
h, err = homedir.Dir()
if err != nil {
return
}
// Try to open the file
f, err := os.Open(filepath.Join(h, ConfigFileName))
if err != nil {
// If it does not exist return an empty config
if os.IsNotExist(err) {
err = nil
return
}
return
}
defer f.Close()
// Read the file and unmarshal it
err = toml.NewDecoder(f).Decode(conf)
})
if conf.Devices == nil {
conf.Devices = make(map[string]device)
}
return conf, err
}
// AddConfig adds a new device to the configuration
func AddConfig(deviceName string, domain string, port uint64, password string) {
loadConfigs()
mu.Lock()
defer mu.Unlock()
d := device{
Domain: domain,
Port: port,
Password: password,
Excludes: make(map[string]Excludes),
}
conf.Devices[deviceName] = d
}
// SaveConfigs writes all known configurations to the config file
func SaveConfigs() error {
mu.Lock()
defer mu.Unlock()
// Marshal the config
bytes, err := toml.Marshal(conf)
if err != nil {
return err
}
// Get the user's home directory
h, err := homedir.Dir()
if err != nil {
return err
}
// Create a temporary file to not kill current contents in case of error
f, err := os.CreateTemp(h, ConfigFileName)
if err != nil {
return err
}
defer f.Close()
// And write to it
if _, err = f.Write(bytes); err != nil {
return err
}
// Explicitely close the file before renaming
f.Close()
// If we get here rename the temporary file to the real name
return os.Rename(f.Name(), filepath.Join(h, ConfigFileName))
}