Skip to content

Commit cc79e40

Browse files
committed
Deprecate most of "templatelib" in favor of Sprig
It implements many of the same functions like `first`, `last`, `ternary`, etc, some just with a different name like `toJson` vs `json`, and gives us *many* more useful functions.
1 parent 8e42901 commit cc79e40

File tree

6 files changed

+61
-54
lines changed

6 files changed

+61
-54
lines changed

cmd/bashbrew/cmd-cat.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func cmdCat(c *cli.Context) error {
4848
}
4949

5050
var i int
51-
tmpl, err := template.New(templateName).Funcs(templatelib.FuncMap).Funcs(template.FuncMap{
51+
tmpl, err := template.New(templateName).Funcs(templatelib.FuncMap()).Funcs(template.FuncMap{
5252
"i": func() int {
5353
return i
5454
},

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ module github.com/docker-library/bashbrew
33
go 1.13
44

55
require (
6+
github.com/Masterminds/sprig/v3 v3.2.2
67
github.com/containerd/containerd v1.4.0
78
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
89
github.com/go-git/go-git/v5 v5.1.0
9-
github.com/imdario/mergo v0.3.11 // indirect
1010
github.com/opencontainers/go-digest v1.0.0 // indirect
1111
github.com/opencontainers/image-spec v1.0.1
1212
github.com/pkg/errors v0.9.1 // indirect

go.sum

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
22
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
3+
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
4+
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
5+
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
6+
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
7+
github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8=
8+
github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
39
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
410
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
511
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
@@ -45,6 +51,10 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
4551
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
4652
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
4753
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
54+
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
55+
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
56+
github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs=
57+
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
4858
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
4959
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
5060
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
@@ -61,8 +71,12 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
6171
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
6272
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
6373
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
74+
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
75+
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
6476
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
6577
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
78+
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
79+
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
6680
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
6781
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
6882
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
@@ -79,15 +93,20 @@ github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0
7993
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
8094
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
8195
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
96+
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
97+
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
8298
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
8399
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
84100
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
85101
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
102+
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
103+
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
86104
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
87105
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
88106
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
89-
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
90107
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
108+
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
109+
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
91110
github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA=
92111
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
93112
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
@@ -97,6 +116,7 @@ golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnf
97116
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
98117
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
99118
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
119+
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
100120
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
101121
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
102122
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=

pkg/templatelib/lib.go

+28-41
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
package templatelib
22

33
import (
4-
"encoding/json"
54
"fmt"
65
"os"
76
"reflect"
87
"strings"
98
"text/template"
9+
10+
"github.com/Masterminds/sprig/v3"
1011
)
1112

1213
func swapStringsFuncBoolArgsOrder(a func(string, string) bool) func(string, string) bool {
@@ -68,55 +69,33 @@ func stringsModifierActionFactory(a func(string, string) string) func([]string,
6869
}
6970
}
7071

71-
var FuncMap = template.FuncMap{
72-
// {{- $isGitHub := hasPrefix "https://github.com/" $url -}}
73-
// {{- $isHtml := hasSuffix ".html" $url -}}
74-
"hasPrefix": swapStringsFuncBoolArgsOrder(strings.HasPrefix),
75-
"hasSuffix": swapStringsFuncBoolArgsOrder(strings.HasSuffix),
76-
77-
// {{- $hugeIfTrue := .SomeValue | ternary "HUGE" "not so huge" -}}
78-
// if .SomeValue is truthy, $hugeIfTrue will be "HUGE"
79-
// (otherwise, "not so huge")
80-
"ternary": func(truthy interface{}, falsey interface{}, val interface{}) interface{} {
81-
if t, ok := template.IsTrue(val); !ok {
82-
panic(fmt.Sprintf(`template.IsTrue(%+v) says things are NOT OK`, val))
83-
} else if t {
84-
return truthy
85-
} else {
86-
return falsey
72+
func FuncMap() template.FuncMap {
73+
funcMap := sprig.TxtFuncMap()
74+
75+
// https://github.com/Masterminds/sprig/pull/276
76+
funcMap["ternary"] = func(vt interface{}, vf interface{}, v interface{}) interface{} {
77+
if truth, ok := template.IsTrue(v); !ok {
78+
panic(fmt.Sprintf(`template.IsTrue(%+v) says things are NOT OK`, v))
79+
} else if truth {
80+
return vt
8781
}
88-
},
82+
return vf
83+
}
8984

90-
// First Tag: {{- .Tags | first -}}
91-
// Last Tag: {{- .Tags | last -}}
92-
"first": thingsActionFactory("first", true, func(args []interface{}, arg interface{}) interface{} { return arg }),
93-
"last": thingsActionFactory("last", false, func(args []interface{}, arg interface{}) interface{} { return arg }),
85+
// Everybody: {{- join ", " .Names -}}
86+
// Concat: {{- join "/" "https://github.com" "jsmith" "some-repo" -}}
87+
funcMap["join"] = stringsActionFactory("join", true, strings.Join)
88+
// (this differs slightly from the Sprig "join" in that it accepts either a list of strings or multiple arguments - Sprig instead has an explicit "list" function which can create a list of strings *from* a list of arguments so that multiple-signature usability like this is not necessary)
9489

9590
// JSON data dump: {{ json . }}
9691
// (especially nice for taking data and piping it to "jq")
9792
// (ie "some-tool inspect --format '{{ json . }}' some-things | jq .")
98-
"json": func(v interface{}) (string, error) {
99-
j, err := json.Marshal(v)
100-
return string(j), err
101-
},
102-
103-
// Everybody: {{- join ", " .Names -}}
104-
// Concat: {{- join "/" "https://github.com" "jsmith" "some-repo" -}}
105-
"join": stringsActionFactory("join", true, strings.Join),
106-
107-
// {{- $mungedUrl := $url | replace "git://" "https://" | trimSuffixes ".git" -}}
108-
// turns: git://github.com/jsmith/some-repo.git
109-
// into: https://github.com/jsmith/some-repo
110-
"trimPrefixes": stringsActionFactory("trimPrefixes", false, stringsModifierActionFactory(strings.TrimPrefix)),
111-
"trimSuffixes": stringsActionFactory("trimSuffixes", false, stringsModifierActionFactory(strings.TrimSuffix)),
112-
"replace": stringsActionFactory("replace", false, func(strs []string, str string) string {
113-
return strings.NewReplacer(strs...).Replace(str)
114-
}),
93+
funcMap["json"] = funcMap["toJson"]
11594

11695
// {{- getenv "PATH" -}}
11796
// {{- getenv "HOME" "no HOME set" -}}
11897
// {{- getenv "HOME" "is set" "is NOT set (or is empty)" -}}
119-
"getenv": thingsActionFactory("getenv", true, func(args []interface{}, arg interface{}) interface{} {
98+
funcMap["getenv"] = thingsActionFactory("getenv", true, func(args []interface{}, arg interface{}) interface{} {
12099
var (
121100
val = os.Getenv(arg.(string))
122101
setVal interface{} = val
@@ -134,5 +113,13 @@ var FuncMap = template.FuncMap{
134113
} else {
135114
return unsetVal
136115
}
137-
}),
116+
})
117+
118+
// {{- $mungedUrl := $url | replace "git://" "https://" | trimSuffixes ".git" -}}
119+
// turns: git://github.com/jsmith/some-repo.git
120+
// into: https://github.com/jsmith/some-repo
121+
funcMap["trimPrefixes"] = stringsActionFactory("trimPrefixes", false, stringsModifierActionFactory(strings.TrimPrefix))
122+
funcMap["trimSuffixes"] = stringsActionFactory("trimSuffixes", false, stringsModifierActionFactory(strings.TrimSuffix))
123+
124+
return funcMap
138125
}

pkg/templatelib/lib_example_test.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
)
99

1010
func Example_prefixSuffix() {
11-
tmpl, err := template.New("github-or-html").Funcs(templatelib.FuncMap).Parse(`
11+
tmpl, err := template.New("github-or-html").Funcs(templatelib.FuncMap()).Parse(`
1212
{{- . -}}
1313
1414
{{- if hasPrefix "https://github.com/" . -}}
@@ -53,7 +53,7 @@ func Example_prefixSuffix() {
5353
}
5454

5555
func Example_ternary() {
56-
tmpl, err := template.New("huge-if-true").Funcs(templatelib.FuncMap).Parse(`
56+
tmpl, err := template.New("huge-if-true").Funcs(templatelib.FuncMap()).Parse(`
5757
{{- range $a := . -}}
5858
{{ printf "%#v: %s\n" $a (ternary "HUGE" "not so huge" $a) }}
5959
{{- end -}}
@@ -91,7 +91,7 @@ func Example_ternary() {
9191
}
9292

9393
func Example_firstLast() {
94-
tmpl, err := template.New("first-and-last").Funcs(templatelib.FuncMap).Parse(`First: {{ . | first }}, Last: {{ . | last }}`)
94+
tmpl, err := template.New("first-and-last").Funcs(templatelib.FuncMap()).Parse(`First: {{ . | first }}, Last: {{ . | last }}`)
9595

9696
err = tmpl.Execute(os.Stdout, []interface{}{
9797
"a",
@@ -107,7 +107,7 @@ func Example_firstLast() {
107107
}
108108

109109
func Example_json() {
110-
tmpl, err := template.New("json").Funcs(templatelib.FuncMap).Parse(`
110+
tmpl, err := template.New("json").Funcs(templatelib.FuncMap()).Parse(`
111111
{{- json . -}}
112112
`)
113113

@@ -125,7 +125,7 @@ func Example_json() {
125125
}
126126

127127
func Example_join() {
128-
tmpl, err := template.New("join").Funcs(templatelib.FuncMap).Parse(`
128+
tmpl, err := template.New("join").Funcs(templatelib.FuncMap()).Parse(`
129129
Array: {{ . | join ", " }}{{ "\n" -}}
130130
Args: {{ join ", " "a" "b" "c" -}}
131131
`)
@@ -145,7 +145,7 @@ func Example_join() {
145145
}
146146

147147
func Example_trimReplaceGitToHttps() {
148-
tmpl, err := template.New("git-to-https").Funcs(templatelib.FuncMap).Parse(`
148+
tmpl, err := template.New("git-to-https").Funcs(templatelib.FuncMap()).Parse(`
149149
{{- range . -}}
150150
{{- . | replace "git://" "https://" | trimSuffixes ".git" }}{{ "\n" -}}
151151
{{- end -}}
@@ -167,7 +167,7 @@ func Example_trimReplaceGitToHttps() {
167167
}
168168

169169
func Example_trimReplaceGitToGo() {
170-
tmpl, err := template.New("git-to-go").Funcs(templatelib.FuncMap).Parse(`
170+
tmpl, err := template.New("git-to-go").Funcs(templatelib.FuncMap()).Parse(`
171171
{{- range . -}}
172172
{{- . | trimPrefixes "git://" "http://" "https://" "ssh://" | trimSuffixes ".git" }}{{ "\n" -}}
173173
{{- end -}}
@@ -193,7 +193,7 @@ func Example_trimReplaceGitToGo() {
193193
}
194194

195195
func Example_getenv() {
196-
tmpl, err := template.New("getenv").Funcs(templatelib.FuncMap).Parse(`
196+
tmpl, err := template.New("getenv").Funcs(templatelib.FuncMap()).Parse(`
197197
The FOO environment variable {{ getenv "FOO" "is set" "is not set" }}. {{- "\n" -}}
198198
BAR: {{ getenv "BAR" "not set" }} {{- "\n" -}}
199199
BAZ: {{ getenv "BAZ" "not set" }} {{- "\n" -}}

pkg/templatelib/lib_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
func TestTernaryPanic(t *testing.T) {
1313
// one of the only places template.IsTrue will return "false" for the "ok" value is an UnsafePointer (hence this test)
1414

15-
tmpl, err := template.New("unsafe-pointer").Funcs(templatelib.FuncMap).Parse(`{{ ternary "true" "false" . }}`)
15+
tmpl, err := template.New("unsafe-pointer").Funcs(templatelib.FuncMap()).Parse(`{{ ternary "true" "false" . }}`)
1616
if err != nil {
1717
t.Errorf("Unexpected error: %v", err)
1818
}
@@ -27,7 +27,7 @@ func TestTernaryPanic(t *testing.T) {
2727
}
2828

2929
func TestJoinPanic(t *testing.T) {
30-
tmpl, err := template.New("join-no-arg").Funcs(templatelib.FuncMap).Parse(`{{ join }}`)
30+
tmpl, err := template.New("join-no-arg").Funcs(templatelib.FuncMap()).Parse(`{{ join }}`)
3131
if err != nil {
3232
t.Errorf("Unexpected error: %v", err)
3333
}

0 commit comments

Comments
 (0)