-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
125 lines (103 loc) · 3.11 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
package main
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"os"
"path"
"regexp"
"text/template"
"github.com/sergi/go-diff/diffmatchpatch"
)
// Handle the -force argument if file exists
func writeForceCheck(path string, force bool) {
if _, err := os.Stat(path); !os.IsNotExist(err) && !force {
fmt.Printf("Error: file exists [%s], use -force to override\n", path)
os.Exit(1)
}
}
func main() {
// Command line argument parsing
args := ParseArgs()
// Init input/output
inputFileRegexp := regexp.MustCompile(`^(.+)\.tmpl$`)
inputFileMatches := inputFileRegexp.FindStringSubmatch(path.Base(args.InputFile))
if len(inputFileMatches) != 2 {
log.Fatalln("Invalid input filename, expecting a go template with a .tmpl file extension (e.g., myfile.conf.tmpl)")
}
var inputFileData []byte
var err error
inputFileData, err = ioutil.ReadFile(args.InputFile)
if err != nil {
log.Fatal(err)
}
var outputFile *os.File
defer outputFile.Close()
if args.WriteFile != "" {
writeForceCheck(args.WriteFile, args.Force)
outputFile, err = os.Create(args.WriteFile)
if err != nil {
log.Fatal(err)
}
} else {
outputFile = os.Stdout
}
// Perform pre-check if requested
if args.PreCheck {
var tmplParsedData bytes.Buffer
// A simple parse of the template
// (to see if existing content manifests as go template syntax errors)
tmpl, err := template.New("root").Parse(string(inputFileData))
if err != nil {
fmt.Println("Failed parsing your file as a go template. This failure points to content being accidentally interpreted as go template code, please fix before editing your file:")
log.Fatal(err)
}
err = tmpl.Execute(&tmplParsedData, "")
if err != nil {
fmt.Println("Failed executing your file as a go template. This failure points to content being accidentally interpreted as go template code, please fix before editing your file:")
log.Fatal(err)
}
// Diff the parsed template against the file to check for differences
if string(inputFileData) != tmplParsedData.String() {
fmt.Println("The following difference(s) were detected in your file when parsed as a go template. These failure(s) point to content being accidentally interpreted as go template code, please fix before editing your file:")
dmp := diffmatchpatch.New()
diffs := dmp.DiffMain(string(inputFileData), tmplParsedData.String(), false)
fmt.Println(dmp.DiffPrettyText(diffs))
os.Exit(1)
} else {
fmt.Println("File passed; no issues detected.")
}
os.Exit(0)
}
// Gather var data and merge in order declared
var tmplValues = make(VarValues)
varIndex := 0
varFileIndex := 0
skipNext := false
for _, v := range os.Args[1:] {
if skipNext {
skipNext = false
continue
}
switch v {
case "-var":
tmplValues.Merge(args.Vars[varIndex].Values())
varIndex++
skipNext = true
case "-var-file":
tmplValues.Merge(args.VarFiles[varFileIndex].Values())
varFileIndex++
skipNext = true
}
}
// Process template
tmpl, err := template.New("root").Parse(string(inputFileData))
if err != nil {
log.Fatal(err)
}
err = tmpl.Execute(outputFile, &tmplValues)
if err != nil {
log.Fatal(err)
}
}