Skip to content

Commit f1131f9

Browse files
authored
Simple Templates (#49)
* add templates to Downloader * add simple template support * add templates to readme example * more about templates in readme
1 parent fcddee8 commit f1131f9

File tree

7 files changed

+228
-44
lines changed

7 files changed

+228
-44
lines changed

.golangci.yml

-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ linters:
1717
- gocyclo
1818
- goconst
1919
- goimports
20-
- maligned
2120
- gocritic
2221
linters-settings:
2322
errcheck:

README.md

+50-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ lowercase GitHub username.
4848
`bindown` is configured with a yaml file. By default it uses a file named
4949
`bindown.yml` in the current directory.
5050

51+
### Templates
52+
53+
Some fields below are marked with "_allows templates_". These fields allow you to use simple go templates that will be
54+
evaluated by bindown using the `os`, `arch` and `vars` values.
55+
5156
### Downloader values
5257

5358
#### os
@@ -62,7 +67,7 @@ _required_
6267
The system architecture this binary is build for. Common values are `amd64`, `386` and `arm`.
6368

6469
#### url
65-
_required_
70+
_required_, _allows templates_
6671

6772
The url to download from. The url can point to either the binary itself or an archive containing the binary.
6873

@@ -74,6 +79,7 @@ can get the value from there or run `bindown config update-checksums <bin-name>`
7479
automatically.
7580

7681
#### archive path
82+
_allows templates_
7783

7884
The path to the binary once the downloaded archive has been extracted. If the download is just the unarchived binary,
7985
this should just be the downloaded file name.
@@ -87,13 +93,20 @@ Whether bindown should create a symlink instead of moving the binary to its fina
8793
_default_: false
8894

8995
#### bin
96+
_allows templates_
9097

9198
What you want the final binary to be called if different from the downloader name.
9299

93100
_default_: the downloader name
94101

102+
#### vars
103+
104+
A map of string values to use in templated values.
105+
95106
### Example
96107

108+
#### Simple config without templates
109+
97110
```yaml
98111
downloaders:
99112
golangci-lint:
@@ -117,6 +130,42 @@ downloaders:
117130
link: true
118131
```
119132
133+
#### With templates
134+
135+
```yaml
136+
downloaders:
137+
golangci-lint:
138+
- os: darwin
139+
arch: amd64
140+
url: https://github.com/golangci/golangci-lint/releases/download/v{{.version}}/golangci-lint-{{.version}}-{{.os}}-{{.arch}}{{.urlsuffix}}
141+
archive_path: golangci-lint-{{.version}}-{{.os}}-{{.arch}}/golangci-lint{{.archivepathsuffix}}
142+
link: true
143+
checksum: 7536c375997cca3d2e1f063958ad0344108ce23aed6bd372b69153bdbda82d13
144+
vars:
145+
archivepathsuffix: ""
146+
urlsuffix: .tar.gz
147+
version: 1.23.7
148+
- os: linux
149+
arch: amd64
150+
url: https://github.com/golangci/golangci-lint/releases/download/v{{.version}}/golangci-lint-{{.version}}-{{.os}}-{{.arch}}{{.urlsuffix}}
151+
archive_path: golangci-lint-{{.version}}-{{.os}}-{{.arch}}/golangci-lint{{.archivepathsuffix}}
152+
link: true
153+
checksum: 34df1794a2ea8e168b3c98eed3cc0f3e13ed4cba735e4e40ef141df5c41bc086
154+
vars:
155+
archivepathsuffix: ""
156+
urlsuffix: .tar.gz
157+
version: 1.23.7
158+
- os: windows
159+
arch: amd64
160+
url: https://github.com/golangci/golangci-lint/releases/download/v{{.version}}/golangci-lint-{{.version}}-{{.os}}-{{.arch}}{{.urlsuffix}}
161+
archive_path: golangci-lint-{{.version}}-{{.os}}-{{.arch}}/golangci-lint{{.archivepathsuffix}}
162+
link: true
163+
checksum: 8ccb76466e4cdaebfc1633c137043c0bec23173749a6bca42846c7350402dcfe
164+
vars:
165+
archivepathsuffix: .exe
166+
urlsuffix: .zip
167+
version: 1.23.7
168+
```
120169
121170
## Usage
122171

bindown.yml

+26-14
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,49 @@ downloaders:
33
- os: darwin
44
arch: amd64
55
url: https://github.com/myitcv/gobin/releases/download/v0.0.10/darwin-amd64
6-
checksum: 84ed966949e06bebd7d006bc343caf9d736932fd8b37df5cb5b268a28d07bd30
76
archive_path: darwin-amd64
7+
checksum: 84ed966949e06bebd7d006bc343caf9d736932fd8b37df5cb5b268a28d07bd30
88
- os: linux
99
arch: amd64
1010
url: https://github.com/myitcv/gobin/releases/download/v0.0.10/linux-amd64
11-
checksum: 415266d9af98578067051653f5057ea267c51ebf085408df48b118a8b978bac6
1211
archive_path: linux-amd64
12+
checksum: 415266d9af98578067051653f5057ea267c51ebf085408df48b118a8b978bac6
1313
- os: windows
1414
arch: amd64
1515
url: https://github.com/myitcv/gobin/releases/download/v0.0.13/windows-amd64
16-
checksum: 70d3688c652bba96f377eb5d3a8068a07274024876c6e3b8d3785f0a63348905
1716
archive_path: windows-amd64
17+
checksum: 70d3688c652bba96f377eb5d3a8068a07274024876c6e3b8d3785f0a63348905
1818
golangci-lint:
1919
- os: darwin
2020
arch: amd64
21-
url: https://github.com/golangci/golangci-lint/releases/download/v1.23.7/golangci-lint-1.23.7-darwin-amd64.tar.gz
22-
checksum: 7536c375997cca3d2e1f063958ad0344108ce23aed6bd372b69153bdbda82d13
23-
archive_path: golangci-lint-1.23.7-darwin-amd64/golangci-lint
21+
url: https://github.com/golangci/golangci-lint/releases/download/v{{.version}}/golangci-lint-{{.version}}-{{.os}}-{{.arch}}{{.urlsuffix}}
22+
archive_path: golangci-lint-{{.version}}-{{.os}}-{{.arch}}/golangci-lint{{.archivepathsuffix}}
2423
link: true
24+
checksum: 7536c375997cca3d2e1f063958ad0344108ce23aed6bd372b69153bdbda82d13
25+
vars:
26+
archivepathsuffix: ""
27+
urlsuffix: .tar.gz
28+
version: 1.23.7
2529
- os: linux
2630
arch: amd64
27-
url: https://github.com/golangci/golangci-lint/releases/download/v1.23.7/golangci-lint-1.23.7-linux-amd64.tar.gz
28-
checksum: 34df1794a2ea8e168b3c98eed3cc0f3e13ed4cba735e4e40ef141df5c41bc086
29-
archive_path: golangci-lint-1.23.7-linux-amd64/golangci-lint
31+
url: https://github.com/golangci/golangci-lint/releases/download/v{{.version}}/golangci-lint-{{.version}}-{{.os}}-{{.arch}}{{.urlsuffix}}
32+
archive_path: golangci-lint-{{.version}}-{{.os}}-{{.arch}}/golangci-lint{{.archivepathsuffix}}
3033
link: true
34+
checksum: 34df1794a2ea8e168b3c98eed3cc0f3e13ed4cba735e4e40ef141df5c41bc086
35+
vars:
36+
archivepathsuffix: ""
37+
urlsuffix: .tar.gz
38+
version: 1.23.7
3139
- os: windows
3240
arch: amd64
33-
url: https://github.com/golangci/golangci-lint/releases/download/v1.23.7/golangci-lint-1.23.7-windows-amd64.zip
34-
checksum: 8ccb76466e4cdaebfc1633c137043c0bec23173749a6bca42846c7350402dcfe
35-
archive_path: golangci-lint-1.23.7-windows-amd64/golangci-lint.exe
41+
url: https://github.com/golangci/golangci-lint/releases/download/v{{.version}}/golangci-lint-{{.version}}-{{.os}}-{{.arch}}{{.urlsuffix}}
42+
archive_path: golangci-lint-{{.version}}-{{.os}}-{{.arch}}/golangci-lint{{.archivepathsuffix}}
3643
link: true
44+
checksum: 8ccb76466e4cdaebfc1633c137043c0bec23173749a6bca42846c7350402dcfe
45+
vars:
46+
archivepathsuffix: .exe
47+
urlsuffix: .zip
48+
version: 1.23.7
3749
goreleaser:
3850
- os: darwin
3951
arch: amd64
@@ -46,8 +58,8 @@ downloaders:
4658
- os: windows
4759
arch: amd64
4860
url: https://github.com/goreleaser/goreleaser/releases/download/v0.120.7/goreleaser_Windows_x86_64.zip
49-
checksum: 0e06f50e1b2213a84b493d32a805dd6d8e8ad960ec9526edd8ecd96e2ab91743
5061
archive_path: goreleaser.exe
62+
checksum: 0e06f50e1b2213a84b493d32a805dd6d8e8ad960ec9526edd8ecd96e2ab91743
5163
semver-next:
5264
- os: darwin
5365
arch: amd64
@@ -60,5 +72,5 @@ downloaders:
6072
- os: windows
6173
arch: amd64
6274
url: https://github.com/WillAbides/semver-next/releases/download/v0.4.0/semver-next_0.4.0_windows_amd64.tar.gz
63-
checksum: 573ea65ef3b40442626fbb19d07880bb4929e7b12fd7161e41732a03f23b2c95
6475
archive_path: semver-next.exe
76+
checksum: 573ea65ef3b40442626fbb19d07880bb4929e7b12fd7161e41732a03f23b2c95

downloader.go

+83-20
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,57 @@ import (
1919

2020
// Downloader downloads a binary
2121
type Downloader struct {
22-
OS string `json:"os"`
23-
Arch string `json:"arch"`
24-
URL string `json:"url"`
25-
Checksum string `json:"checksum,omitempty" yaml:",omitempty"`
26-
ArchivePath string `json:"archive_path,omitempty" yaml:"archive_path,omitempty"`
27-
Link bool `json:"link,omitempty" yaml:",omitempty"`
28-
BinName string `json:"bin,omitempty" yaml:"bin,omitempty"`
22+
OS string `json:"os"`
23+
Arch string `json:"arch"`
24+
URL string `json:"url"`
25+
ArchivePath string `json:"archive_path,omitempty" yaml:"archive_path,omitempty"`
26+
BinName string `json:"bin,omitempty" yaml:"bin,omitempty"`
27+
Link bool `json:"link,omitempty" yaml:",omitempty"`
28+
Checksum string `json:"checksum,omitempty" yaml:",omitempty"`
29+
Vars map[string]string `json:"vars,omitempty" yaml:"vars,omitempty"`
30+
31+
//set to true by applyTemplates
32+
tmplApplied bool
33+
}
34+
35+
func (d *Downloader) clone() *Downloader {
36+
c := new(Downloader)
37+
*c = *d
38+
if c.Vars != nil {
39+
c.Vars = util.CopyStringMap(c.Vars)
40+
}
41+
return c
42+
}
43+
44+
func (d *Downloader) requireApplyTemplates() {
45+
if !d.tmplApplied {
46+
panic("templates not applied")
47+
}
48+
}
49+
50+
func (d *Downloader) applyTemplates() error {
51+
executeTemplate := func(tmpl string) (string, error) {
52+
return util.ExecuteTemplate(tmpl, d.OS, d.Arch, d.Vars)
53+
}
54+
var err error
55+
d.URL, err = executeTemplate(d.URL)
56+
if err != nil {
57+
return err
58+
}
59+
d.ArchivePath, err = executeTemplate(d.ArchivePath)
60+
if err != nil {
61+
return err
62+
}
63+
d.BinName, err = executeTemplate(d.BinName)
64+
if err != nil {
65+
return err
66+
}
67+
d.tmplApplied = true
68+
return nil
2969
}
3070

3171
func (d *Downloader) downloadableName() (string, error) {
72+
d.requireApplyTemplates()
3273
u, err := url.Parse(d.URL)
3374
if err != nil {
3475
return "", err
@@ -37,6 +78,7 @@ func (d *Downloader) downloadableName() (string, error) {
3778
}
3879

3980
func (d *Downloader) downloadablePath(targetDir string) (string, error) {
81+
d.requireApplyTemplates()
4082
name, err := d.downloadableName()
4183
if err != nil {
4284
return "", err
@@ -45,6 +87,7 @@ func (d *Downloader) downloadablePath(targetDir string) (string, error) {
4587
}
4688

4789
func (d *Downloader) binPath(targetDir string) string {
90+
d.requireApplyTemplates()
4891
return filepath.Join(targetDir, d.BinName)
4992
}
5093

@@ -53,6 +96,7 @@ func (d *Downloader) chmod(targetDir string) error {
5396
}
5497

5598
func (d *Downloader) moveOrLinkBin(targetDir, extractDir string) error {
99+
d.requireApplyTemplates()
56100
archivePath := filepath.FromSlash(d.ArchivePath)
57101
if archivePath == "" {
58102
archivePath = filepath.FromSlash(d.BinName)
@@ -103,6 +147,7 @@ func (d *Downloader) moveOrLinkBin(targetDir, extractDir string) error {
103147
}
104148

105149
func (d *Downloader) extract(downloadDir, extractDir string) error {
150+
d.requireApplyTemplates()
106151
dlName, err := d.downloadableName()
107152
if err != nil {
108153
return err
@@ -124,6 +169,7 @@ func (d *Downloader) extract(downloadDir, extractDir string) error {
124169
}
125170

126171
func (d *Downloader) download(downloadDir string) error {
172+
d.requireApplyTemplates()
127173
dlPath, err := d.downloadablePath(downloadDir)
128174
if err != nil {
129175
return err
@@ -149,6 +195,7 @@ func (d *Downloader) setDefaultBinName(defaultName string) {
149195
}
150196

151197
func (d *Downloader) validateChecksum(targetDir string) error {
198+
d.requireApplyTemplates()
152199
targetFile, err := d.downloadablePath(targetDir)
153200
if err != nil {
154201
return err
@@ -179,12 +226,26 @@ type UpdateChecksumOpts struct {
179226

180227
//UpdateChecksum updates the checksum based on a fresh download
181228
func (d *Downloader) UpdateChecksum(opts UpdateChecksumOpts) error {
229+
sum, err := d.getUpdatedChecksum(opts)
230+
if err != nil {
231+
return err
232+
}
233+
d.Checksum = sum
234+
return nil
235+
}
236+
237+
//getUpdatedChecksum downloads the archive and returns its actual checksum.
238+
func (d *Downloader) getUpdatedChecksum(opts UpdateChecksumOpts) (string, error) {
239+
d = d.clone()
240+
err := d.applyTemplates()
241+
if err != nil {
242+
return "", err
243+
}
182244
cellarDir := opts.CellarDir
183-
var err error
184245
if cellarDir == "" {
185246
cellarDir, err = ioutil.TempDir("", "bindown")
186247
if err != nil {
187-
return err
248+
return "", err
188249
}
189250
defer func() {
190251
_ = os.RemoveAll(cellarDir) //nolint:errcheck
@@ -196,21 +257,15 @@ func (d *Downloader) UpdateChecksum(opts UpdateChecksumOpts) error {
196257
err = d.download(downloadDir)
197258
if err != nil {
198259
log.Printf("error downloading: %v", err)
199-
return err
260+
return "", err
200261
}
201262

202263
dlPath, err := d.downloadablePath(downloadDir)
203264
if err != nil {
204-
return err
205-
}
206-
207-
checkSum, err := fileChecksum(dlPath)
208-
if err != nil {
209-
return err
265+
return "", err
210266
}
211267

212-
d.Checksum = checkSum
213-
return nil
268+
return fileChecksum(dlPath)
214269
}
215270

216271
//InstallOpts options for Install
@@ -235,6 +290,10 @@ func (d *Downloader) extractsSubName() string {
235290

236291
//Install downloads and installs a bin
237292
func (d *Downloader) Install(opts InstallOpts) error {
293+
err := d.applyTemplates()
294+
if err != nil {
295+
return err
296+
}
238297
d.setDefaultBinName(opts.DownloaderName)
239298
cellarDir := opts.CellarDir
240299
if cellarDir == "" {
@@ -245,13 +304,13 @@ func (d *Downloader) Install(opts InstallOpts) error {
245304
extractDir := filepath.Join(cellarDir, "extracts", d.extractsSubName())
246305

247306
if opts.Force {
248-
err := os.RemoveAll(downloadDir)
307+
err = os.RemoveAll(downloadDir)
249308
if err != nil {
250309
return err
251310
}
252311
}
253312

254-
err := d.download(downloadDir)
313+
err = d.download(downloadDir)
255314
if err != nil {
256315
log.Printf("error downloading: %v", err)
257316
return err
@@ -295,6 +354,10 @@ type ValidateOpts struct {
295354
//Validate installs the downloader to a temporary directory and returns an error if it was unsuccessful.
296355
// If cellarDir is "", it will use a temp directory
297356
func (d *Downloader) Validate(opts ValidateOpts) error {
357+
err := d.applyTemplates()
358+
if err != nil {
359+
return err
360+
}
298361
tmpDir, err := ioutil.TempDir("", "bindown")
299362
if err != nil {
300363
return err

0 commit comments

Comments
 (0)