/
utils.go
159 lines (142 loc) · 3.46 KB
/
utils.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
package util
import (
"bufio"
"bytes"
"errors"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"text/template"
"github.com/mgutz/str"
)
// PackageName determines the package name from sourceFile if it is within $GOPATH
func PackageName(sourceFile string) (string, error) {
if filepath.Ext(sourceFile) != ".go" {
return "", errors.New("sourcefile must end with .go")
}
sourceFile, err := filepath.Abs(sourceFile)
if err != nil {
Panic("util", "Could not convert to absolute path: %s", sourceFile)
}
gopath := os.Getenv("GOPATH")
if gopath == "" {
return "", errors.New("Environment variable GOPATH is not set")
}
paths := strings.Split(gopath, string(os.PathListSeparator))
for _, path := range paths {
srcDir := filepath.Join(path, "src")
srcDir, err := filepath.Abs(srcDir)
if err != nil {
continue
}
//log.Printf("srcDir %s sourceFile %s\n", srcDir, sourceFile)
rel, err := filepath.Rel(srcDir, sourceFile)
if err != nil {
continue
}
return filepath.Dir(rel), nil
}
return "", errors.New("sourceFile not reachable from GOPATH")
}
// Template reads a go template and writes it to dist given data.
func Template(src string, dest string, data map[string]interface{}) {
content, err := ioutil.ReadFile(src)
if err != nil {
Panic("template", "Could not read file %s\n%v\n", src, err)
}
tpl := template.New("t")
tpl, err = tpl.Parse(string(content))
if err != nil {
Panic("template", "Could not parse template %s\n%v\n", src, err)
}
f, err := os.Create(dest)
if err != nil {
Panic("template", "Could not create file for writing %s\n%v\n", dest, err)
}
defer f.Close()
err = tpl.Execute(f, data)
if err != nil {
Panic("template", "Could not execute template %s\n%v\n", src, err)
}
}
// StrTemplate reads a go template and writes it to dist given data.
func StrTemplate(src string, data map[string]interface{}) (string, error) {
tpl := template.New("t")
tpl, err := tpl.Parse(src)
if err != nil {
return "", err
}
var buf bytes.Buffer
err = tpl.Execute(&buf, data)
if err != nil {
return "", err
}
return buf.String(), nil
}
// PartitionKV partitions a reader then parses key-value meta using an assignment string.
//
// Example
//
// PartitionKV(buf.NewBufferString(`
// --@ key=SelectUser
// SELECT * FROM users;
// `, "--@", "=") => [{"_kind": "key", "key": "SelectUser", "_body": "SELECT * FROM users;"}]
func PartitionKV(r io.Reader, prefix string, assignment string) ([]map[string]string, error) {
scanner := bufio.NewScanner(r)
var buf bytes.Buffer
var kv string
var text string
var result []map[string]string
collect := false
parseKV := func(kv string) {
argv := str.ToArgv(kv)
body := buf.String()
for i, arg := range argv {
m := map[string]string{}
var key string
var value string
if strings.Contains(arg, assignment) {
parts := strings.Split(arg, assignment)
key = parts[0]
value = parts[1]
} else {
key = arg
value = ""
}
m[key] = value
m["_body"] = body
if i == 0 {
m["_kind"] = key
}
result = append(result, m)
}
}
for scanner.Scan() {
text = scanner.Text()
if strings.HasPrefix(text, prefix) {
if kv != "" {
parseKV(kv)
}
kv = text[len(prefix):]
collect = true
buf.Reset()
continue
}
if collect {
buf.WriteString(text)
buf.WriteRune('\n')
}
}
if err := scanner.Err(); err != nil {
return nil, err
}
if kv != "" && buf.Len() > 0 {
parseKV(kv)
}
if collect {
return result, nil
}
return nil, nil
}