-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
142 lines (122 loc) · 3.02 KB
/
main.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
package main
import (
"bufio"
"flag"
"fmt"
"io"
"os"
"sort"
"strings"
)
type Config struct {
// Name of the package to use in generated code. Defaults to 'env'.
Package string
// Output defines the output file for the generated code.
// If left empty, prints to stdout.
Output string
// Space separated list of environment variables NOT to capture.
Ignore string
// Generate a file that doesn't set any default environment variables.
Dev bool
}
var alwaysIgnore = []string{"PWD", "SHLVL", "_", "PATH"}
func NewDefaultConfig() *Config {
return &Config{
Package: "env",
}
}
func parseArgs() *Config {
c := NewDefaultConfig()
flag.StringVar(&c.Package, "pkg", c.Package, "Package name to use in generated code.")
flag.StringVar(&c.Output, "o", c.Output, "Optional name of the output file to be generated.")
flag.StringVar(&c.Ignore, "ignore", c.Ignore, "Space separated list of environment variables to ignore.")
flag.BoolVar(&c.Dev, "dev", c.Dev, "Do not capture the environment, but instead generate a file that just reads from the runtime environment.")
flag.Parse()
return c
}
func writeDev(w io.Writer, c *Config) error {
return writeRelease(w, c, nil)
}
func writeRelease(w io.Writer, c *Config, env map[string]string) error {
var defaultsMapExpr string
if len(env) == 0 {
defaultsMapExpr = ""
} else {
var kvExprs []string
for k, v := range env {
kvExprs = append(kvExprs, fmt.Sprintf("\t%q: %q,", k, v))
}
sort.Strings(kvExprs) // sort for stable ordering
defaultsMapExpr = "\n" + strings.Join(kvExprs, "\n") + "\n"
}
_, err := fmt.Fprintf(w, `// Package %s sets default values for environment variables.
// Usage: in any package that calls os.Getenv or references the environment, include:
//
// import _ "full/path/to/%s"
//
package %s
import "os"
var defaults = map[string]string{%s}
func init() {
setDefaultEnv()
}
func setDefaultEnv() {
for k, v := range defaults {
if os.Getenv(k) == "" {
os.Setenv(k, v)
}
}
}
`, c.Package, c.Package, c.Package, defaultsMapExpr)
if err != nil {
return err
}
return nil
}
// Transcribe reads environment variables and emits a Go source file with their default values.
func Transcribe(c *Config) error {
// Get environment to capture
ignore_ := strings.Fields(c.Ignore)
ignore := make(map[string]bool)
for _, ig := range ignore_ {
ignore[ig] = true
}
for _, ig := range alwaysIgnore {
ignore[ig] = true
}
env := make(map[string]string)
for _, keyval := range os.Environ() {
key := strings.SplitN(keyval, "=", 2)[0]
val := os.Getenv(key)
if !ignore[key] {
env[key] = val
}
}
// Write file
var out io.Writer
if c.Output == "" {
out = os.Stdout
} else {
fd, err := os.Create(c.Output)
if err != nil {
return nil
}
defer fd.Close()
bfd := bufio.NewWriter(fd)
defer bfd.Flush()
out = bfd
}
if c.Dev {
writeDev(out, c)
} else {
writeRelease(out, c, env)
}
return nil
}
func main() {
c := parseArgs()
if err := Transcribe(c); err != nil {
fmt.Fprintf(os.Stderr, "go-envdata: %v\n", err)
os.Exit(1)
}
}