forked from badgerodon/penv
-
Notifications
You must be signed in to change notification settings - Fork 2
/
penv.go
167 lines (151 loc) · 3.83 KB
/
penv.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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package penv
import (
"fmt"
"sort"
"strings"
)
type (
// Environment is a collection of appenders, setters and unsetters
Environment struct {
Appenders []NameValue
Setters []NameValue
Unsetters []NameValue
}
// NameValue is a name value pair
NameValue struct {
Name string
Value string
}
)
func uniquei(arr []string) []string {
u := make([]string, 0, len(arr))
h := map[string]struct{}{}
for _, str := range arr {
stri := strings.ToLower(str)
if _, ok := h[stri]; ok {
continue
}
h[stri] = struct{}{}
u = append(u, str)
}
return u
}
func filter(arr []NameValue, cond func(NameValue) bool) []NameValue {
nvs := make([]NameValue, 0, len(arr))
for _, nv := range arr {
if cond(nv) {
nvs = append(nvs, nv)
}
}
return nvs
}
type registeredDAO struct {
DAO DAO
Condition func() bool
Priority int
}
type registeredDAOs []registeredDAO
var registered = make(registeredDAOs, 0)
func (r registeredDAOs) Len() int {
return len(r)
}
func (r registeredDAOs) Less(i, j int) bool {
return r[i].Priority < r[j].Priority
}
func (r registeredDAOs) Swap(i, j int) {
r[i], r[j] = r[j], r[i]
}
// RegisterDAO registers a new data access object. DAOs are evaluted based on
// priority and the condition function
func RegisterDAO(priority int, condition func() bool, dao DAO) {
registered = append(registered, registeredDAO{dao, condition, priority})
sort.Sort(registered)
}
// DAO defines the interface for loading and saving a set of environment
// variables
type DAO interface {
Load() (*Environment, error)
Save(*Environment) error
}
// Load loads the environment
func Load() (*Environment, error) {
for _, r := range registered {
if r.Condition() {
return r.DAO.Load()
}
}
return nil, fmt.Errorf("no environment DAO found")
}
// Save saves the environment
func Save(env *Environment) error {
for _, r := range registered {
if r.Condition() {
return r.DAO.Save(env)
}
}
return fmt.Errorf("no environment DAO found")
}
// AppendEnv permanently appends an environment variable
func AppendEnv(name, value string) error {
env, err := Load()
if err != nil {
return fmt.Errorf("failed to load environment: %v", err)
}
env.Setters = filter(env.Setters, func(nv NameValue) bool {
return nv.Name != name || nv.Value != value
})
env.Appenders = filter(env.Appenders, func(nv NameValue) bool {
return nv.Name != name || nv.Value != value
})
env.Appenders = append(env.Appenders, NameValue{name, value})
// if it's being unset, remove it from the list
env.Unsetters = filter(env.Unsetters, func(nv NameValue) bool {
return nv.Name != name
})
err = Save(env)
if err != nil {
return fmt.Errorf("failed to save environment: %v", err)
}
return nil
}
// SetEnv permanently sets an environment variable
func SetEnv(name, value string) error {
env, err := Load()
if err != nil {
return fmt.Errorf("failed to load environment: %v", err)
}
env.Setters = filter(env.Setters, func(nv NameValue) bool {
return nv.Name != name
})
env.Setters = append(env.Setters, NameValue{name, value})
env.Unsetters = filter(env.Unsetters, func(nv NameValue) bool {
return nv.Name != name
})
err = Save(env)
if err != nil {
return fmt.Errorf("failed to save environment: %v", err)
}
return nil
}
// UnsetEnv permanently unsets an environment variable
func UnsetEnv(name string) error {
env, err := Load()
if err != nil {
return fmt.Errorf("failed to load environment: %v", err)
}
env.Setters = filter(env.Setters, func(nv NameValue) bool {
return nv.Name != name
})
env.Appenders = filter(env.Appenders, func(nv NameValue) bool {
return nv.Name != name
})
env.Unsetters = filter(env.Unsetters, func(nv NameValue) bool {
return nv.Name != name
})
env.Unsetters = append(env.Unsetters, NameValue{name, ""})
err = Save(env)
if err != nil {
return fmt.Errorf("failed to save environment: %v", err)
}
return nil
}