Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate most of "templatelib" in favor of Sprig #23

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/bashbrew/cmd-cat.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func cmdCat(c *cli.Context) error {
}

var i int
tmpl, err := template.New(templateName).Funcs(templatelib.FuncMap).Funcs(template.FuncMap{
tmpl, err := template.New(templateName).Funcs(templatelib.FuncMap()).Funcs(template.FuncMap{
"i": func() int {
return i
},
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ module github.com/docker-library/bashbrew
go 1.13

require (
github.com/Masterminds/sprig/v3 v3.2.2
github.com/containerd/containerd v1.4.0
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/go-git/go-git/v5 v5.1.0
github.com/imdario/mergo v0.3.11 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.1
github.com/pkg/errors v0.9.1 // indirect
Expand Down
22 changes: 21 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8=
github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
Expand Down Expand Up @@ -45,6 +51,10 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs=
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
Expand All @@ -61,8 +71,12 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
Expand All @@ -79,15 +93,20 @@ github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA=
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
Expand All @@ -97,6 +116,7 @@ golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
Expand Down
69 changes: 28 additions & 41 deletions pkg/templatelib/lib.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package templatelib

import (
"encoding/json"
"fmt"
"os"
"reflect"
"strings"
"text/template"

"github.com/Masterminds/sprig/v3"
)

func swapStringsFuncBoolArgsOrder(a func(string, string) bool) func(string, string) bool {
Expand Down Expand Up @@ -68,55 +69,33 @@ func stringsModifierActionFactory(a func(string, string) string) func([]string,
}
}

var FuncMap = template.FuncMap{
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I could get fancy with github.com/imdario/mergo to avoid changing the signature of templatelib.FuncMap, but I'm not aware of any actual users of it, so I'm not sure it's worth going to the trouble? 😇

(I'd love to convert our uses of functions like trimSuffixes, trimPrefixes, join, and getenv to be compatible with their Sprig counterparts so we could deprecate/remove our custom versions too, which shouldn't be too much work.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// {{- $isGitHub := hasPrefix "https://github.com/" $url -}}
// {{- $isHtml := hasSuffix ".html" $url -}}
"hasPrefix": swapStringsFuncBoolArgsOrder(strings.HasPrefix),
"hasSuffix": swapStringsFuncBoolArgsOrder(strings.HasSuffix),

// {{- $hugeIfTrue := .SomeValue | ternary "HUGE" "not so huge" -}}
// if .SomeValue is truthy, $hugeIfTrue will be "HUGE"
// (otherwise, "not so huge")
"ternary": func(truthy interface{}, falsey interface{}, val interface{}) interface{} {
if t, ok := template.IsTrue(val); !ok {
panic(fmt.Sprintf(`template.IsTrue(%+v) says things are NOT OK`, val))
} else if t {
return truthy
} else {
return falsey
func FuncMap() template.FuncMap {
funcMap := sprig.TxtFuncMap()

// https://github.com/Masterminds/sprig/pull/276
funcMap["ternary"] = func(vt interface{}, vf interface{}, v interface{}) interface{} {
if truth, ok := template.IsTrue(v); !ok {
panic(fmt.Sprintf(`template.IsTrue(%+v) says things are NOT OK`, v))
} else if truth {
return vt
}
},
return vf
}

// First Tag: {{- .Tags | first -}}
// Last Tag: {{- .Tags | last -}}
"first": thingsActionFactory("first", true, func(args []interface{}, arg interface{}) interface{} { return arg }),
"last": thingsActionFactory("last", false, func(args []interface{}, arg interface{}) interface{} { return arg }),
// Everybody: {{- join ", " .Names -}}
// Concat: {{- join "/" "https://github.com" "jsmith" "some-repo" -}}
funcMap["join"] = stringsActionFactory("join", true, strings.Join)
// (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)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess in looking at https://masterminds.github.io/sprig/string_slice.html, the key here will be to verify that we can start porting to the list ... | join ... syntax with this implementation so that at some point we can drop this.


// JSON data dump: {{ json . }}
// (especially nice for taking data and piping it to "jq")
// (ie "some-tool inspect --format '{{ json . }}' some-things | jq .")
"json": func(v interface{}) (string, error) {
j, err := json.Marshal(v)
return string(j), err
},

// Everybody: {{- join ", " .Names -}}
// Concat: {{- join "/" "https://github.com" "jsmith" "some-repo" -}}
"join": stringsActionFactory("join", true, strings.Join),

// {{- $mungedUrl := $url | replace "git://" "https://" | trimSuffixes ".git" -}}
// turns: git://github.com/jsmith/some-repo.git
// into: https://github.com/jsmith/some-repo
"trimPrefixes": stringsActionFactory("trimPrefixes", false, stringsModifierActionFactory(strings.TrimPrefix)),
"trimSuffixes": stringsActionFactory("trimSuffixes", false, stringsModifierActionFactory(strings.TrimSuffix)),
"replace": stringsActionFactory("replace", false, func(strs []string, str string) string {
return strings.NewReplacer(strs...).Replace(str)
}),
funcMap["json"] = funcMap["toJson"]

// {{- getenv "PATH" -}}
// {{- getenv "HOME" "no HOME set" -}}
// {{- getenv "HOME" "is set" "is NOT set (or is empty)" -}}
"getenv": thingsActionFactory("getenv", true, func(args []interface{}, arg interface{}) interface{} {
funcMap["getenv"] = thingsActionFactory("getenv", true, func(args []interface{}, arg interface{}) interface{} {
var (
val = os.Getenv(arg.(string))
setVal interface{} = val
Expand All @@ -134,5 +113,13 @@ var FuncMap = template.FuncMap{
} else {
return unsetVal
}
}),
})

// {{- $mungedUrl := $url | replace "git://" "https://" | trimSuffixes ".git" -}}
// turns: git://github.com/jsmith/some-repo.git
// into: https://github.com/jsmith/some-repo
funcMap["trimPrefixes"] = stringsActionFactory("trimPrefixes", false, stringsModifierActionFactory(strings.TrimPrefix))
funcMap["trimSuffixes"] = stringsActionFactory("trimSuffixes", false, stringsModifierActionFactory(strings.TrimSuffix))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These support a list of prefixes/suffixes, but I'm reasonably certain we've never actually used that functionality, so all our uses should be able to port to trimPrefix and trimSuffix.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just confirmed, trimPrefixes is something we've never actually used, and trimSuffixes is literally only used with .git as a single argument. 😅


return funcMap
}
16 changes: 8 additions & 8 deletions pkg/templatelib/lib_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

func Example_prefixSuffix() {
tmpl, err := template.New("github-or-html").Funcs(templatelib.FuncMap).Parse(`
tmpl, err := template.New("github-or-html").Funcs(templatelib.FuncMap()).Parse(`
{{- . -}}

{{- if hasPrefix "https://github.com/" . -}}
Expand Down Expand Up @@ -53,7 +53,7 @@ func Example_prefixSuffix() {
}

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

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

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

func Example_json() {
tmpl, err := template.New("json").Funcs(templatelib.FuncMap).Parse(`
tmpl, err := template.New("json").Funcs(templatelib.FuncMap()).Parse(`
{{- json . -}}
`)

Expand All @@ -125,7 +125,7 @@ func Example_json() {
}

func Example_join() {
tmpl, err := template.New("join").Funcs(templatelib.FuncMap).Parse(`
tmpl, err := template.New("join").Funcs(templatelib.FuncMap()).Parse(`
Array: {{ . | join ", " }}{{ "\n" -}}
Args: {{ join ", " "a" "b" "c" -}}
`)
Expand All @@ -145,7 +145,7 @@ func Example_join() {
}

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

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

func Example_getenv() {
tmpl, err := template.New("getenv").Funcs(templatelib.FuncMap).Parse(`
tmpl, err := template.New("getenv").Funcs(templatelib.FuncMap()).Parse(`
The FOO environment variable {{ getenv "FOO" "is set" "is not set" }}. {{- "\n" -}}
BAR: {{ getenv "BAR" "not set" }} {{- "\n" -}}
BAZ: {{ getenv "BAZ" "not set" }} {{- "\n" -}}
Expand Down
4 changes: 2 additions & 2 deletions pkg/templatelib/lib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
func TestTernaryPanic(t *testing.T) {
// one of the only places template.IsTrue will return "false" for the "ok" value is an UnsafePointer (hence this test)

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

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