mirror of
https://github.com/go-task/task.git
synced 2026-06-23 12:45:52 +00:00
Compare commits
259 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3084ef129c | ||
|
|
c0d112f858 | ||
|
|
2265dda84c | ||
|
|
263b094cab | ||
|
|
fbd13614a5 | ||
|
|
0494d7ebe3 | ||
|
|
9a8442c946 | ||
|
|
e1dcd0b441 | ||
|
|
a152db7054 | ||
|
|
b9e092674e | ||
|
|
4162b5f41d | ||
|
|
67ae6f210f | ||
|
|
f6c5a46626 | ||
|
|
d6f7e01c53 | ||
|
|
46463e4e24 | ||
|
|
5c420f3a34 | ||
|
|
393712ead2 | ||
|
|
84da80356d | ||
|
|
bcbb85eac3 | ||
|
|
0e1d8a72e6 | ||
|
|
bbdd698869 | ||
|
|
8f684ffa6d | ||
|
|
9be3666fe7 | ||
|
|
b7785678f4 | ||
|
|
d8005b4cf6 | ||
|
|
52028fc3bc | ||
|
|
5285ec23ae | ||
|
|
3c882e5c57 | ||
|
|
ad569a8a36 | ||
|
|
0d9fdbaac1 | ||
|
|
f5cd3eab9e | ||
|
|
8987cd64a0 | ||
|
|
fac51dcf03 | ||
|
|
01101a4c9b | ||
|
|
d561e40817 | ||
|
|
0cb298ebdf | ||
|
|
a149368725 | ||
|
|
afeefe8259 | ||
|
|
690d3c27a2 | ||
|
|
3d56ea5ce5 | ||
|
|
fdff7f80a3 | ||
|
|
fe6978b107 | ||
|
|
57db6865d2 | ||
|
|
d235d5ab28 | ||
|
|
613dfe06d3 | ||
|
|
a312d61d68 | ||
|
|
e414c1f7b0 | ||
|
|
955359b073 | ||
|
|
26e0c0887a | ||
|
|
4c295b564a | ||
|
|
2eb52da0db | ||
|
|
d8bfb3ab13 | ||
|
|
d970e93507 | ||
|
|
762714de68 | ||
|
|
82a3651a18 | ||
|
|
abe0352de9 | ||
|
|
4cee4aa5a8 | ||
|
|
9c68c7c50b | ||
|
|
0608782cfa | ||
|
|
edeaf3794a | ||
|
|
fe2b8c8afa | ||
|
|
b66bf58064 | ||
|
|
957dfa9cdf | ||
|
|
cc9264854e | ||
|
|
d1463b3e24 | ||
|
|
f1082520e1 | ||
|
|
733c563194 | ||
|
|
0200d043c3 | ||
|
|
9c475c36e7 | ||
|
|
c663c5c507 | ||
|
|
1e93c38307 | ||
|
|
81baf808c9 | ||
|
|
74537689dc | ||
|
|
12ab01d5e6 | ||
|
|
044d3a0ff9 | ||
|
|
659cae6a4c | ||
|
|
bd5882f0f0 | ||
|
|
6ff9ba9df9 | ||
|
|
b2df398a12 | ||
|
|
83d618e1eb | ||
|
|
f0768b3af1 | ||
|
|
0233ce52ed | ||
|
|
6e6f337509 | ||
|
|
1546415b8f | ||
|
|
20725c69bf | ||
|
|
90613220c6 | ||
|
|
659fd2ae93 | ||
|
|
29d899f7da | ||
|
|
902a0a01a9 | ||
|
|
8001fb3915 | ||
|
|
e81e2802f0 | ||
|
|
1ee066ec42 | ||
|
|
53d54d1c4a | ||
|
|
10082b60b8 | ||
|
|
c5b9773922 | ||
|
|
de11323d28 | ||
|
|
9f269e1a95 | ||
|
|
e4204168a0 | ||
|
|
9c350f8ef1 | ||
|
|
db19fdac29 | ||
|
|
d516b238b1 | ||
|
|
f9330f6cd9 | ||
|
|
360da29e1f | ||
|
|
9cfac1642a | ||
|
|
db90e87d10 | ||
|
|
b7564080bc | ||
|
|
1d783bf6c7 | ||
|
|
1025c2e3a1 | ||
|
|
4fd82ab222 | ||
|
|
8eadfc1bf6 | ||
|
|
f66edbad50 | ||
|
|
c7f17b5319 | ||
|
|
23c4adcef6 | ||
|
|
808542bed0 | ||
|
|
93bfd57856 | ||
|
|
7e7e1bccba | ||
|
|
34f6da86c3 | ||
|
|
15c0381c3c | ||
|
|
c2f4a57e02 | ||
|
|
f945cf2343 | ||
|
|
5bca3cfd71 | ||
|
|
26ce4e6886 | ||
|
|
f5f0e0c376 | ||
|
|
9dea1e7f3e | ||
|
|
c2e0f8c81f | ||
|
|
d341bc25ce | ||
|
|
0379e2b51b | ||
|
|
e79026b840 | ||
|
|
fc34d6b56f | ||
|
|
2a1571a99e | ||
|
|
c158608255 | ||
|
|
3ca590b185 | ||
|
|
3f8ee21849 | ||
|
|
845b88a193 | ||
|
|
e252972c7f | ||
|
|
a9012ebfc5 | ||
|
|
5cfd9bbbbd | ||
|
|
c82a7240bb | ||
|
|
a4a20d92a4 | ||
|
|
890996f595 | ||
|
|
474f27c6d3 | ||
|
|
33f3894372 | ||
|
|
24436ac76e | ||
|
|
3ee66ef705 | ||
|
|
a1765e1d33 | ||
|
|
765e3dbf72 | ||
|
|
80f5cee599 | ||
|
|
4dcb124693 | ||
|
|
31ecf167cc | ||
|
|
3999480d64 | ||
|
|
9dbb503c23 | ||
|
|
a98f803d87 | ||
|
|
9e9ffeb5d5 | ||
|
|
33d4ad4d84 | ||
|
|
d05d418c4c | ||
|
|
06d0af7a1d | ||
|
|
9a3b726068 | ||
|
|
2676ab9a59 | ||
|
|
a1837d553e | ||
|
|
fdbc130d8d | ||
|
|
4b3cea3812 | ||
|
|
1c3082ffa6 | ||
|
|
0446cfdba0 | ||
|
|
db1d3183b6 | ||
|
|
fb666394fc | ||
|
|
1054c89a9d | ||
|
|
8dd87dc482 | ||
|
|
b2edbf05a1 | ||
|
|
6fb53a406b | ||
|
|
b05fa0821d | ||
|
|
0a808b1212 | ||
|
|
f1d83e92a7 | ||
|
|
31b60f7f60 | ||
|
|
c0f9af5daa | ||
|
|
b25a9e8884 | ||
|
|
3c0cf3cd55 | ||
|
|
1ac6f17e6a | ||
|
|
399a2b38f3 | ||
|
|
b97221cdb2 | ||
|
|
0164bc21ea | ||
|
|
5a23250d32 | ||
|
|
80d88d9789 | ||
|
|
31ead854c7 | ||
|
|
4b64fcb8a4 | ||
|
|
a951f2403d | ||
|
|
f9adeba7f1 | ||
|
|
5c823d51d0 | ||
|
|
9be7521b83 | ||
|
|
c73ddc3552 | ||
|
|
4b7f058f41 | ||
|
|
07221a1b20 | ||
|
|
13614fb3c4 | ||
|
|
4fa983bde7 | ||
|
|
9cb1db8c0a | ||
|
|
5738436d55 | ||
|
|
5e49b38c33 | ||
|
|
0c94adaff9 | ||
|
|
f8a6c5d06c | ||
|
|
21e66c7c02 | ||
|
|
902f0d3ac4 | ||
|
|
713ecd35f6 | ||
|
|
27b35157cd | ||
|
|
f8fb639870 | ||
|
|
14f41ae619 | ||
|
|
a026d72924 | ||
|
|
2cb070f5b3 | ||
|
|
1dec956e99 | ||
|
|
310394aa60 | ||
|
|
468ff18243 | ||
|
|
44a63580f0 | ||
|
|
4ac1fa43aa | ||
|
|
6f992a3cf7 | ||
|
|
fd4ce656d5 | ||
|
|
9ed2dca427 | ||
|
|
dfb804fe3f | ||
|
|
4f2a84b426 | ||
|
|
14a127b6b3 | ||
|
|
06000533fb | ||
|
|
7722aba403 | ||
|
|
4817d8c67f | ||
|
|
9a062d90d1 | ||
|
|
959eb45373 | ||
|
|
a42f2af9eb | ||
|
|
4ddad68212 | ||
|
|
aac6c5a1c7 | ||
|
|
5572e31fd4 | ||
|
|
233b8bf81a | ||
|
|
2ae3810f80 | ||
|
|
736165876c | ||
|
|
61b3fca9a3 | ||
|
|
469863b7b3 | ||
|
|
5238bc55fd | ||
|
|
57a01aa6ff | ||
|
|
9361dbc39e | ||
|
|
11d257cb26 | ||
|
|
a928ab75e3 | ||
|
|
55a240c82e | ||
|
|
f8aedf438b | ||
|
|
9f1bb9a42e | ||
|
|
0ed7274610 | ||
|
|
df032b09a7 | ||
|
|
7dba742e4c | ||
|
|
83dbe78965 | ||
|
|
95b75c5330 | ||
|
|
780bd08490 | ||
|
|
a9b1f38a7c | ||
|
|
4ed4ad9852 | ||
|
|
81f172315c | ||
|
|
54666221a4 | ||
|
|
5327d702f8 | ||
|
|
a701ea3007 | ||
|
|
f0fb7d9661 | ||
|
|
3cbc89769d | ||
|
|
cb95200be3 | ||
|
|
a52f6c0acf | ||
|
|
77f9e3dd41 | ||
|
|
259d3e2df1 | ||
|
|
6eee5421b0 | ||
|
|
8004e9c943 |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
open_collective: task
|
||||||
30
.github/workflows/test.yml
vendored
Normal file
30
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
name: Test
|
||||||
|
on: [push, pull_request]
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: Test
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
go-version: [1.12.x, 1.13.x]
|
||||||
|
platform: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
|
runs-on: ${{matrix.platform}}
|
||||||
|
steps:
|
||||||
|
- name: Set up Go ${{matrix.go-version}}
|
||||||
|
uses: actions/setup-go@v1
|
||||||
|
with:
|
||||||
|
go-version: ${{matrix.go-version}}
|
||||||
|
id: go
|
||||||
|
|
||||||
|
- name: Check out code into the Go module directory
|
||||||
|
uses: actions/checkout@v1
|
||||||
|
|
||||||
|
- name: Download Go modules
|
||||||
|
run: go mod download
|
||||||
|
env:
|
||||||
|
GOPROXY: https://proxy.golang.org
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: go build -o ./bin/task -v ./cmd/task
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: ./bin/task test
|
||||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -14,6 +14,15 @@
|
|||||||
.glide/
|
.glide/
|
||||||
|
|
||||||
./task
|
./task
|
||||||
|
.task
|
||||||
dist/
|
dist/
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# intellij idea/goland
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# exuberant ctags
|
||||||
|
tags
|
||||||
|
|
||||||
|
/bin
|
||||||
|
|||||||
@@ -14,12 +14,11 @@ build:
|
|||||||
env:
|
env:
|
||||||
- CGO_ENABLED=0
|
- CGO_ENABLED=0
|
||||||
|
|
||||||
archive:
|
archives:
|
||||||
name_template: "{{.Binary}}_{{.Os}}_{{.Arch}}"
|
- name_template: "{{.Binary}}_{{.Os}}_{{.Arch}}"
|
||||||
|
format_overrides:
|
||||||
format_overrides:
|
- goos: windows
|
||||||
- goos: windows
|
format: zip
|
||||||
format: zip
|
|
||||||
|
|
||||||
release:
|
release:
|
||||||
draft: true
|
draft: true
|
||||||
@@ -30,15 +29,15 @@ snapshot:
|
|||||||
checksum:
|
checksum:
|
||||||
name_template: "task_checksums.txt"
|
name_template: "task_checksums.txt"
|
||||||
|
|
||||||
nfpm:
|
nfpms:
|
||||||
vendor: Task
|
- vendor: Task
|
||||||
homepage: https://github.com/go-task/task
|
homepage: https://github.com/go-task/task
|
||||||
maintainer: Andrey Nering <andrey.nering@gmail.com>
|
maintainer: Andrey Nering <andrey.nering@gmail.com>
|
||||||
description: Simple task runner written in Go
|
description: Simple task runner written in Go
|
||||||
license: MIT
|
license: MIT
|
||||||
conflicts:
|
conflicts:
|
||||||
- taskwarrior
|
- taskwarrior
|
||||||
formats:
|
formats:
|
||||||
- deb
|
- deb
|
||||||
- rpm
|
- rpm
|
||||||
name_template: "{{.ProjectName}}_{{.Os}}_{{.Arch}}"
|
name_template: "{{.ProjectName}}_{{.Os}}_{{.Arch}}"
|
||||||
|
|||||||
17
.travis.yml
17
.travis.yml
@@ -1,8 +1,11 @@
|
|||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.9.x
|
- 1.12.x
|
||||||
- 1.10.x
|
- 1.13.x
|
||||||
|
|
||||||
|
env:
|
||||||
|
- GO111MODULE=on
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
@@ -10,13 +13,5 @@ addons:
|
|||||||
- rpm
|
- rpm
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- go install github.com/go-task/task/cmd/task
|
- go install -v ./cmd/task
|
||||||
- task ci
|
- task ci
|
||||||
|
|
||||||
deploy:
|
|
||||||
- provider: script
|
|
||||||
skip_cleanup: true
|
|
||||||
script: curl -sL http://git.io/goreleaser | bash
|
|
||||||
on:
|
|
||||||
tags: true
|
|
||||||
condition: $TRAVIS_OS_NAME = linux
|
|
||||||
|
|||||||
216
CHANGELOG.md
Normal file
216
CHANGELOG.md
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## v2.7.1 - 2019-11-10
|
||||||
|
|
||||||
|
- Fix error being raised when `exit 0` was called
|
||||||
|
([#251](https://github.com/go-task/task/issues/251)).
|
||||||
|
|
||||||
|
## v2.7.0 - 2019-09-22
|
||||||
|
|
||||||
|
- Fixed panic bug when assigning a global variable
|
||||||
|
([#229](https://github.com/go-task/task/issues/229), [#243](https://github.com/go-task/task/issues/234)).
|
||||||
|
- A task with `method: checksum` will now re-run if generated files are deleted
|
||||||
|
([#228](https://github.com/go-task/task/pull/228), [#238](https://github.com/go-task/task/issues/238)).
|
||||||
|
|
||||||
|
## v2.6.0 - 2019-07-21
|
||||||
|
|
||||||
|
- Fixed some bugs regarding minor version checks on `version:`.
|
||||||
|
- Add `preconditions:` to task
|
||||||
|
([#205](https://github.com/go-task/task/pull/205)).
|
||||||
|
- Create directory informed on `dir:` if it doesn't exist
|
||||||
|
([#209](https://github.com/go-task/task/issues/209), [#211](https://github.com/go-task/task/pull/211)).
|
||||||
|
- We now have a `--taskfile` flag (alias `-t`), which can be used to run
|
||||||
|
another Taskfile (other than the default `Taskfile.yml`)
|
||||||
|
([#221](https://github.com/go-task/task/pull/221)).
|
||||||
|
- It's now possible to install Task using Homebrew on Linux
|
||||||
|
([go-task/homebrew-tap#1](https://github.com/go-task/homebrew-tap/pull/1)).
|
||||||
|
|
||||||
|
## v2.5.2 - 2019-05-11
|
||||||
|
|
||||||
|
- Reverted YAML upgrade due issues with CRLF on Windows
|
||||||
|
([#201](https://github.com/go-task/task/issues/201), [go-yaml/yaml#450](https://github.com/go-yaml/yaml/issues/450)).
|
||||||
|
- Allow setting global variables through the CLI
|
||||||
|
([#192](https://github.com/go-task/task/issues/192)).
|
||||||
|
|
||||||
|
## 2.5.1 - 2019-04-27
|
||||||
|
|
||||||
|
- Fixed some issues with interactive command line tools, where sometimes
|
||||||
|
the output were not being shown, and similar issues
|
||||||
|
([#114](https://github.com/go-task/task/issues/114), [#190](https://github.com/go-task/task/issues/190), [#200](https://github.com/go-task/task/pull/200)).
|
||||||
|
- Upgraded [go-yaml/yaml](https://github.com/go-yaml/yaml) from v2 to v3.
|
||||||
|
|
||||||
|
## v2.5.0 - 2019-03-16
|
||||||
|
|
||||||
|
- We moved from the taskfile.org domain to the new fancy taskfile.dev domain.
|
||||||
|
While stuff is being redirected, we strongly recommend to everyone that use
|
||||||
|
[this install script](https://taskfile.dev/#/installation?id=install-script)
|
||||||
|
to use the new taskfile.dev domain on scripts from now on.
|
||||||
|
- Fixed to the ZSH completion
|
||||||
|
([#182](https://github.com/go-task/task/pull/182)).
|
||||||
|
- Add [`--summary` flag along with `summary:` task attribute](https://taskfile.org/#/usage?id=display-summary-of-task)
|
||||||
|
([#180](https://github.com/go-task/task/pull/180)).
|
||||||
|
|
||||||
|
## v2.4.0 - 2019-02-21
|
||||||
|
|
||||||
|
- Allow calling a task of the root Taskfile from an included Taskfile
|
||||||
|
by prefixing it with `:`
|
||||||
|
([#161](https://github.com/go-task/task/issues/161), [#172](https://github.com/go-task/task/issues/172)),
|
||||||
|
- Add flag to override the `output` option
|
||||||
|
([#173](https://github.com/go-task/task/pull/173));
|
||||||
|
- Fix bug where Task was persisting the new checksum on the disk when the Dry
|
||||||
|
Mode is enabled
|
||||||
|
([#166](https://github.com/go-task/task/issues/166));
|
||||||
|
- Fix file timestamp issue when the file name has spaces
|
||||||
|
([#176](https://github.com/go-task/task/issues/176));
|
||||||
|
- Mitigating path expanding issues on Windows
|
||||||
|
([#170](https://github.com/go-task/task/pull/170)).
|
||||||
|
|
||||||
|
## v2.3.0 - 2019-01-02
|
||||||
|
|
||||||
|
- On Windows, Task can now be installed using [Scoop](https://scoop.sh/)
|
||||||
|
([#152](https://github.com/go-task/task/pull/152));
|
||||||
|
- Fixed issue with file/directory globing
|
||||||
|
([#153](https://github.com/go-task/task/issues/153));
|
||||||
|
- Added ability to globally set environment variables
|
||||||
|
(
|
||||||
|
[#138](https://github.com/go-task/task/pull/138),
|
||||||
|
[#159](https://github.com/go-task/task/pull/159)
|
||||||
|
).
|
||||||
|
|
||||||
|
## v2.2.1 - 2018-12-09
|
||||||
|
|
||||||
|
- This repository now uses Go Modules (#143). We'll still keep the `vendor` directory in sync for some time, though;
|
||||||
|
- Fixing a bug when the Taskfile has no tasks but includes another Taskfile (#150);
|
||||||
|
- Fix a bug when calling another task or a dependency in an included Taskfile (#151).
|
||||||
|
|
||||||
|
## v2.2.0 - 2018-10-25
|
||||||
|
|
||||||
|
- Added support for [including other Taskfiles](https://taskfile.org/#/usage?id=including-other-taskfiles) (#98)
|
||||||
|
- This should be considered experimental. For now, only including local files is supported, but support for including remote Taskfiles is being discussed. If you have any feedback, please comment on #98.
|
||||||
|
- Task now have a dedicated documentation site: https://taskfile.org
|
||||||
|
- Thanks to [Docsify](https://docsify.js.org/) for making this pretty easy. To check the source code, just take a look at the [docs](https://github.com/go-task/task/tree/master/docs) directory of this repository. Contributions to the documentation is really appreciated.
|
||||||
|
|
||||||
|
## v2.1.1 - 2018-09-17
|
||||||
|
|
||||||
|
- Fix suggestion to use `task --init` not being shown anymore (when a `Taskfile.yml` is not found)
|
||||||
|
- Fix error when using checksum method and no file exists for a source glob (#131)
|
||||||
|
- Fix signal handling when the `--watch` flag is given (#132)
|
||||||
|
|
||||||
|
## v2.1.0 - 2018-08-19
|
||||||
|
|
||||||
|
- Add a `ignore_error` option to task and command (#123)
|
||||||
|
- Add a dry run mode (`--dry` flag) (#126)
|
||||||
|
|
||||||
|
## v2.0.3 - 2018-06-24
|
||||||
|
|
||||||
|
- Expand environment variables on "dir", "sources" and "generates" (#116)
|
||||||
|
- Fix YAML merging syntax (#112)
|
||||||
|
- Add ZSH completion (#111)
|
||||||
|
- Implement new `output` option. Please check out the [documentation](https://github.com/go-task/task#output-syntax)
|
||||||
|
|
||||||
|
## v2.0.2 - 2018-05-01
|
||||||
|
|
||||||
|
- Fix merging of YAML anchors (#112)
|
||||||
|
|
||||||
|
## v2.0.1 - 2018-03-11
|
||||||
|
|
||||||
|
- Fixes panic on `task --list`
|
||||||
|
|
||||||
|
## v2.0.0 - 2018-03-08
|
||||||
|
|
||||||
|
Version 2.0.0 is here, with a new Taskfile format.
|
||||||
|
|
||||||
|
Please, make sure to read the [Taskfile versions](https://github.com/go-task/task/blob/master/TASKFILE_VERSIONS.md) document, since it describes in depth what changed for this version.
|
||||||
|
|
||||||
|
* New Taskfile version 2 (https://github.com/go-task/task/issues/77)
|
||||||
|
* Possibility to have global variables in the `Taskfile.yml` instead of `Taskvars.yml` (https://github.com/go-task/task/issues/66)
|
||||||
|
* Small improvements and fixes
|
||||||
|
|
||||||
|
## v1.4.4 - 2017-11-19
|
||||||
|
|
||||||
|
- Handle SIGINT and SIGTERM (#75);
|
||||||
|
- List: print message with there's no task with description;
|
||||||
|
- Expand home dir ("~" symbol) on paths (#74);
|
||||||
|
- Add Snap as an installation method;
|
||||||
|
- Move examples to its own repo;
|
||||||
|
- Watch: also walk on tasks called on on "cmds", and not only on "deps";
|
||||||
|
- Print logs to stderr instead of stdout (#68);
|
||||||
|
- Remove deprecated `set` keyword;
|
||||||
|
- Add checksum based status check, alternative to timestamp based.
|
||||||
|
|
||||||
|
## v1.4.3 - 2017-09-07
|
||||||
|
|
||||||
|
- Allow assigning variables to tasks at run time via CLI (#33)
|
||||||
|
- Added suport for multiline variables from sh (#64)
|
||||||
|
- Fixes env: remove square braces and evaluate shell (#62)
|
||||||
|
- Watch: change watch library and few fixes and improvements
|
||||||
|
- When use watching, cancel and restart long running process on file change (#59 and #60)
|
||||||
|
|
||||||
|
## v1.4.2 - 2017-07-30
|
||||||
|
|
||||||
|
- Flag to set directory of execution
|
||||||
|
- Always echo command if is verbose mode
|
||||||
|
- Add silent mode to disable echoing of commands
|
||||||
|
- Fixes and improvements of variables (#56)
|
||||||
|
|
||||||
|
## v1.4.1 - 2017-07-15
|
||||||
|
|
||||||
|
- Allow use of YAML for dynamic variables instead of $ prefix
|
||||||
|
- `VAR: {sh: echo Hello}` instead of `VAR: $echo Hello`
|
||||||
|
- Add `--list` (or `-l`) flag to print existing tasks
|
||||||
|
- OS specific Taskvars file (e.g. `Taskvars_windows.yml`, `Taskvars_linux.yml`, etc)
|
||||||
|
- Consider task up-to-date on equal timestamps (#49)
|
||||||
|
- Allow absolute path in generates section (#48)
|
||||||
|
- Bugfix: allow templating when calling deps (#42)
|
||||||
|
- Fix panic for invalid task in cyclic dep detection
|
||||||
|
- Better error output for dynamic variables in Taskvars.yml (#41)
|
||||||
|
- Allow template evaluation in parameters
|
||||||
|
|
||||||
|
## v1.4.0 - 2017-07-06
|
||||||
|
|
||||||
|
- Cache dynamic variables
|
||||||
|
- Add verbose mode (`-v` flag)
|
||||||
|
- Support to task parameters (overriding vars) (#31) (#32)
|
||||||
|
- Print command, also when "set:" is specified (#35)
|
||||||
|
- Improve task command help text (#35)
|
||||||
|
|
||||||
|
## v1.3.1 - 2017-06-14
|
||||||
|
|
||||||
|
- Fix glob not working on commands (#28)
|
||||||
|
- Add ExeExt template function
|
||||||
|
- Add `--init` flag to create a new Taskfile
|
||||||
|
- Add status option to prevent task from running (#27)
|
||||||
|
- Allow interpolation on `generates` and `sources` attributes (#26)
|
||||||
|
|
||||||
|
## v1.3.0 - 2017-04-24
|
||||||
|
|
||||||
|
- Migrate from os/exec.Cmd to a native Go sh/bash interpreter
|
||||||
|
- This is a potentially breaking change if you use Windows.
|
||||||
|
- Now, `cmd` is not used anymore on Windows. Always use Bash-like syntax for your commands, even on Windows.
|
||||||
|
- Add "ToSlash" and "FromSlash" to template functions
|
||||||
|
- Use functions defined on github.com/Masterminds/sprig
|
||||||
|
- Do not redirect stdin while running variables commands
|
||||||
|
- Using `context` and `errgroup` packages (this will make other tasks to be cancelled, if one returned an error)
|
||||||
|
|
||||||
|
## v1.2.0 - 2017-04-02
|
||||||
|
|
||||||
|
- More tests and Travis integration
|
||||||
|
- Watch a task (experimental)
|
||||||
|
- Possibility to call another task
|
||||||
|
- Fix "=" not being reconized in variables/environment variables
|
||||||
|
- Tasks can now have a description, and help will print them (#10)
|
||||||
|
- Task dependencies now run concurrently
|
||||||
|
- Support for a default task (#16)
|
||||||
|
|
||||||
|
## v1.1.0 - 2017-03-08
|
||||||
|
|
||||||
|
- Support for YAML, TOML and JSON (#1)
|
||||||
|
- Support running command in another directory (#4)
|
||||||
|
- `--force` or `-f` flag to force execution of task even when it's up-to-date
|
||||||
|
- Detection of cyclic dependencies (#5)
|
||||||
|
- Support for variables (#6, #9, #14)
|
||||||
|
- Operation System specific commands and variables (#13)
|
||||||
|
|
||||||
|
## v1.0.0 - 2017-02-28
|
||||||
|
|
||||||
|
- Add LICENSE file
|
||||||
188
Gopkg.lock
generated
188
Gopkg.lock
generated
@@ -1,188 +0,0 @@
|
|||||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
|
||||||
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
digest = "1:f3960e064201714a3507bf96183be246b3d941568af01dc5cff2a388ac4c7515"
|
|
||||||
name = "github.com/Masterminds/semver"
|
|
||||||
packages = ["."]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "c84ddcca87bf5a941b138dde832a7e20b0159ad8"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
digest = "1:58551c80f84fd3ba2954668f5f850a8179dc3c5bb4885fc7eed5a8e2ae815c99"
|
|
||||||
name = "github.com/Masterminds/sprig"
|
|
||||||
packages = ["."]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "77bb58b7f5e10889a1195c21b9e7a96ee166f199"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
digest = "1:975108e8d4f5dab096fc991326e96a5716ee8d02e5e7386bb4796171afc4ab9a"
|
|
||||||
name = "github.com/aokoli/goutils"
|
|
||||||
packages = ["."]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "3391d3790d23d03408670993e957e8f408993c34"
|
|
||||||
version = "v1.0.1"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec"
|
|
||||||
name = "github.com/davecgh/go-spew"
|
|
||||||
packages = ["spew"]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
|
|
||||||
version = "v1.1.1"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
digest = "1:a1578f7323eca2b88021fdc9a79a99833d40b12c32a5ea4f284e2fad19ea2657"
|
|
||||||
name = "github.com/google/uuid"
|
|
||||||
packages = ["."]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "d460ce9f8df2e77fb1ba55ca87fafed96c607494"
|
|
||||||
version = "v1.0.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
digest = "1:ed24122ea28f4f65f82f5b4703389fdbb5f246efc971e4d74f01f7c47c0b81b2"
|
|
||||||
name = "github.com/huandu/xstrings"
|
|
||||||
packages = ["."]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "55ae428c2ac4f74d7430952ef528631e656ac92c"
|
|
||||||
version = "v1.1.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
digest = "1:9a52adf44086cead3b384e5d0dbf7a1c1cce65e67552ee3383a8561c42a18cd3"
|
|
||||||
name = "github.com/imdario/mergo"
|
|
||||||
packages = ["."]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "9f23e2d6bd2a77f959b2bf6acdbefd708a83a4a4"
|
|
||||||
version = "v0.3.6"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
digest = "1:729c1199021f057f38487f7e64432f3539f9efac444185e64b4b7e121414ac68"
|
|
||||||
name = "github.com/mattn/go-zglob"
|
|
||||||
packages = [
|
|
||||||
".",
|
|
||||||
"fastwalk",
|
|
||||||
]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "2ea3427bfa539cca900ca2768d8663ecc8a708c1"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
digest = "1:a4df73029d2c42fabcb6b41e327d2f87e685284ec03edf76921c267d9cfc9c23"
|
|
||||||
name = "github.com/mitchellh/go-homedir"
|
|
||||||
packages = ["."]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "ae18d6b8b3205b561c79e8e5f69bff09736185f4"
|
|
||||||
version = "v1.0.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe"
|
|
||||||
name = "github.com/pmezard/go-difflib"
|
|
||||||
packages = ["difflib"]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
|
|
||||||
version = "v1.0.0"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
digest = "1:5089085e1b27a57be4fb7acf32bfa71fb6236dc0e8371165651c9e15285a9ce0"
|
|
||||||
name = "github.com/radovskyb/watcher"
|
|
||||||
packages = ["."]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "0d9d32686dbf6395752c9b209398a59e302a7f1e"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
digest = "1:9d8420bbf131d1618bde6530af37c3799340d3762cc47210c1d9532a4c3a2779"
|
|
||||||
name = "github.com/spf13/pflag"
|
|
||||||
packages = ["."]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "298182f68c66c05229eb03ac171abe6e309ee79a"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
digest = "1:bacb8b590716ab7c33f2277240972c9582d389593ee8d66fc10074e0508b8126"
|
|
||||||
name = "github.com/stretchr/testify"
|
|
||||||
packages = ["assert"]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686"
|
|
||||||
version = "v1.2.2"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
digest = "1:69b3fcb7a41b18436a85471cbdcfc70ad10ba3206f8c87563e1c773610e1bcad"
|
|
||||||
name = "golang.org/x/crypto"
|
|
||||||
packages = [
|
|
||||||
"pbkdf2",
|
|
||||||
"scrypt",
|
|
||||||
"ssh/terminal",
|
|
||||||
]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "182538f80094b6a8efaade63a8fd8e0d9d5843dd"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
digest = "1:76ee51c3f468493aff39dbacc401e8831fbb765104cbf613b89bef01cf4bad70"
|
|
||||||
name = "golang.org/x/net"
|
|
||||||
packages = ["context"]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "8a410e7b638dca158bf9e766925842f6651ff828"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
digest = "1:39ebcc2b11457b703ae9ee2e8cca0f68df21969c6102cb3b705f76cca0ea0239"
|
|
||||||
name = "golang.org/x/sync"
|
|
||||||
packages = ["errgroup"]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
digest = "1:8270f14d85e8d36e852e018872ac923f7a2067648bfe8428d01be288818aa337"
|
|
||||||
name = "golang.org/x/sys"
|
|
||||||
packages = [
|
|
||||||
"unix",
|
|
||||||
"windows",
|
|
||||||
]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "fa5fdf94c78965f1aa8423f0cc50b8b8d728b05a"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "v2"
|
|
||||||
digest = "1:7c95b35057a0ff2e19f707173cc1a947fa43a6eb5c4d300d196ece0334046082"
|
|
||||||
name = "gopkg.in/yaml.v2"
|
|
||||||
packages = ["."]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
|
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
branch = "master"
|
|
||||||
digest = "1:e647f1f4fcc94a6baad3965a347c1ac4ed669f31c87c826516314e415d1a4ad2"
|
|
||||||
name = "mvdan.cc/sh"
|
|
||||||
packages = [
|
|
||||||
"interp",
|
|
||||||
"shell",
|
|
||||||
"syntax",
|
|
||||||
]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "3a244a89e2e520d2777e94693d51bef800761879"
|
|
||||||
|
|
||||||
[solve-meta]
|
|
||||||
analyzer-name = "dep"
|
|
||||||
analyzer-version = 1
|
|
||||||
input-imports = [
|
|
||||||
"github.com/Masterminds/semver",
|
|
||||||
"github.com/Masterminds/sprig",
|
|
||||||
"github.com/mattn/go-zglob",
|
|
||||||
"github.com/mitchellh/go-homedir",
|
|
||||||
"github.com/radovskyb/watcher",
|
|
||||||
"github.com/spf13/pflag",
|
|
||||||
"github.com/stretchr/testify/assert",
|
|
||||||
"golang.org/x/sync/errgroup",
|
|
||||||
"gopkg.in/yaml.v2",
|
|
||||||
"mvdan.cc/sh/interp",
|
|
||||||
"mvdan.cc/sh/shell",
|
|
||||||
"mvdan.cc/sh/syntax",
|
|
||||||
]
|
|
||||||
solver-name = "gps-cdcl"
|
|
||||||
solver-version = 1
|
|
||||||
36
Gopkg.toml
36
Gopkg.toml
@@ -1,36 +0,0 @@
|
|||||||
[prune]
|
|
||||||
unused-packages = true
|
|
||||||
non-go = true
|
|
||||||
go-tests = true
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/Masterminds/sprig"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/mattn/go-zglob"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "mvdan.cc/sh"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/spf13/pflag"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "golang.org/x/sync"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "v2"
|
|
||||||
name = "gopkg.in/yaml.v2"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/radovskyb/watcher"
|
|
||||||
|
|
||||||
[[constraint]]
|
|
||||||
branch = "master"
|
|
||||||
name = "github.com/Masterminds/semver"
|
|
||||||
16
README.md
16
README.md
@@ -3,10 +3,20 @@
|
|||||||
# Task
|
# Task
|
||||||
|
|
||||||
Task is a task runner / build tool that aims to be simpler and easier to use
|
Task is a task runner / build tool that aims to be simpler and easier to use
|
||||||
than, for example, [GNU Make][make].
|
than, for example, [GNU Make](https://www.gnu.org/software/make/).
|
||||||
|
|
||||||
|
See [taskfile.dev](https://taskfile.dev) for documentation.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
See [taskfile.org](https://taskfile.org) for documentation.
|
## Sponsors
|
||||||
|
|
||||||
[make]: https://www.gnu.org/software/make/
|
[](https://opencollective.com/task)
|
||||||
|
|
||||||
|
## Backers
|
||||||
|
|
||||||
|
[](https://opencollective.com/task)
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
[](https://github.com/go-task/task/graphs/contributors)
|
||||||
|
|||||||
20
Taskfile.yml
20
Taskfile.yml
@@ -1,5 +1,8 @@
|
|||||||
version: '2'
|
version: '2'
|
||||||
|
|
||||||
|
includes:
|
||||||
|
docs: ./docs
|
||||||
|
|
||||||
vars:
|
vars:
|
||||||
GIT_COMMIT:
|
GIT_COMMIT:
|
||||||
sh: git log -n 1 --format=%h
|
sh: git log -n 1 --format=%h
|
||||||
@@ -24,13 +27,16 @@ tasks:
|
|||||||
cmds:
|
cmds:
|
||||||
- task: go-get
|
- task: go-get
|
||||||
vars: {REPO: golang.org/x/lint/golint}
|
vars: {REPO: golang.org/x/lint/golint}
|
||||||
- task: go-get
|
|
||||||
vars: {REPO: github.com/golang/dep/cmd/dep}
|
|
||||||
- task: go-get
|
- task: go-get
|
||||||
vars: {REPO: github.com/goreleaser/goreleaser}
|
vars: {REPO: github.com/goreleaser/goreleaser}
|
||||||
- task: go-get
|
- task: go-get
|
||||||
vars: {REPO: github.com/goreleaser/godownloader}
|
vars: {REPO: github.com/goreleaser/godownloader}
|
||||||
|
|
||||||
|
vendor:
|
||||||
|
desc: Sync vendor/ directory according to go.mod file
|
||||||
|
cmds:
|
||||||
|
- go mod vendor
|
||||||
|
|
||||||
update-deps:
|
update-deps:
|
||||||
desc: Updates dependencies
|
desc: Updates dependencies
|
||||||
cmds:
|
cmds:
|
||||||
@@ -80,13 +86,3 @@ tasks:
|
|||||||
cmds:
|
cmds:
|
||||||
- echo '{{.GO_PACKAGES}}'
|
- echo '{{.GO_PACKAGES}}'
|
||||||
silent: true
|
silent: true
|
||||||
|
|
||||||
docs:install:
|
|
||||||
desc: Installs docsify to work the on the documentation site
|
|
||||||
cmds:
|
|
||||||
- npm install docsify-cli -g
|
|
||||||
|
|
||||||
docs:serve:
|
|
||||||
desc: Serves the documentation site locally
|
|
||||||
cmds:
|
|
||||||
- docsify serve docs
|
|
||||||
|
|||||||
421
cmd/redirector/redirector.go
Normal file
421
cmd/redirector/redirector.go
Normal file
@@ -0,0 +1,421 @@
|
|||||||
|
// This small web app is used to redirect from the old taskfile.org domain
|
||||||
|
// to the new taskfile.dev without breaking CIs that uses cURL to download
|
||||||
|
// "/install.sh" without the -L flag (which follow redirects).
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.URL.Path == "/install.sh" {
|
||||||
|
println("Dumping install.sh")
|
||||||
|
|
||||||
|
w.Write(installShContent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
println("Redirecting to https://taskfile.dev" + r.URL.Path)
|
||||||
|
|
||||||
|
w.Header().Set("Location", "https://taskfile.dev"+r.URL.Path)
|
||||||
|
w.WriteHeader(301)
|
||||||
|
})
|
||||||
|
|
||||||
|
println("Listening :8080")
|
||||||
|
|
||||||
|
panic(http.ListenAndServe(":8080", nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
var installShContent = []byte(`#!/bin/sh
|
||||||
|
set -e
|
||||||
|
# Code generated by godownloader on 2018-04-07T17:47:38Z. DO NOT EDIT.
|
||||||
|
#
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
this=$1
|
||||||
|
cat <<EOF
|
||||||
|
$this: download go binaries for go-task/task
|
||||||
|
|
||||||
|
Usage: $this [-b] bindir [-d] [tag]
|
||||||
|
-b sets bindir or installation directory, Defaults to ./bin
|
||||||
|
-d turns on debug logging
|
||||||
|
[tag] is a tag from
|
||||||
|
https://github.com/go-task/task/releases
|
||||||
|
If tag is missing, then the latest will be used.
|
||||||
|
|
||||||
|
Generated by godownloader
|
||||||
|
https://github.com/goreleaser/godownloader
|
||||||
|
|
||||||
|
EOF
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_args() {
|
||||||
|
#BINDIR is ./bin unless set be ENV
|
||||||
|
# over-ridden by flag below
|
||||||
|
|
||||||
|
BINDIR=${BINDIR:-./bin}
|
||||||
|
while getopts "b:dh?" arg; do
|
||||||
|
case "$arg" in
|
||||||
|
b) BINDIR="$OPTARG" ;;
|
||||||
|
d) log_set_priority 10 ;;
|
||||||
|
h | \?) usage "$0" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
shift $((OPTIND - 1))
|
||||||
|
TAG=$1
|
||||||
|
}
|
||||||
|
# this function wraps all the destructive operations
|
||||||
|
# if a curl|bash cuts off the end of the script due to
|
||||||
|
# network, either nothing will happen or will syntax error
|
||||||
|
# out preventing half-done work
|
||||||
|
execute() {
|
||||||
|
tmpdir=$(mktmpdir)
|
||||||
|
log_debug "downloading files into ${tmpdir}"
|
||||||
|
http_download "${tmpdir}/${TARBALL}" "${TARBALL_URL}"
|
||||||
|
http_download "${tmpdir}/${CHECKSUM}" "${CHECKSUM_URL}"
|
||||||
|
hash_sha256_verify "${tmpdir}/${TARBALL}" "${tmpdir}/${CHECKSUM}"
|
||||||
|
srcdir="${tmpdir}"
|
||||||
|
(cd "${tmpdir}" && untar "${TARBALL}")
|
||||||
|
install -d "${BINDIR}"
|
||||||
|
for binexe in "task" ; do
|
||||||
|
if [ "$OS" = "windows" ]; then
|
||||||
|
binexe="${binexe}.exe"
|
||||||
|
fi
|
||||||
|
install "${srcdir}/${binexe}" "${BINDIR}/"
|
||||||
|
log_info "installed ${BINDIR}/${binexe}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
is_supported_platform() {
|
||||||
|
platform=$1
|
||||||
|
found=1
|
||||||
|
case "$platform" in
|
||||||
|
windows/386) found=0 ;;
|
||||||
|
windows/amd64) found=0 ;;
|
||||||
|
darwin/386) found=0 ;;
|
||||||
|
darwin/amd64) found=0 ;;
|
||||||
|
linux/386) found=0 ;;
|
||||||
|
linux/amd64) found=0 ;;
|
||||||
|
esac
|
||||||
|
case "$platform" in
|
||||||
|
darwin/386) found=1 ;;
|
||||||
|
esac
|
||||||
|
return $found
|
||||||
|
}
|
||||||
|
check_platform() {
|
||||||
|
if is_supported_platform "$PLATFORM"; then
|
||||||
|
# optional logging goes here
|
||||||
|
true
|
||||||
|
else
|
||||||
|
log_crit "platform $PLATFORM is not supported. Make sure this script is up-to-date and file request at https://github.com/${PREFIX}/issues/new"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
tag_to_version() {
|
||||||
|
if [ -z "${TAG}" ]; then
|
||||||
|
log_info "checking GitHub for latest tag"
|
||||||
|
else
|
||||||
|
log_info "checking GitHub for tag '${TAG}'"
|
||||||
|
fi
|
||||||
|
REALTAG=$(github_release "$OWNER/$REPO" "${TAG}") && true
|
||||||
|
if test -z "$REALTAG"; then
|
||||||
|
log_crit "unable to find '${TAG}' - use 'latest' or see https://github.com/${PREFIX}/releases for details"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# if version starts with 'v', remove it
|
||||||
|
TAG="$REALTAG"
|
||||||
|
VERSION=${TAG#v}
|
||||||
|
}
|
||||||
|
adjust_format() {
|
||||||
|
# change format (tar.gz or zip) based on ARCH
|
||||||
|
case ${ARCH} in
|
||||||
|
windows) FORMAT=zip ;;
|
||||||
|
esac
|
||||||
|
true
|
||||||
|
}
|
||||||
|
adjust_os() {
|
||||||
|
# adjust archive name based on OS
|
||||||
|
true
|
||||||
|
}
|
||||||
|
adjust_arch() {
|
||||||
|
# adjust archive name based on ARCH
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
cat /dev/null <<EOF
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
https://github.com/client9/shlib - portable posix shell functions
|
||||||
|
Public domain - http://unlicense.org
|
||||||
|
https://github.com/client9/shlib/blob/master/LICENSE.md
|
||||||
|
but credit (and pull requests) appreciated.
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
EOF
|
||||||
|
is_command() {
|
||||||
|
command -v "$1" >/dev/null
|
||||||
|
}
|
||||||
|
echoerr() {
|
||||||
|
echo "$@" 1>&2
|
||||||
|
}
|
||||||
|
log_prefix() {
|
||||||
|
echo "$0"
|
||||||
|
}
|
||||||
|
_logp=6
|
||||||
|
log_set_priority() {
|
||||||
|
_logp="$1"
|
||||||
|
}
|
||||||
|
log_priority() {
|
||||||
|
if test -z "$1"; then
|
||||||
|
echo "$_logp"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
[ "$1" -le "$_logp" ]
|
||||||
|
}
|
||||||
|
log_tag() {
|
||||||
|
case $1 in
|
||||||
|
0) echo "emerg" ;;
|
||||||
|
1) echo "alert" ;;
|
||||||
|
2) echo "crit" ;;
|
||||||
|
3) echo "err" ;;
|
||||||
|
4) echo "warning" ;;
|
||||||
|
5) echo "notice" ;;
|
||||||
|
6) echo "info" ;;
|
||||||
|
7) echo "debug" ;;
|
||||||
|
*) echo "$1" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
log_debug() {
|
||||||
|
log_priority 7 || return 0
|
||||||
|
echoerr "$(log_prefix)" "$(log_tag 7)" "$@"
|
||||||
|
}
|
||||||
|
log_info() {
|
||||||
|
log_priority 6 || return 0
|
||||||
|
echoerr "$(log_prefix)" "$(log_tag 6)" "$@"
|
||||||
|
}
|
||||||
|
log_err() {
|
||||||
|
log_priority 3 || return 0
|
||||||
|
echoerr "$(log_prefix)" "$(log_tag 3)" "$@"
|
||||||
|
}
|
||||||
|
log_crit() {
|
||||||
|
log_priority 2 || return 0
|
||||||
|
echoerr "$(log_prefix)" "$(log_tag 2)" "$@"
|
||||||
|
}
|
||||||
|
uname_os() {
|
||||||
|
os=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||||
|
case "$os" in
|
||||||
|
msys_nt) os="windows" ;;
|
||||||
|
esac
|
||||||
|
echo "$os"
|
||||||
|
}
|
||||||
|
uname_arch() {
|
||||||
|
arch=$(uname -m)
|
||||||
|
case $arch in
|
||||||
|
x86_64) arch="amd64" ;;
|
||||||
|
x86) arch="386" ;;
|
||||||
|
i686) arch="386" ;;
|
||||||
|
i386) arch="386" ;;
|
||||||
|
aarch64) arch="arm64" ;;
|
||||||
|
armv5*) arch="arm5" ;;
|
||||||
|
armv6*) arch="arm6" ;;
|
||||||
|
armv7*) arch="arm7" ;;
|
||||||
|
esac
|
||||||
|
echo ${arch}
|
||||||
|
}
|
||||||
|
uname_os_check() {
|
||||||
|
os=$(uname_os)
|
||||||
|
case "$os" in
|
||||||
|
darwin) return 0 ;;
|
||||||
|
dragonfly) return 0 ;;
|
||||||
|
freebsd) return 0 ;;
|
||||||
|
linux) return 0 ;;
|
||||||
|
android) return 0 ;;
|
||||||
|
nacl) return 0 ;;
|
||||||
|
netbsd) return 0 ;;
|
||||||
|
openbsd) return 0 ;;
|
||||||
|
plan9) return 0 ;;
|
||||||
|
solaris) return 0 ;;
|
||||||
|
windows) return 0 ;;
|
||||||
|
esac
|
||||||
|
log_crit "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
uname_arch_check() {
|
||||||
|
arch=$(uname_arch)
|
||||||
|
case "$arch" in
|
||||||
|
386) return 0 ;;
|
||||||
|
amd64) return 0 ;;
|
||||||
|
arm64) return 0 ;;
|
||||||
|
armv5) return 0 ;;
|
||||||
|
armv6) return 0 ;;
|
||||||
|
armv7) return 0 ;;
|
||||||
|
ppc64) return 0 ;;
|
||||||
|
ppc64le) return 0 ;;
|
||||||
|
mips) return 0 ;;
|
||||||
|
mipsle) return 0 ;;
|
||||||
|
mips64) return 0 ;;
|
||||||
|
mips64le) return 0 ;;
|
||||||
|
s390x) return 0 ;;
|
||||||
|
amd64p32) return 0 ;;
|
||||||
|
esac
|
||||||
|
log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value. Please file bug report at https://github.com/client9/shlib"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
untar() {
|
||||||
|
tarball=$1
|
||||||
|
case "${tarball}" in
|
||||||
|
*.tar.gz | *.tgz) tar -xzf "${tarball}" ;;
|
||||||
|
*.tar) tar -xf "${tarball}" ;;
|
||||||
|
*.zip) unzip "${tarball}" ;;
|
||||||
|
*)
|
||||||
|
log_err "untar unknown archive format for ${tarball}"
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
mktmpdir() {
|
||||||
|
test -z "$TMPDIR" && TMPDIR="$(mktemp -d)"
|
||||||
|
mkdir -p "${TMPDIR}"
|
||||||
|
echo "${TMPDIR}"
|
||||||
|
}
|
||||||
|
http_download_curl() {
|
||||||
|
local_file=$1
|
||||||
|
source_url=$2
|
||||||
|
header=$3
|
||||||
|
if [ -z "$header" ]; then
|
||||||
|
code=$(curl -w '%{http_code}' -sL -o "$local_file" "$source_url")
|
||||||
|
else
|
||||||
|
code=$(curl -w '%{http_code}' -sL -H "$header" -o "$local_file" "$source_url")
|
||||||
|
fi
|
||||||
|
if [ "$code" != "200" ]; then
|
||||||
|
log_debug "http_download_curl received HTTP status $code"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
http_download_wget() {
|
||||||
|
local_file=$1
|
||||||
|
source_url=$2
|
||||||
|
header=$3
|
||||||
|
if [ -z "$header" ]; then
|
||||||
|
wget -q -O "$local_file" "$source_url"
|
||||||
|
else
|
||||||
|
wget -q --header "$header" -O "$local_file" "$source_url"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
http_download() {
|
||||||
|
log_debug "http_download $2"
|
||||||
|
if is_command curl; then
|
||||||
|
http_download_curl "$@"
|
||||||
|
return
|
||||||
|
elif is_command wget; then
|
||||||
|
http_download_wget "$@"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
log_crit "http_download unable to find wget or curl"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
http_copy() {
|
||||||
|
tmp=$(mktemp)
|
||||||
|
http_download "${tmp}" "$1" "$2" || return 1
|
||||||
|
body=$(cat "$tmp")
|
||||||
|
rm -f "${tmp}"
|
||||||
|
echo "$body"
|
||||||
|
}
|
||||||
|
github_release() {
|
||||||
|
owner_repo=$1
|
||||||
|
version=$2
|
||||||
|
test -z "$version" && version="latest"
|
||||||
|
giturl="https://github.com/${owner_repo}/releases/${version}"
|
||||||
|
json=$(http_copy "$giturl" "Accept:application/json")
|
||||||
|
test -z "$json" && return 1
|
||||||
|
version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//')
|
||||||
|
test -z "$version" && return 1
|
||||||
|
echo "$version"
|
||||||
|
}
|
||||||
|
hash_sha256() {
|
||||||
|
TARGET=${1:-/dev/stdin}
|
||||||
|
if is_command gsha256sum; then
|
||||||
|
hash=$(gsha256sum "$TARGET") || return 1
|
||||||
|
echo "$hash" | cut -d ' ' -f 1
|
||||||
|
elif is_command sha256sum; then
|
||||||
|
hash=$(sha256sum "$TARGET") || return 1
|
||||||
|
echo "$hash" | cut -d ' ' -f 1
|
||||||
|
elif is_command shasum; then
|
||||||
|
hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1
|
||||||
|
echo "$hash" | cut -d ' ' -f 1
|
||||||
|
elif is_command openssl; then
|
||||||
|
hash=$(openssl -dst openssl dgst -sha256 "$TARGET") || return 1
|
||||||
|
echo "$hash" | cut -d ' ' -f a
|
||||||
|
else
|
||||||
|
log_crit "hash_sha256 unable to find command to compute sha-256 hash"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
hash_sha256_verify() {
|
||||||
|
TARGET=$1
|
||||||
|
checksums=$2
|
||||||
|
if [ -z "$checksums" ]; then
|
||||||
|
log_err "hash_sha256_verify checksum file not specified in arg2"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
BASENAME=${TARGET##*/}
|
||||||
|
want=$(grep "${BASENAME}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1)
|
||||||
|
if [ -z "$want" ]; then
|
||||||
|
log_err "hash_sha256_verify unable to find checksum for '${TARGET}' in '${checksums}'"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
got=$(hash_sha256 "$TARGET")
|
||||||
|
if [ "$want" != "$got" ]; then
|
||||||
|
log_err "hash_sha256_verify checksum for '$TARGET' did not verify ${want} vs $got"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
cat /dev/null <<EOF
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
End of functions from https://github.com/client9/shlib
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
EOF
|
||||||
|
|
||||||
|
PROJECT_NAME="task"
|
||||||
|
OWNER=go-task
|
||||||
|
REPO="task"
|
||||||
|
BINARY=task
|
||||||
|
FORMAT=tar.gz
|
||||||
|
OS=$(uname_os)
|
||||||
|
ARCH=$(uname_arch)
|
||||||
|
PREFIX="$OWNER/$REPO"
|
||||||
|
|
||||||
|
# use in logging routines
|
||||||
|
log_prefix() {
|
||||||
|
echo "$PREFIX"
|
||||||
|
}
|
||||||
|
PLATFORM="${OS}/${ARCH}"
|
||||||
|
GITHUB_DOWNLOAD=https://github.com/${OWNER}/${REPO}/releases/download
|
||||||
|
|
||||||
|
uname_os_check "$OS"
|
||||||
|
uname_arch_check "$ARCH"
|
||||||
|
|
||||||
|
parse_args "$@"
|
||||||
|
|
||||||
|
check_platform
|
||||||
|
|
||||||
|
tag_to_version
|
||||||
|
|
||||||
|
adjust_format
|
||||||
|
|
||||||
|
adjust_os
|
||||||
|
|
||||||
|
adjust_arch
|
||||||
|
|
||||||
|
log_info "found version: ${VERSION} for ${TAG}/${OS}/${ARCH}"
|
||||||
|
|
||||||
|
NAME=${BINARY}_${OS}_${ARCH}
|
||||||
|
TARBALL=${NAME}.${FORMAT}
|
||||||
|
TARBALL_URL=${GITHUB_DOWNLOAD}/${TAG}/${TARBALL}
|
||||||
|
CHECKSUM=task_checksums.txt
|
||||||
|
CHECKSUM_URL=${GITHUB_DOWNLOAD}/${TAG}/${CHECKSUM}
|
||||||
|
|
||||||
|
|
||||||
|
execute
|
||||||
|
`)
|
||||||
@@ -5,10 +5,11 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/go-task/task"
|
"github.com/go-task/task/v2"
|
||||||
"github.com/go-task/task/internal/args"
|
"github.com/go-task/task/v2/internal/args"
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
@@ -17,7 +18,7 @@ var (
|
|||||||
version = "master"
|
version = "master"
|
||||||
)
|
)
|
||||||
|
|
||||||
const usage = `Usage: task [-ilfwvsd] [--init] [--list] [--force] [--watch] [--verbose] [--silent] [--dir] [--dry] [task...]
|
const usage = `Usage: task [-ilfwvsd] [--init] [--list] [--force] [--watch] [--verbose] [--silent] [--dir] [--taskfile] [--dry] [--summary] [task...]
|
||||||
|
|
||||||
Runs the specified task(s). Falls back to the "default" task if no task name
|
Runs the specified task(s). Falls back to the "default" task if no task name
|
||||||
was specified, or lists all tasks if an unknown task name was specified.
|
was specified, or lists all tasks if an unknown task name was specified.
|
||||||
@@ -56,7 +57,10 @@ func main() {
|
|||||||
verbose bool
|
verbose bool
|
||||||
silent bool
|
silent bool
|
||||||
dry bool
|
dry bool
|
||||||
|
summary bool
|
||||||
dir string
|
dir string
|
||||||
|
entrypoint string
|
||||||
|
output string
|
||||||
)
|
)
|
||||||
|
|
||||||
pflag.BoolVar(&versionFlag, "version", false, "show Task version")
|
pflag.BoolVar(&versionFlag, "version", false, "show Task version")
|
||||||
@@ -68,7 +72,10 @@ func main() {
|
|||||||
pflag.BoolVarP(&verbose, "verbose", "v", false, "enables verbose mode")
|
pflag.BoolVarP(&verbose, "verbose", "v", false, "enables verbose mode")
|
||||||
pflag.BoolVarP(&silent, "silent", "s", false, "disables echoing")
|
pflag.BoolVarP(&silent, "silent", "s", false, "disables echoing")
|
||||||
pflag.BoolVar(&dry, "dry", false, "compiles and prints tasks in the order that they would be run, without executing them")
|
pflag.BoolVar(&dry, "dry", false, "compiles and prints tasks in the order that they would be run, without executing them")
|
||||||
|
pflag.BoolVar(&summary, "summary", false, "show summary about a task")
|
||||||
pflag.StringVarP(&dir, "dir", "d", "", "sets directory of execution")
|
pflag.StringVarP(&dir, "dir", "d", "", "sets directory of execution")
|
||||||
|
pflag.StringVarP(&entrypoint, "taskfile", "t", "", `choose which Taskfile to run. Defaults to "Taskfile.yml"`)
|
||||||
|
pflag.StringVarP(&output, "output", "o", "", "sets output style: [interleaved|group|prefixed]")
|
||||||
pflag.Parse()
|
pflag.Parse()
|
||||||
|
|
||||||
if versionFlag {
|
if versionFlag {
|
||||||
@@ -87,24 +94,32 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
if dir != "" && entrypoint != "" {
|
||||||
if !watch {
|
log.Fatal("task: You can't set both --dir and --taskfile")
|
||||||
ctx = getSignalContext()
|
return
|
||||||
|
}
|
||||||
|
if entrypoint != "" {
|
||||||
|
dir = filepath.Dir(entrypoint)
|
||||||
|
entrypoint = filepath.Base(entrypoint)
|
||||||
|
} else {
|
||||||
|
entrypoint = "Taskfile.yml"
|
||||||
}
|
}
|
||||||
|
|
||||||
e := task.Executor{
|
e := task.Executor{
|
||||||
Force: force,
|
Force: force,
|
||||||
Watch: watch,
|
Watch: watch,
|
||||||
Verbose: verbose,
|
Verbose: verbose,
|
||||||
Silent: silent,
|
Silent: silent,
|
||||||
Dir: dir,
|
Dir: dir,
|
||||||
Dry: dry,
|
Dry: dry,
|
||||||
|
Entrypoint: entrypoint,
|
||||||
Context: ctx,
|
Summary: summary,
|
||||||
|
|
||||||
Stdin: os.Stdin,
|
Stdin: os.Stdin,
|
||||||
Stdout: os.Stdout,
|
Stdout: os.Stdout,
|
||||||
Stderr: os.Stderr,
|
Stderr: os.Stderr,
|
||||||
|
|
||||||
|
OutputStyle: output,
|
||||||
}
|
}
|
||||||
if err := e.Setup(); err != nil {
|
if err := e.Setup(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
@@ -121,19 +136,24 @@ func main() {
|
|||||||
arguments = []string{"default"}
|
arguments = []string{"default"}
|
||||||
}
|
}
|
||||||
|
|
||||||
calls, err := args.Parse(arguments...)
|
calls, globals := args.Parse(arguments...)
|
||||||
if err != nil {
|
for name, value := range globals {
|
||||||
log.Fatal(err)
|
e.Taskfile.Vars[name] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
if !watch {
|
||||||
|
ctx = getSignalContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
if status {
|
if status {
|
||||||
if err = e.Status(calls...); err != nil {
|
if err := e.Status(ctx, calls...); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := e.Run(calls...); err != nil {
|
if err := e.Run(ctx, calls...); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
completion/bash/task.bash
Normal file
21
completion/bash/task.bash
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
_task_completion()
|
||||||
|
{
|
||||||
|
local scripts;
|
||||||
|
local curr_arg;
|
||||||
|
|
||||||
|
# Remove colon from word breaks
|
||||||
|
COMP_WORDBREAKS=${COMP_WORDBREAKS//:}
|
||||||
|
|
||||||
|
scripts=$(task -l | sed '1d' | sed 's/^\* //' | awk '{ print $1 }');
|
||||||
|
|
||||||
|
curr_arg="${COMP_WORDS[COMP_CWORD]:-"."}"
|
||||||
|
|
||||||
|
# Do not accept more than 1 argument
|
||||||
|
if [ "${#COMP_WORDS[@]}" != "2" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
COMPREPLY=($(compgen -c | echo "$scripts" | grep $curr_arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
complete -F _task_completion task
|
||||||
2
completion/zsh/_task
Normal file → Executable file
2
completion/zsh/_task
Normal file → Executable file
@@ -5,7 +5,7 @@ function __list() {
|
|||||||
local -a scripts
|
local -a scripts
|
||||||
|
|
||||||
if [ -f Taskfile.yml ]; then
|
if [ -f Taskfile.yml ]; then
|
||||||
scripts=($(task -l | sed '1d' | sed 's/://' | awk '{ print $2 }'))
|
scripts=($(task -l | sed '1d' | sed 's/^\* //' | awk '{ print $1 }' | sed 's/:$//' | sed 's/:/\\:/'))
|
||||||
_describe 'script' scripts
|
_describe 'script' scripts
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
taskfile.org
|
taskfile.dev
|
||||||
@@ -7,7 +7,7 @@ Since it's written in [Go][go], Task is just a single binary and has no other
|
|||||||
dependencies, which means you don't need to mess with any complicated install
|
dependencies, which means you don't need to mess with any complicated install
|
||||||
setups just to use a build tool.
|
setups just to use a build tool.
|
||||||
|
|
||||||
Once [installed](installation), you just need to describe your build tasks
|
Once [installed](installation.md), you just need to describe your build tasks
|
||||||
using a simple [YAML][yaml] schema in a file called `Taskfile.yml`:
|
using a simple [YAML][yaml] schema in a file called `Taskfile.yml`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@@ -22,25 +22,38 @@ tasks:
|
|||||||
|
|
||||||
And call it by running `task hello` from you terminal.
|
And call it by running `task hello` from you terminal.
|
||||||
|
|
||||||
The above example is just the start, you can take a look at the [usage](usage)
|
The above example is just the start, you can take a look at the [usage](usage.md)
|
||||||
guide to check the full schema documentation and Task features.
|
guide to check the full schema documentation and Task features.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- [Easy installation](installation): just download a single binary, add to
|
- [Easy installation](installation.md): just download a single binary, add to
|
||||||
$PATH and you're done! Or you can also install using [Homebrew][homebrew] or
|
$PATH and you're done! Or you can also install using [Homebrew][homebrew],
|
||||||
[Snapcraft][snapcraft] if you want;
|
[Snapcraft][snapcraft], or [Scoop][scoop] if you want;
|
||||||
- Available on CIs: by adding [this simple command](installation#install-script)
|
- Available on CIs: by adding [this simple command](installation.md#install-script)
|
||||||
to install on your CI script and you're done to use Task as part of your CI pipeline;
|
to install on your CI script and you're done to use Task as part of your CI pipeline;
|
||||||
- Truly cross-platform: while most build tools only work well on Linux or macOS,
|
- Truly cross-platform: while most build tools only work well on Linux or macOS,
|
||||||
Task also supports Windows thanks to [this awesome shell interpreter for Go][sh];
|
Task also supports Windows thanks to [this awesome shell interpreter for Go][sh];
|
||||||
- Great for code generation: you can easily [prevent a task from running](usage#prevent-unnecessary-work)
|
- Great for code generation: you can easily [prevent a task from running](usage.md#prevent-unnecessary-work)
|
||||||
if a given set of files haven't changed since last run (based either on its
|
if a given set of files haven't changed since last run (based either on its
|
||||||
timestamp or content).
|
timestamp or content).
|
||||||
|
|
||||||
|
## Sponsors
|
||||||
|
|
||||||
|
[](https://opencollective.com/task)
|
||||||
|
|
||||||
|
## Backers
|
||||||
|
|
||||||
|
[](https://opencollective.com/task)
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
[](https://github.com/go-task/task/graphs/contributors)
|
||||||
|
|
||||||
[make]: https://www.gnu.org/software/make/
|
[make]: https://www.gnu.org/software/make/
|
||||||
[go]: https://golang.org/
|
[go]: https://golang.org/
|
||||||
[yaml]: http://yaml.org/
|
[yaml]: http://yaml.org/
|
||||||
[homebrew]: https://brew.sh/
|
[homebrew]: https://brew.sh/
|
||||||
[snapcraft]: https://snapcraft.io/
|
[snapcraft]: https://snapcraft.io/
|
||||||
|
[scoop]: https://scoop.sh/
|
||||||
[sh]: https://mvdan.cc/sh
|
[sh]: https://mvdan.cc/sh
|
||||||
|
|||||||
12
docs/Taskfile.yml
Normal file
12
docs/Taskfile.yml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
version: '2'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
install:
|
||||||
|
desc: Installs docsify to work the on the documentation site
|
||||||
|
cmds:
|
||||||
|
- npm install docsify-cli -g
|
||||||
|
|
||||||
|
serve:
|
||||||
|
desc: Serves the documentation site locally
|
||||||
|
cmds:
|
||||||
|
- docsify serve docs
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
- [Installation](installation)
|
- [Installation](installation.md)
|
||||||
- [Usage](usage)
|
- [Usage](usage.md)
|
||||||
- [Taskfile Versions](taskfile_versions)
|
- [Styleguide](styleguide.md)
|
||||||
- [Examples](examples)
|
- [Taskfile Versions](taskfile_versions.md)
|
||||||
- [Releasing Task](releasing_task)
|
- [Examples](examples.md)
|
||||||
- [Alternative Task Runners](alternative_task_runners)
|
- [Releasing Task](releasing_task.md)
|
||||||
- [Sponsors and Backers](sponsors_and_backers)
|
- [Alternative Task Runners](alternative_task_runners.md)
|
||||||
- [Github](https://github.com/go-task/task)
|
- [Github](https://github.com/go-task/task)
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
name: 'Task',
|
name: 'Task',
|
||||||
repo: 'go-task/task',
|
repo: 'go-task/task',
|
||||||
ga: 'UA-126286662-1',
|
ga: 'UA-126286662-1',
|
||||||
themeColor: '#83d0f2',
|
themeColor: '#00add8',
|
||||||
loadSidebar: true,
|
loadSidebar: true,
|
||||||
auto2top: true,
|
auto2top: true,
|
||||||
maxLevel: 3,
|
maxLevel: 3,
|
||||||
|
|||||||
@@ -8,13 +8,15 @@ The `task_checksums.txt` file contains the sha256 checksum for each file.
|
|||||||
|
|
||||||
## Homebrew
|
## Homebrew
|
||||||
|
|
||||||
If you're on macOS and have [Homebrew][homebrew] installed, getting Task is
|
If you're on macOS or Linux and have [Homebrew][homebrew] installed, getting
|
||||||
as simple as running:
|
Task is as simple as running:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
brew install go-task/tap/go-task
|
brew install go-task/tap/go-task
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> This installation method is only currently supported on amd64 architectures.
|
||||||
|
|
||||||
## Snap
|
## Snap
|
||||||
|
|
||||||
Task is available for [Snapcraft][snapcraft], but keep in mind that your
|
Task is available for [Snapcraft][snapcraft], but keep in mind that your
|
||||||
@@ -25,29 +27,74 @@ right:
|
|||||||
sudo snap install task
|
sudo snap install task
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Scoop
|
||||||
|
|
||||||
|
If you're on Windows and have [Scoop][scoop] installed, use `extras` bucket
|
||||||
|
to install Task like:
|
||||||
|
|
||||||
|
```cmd
|
||||||
|
scoop bucket add extras
|
||||||
|
scoop install task
|
||||||
|
```
|
||||||
|
|
||||||
|
This installation method is community owned. After a new release of Task, it
|
||||||
|
may take some time until it's available on Scoop.
|
||||||
|
|
||||||
## Go
|
## Go
|
||||||
|
|
||||||
If you have a [Go][go] environment setup, you can simply run:
|
Task now uses [Go Modules](https://github.com/golang/go/wiki/Modules), which
|
||||||
|
means you may have trouble compiling it on older Go versions or using
|
||||||
|
`$GOPATH`.
|
||||||
|
|
||||||
|
For CI environments we recommend using the [Install Script](#install-script)
|
||||||
|
instead, which is faster and more stable, since it'll just download the latest
|
||||||
|
released binary, instead of compiling the edge (master branch) version.
|
||||||
|
|
||||||
|
Installing in another directory:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go get -u -v github.com/go-task/task/cmd/task
|
git clone https://github.com/go-task/task
|
||||||
|
cd task
|
||||||
|
|
||||||
|
# compiling binary to $GOPATH/bin
|
||||||
|
go install -v ./cmd/task
|
||||||
|
|
||||||
|
# compiling it to another location
|
||||||
|
# use -o ./task.exe on Windows
|
||||||
|
go build -v -o ./task ./cmd/task
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Both methods requires having the [Go][go] environment properly setup locally.
|
||||||
|
|
||||||
## Install script
|
## Install script
|
||||||
|
|
||||||
We also have a [install script][installscript], which is very useful on
|
We also have a [install script][installscript], which is very useful on
|
||||||
scanarios like CIs. Many thanks to [godownloader][godownloader] for allowing
|
scenarios like CIs. Many thanks to [godownloader][godownloader] for allowing
|
||||||
easily generating this script.
|
easily generating this script.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -s https://taskfile.org/install.sh | sh
|
curl -sL https://taskfile.dev/install.sh | sh
|
||||||
```
|
```
|
||||||
|
|
||||||
> This method will download the binary on the local `./bin` directory by default.
|
> This method will download the binary on the local `./bin` directory by default.
|
||||||
|
|
||||||
|
## GitHub Actions
|
||||||
|
|
||||||
|
If you want to install Task in GitHub Actions you can try using
|
||||||
|
[this action](https://github.com/arduino/actions/tree/master/setup-taskfile)
|
||||||
|
by the Arduino team:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Install Task
|
||||||
|
uses: Arduino/actions/setup-taskfile@master
|
||||||
|
```
|
||||||
|
|
||||||
|
This installation method is community owned.
|
||||||
|
|
||||||
[go]: https://golang.org/
|
[go]: https://golang.org/
|
||||||
[snapcraft]: https://snapcraft.io/
|
[snapcraft]: https://snapcraft.io/
|
||||||
[homebrew]: https://brew.sh/
|
[homebrew]: https://brew.sh/
|
||||||
[installscript]: https://github.com/go-task/task/blob/master/install-task.sh
|
[installscript]: https://github.com/go-task/task/blob/master/install-task.sh
|
||||||
[releases]: https://github.com/go-task/task/releases
|
[releases]: https://github.com/go-task/task/releases
|
||||||
[godownloader]: https://github.com/goreleaser/godownloader
|
[godownloader]: https://github.com/goreleaser/godownloader
|
||||||
|
[scoop]: https://scoop.sh/
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Releasing Task
|
# Releasing Task
|
||||||
|
|
||||||
The release process of Task is done is done with the help of
|
The release process of Task is done with the help of
|
||||||
[GoReleaser][goreleaser]. You can test the release process locally by calling
|
[GoReleaser][goreleaser]. You can test the release process locally by calling
|
||||||
the `test-release` task of the Taskfile.
|
the `test-release` task of the Taskfile.
|
||||||
|
|
||||||
@@ -22,7 +22,14 @@ the binaries:
|
|||||||
|
|
||||||
* Updating the current version on [snapcraft.yaml][snapcraftyaml];
|
* Updating the current version on [snapcraft.yaml][snapcraftyaml];
|
||||||
* Moving both `i386` and `amd64` new artifacts to the stable channel on
|
* Moving both `i386` and `amd64` new artifacts to the stable channel on
|
||||||
the [Snapscraft dashboard][snapcraftdashboard]
|
the [Snapcraft dashboard][snapcraftdashboard]
|
||||||
|
|
||||||
|
# Scoop
|
||||||
|
|
||||||
|
Scoop is a community owned installation method. Scoop owners usually take care
|
||||||
|
of updating versions there by editing
|
||||||
|
[this file](https://github.com/lukesampson/scoop-extras/blob/master/bucket/task.json).
|
||||||
|
If you think its Task version is outdated, open an issue to let us know.
|
||||||
|
|
||||||
[goreleaser]: https://goreleaser.com/#continuous_integration
|
[goreleaser]: https://goreleaser.com/#continuous_integration
|
||||||
[homebrewtap]: https://github.com/go-task/homebrew-tap
|
[homebrewtap]: https://github.com/go-task/homebrew-tap
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
# Sponsors and Backers
|
|
||||||
|
|
||||||
## Sponsors
|
|
||||||
|
|
||||||
[][opencollective]
|
|
||||||
|
|
||||||
## Backers
|
|
||||||
|
|
||||||
[][opencollective]
|
|
||||||
|
|
||||||
## Contributors
|
|
||||||
|
|
||||||
[][contributors]
|
|
||||||
|
|
||||||
[opencollective]: https://opencollective.com/task
|
|
||||||
[contributors]: https://github.com/go-task/task/graphs/contributors
|
|
||||||
213
docs/styleguide.md
Normal file
213
docs/styleguide.md
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
# Styleguide
|
||||||
|
|
||||||
|
This is the official Task styleguide for `Taskfile.yml` files. This guide
|
||||||
|
contains some basic instructions to keep your Taskfile clean and familiar to
|
||||||
|
other users.
|
||||||
|
|
||||||
|
This contains general guidelines, but don't necessarely need to be strictly
|
||||||
|
followed. Feel free to disagree and proceed differently in some point if you
|
||||||
|
need or want to. Also, feel free to open issues or pull requests with
|
||||||
|
improvements to this guide.
|
||||||
|
|
||||||
|
## Use `Taskfile.yml` and not `taskfile.yml`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# bad
|
||||||
|
taskfile.yml
|
||||||
|
|
||||||
|
|
||||||
|
# good
|
||||||
|
Taskfile.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
This is important to specially to Linux users. Windows and macOS have case
|
||||||
|
insensitive filesystems, so `taskfile.yml` will end up working, even that not
|
||||||
|
officially supported. On Linux, only `Taskfile.yml` will work, though.
|
||||||
|
|
||||||
|
## Use the correct order of keywords
|
||||||
|
|
||||||
|
- `version:`
|
||||||
|
- `includes:`
|
||||||
|
- Configuration ones, like `output:` and `expansions:`
|
||||||
|
- `vars:`
|
||||||
|
- `env:`
|
||||||
|
- `tasks:`
|
||||||
|
|
||||||
|
## Use 2 spaces for indentation
|
||||||
|
|
||||||
|
This is the most common convention for YAML files, and Task follows it.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# bad
|
||||||
|
tasks:
|
||||||
|
foo:
|
||||||
|
cmds:
|
||||||
|
- echo 'foo'
|
||||||
|
|
||||||
|
|
||||||
|
# good
|
||||||
|
tasks:
|
||||||
|
foo:
|
||||||
|
cmds:
|
||||||
|
- echo 'foo'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Separate with spaces the mains sections
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# bad
|
||||||
|
version: 2
|
||||||
|
includes:
|
||||||
|
docker: ./docker/Taskfile.yml
|
||||||
|
output: prefixed
|
||||||
|
expansions: 3
|
||||||
|
vars:
|
||||||
|
FOO: bar
|
||||||
|
env:
|
||||||
|
BAR: baz
|
||||||
|
tasks:
|
||||||
|
# ...
|
||||||
|
|
||||||
|
|
||||||
|
# good
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
includes:
|
||||||
|
docker: ./docker/Taskfile.yml
|
||||||
|
|
||||||
|
output: prefixed
|
||||||
|
expansions: 3
|
||||||
|
|
||||||
|
vars:
|
||||||
|
FOO: bar
|
||||||
|
|
||||||
|
env:
|
||||||
|
BAR: baz
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
# ...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Add spaces between tasks
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# bad
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
foo:
|
||||||
|
cmds:
|
||||||
|
- echo 'foo'
|
||||||
|
bar:
|
||||||
|
cmds:
|
||||||
|
- echo 'bar'
|
||||||
|
baz:
|
||||||
|
cmds:
|
||||||
|
- echo 'baz'
|
||||||
|
|
||||||
|
|
||||||
|
# good
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
foo:
|
||||||
|
cmds:
|
||||||
|
- echo 'foo'
|
||||||
|
|
||||||
|
bar:
|
||||||
|
cmds:
|
||||||
|
- echo 'bar'
|
||||||
|
|
||||||
|
baz:
|
||||||
|
cmds:
|
||||||
|
- echo 'baz'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use upper-case variable names
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# bad
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
vars:
|
||||||
|
binary_name: myapp
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
build:
|
||||||
|
cmds:
|
||||||
|
- go build -o {{.binary_name}} .
|
||||||
|
|
||||||
|
|
||||||
|
# good
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
vars:
|
||||||
|
BINARY_NAME: myapp
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
build:
|
||||||
|
cmds:
|
||||||
|
- go build -o {{.BINARY_NAME}} .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Don't wrap vars in spaces when templating
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# bad
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
greet:
|
||||||
|
cmds:
|
||||||
|
- echo '{{ .MESSAGE }}'
|
||||||
|
|
||||||
|
|
||||||
|
# good
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
greet:
|
||||||
|
cmds:
|
||||||
|
- echo '{{.MESSAGE}}'
|
||||||
|
```
|
||||||
|
|
||||||
|
This convention is also used by most people for any Go templating.
|
||||||
|
|
||||||
|
## Separate task name words with a dash
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# bad
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
do_something_fancy:
|
||||||
|
cmds:
|
||||||
|
- echo 'Do something'
|
||||||
|
|
||||||
|
|
||||||
|
# good
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
do-something-fancy:
|
||||||
|
cmds:
|
||||||
|
- echo 'Do something'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use colon for task namespacing
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# good
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
docker:build:
|
||||||
|
cmds:
|
||||||
|
- docker ...
|
||||||
|
|
||||||
|
docker:run:
|
||||||
|
cmds:
|
||||||
|
- docker-compose ...
|
||||||
|
```
|
||||||
|
|
||||||
|
This is also done automatically when using included Taskfiles.
|
||||||
@@ -141,8 +141,23 @@ includes:
|
|||||||
docker: ./DockerTasks.yml
|
docker: ./DockerTasks.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Version 2.6
|
||||||
|
|
||||||
|
Version 2.6 comes with `preconditions` stanza in tasks.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '2'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
upload_environment:
|
||||||
|
preconditions:
|
||||||
|
- test -f .env
|
||||||
|
cmds:
|
||||||
|
- aws s3 cp .env s3://myenvironment
|
||||||
|
```
|
||||||
|
|
||||||
Please check the [documentation][includes]
|
Please check the [documentation][includes]
|
||||||
|
|
||||||
[output]: usage#output-syntax
|
[output]: usage.md#output-syntax
|
||||||
[ignore_errors]: usage#ignore-errors
|
[ignore_errors]: usage.md#ignore-errors
|
||||||
[includes]: usage#including-other-taskfiles
|
[includes]: usage.md#including-other-taskfiles
|
||||||
|
|||||||
152
docs/usage.md
152
docs/usage.md
@@ -31,23 +31,41 @@ interpreter. So you can write sh/bash commands and it will work even on
|
|||||||
Windows, where `sh` or `bash` are usually not available. Just remember any
|
Windows, where `sh` or `bash` are usually not available. Just remember any
|
||||||
executable called must be available by the OS or in PATH.
|
executable called must be available by the OS or in PATH.
|
||||||
|
|
||||||
If you ommit a task name, "default" will be assumed.
|
If you omit a task name, "default" will be assumed.
|
||||||
|
|
||||||
## Environment
|
## Environment
|
||||||
|
|
||||||
You can specify environment variables that are added when running a command:
|
You can use `env` to set custom environment variables for a specific task:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
version: '2'
|
version: '2'
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
build:
|
greet:
|
||||||
cmds:
|
cmds:
|
||||||
- echo $hallo
|
- echo $GREETING
|
||||||
env:
|
env:
|
||||||
hallo: welt
|
GREETING: Hey, there!
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Additionally, you can set globally environment variables, that'll be available
|
||||||
|
to all tasks:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '2'
|
||||||
|
|
||||||
|
env:
|
||||||
|
GREETING: Hey, there!
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
greet:
|
||||||
|
cmds:
|
||||||
|
- echo $GREETING
|
||||||
|
```
|
||||||
|
|
||||||
|
> NOTE: `env` supports expansion and retrieving output from a shell command
|
||||||
|
> just like variables, as you can see on the [Variables](#variables) section.
|
||||||
|
|
||||||
## Operating System specific tasks
|
## Operating System specific tasks
|
||||||
|
|
||||||
If you add a `Taskfile_{{GOOS}}.yml` you can override or amend your Taskfile
|
If you add a `Taskfile_{{GOOS}}.yml` you can override or amend your Taskfile
|
||||||
@@ -83,11 +101,13 @@ Keep in mind that the version of the files should match. Also, when redefining
|
|||||||
a task the whole task is replaced, properties of the task are not merged.
|
a task the whole task is replaced, properties of the task are not merged.
|
||||||
|
|
||||||
It's also possible to have an OS specific `Taskvars.yml` file, like
|
It's also possible to have an OS specific `Taskvars.yml` file, like
|
||||||
`Taskvars_windows.yml`, `Taskfile_linux.yml`, or `Taskvars_darwin.yml`. See the
|
`Taskvars_windows.yml`, `Taskvars_linux.yml`, or `Taskvars_darwin.yml`. See the
|
||||||
[variables section](#variables) below.
|
[variables section](#variables) below.
|
||||||
|
|
||||||
## Including other Taskfiles
|
## Including other Taskfiles
|
||||||
|
|
||||||
|
> This feature is still experimental and may have bugs.
|
||||||
|
|
||||||
If you want to share tasks between different projects (Taskfiles), you can use
|
If you want to share tasks between different projects (Taskfiles), you can use
|
||||||
the importing mechanism to include other Taskfiles using the `includes` keyword:
|
the importing mechanism to include other Taskfiles using the `includes` keyword:
|
||||||
|
|
||||||
@@ -128,6 +148,8 @@ tasks:
|
|||||||
- caddy
|
- caddy
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If the directory doesn't exist, `task` creates it.
|
||||||
|
|
||||||
## Task dependencies
|
## Task dependencies
|
||||||
|
|
||||||
You may have tasks that depend on others. Just pointing them on `deps` will
|
You may have tasks that depend on others. Just pointing them on `deps` will
|
||||||
@@ -238,6 +260,10 @@ tasks:
|
|||||||
|
|
||||||
The above syntax is also supported in `deps`.
|
The above syntax is also supported in `deps`.
|
||||||
|
|
||||||
|
> NOTE: If you want to call a task declared in the root Taskfile from within an
|
||||||
|
> [included Taskfile](#including-other-taskfiles), add a leading `:` like this:
|
||||||
|
> `task: :task-name`.
|
||||||
|
|
||||||
## Prevent unnecessary work
|
## Prevent unnecessary work
|
||||||
|
|
||||||
If a task generates something, you can inform Task the source and generated
|
If a task generates something, you can inform Task the source and generated
|
||||||
@@ -320,12 +346,61 @@ up-to-date.
|
|||||||
Also, `task --status [tasks]...` will exit with a non-zero exit code if any of
|
Also, `task --status [tasks]...` will exit with a non-zero exit code if any of
|
||||||
the tasks are not up-to-date.
|
the tasks are not up-to-date.
|
||||||
|
|
||||||
|
If you need a certain set of conditions to be _true_ you can use the
|
||||||
|
`preconditions` stanza. `preconditions` are very similar to `status`
|
||||||
|
lines except they support `sh` expansion and they SHOULD all return 0.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '2'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
generate-files:
|
||||||
|
cmds:
|
||||||
|
- mkdir directory
|
||||||
|
- touch directory/file1.txt
|
||||||
|
- touch directory/file2.txt
|
||||||
|
# test existence of files
|
||||||
|
preconditions:
|
||||||
|
- test -f .env
|
||||||
|
- sh: "[ 1 = 0 ]"
|
||||||
|
msg: "One doesn't equal Zero, Halting"
|
||||||
|
```
|
||||||
|
|
||||||
|
Preconditions can set specific failure messages that can tell
|
||||||
|
a user what steps to take using the `msg` field.
|
||||||
|
|
||||||
|
If a task has a dependency on a sub-task with a precondition, and that
|
||||||
|
precondition is not met - the calling task will fail. Note that a task
|
||||||
|
executed with a failing precondition will not run unless `--force` is
|
||||||
|
given.
|
||||||
|
|
||||||
|
Unlike `status` which will skip a task if it is up to date, and continue
|
||||||
|
executing tasks that depend on it, a `precondition` will fail a task, along
|
||||||
|
with any other tasks that depend on it.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '2'
|
||||||
|
tasks:
|
||||||
|
task_will_fail:
|
||||||
|
preconditions:
|
||||||
|
- sh: "exit 1"
|
||||||
|
|
||||||
|
task_will_also_fail:
|
||||||
|
deps:
|
||||||
|
- task_will_fail
|
||||||
|
|
||||||
|
task_will_still_fail:
|
||||||
|
cmds:
|
||||||
|
- task: task_will_fail
|
||||||
|
- echo "I will not run"
|
||||||
|
```
|
||||||
|
|
||||||
## Variables
|
## Variables
|
||||||
|
|
||||||
When doing interpolation of variables, Task will look for the below.
|
When doing interpolation of variables, Task will look for the below.
|
||||||
They are listed below in order of importance (e.g. most important first):
|
They are listed below in order of importance (e.g. most important first):
|
||||||
|
|
||||||
- Variables declared locally in the task
|
- Variables declared in the task definition
|
||||||
- Variables given while calling a task from another.
|
- Variables given while calling a task from another.
|
||||||
(See [Calling another task](#calling-another-task) above)
|
(See [Calling another task](#calling-another-task) above)
|
||||||
- Variables declared in the `vars:` option in the `Taskfile`
|
- Variables declared in the `vars:` option in the `Taskfile`
|
||||||
@@ -347,6 +422,12 @@ right before.
|
|||||||
$ task write-file FILE=file.txt "CONTENT=Hello, World!" print "MESSAGE=All done!"
|
$ task write-file FILE=file.txt "CONTENT=Hello, World!" print "MESSAGE=All done!"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you want to set global variables using this syntax, give it before any task:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ task OUTPUT=file.txt generate-file
|
||||||
|
```
|
||||||
|
|
||||||
Example of locally declared vars:
|
Example of locally declared vars:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@@ -355,7 +436,7 @@ version: '2'
|
|||||||
tasks:
|
tasks:
|
||||||
print-var:
|
print-var:
|
||||||
cmds:
|
cmds:
|
||||||
echo "{{.VAR}}"
|
- echo "{{.VAR}}"
|
||||||
vars:
|
vars:
|
||||||
VAR: Hello!
|
VAR: Hello!
|
||||||
```
|
```
|
||||||
@@ -453,7 +534,7 @@ Task also adds the following functions:
|
|||||||
- `catLines`: Replaces Unix (\n) and Windows (\r\n) styled newlines with a space.
|
- `catLines`: Replaces Unix (\n) and Windows (\r\n) styled newlines with a space.
|
||||||
- `toSlash`: Does nothing on Unix, but on Windows converts a string from `\`
|
- `toSlash`: Does nothing on Unix, but on Windows converts a string from `\`
|
||||||
path format to `/`.
|
path format to `/`.
|
||||||
- `fromSlash`: Oposite of `toSlash`. Does nothing on Unix, but on Windows
|
- `fromSlash`: Opposite of `toSlash`. Does nothing on Unix, but on Windows
|
||||||
converts a string from `\` path format to `/`.
|
converts a string from `\` path format to `/`.
|
||||||
- `exeExt`: Returns the right executable extension for the current OS
|
- `exeExt`: Returns the right executable extension for the current OS
|
||||||
(`".exe"` for Windows, `""` for others).
|
(`".exe"` for Windows, `""` for others).
|
||||||
@@ -486,7 +567,7 @@ tasks:
|
|||||||
## Help
|
## Help
|
||||||
|
|
||||||
Running `task --list` (or `task -l`) lists all tasks with a description.
|
Running `task --list` (or `task -l`) lists all tasks with a description.
|
||||||
The following taskfile:
|
The following Taskfile:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
version: '2'
|
version: '2'
|
||||||
@@ -518,6 +599,51 @@ would print the following output:
|
|||||||
* test: Run all the go tests.
|
* test: Run all the go tests.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Display summary of task
|
||||||
|
|
||||||
|
Running `task --summary task-name` will show a summary of a task
|
||||||
|
The following Taskfile:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '2'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
release:
|
||||||
|
deps: [build]
|
||||||
|
summary: |
|
||||||
|
Release your project to github
|
||||||
|
|
||||||
|
It will build your project before starting the release it.
|
||||||
|
Please make sure that you have set GITHUB_TOKEN before starting.
|
||||||
|
cmds:
|
||||||
|
- your-release-tool
|
||||||
|
|
||||||
|
build:
|
||||||
|
cmds:
|
||||||
|
- your-build-tool
|
||||||
|
```
|
||||||
|
|
||||||
|
with running ``task --summary release`` would print the following output:
|
||||||
|
|
||||||
|
```
|
||||||
|
task: release
|
||||||
|
|
||||||
|
Release your project to github
|
||||||
|
|
||||||
|
It will build your project before starting the release it.
|
||||||
|
Please make sure that you have set GITHUB_TOKEN before starting.
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- build
|
||||||
|
|
||||||
|
commands:
|
||||||
|
- your-release-tool
|
||||||
|
```
|
||||||
|
If a summary is missing, the description will be printed.
|
||||||
|
If the task does not have a summary or a description, a warning is printed.
|
||||||
|
|
||||||
|
Please note: *showing the summary will not execute the command*.
|
||||||
|
|
||||||
## Silent mode
|
## Silent mode
|
||||||
|
|
||||||
Silent mode disables echoing of commands before Task runs it.
|
Silent mode disables echoing of commands before Task runs it.
|
||||||
@@ -573,7 +699,7 @@ tasks:
|
|||||||
|
|
||||||
* Or globally with `--silent` or `-s` flag
|
* Or globally with `--silent` or `-s` flag
|
||||||
|
|
||||||
If you want to suppress stdout instead, just redirect a command to `/dev/null`:
|
If you want to suppress STDOUT instead, just redirect a command to `/dev/null`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
version: '2'
|
version: '2'
|
||||||
@@ -618,7 +744,7 @@ tasks:
|
|||||||
- echo "Hello World"
|
- echo "Hello World"
|
||||||
```
|
```
|
||||||
|
|
||||||
`ignore_error` can also be set for a task, which mean errors will be supressed
|
`ignore_error` can also be set for a task, which mean errors will be suppressed
|
||||||
for all commands. But keep in mind this option won't propagate to other tasks
|
for all commands. But keep in mind this option won't propagate to other tasks
|
||||||
called either by `deps` or `cmds`!
|
called either by `deps` or `cmds`!
|
||||||
|
|
||||||
@@ -684,6 +810,8 @@ $ task default
|
|||||||
[print-baz] baz
|
[print-baz] baz
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> The `output` option can also be specified by the `--output` or `-o` flags.
|
||||||
|
|
||||||
## Watch tasks
|
## Watch tasks
|
||||||
|
|
||||||
If you give a `--watch` or `-w` argument, task will watch for file changes
|
If you give a `--watch` or `-w` argument, task will watch for file changes
|
||||||
|
|||||||
20
go.mod
Normal file
20
go.mod
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
module github.com/go-task/task/v2
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/Masterminds/semver v1.4.2 // indirect
|
||||||
|
github.com/Masterminds/sprig v2.16.0+incompatible
|
||||||
|
github.com/aokoli/goutils v1.0.1 // indirect
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/google/uuid v1.0.0 // indirect
|
||||||
|
github.com/huandu/xstrings v1.1.0 // indirect
|
||||||
|
github.com/imdario/mergo v0.3.6 // indirect
|
||||||
|
github.com/mattn/go-zglob v0.0.1
|
||||||
|
github.com/radovskyb/watcher v1.0.5
|
||||||
|
github.com/spf13/pflag v1.0.3
|
||||||
|
github.com/stretchr/testify v1.4.0
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58
|
||||||
|
gopkg.in/yaml.v2 v2.2.2
|
||||||
|
mvdan.cc/sh/v3 v3.0.0-alpha3
|
||||||
|
)
|
||||||
|
|
||||||
|
go 1.13
|
||||||
56
go.sum
Normal file
56
go.sum
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc=
|
||||||
|
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||||
|
github.com/Masterminds/sprig v2.16.0+incompatible h1:QZbMUPxRQ50EKAq3LFMnxddMu88/EUUG3qmxwtDmPsY=
|
||||||
|
github.com/Masterminds/sprig v2.16.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
|
||||||
|
github.com/aokoli/goutils v1.0.1 h1:7fpzNGoJ3VA8qcrm++XEE1QUe0mIwNeLa02Nwq7RDkg=
|
||||||
|
github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
|
||||||
|
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/huandu/xstrings v1.1.0 h1:9oZY6Z/H3A1gytJxzuicbmV5QoR8M1TAPcn9WTg7vqg=
|
||||||
|
github.com/huandu/xstrings v1.1.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4=
|
||||||
|
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
|
||||||
|
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||||
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/mattn/go-zglob v0.0.1 h1:xsEx/XUoVlI6yXjqBK062zYhRTZltCNmYPx6v+8DNaY=
|
||||||
|
github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
|
||||||
|
github.com/pkg/diff v0.0.0-20190915214748-c72a55596e99/go.mod h1:kFj35MyHn14a6pIgWhm46KVjJr5CHys3eEYxkuKD1EI=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/radovskyb/watcher v1.0.5 h1:wqt7gb+HjGacvFoLTKeT44C+XVPxu7bvHvKT1IvZ7rw=
|
||||||
|
github.com/radovskyb/watcher v1.0.5/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg=
|
||||||
|
github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||||
|
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||||
|
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||||
|
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.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7 h1:0hQKqeLdqlt5iIwVOBErRisrHJAN57yOiPRQItI20fU=
|
||||||
|
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190910064555-bbd175535a8b h1:3S2h5FadpNr0zUUCVZjlKIEYF+KaX/OBplTGo89CYHI=
|
||||||
|
golang.org/x/sys v0.0.0-20190910064555-bbd175535a8b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
mvdan.cc/sh/v3 v3.0.0-alpha3 h1:P9Kvg+bAwBksU9ATd8MNl1FEsObQ0yNsahZYLA4HRPs=
|
||||||
|
mvdan.cc/sh/v3 v3.0.0-alpha3/go.mod h1:VowSI5HikxXG/UBAS3NOTV4cDOWB+uTj+Qa7src2EYo=
|
||||||
2
help.go
2
help.go
@@ -5,7 +5,7 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/go-task/task/internal/taskfile"
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PrintTasksHelp prints help os tasks that have a description
|
// PrintTasksHelp prints help os tasks that have a description
|
||||||
|
|||||||
2
init.go
2
init.go
@@ -8,7 +8,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultTaskfile = `# github.com/go-task/task
|
const defaultTaskfile = `# https://taskfile.dev
|
||||||
|
|
||||||
version: '2'
|
version: '2'
|
||||||
|
|
||||||
|
|||||||
@@ -1,36 +1,43 @@
|
|||||||
package args
|
package args
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-task/task/internal/taskfile"
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// ErrVariableWithoutTask is returned when variables are given before any task
|
|
||||||
ErrVariableWithoutTask = errors.New("task: variable given before any task")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Parse parses command line argument: tasks and vars of each task
|
// Parse parses command line argument: tasks and vars of each task
|
||||||
func Parse(args ...string) ([]taskfile.Call, error) {
|
func Parse(args ...string) ([]taskfile.Call, taskfile.Vars) {
|
||||||
var calls []taskfile.Call
|
var calls []taskfile.Call
|
||||||
|
var globals taskfile.Vars
|
||||||
|
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
if !strings.Contains(arg, "=") {
|
if !strings.Contains(arg, "=") {
|
||||||
calls = append(calls, taskfile.Call{Task: arg})
|
calls = append(calls, taskfile.Call{Task: arg})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(calls) < 1 {
|
if len(calls) < 1 {
|
||||||
return nil, ErrVariableWithoutTask
|
if globals == nil {
|
||||||
}
|
globals = taskfile.Vars{}
|
||||||
|
}
|
||||||
|
|
||||||
if calls[len(calls)-1].Vars == nil {
|
name, value := splitVar(arg)
|
||||||
calls[len(calls)-1].Vars = make(taskfile.Vars)
|
globals[name] = taskfile.Var{Static: value}
|
||||||
}
|
} else {
|
||||||
|
if calls[len(calls)-1].Vars == nil {
|
||||||
|
calls[len(calls)-1].Vars = make(taskfile.Vars)
|
||||||
|
}
|
||||||
|
|
||||||
pair := strings.SplitN(arg, "=", 2)
|
name, value := splitVar((arg))
|
||||||
calls[len(calls)-1].Vars[pair[0]] = taskfile.Var{Static: pair[1]}
|
calls[len(calls)-1].Vars[name] = taskfile.Var{Static: value}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return calls, nil
|
|
||||||
|
return calls, globals
|
||||||
|
}
|
||||||
|
|
||||||
|
func splitVar(s string) (string, string) {
|
||||||
|
pair := strings.SplitN(s, "=", 2)
|
||||||
|
return pair[0], pair[1]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,21 +4,21 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-task/task/internal/args"
|
"github.com/go-task/task/v2/internal/args"
|
||||||
"github.com/go-task/task/internal/taskfile"
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestArgs(t *testing.T) {
|
func TestArgs(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
Args []string
|
Args []string
|
||||||
Expected []taskfile.Call
|
ExpectedCalls []taskfile.Call
|
||||||
Err error
|
ExpectedGlobals taskfile.Vars
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
Args: []string{"task-a", "task-b", "task-c"},
|
Args: []string{"task-a", "task-b", "task-c"},
|
||||||
Expected: []taskfile.Call{
|
ExpectedCalls: []taskfile.Call{
|
||||||
{Task: "task-a"},
|
{Task: "task-a"},
|
||||||
{Task: "task-b"},
|
{Task: "task-b"},
|
||||||
{Task: "task-c"},
|
{Task: "task-c"},
|
||||||
@@ -26,7 +26,7 @@ func TestArgs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Args: []string{"task-a", "FOO=bar", "task-b", "task-c", "BAR=baz", "BAZ=foo"},
|
Args: []string{"task-a", "FOO=bar", "task-b", "task-c", "BAR=baz", "BAZ=foo"},
|
||||||
Expected: []taskfile.Call{
|
ExpectedCalls: []taskfile.Call{
|
||||||
{
|
{
|
||||||
Task: "task-a",
|
Task: "task-a",
|
||||||
Vars: taskfile.Vars{
|
Vars: taskfile.Vars{
|
||||||
@@ -45,7 +45,7 @@ func TestArgs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
Args: []string{"task-a", "CONTENT=with some spaces"},
|
Args: []string{"task-a", "CONTENT=with some spaces"},
|
||||||
Expected: []taskfile.Call{
|
ExpectedCalls: []taskfile.Call{
|
||||||
{
|
{
|
||||||
Task: "task-a",
|
Task: "task-a",
|
||||||
Vars: taskfile.Vars{
|
Vars: taskfile.Vars{
|
||||||
@@ -55,16 +55,22 @@ func TestArgs(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Args: []string{"FOO=bar", "task-a"},
|
Args: []string{"FOO=bar", "task-a", "task-b"},
|
||||||
Err: args.ErrVariableWithoutTask,
|
ExpectedCalls: []taskfile.Call{
|
||||||
|
{Task: "task-a"},
|
||||||
|
{Task: "task-b"},
|
||||||
|
},
|
||||||
|
ExpectedGlobals: taskfile.Vars{
|
||||||
|
"FOO": {Static: "bar"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
t.Run(fmt.Sprintf("TestArgs%d", i+1), func(t *testing.T) {
|
t.Run(fmt.Sprintf("TestArgs%d", i+1), func(t *testing.T) {
|
||||||
calls, err := args.Parse(test.Args...)
|
calls, globals := args.Parse(test.Args...)
|
||||||
assert.Equal(t, test.Err, err)
|
assert.Equal(t, test.ExpectedCalls, calls)
|
||||||
assert.Equal(t, test.Expected, calls)
|
assert.Equal(t, test.ExpectedGlobals, globals)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package compiler
|
package compiler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/go-task/task/internal/taskfile"
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Compiler handles compilation of a task before its execution.
|
// Compiler handles compilation of a task before its execution.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-task/task/internal/taskfile"
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetEnviron the all return all environment variables encapsulated on a
|
// GetEnviron the all return all environment variables encapsulated on a
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/go-task/task/internal/compiler"
|
"github.com/go-task/task/v2/internal/compiler"
|
||||||
"github.com/go-task/task/internal/execext"
|
"github.com/go-task/task/v2/internal/execext"
|
||||||
"github.com/go-task/task/internal/logger"
|
"github.com/go-task/task/v2/internal/logger"
|
||||||
"github.com/go-task/task/internal/taskfile"
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
"github.com/go-task/task/internal/templater"
|
"github.com/go-task/task/v2/internal/templater"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ compiler.Compiler = &CompilerV1{}
|
var _ compiler.Compiler = &CompilerV1{}
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/go-task/task/internal/compiler"
|
"github.com/go-task/task/v2/internal/compiler"
|
||||||
"github.com/go-task/task/internal/execext"
|
"github.com/go-task/task/v2/internal/execext"
|
||||||
"github.com/go-task/task/internal/logger"
|
"github.com/go-task/task/v2/internal/logger"
|
||||||
"github.com/go-task/task/internal/taskfile"
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
"github.com/go-task/task/internal/templater"
|
"github.com/go-task/task/v2/internal/templater"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ compiler.Compiler = &CompilerV2{}
|
var _ compiler.Compiler = &CompilerV2{}
|
||||||
|
|||||||
@@ -5,10 +5,13 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"mvdan.cc/sh/interp"
|
"mvdan.cc/sh/v3/expand"
|
||||||
"mvdan.cc/sh/syntax"
|
"mvdan.cc/sh/v3/interp"
|
||||||
|
"mvdan.cc/sh/v3/shell"
|
||||||
|
"mvdan.cc/sh/v3/syntax"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RunCommandOptions is the options for the RunCommand func
|
// RunCommandOptions is the options for the RunCommand func
|
||||||
@@ -41,17 +44,12 @@ func RunCommand(ctx context.Context, opts *RunCommandOptions) error {
|
|||||||
if len(environ) == 0 {
|
if len(environ) == 0 {
|
||||||
environ = os.Environ()
|
environ = os.Environ()
|
||||||
}
|
}
|
||||||
env, err := interp.EnvFromList(environ)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := interp.New(
|
r, err := interp.New(
|
||||||
interp.Dir(opts.Dir),
|
interp.Dir(opts.Dir),
|
||||||
interp.Env(env),
|
interp.Env(expand.ListEnviron(environ...)),
|
||||||
|
|
||||||
interp.Module(interp.DefaultExec),
|
interp.WithOpenModules(interp.OpenDevImpls),
|
||||||
interp.Module(interp.OpenDevImpls(interp.DefaultOpen)),
|
|
||||||
|
|
||||||
interp.StdIO(opts.Stdin, opts.Stdout, opts.Stderr),
|
interp.StdIO(opts.Stdin, opts.Stdout, opts.Stderr),
|
||||||
)
|
)
|
||||||
@@ -64,9 +62,24 @@ func RunCommand(ctx context.Context, opts *RunCommandOptions) error {
|
|||||||
// IsExitError returns true the given error is an exis status error
|
// IsExitError returns true the given error is an exis status error
|
||||||
func IsExitError(err error) bool {
|
func IsExitError(err error) bool {
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
case interp.ExitStatus, interp.ShellExitStatus:
|
case interp.ExitStatus:
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expand is a helper to mvdan.cc/shell.Fields that returns the first field
|
||||||
|
// if available.
|
||||||
|
func Expand(s string) (string, error) {
|
||||||
|
s = filepath.ToSlash(s)
|
||||||
|
s = strings.Replace(s, " ", `\ `, -1)
|
||||||
|
fields, err := shell.Fields(s, nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if len(fields) > 0 {
|
||||||
|
return fields[0], nil
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
type Group struct{}
|
type Group struct{}
|
||||||
|
|
||||||
func (Group) WrapWriter(w io.Writer, _ string) io.WriteCloser {
|
func (Group) WrapWriter(w io.Writer, _ string) io.Writer {
|
||||||
return &groupWriter{writer: w}
|
return &groupWriter{writer: w}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,18 +6,6 @@ import (
|
|||||||
|
|
||||||
type Interleaved struct{}
|
type Interleaved struct{}
|
||||||
|
|
||||||
func (Interleaved) WrapWriter(w io.Writer, _ string) io.WriteCloser {
|
func (Interleaved) WrapWriter(w io.Writer, _ string) io.Writer {
|
||||||
return nopWriterCloser{w: w}
|
return w
|
||||||
}
|
|
||||||
|
|
||||||
type nopWriterCloser struct {
|
|
||||||
w io.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wc nopWriterCloser) Write(p []byte) (int, error) {
|
|
||||||
return wc.w.Write(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wc nopWriterCloser) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Output interface {
|
type Output interface {
|
||||||
WrapWriter(w io.Writer, prefix string) io.WriteCloser
|
WrapWriter(w io.Writer, prefix string) io.Writer
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,10 @@ package output_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-task/task/internal/output"
|
"github.com/go-task/task/v2/internal/output"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@@ -24,7 +25,7 @@ func TestInterleaved(t *testing.T) {
|
|||||||
func TestGroup(t *testing.T) {
|
func TestGroup(t *testing.T) {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
var o output.Output = output.Group{}
|
var o output.Output = output.Group{}
|
||||||
var w = o.WrapWriter(&b, "")
|
var w = o.WrapWriter(&b, "").(io.WriteCloser)
|
||||||
|
|
||||||
fmt.Fprintln(w, "foo\nbar")
|
fmt.Fprintln(w, "foo\nbar")
|
||||||
assert.Equal(t, "", b.String())
|
assert.Equal(t, "", b.String())
|
||||||
@@ -37,7 +38,7 @@ func TestGroup(t *testing.T) {
|
|||||||
func TestPrefixed(t *testing.T) {
|
func TestPrefixed(t *testing.T) {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
var o output.Output = output.Prefixed{}
|
var o output.Output = output.Prefixed{}
|
||||||
var w = o.WrapWriter(&b, "prefix")
|
var w = o.WrapWriter(&b, "prefix").(io.WriteCloser)
|
||||||
|
|
||||||
t.Run("simple use cases", func(t *testing.T) {
|
t.Run("simple use cases", func(t *testing.T) {
|
||||||
b.Reset()
|
b.Reset()
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
type Prefixed struct{}
|
type Prefixed struct{}
|
||||||
|
|
||||||
func (Prefixed) WrapWriter(w io.Writer, prefix string) io.WriteCloser {
|
func (Prefixed) WrapWriter(w io.Writer, prefix string) io.Writer {
|
||||||
return &prefixWriter{writer: w, prefix: prefix}
|
return &prefixWriter{writer: w, prefix: prefix}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,12 +34,12 @@ func (pw *prefixWriter) Close() error {
|
|||||||
|
|
||||||
func (pw *prefixWriter) writeOutputLines(force bool) error {
|
func (pw *prefixWriter) writeOutputLines(force bool) error {
|
||||||
for {
|
for {
|
||||||
line, err := pw.buff.ReadString('\n')
|
switch line, err := pw.buff.ReadString('\n'); err {
|
||||||
if err == nil {
|
case nil:
|
||||||
if err = pw.writeLine(line); err != nil {
|
if err = pw.writeLine(line); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if err == io.EOF {
|
case io.EOF:
|
||||||
// if this line was not a complete line, re-add to the buffer
|
// if this line was not a complete line, re-add to the buffer
|
||||||
if !force && !strings.HasSuffix(line, "\n") {
|
if !force && !strings.HasSuffix(line, "\n") {
|
||||||
_, err = pw.buff.WriteString(line)
|
_, err = pw.buff.WriteString(line)
|
||||||
@@ -47,7 +47,7 @@ func (pw *prefixWriter) writeOutputLines(force bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return pw.writeLine(line)
|
return pw.writeLine(line)
|
||||||
} else {
|
default:
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,11 @@ import (
|
|||||||
// Checksum validades if a task is up to date by calculating its source
|
// Checksum validades if a task is up to date by calculating its source
|
||||||
// files checksum
|
// files checksum
|
||||||
type Checksum struct {
|
type Checksum struct {
|
||||||
Dir string
|
Dir string
|
||||||
Task string
|
Task string
|
||||||
Sources []string
|
Sources []string
|
||||||
|
Generates []string
|
||||||
|
Dry bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsUpToDate implements the Checker interface
|
// IsUpToDate implements the Checker interface
|
||||||
@@ -26,7 +28,7 @@ func (c *Checksum) IsUpToDate() (bool, error) {
|
|||||||
data, _ := ioutil.ReadFile(checksumFile)
|
data, _ := ioutil.ReadFile(checksumFile)
|
||||||
oldMd5 := strings.TrimSpace(string(data))
|
oldMd5 := strings.TrimSpace(string(data))
|
||||||
|
|
||||||
sources, err := glob(c.Dir, c.Sources)
|
sources, err := globs(c.Dir, c.Sources)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@@ -36,10 +38,29 @@ func (c *Checksum) IsUpToDate() (bool, error) {
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = os.MkdirAll(filepath.Join(c.Dir, ".task", "checksum"), 0755)
|
if !c.Dry {
|
||||||
if err = ioutil.WriteFile(checksumFile, []byte(newMd5+"\n"), 0644); err != nil {
|
_ = os.MkdirAll(filepath.Join(c.Dir, ".task", "checksum"), 0755)
|
||||||
return false, err
|
if err = ioutil.WriteFile(checksumFile, []byte(newMd5+"\n"), 0644); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(c.Generates) > 0 {
|
||||||
|
// For each specified 'generates' field, check whether the files actually exist
|
||||||
|
for _, g := range c.Generates {
|
||||||
|
generates, err := glob(c.Dir, g)
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if len(generates) == 0 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return oldMd5 == newMd5, nil
|
return oldMd5 == newMd5, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,21 +68,14 @@ func (c *Checksum) checksum(files ...string) (string, error) {
|
|||||||
h := md5.New()
|
h := md5.New()
|
||||||
|
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
|
// also sum the filename, so checksum changes for renaming a file
|
||||||
|
if _, err := io.Copy(h, strings.NewReader(filepath.Base(f))); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
f, err := os.Open(f)
|
f, err := os.Open(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
info, err := f.Stat()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if info.IsDir() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// also sum the filename, so checksum changes for renaming a file
|
|
||||||
if _, err = io.Copy(h, strings.NewReader(info.Name())); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if _, err = io.Copy(h, f); err != nil {
|
if _, err = io.Copy(h, f); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,50 @@
|
|||||||
package status
|
package status
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v2/internal/execext"
|
||||||
|
|
||||||
"github.com/mattn/go-zglob"
|
"github.com/mattn/go-zglob"
|
||||||
"mvdan.cc/sh/shell"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func glob(dir string, globs []string) (files []string, err error) {
|
func globs(dir string, globs []string) ([]string, error) {
|
||||||
|
files := make([]string, 0)
|
||||||
for _, g := range globs {
|
for _, g := range globs {
|
||||||
if !filepath.IsAbs(g) {
|
f, err := glob(dir, g)
|
||||||
g = filepath.Join(dir, g)
|
|
||||||
}
|
|
||||||
g, err = shell.Expand(g, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
f, err := zglob.Glob(g)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
files = append(files, f...)
|
files = append(files, f...)
|
||||||
}
|
}
|
||||||
sort.Strings(files)
|
sort.Strings(files)
|
||||||
return
|
return files, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func glob(dir string, g string) ([]string, error) {
|
||||||
|
files := make([]string, 0)
|
||||||
|
if !filepath.IsAbs(g) {
|
||||||
|
g = filepath.Join(dir, g)
|
||||||
|
}
|
||||||
|
g, err := execext.Expand(g)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fs, err := zglob.Glob(g)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, f := range fs {
|
||||||
|
info, err := os.Stat(f)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if info.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
files = append(files, f)
|
||||||
|
}
|
||||||
|
return files, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ func (t *Timestamp) IsUpToDate() (bool, error) {
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
sources, err := glob(t.Dir, t.Sources)
|
sources, err := globs(t.Dir, t.Sources)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
generates, err := glob(t.Dir, t.Generates)
|
generates, err := globs(t.Dir, t.Generates)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|||||||
103
internal/summary/summary.go
Normal file
103
internal/summary/summary.go
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
package summary
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v2/internal/logger"
|
||||||
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PrintTasks(l *logger.Logger, t *taskfile.Taskfile, c []taskfile.Call) {
|
||||||
|
for i, call := range c {
|
||||||
|
printSpaceBetweenSummaries(l, i)
|
||||||
|
PrintTask(l, t.Tasks[call.Task])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printSpaceBetweenSummaries(l *logger.Logger, i int) {
|
||||||
|
spaceRequired := i > 0
|
||||||
|
if !spaceRequired {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Outf("")
|
||||||
|
l.Outf("")
|
||||||
|
}
|
||||||
|
|
||||||
|
func PrintTask(l *logger.Logger, t *taskfile.Task) {
|
||||||
|
printTaskName(l, t)
|
||||||
|
printTaskDescribingText(t, l)
|
||||||
|
printTaskDependencies(l, t)
|
||||||
|
printTaskCommands(l, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printTaskDescribingText(t *taskfile.Task, l *logger.Logger) {
|
||||||
|
if hasSummary(t) {
|
||||||
|
printTaskSummary(l, t)
|
||||||
|
} else if hasDescription(t) {
|
||||||
|
printTaskDescription(l, t)
|
||||||
|
} else {
|
||||||
|
printNoDescriptionOrSummary(l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasSummary(t *taskfile.Task) bool {
|
||||||
|
return t.Summary != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func printTaskSummary(l *logger.Logger, t *taskfile.Task) {
|
||||||
|
lines := strings.Split(t.Summary, "\n")
|
||||||
|
for i, line := range lines {
|
||||||
|
notLastLine := i+1 < len(lines)
|
||||||
|
if notLastLine || line != "" {
|
||||||
|
l.Outf(line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printTaskName(l *logger.Logger, t *taskfile.Task) {
|
||||||
|
l.Outf("task: %s", t.Task)
|
||||||
|
l.Outf("")
|
||||||
|
}
|
||||||
|
|
||||||
|
func hasDescription(t *taskfile.Task) bool {
|
||||||
|
return t.Desc != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func printTaskDescription(l *logger.Logger, t *taskfile.Task) {
|
||||||
|
l.Outf(t.Desc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printNoDescriptionOrSummary(l *logger.Logger) {
|
||||||
|
l.Outf("(task does not have description or summary)")
|
||||||
|
}
|
||||||
|
|
||||||
|
func printTaskDependencies(l *logger.Logger, t *taskfile.Task) {
|
||||||
|
if len(t.Deps) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Outf("")
|
||||||
|
l.Outf("dependencies:")
|
||||||
|
|
||||||
|
for _, d := range t.Deps {
|
||||||
|
l.Outf(" - %s", d.Task)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printTaskCommands(l *logger.Logger, t *taskfile.Task) {
|
||||||
|
if len(t.Cmds) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Outf("")
|
||||||
|
l.Outf("commands:")
|
||||||
|
for _, c := range t.Cmds {
|
||||||
|
isCommand := c.Cmd != ""
|
||||||
|
if isCommand {
|
||||||
|
l.Outf(" - %s", c.Cmd)
|
||||||
|
} else {
|
||||||
|
l.Outf(" - Task: %s", c.Task)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
173
internal/summary/summary_test.go
Normal file
173
internal/summary/summary_test.go
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
package summary_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v2/internal/logger"
|
||||||
|
"github.com/go-task/task/v2/internal/summary"
|
||||||
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPrintsDependenciesIfPresent(t *testing.T) {
|
||||||
|
buffer, l := createDummyLogger()
|
||||||
|
task := &taskfile.Task{
|
||||||
|
Deps: []*taskfile.Dep{
|
||||||
|
{Task: "dep1"},
|
||||||
|
{Task: "dep2"},
|
||||||
|
{Task: "dep3"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
summary.PrintTask(&l, task)
|
||||||
|
|
||||||
|
assert.Contains(t, buffer.String(), "\ndependencies:\n - dep1\n - dep2\n - dep3\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func createDummyLogger() (*bytes.Buffer, logger.Logger) {
|
||||||
|
buffer := &bytes.Buffer{}
|
||||||
|
l := logger.Logger{
|
||||||
|
Stderr: buffer,
|
||||||
|
Stdout: buffer,
|
||||||
|
Verbose: false,
|
||||||
|
}
|
||||||
|
return buffer, l
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDoesNotPrintDependenciesIfMissing(t *testing.T) {
|
||||||
|
buffer, l := createDummyLogger()
|
||||||
|
task := &taskfile.Task{
|
||||||
|
Deps: []*taskfile.Dep{},
|
||||||
|
}
|
||||||
|
|
||||||
|
summary.PrintTask(&l, task)
|
||||||
|
|
||||||
|
assert.NotContains(t, buffer.String(), "dependencies:")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrintTaskName(t *testing.T) {
|
||||||
|
buffer, l := createDummyLogger()
|
||||||
|
task := &taskfile.Task{
|
||||||
|
Task: "my-task-name",
|
||||||
|
}
|
||||||
|
|
||||||
|
summary.PrintTask(&l, task)
|
||||||
|
|
||||||
|
assert.Contains(t, buffer.String(), "task: my-task-name\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrintTaskCommandsIfPresent(t *testing.T) {
|
||||||
|
buffer, l := createDummyLogger()
|
||||||
|
task := &taskfile.Task{
|
||||||
|
Cmds: []*taskfile.Cmd{
|
||||||
|
{Cmd: "command-1"},
|
||||||
|
{Cmd: "command-2"},
|
||||||
|
{Task: "task-1"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
summary.PrintTask(&l, task)
|
||||||
|
|
||||||
|
assert.Contains(t, buffer.String(), "\ncommands:\n")
|
||||||
|
assert.Contains(t, buffer.String(), "\n - command-1\n")
|
||||||
|
assert.Contains(t, buffer.String(), "\n - command-2\n")
|
||||||
|
assert.Contains(t, buffer.String(), "\n - Task: task-1\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDoesNotPrintCommandIfMissing(t *testing.T) {
|
||||||
|
buffer, l := createDummyLogger()
|
||||||
|
task := &taskfile.Task{
|
||||||
|
Cmds: []*taskfile.Cmd{},
|
||||||
|
}
|
||||||
|
|
||||||
|
summary.PrintTask(&l, task)
|
||||||
|
|
||||||
|
assert.NotContains(t, buffer.String(), "commands")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLayout(t *testing.T) {
|
||||||
|
buffer, l := createDummyLogger()
|
||||||
|
task := &taskfile.Task{
|
||||||
|
Task: "sample-task",
|
||||||
|
Summary: "line1\nline2\nline3\n",
|
||||||
|
Deps: []*taskfile.Dep{
|
||||||
|
{Task: "dependency"},
|
||||||
|
},
|
||||||
|
Cmds: []*taskfile.Cmd{
|
||||||
|
{Cmd: "command"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
summary.PrintTask(&l, task)
|
||||||
|
|
||||||
|
assert.Equal(t, expectedOutput(), buffer.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func expectedOutput() string {
|
||||||
|
expected := `task: sample-task
|
||||||
|
|
||||||
|
line1
|
||||||
|
line2
|
||||||
|
line3
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- dependency
|
||||||
|
|
||||||
|
commands:
|
||||||
|
- command
|
||||||
|
`
|
||||||
|
return expected
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrintDescriptionAsFallback(t *testing.T) {
|
||||||
|
buffer, l := createDummyLogger()
|
||||||
|
taskWithoutSummary := &taskfile.Task{
|
||||||
|
Desc: "description",
|
||||||
|
}
|
||||||
|
|
||||||
|
taskWithSummary := &taskfile.Task{
|
||||||
|
Desc: "description",
|
||||||
|
Summary: "summary",
|
||||||
|
}
|
||||||
|
taskWithoutSummaryOrDescription := &taskfile.Task{}
|
||||||
|
|
||||||
|
summary.PrintTask(&l, taskWithoutSummary)
|
||||||
|
|
||||||
|
assert.Contains(t, buffer.String(), "description")
|
||||||
|
|
||||||
|
buffer.Reset()
|
||||||
|
summary.PrintTask(&l, taskWithSummary)
|
||||||
|
|
||||||
|
assert.NotContains(t, buffer.String(), "description")
|
||||||
|
|
||||||
|
buffer.Reset()
|
||||||
|
summary.PrintTask(&l, taskWithoutSummaryOrDescription)
|
||||||
|
|
||||||
|
assert.Contains(t, buffer.String(), "\n(task does not have description or summary)\n")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrintAllWithSpaces(t *testing.T) {
|
||||||
|
buffer, l := createDummyLogger()
|
||||||
|
|
||||||
|
t1 := &taskfile.Task{Task: "t1"}
|
||||||
|
t2 := &taskfile.Task{Task: "t2"}
|
||||||
|
t3 := &taskfile.Task{Task: "t3"}
|
||||||
|
|
||||||
|
tasks := make(taskfile.Tasks, 3)
|
||||||
|
tasks["t1"] = t1
|
||||||
|
tasks["t2"] = t2
|
||||||
|
tasks["t3"] = t3
|
||||||
|
|
||||||
|
summary.PrintTasks(&l,
|
||||||
|
&taskfile.Taskfile{Tasks: tasks},
|
||||||
|
[]taskfile.Call{{Task: "t1"}, {Task: "t2"}, {Task: "t3"}})
|
||||||
|
|
||||||
|
assert.True(t, strings.HasPrefix(buffer.String(), "task: t1"))
|
||||||
|
assert.Contains(t, buffer.String(), "\n(task does not have description or summary)\n\n\ntask: t2")
|
||||||
|
assert.Contains(t, buffer.String(), "\n(task does not have description or summary)\n\n\ntask: t3")
|
||||||
|
|
||||||
|
}
|
||||||
@@ -20,19 +20,54 @@ func Merge(t1, t2 *Taskfile, namespaces ...string) error {
|
|||||||
if t2.Output != "" {
|
if t2.Output != "" {
|
||||||
t1.Output = t2.Output
|
t1.Output = t2.Output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if t1.Includes == nil {
|
||||||
|
t1.Includes = make(map[string]string)
|
||||||
|
}
|
||||||
for k, v := range t2.Includes {
|
for k, v := range t2.Includes {
|
||||||
t1.Includes[k] = v
|
t1.Includes[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if t1.Vars == nil {
|
||||||
|
t1.Vars = make(Vars)
|
||||||
|
}
|
||||||
for k, v := range t2.Vars {
|
for k, v := range t2.Vars {
|
||||||
t1.Vars[k] = v
|
t1.Vars[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if t1.Env == nil {
|
||||||
|
t1.Env = make(Vars)
|
||||||
|
}
|
||||||
|
for k, v := range t2.Env {
|
||||||
|
t1.Env[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
if t1.Tasks == nil {
|
||||||
|
t1.Tasks = make(Tasks)
|
||||||
|
}
|
||||||
for k, v := range t2.Tasks {
|
for k, v := range t2.Tasks {
|
||||||
|
// FIXME(@andreynering): Refactor this block, otherwise we can
|
||||||
|
// have serious side-effects in the future, since we're editing
|
||||||
|
// the original references instead of deep copying them.
|
||||||
|
|
||||||
t1.Tasks[taskNameWithNamespace(k, namespaces...)] = v
|
t1.Tasks[taskNameWithNamespace(k, namespaces...)] = v
|
||||||
|
|
||||||
|
for _, dep := range v.Deps {
|
||||||
|
dep.Task = taskNameWithNamespace(dep.Task, namespaces...)
|
||||||
|
}
|
||||||
|
for _, cmd := range v.Cmds {
|
||||||
|
if cmd.Task != "" {
|
||||||
|
cmd.Task = taskNameWithNamespace(cmd.Task, namespaces...)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func taskNameWithNamespace(taskName string, namespaces ...string) string {
|
func taskNameWithNamespace(taskName string, namespaces ...string) string {
|
||||||
|
if strings.HasPrefix(taskName, ":") {
|
||||||
|
return strings.TrimPrefix(taskName, ":")
|
||||||
|
}
|
||||||
return strings.Join(append(namespaces, taskName), NamespaceSeparator)
|
return strings.Join(append(namespaces, taskName), NamespaceSeparator)
|
||||||
}
|
}
|
||||||
|
|||||||
45
internal/taskfile/precondition.go
Normal file
45
internal/taskfile/precondition.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package taskfile
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrCantUnmarshalPrecondition is returned for invalid precond YAML.
|
||||||
|
ErrCantUnmarshalPrecondition = errors.New("task: Can't unmarshal precondition value")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Precondition represents a precondition necessary for a task to run
|
||||||
|
type Precondition struct {
|
||||||
|
Sh string
|
||||||
|
Msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalYAML implements yaml.Unmarshaler interface.
|
||||||
|
func (p *Precondition) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
|
var cmd string
|
||||||
|
|
||||||
|
if err := unmarshal(&cmd); err == nil {
|
||||||
|
p.Sh = cmd
|
||||||
|
p.Msg = fmt.Sprintf("`%s` failed", cmd)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var sh struct {
|
||||||
|
Sh string
|
||||||
|
Msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := unmarshal(&sh); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Sh = sh.Sh
|
||||||
|
p.Msg = sh.Msg
|
||||||
|
if p.Msg == "" {
|
||||||
|
p.Msg = fmt.Sprintf("%s failed", sh.Sh)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
48
internal/taskfile/precondition_test.go
Normal file
48
internal/taskfile/precondition_test.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package taskfile_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPreconditionParse(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
content string
|
||||||
|
v interface{}
|
||||||
|
expected interface{}
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"test -f foo.txt",
|
||||||
|
&taskfile.Precondition{},
|
||||||
|
&taskfile.Precondition{Sh: `test -f foo.txt`, Msg: "`test -f foo.txt` failed"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"sh: '[ 1 = 0 ]'",
|
||||||
|
&taskfile.Precondition{},
|
||||||
|
&taskfile.Precondition{Sh: "[ 1 = 0 ]", Msg: "[ 1 = 0 ] failed"},
|
||||||
|
},
|
||||||
|
{`
|
||||||
|
sh: "[ 1 = 2 ]"
|
||||||
|
msg: "1 is not 2"
|
||||||
|
`,
|
||||||
|
&taskfile.Precondition{},
|
||||||
|
&taskfile.Precondition{Sh: "[ 1 = 2 ]", Msg: "1 is not 2"},
|
||||||
|
},
|
||||||
|
{`
|
||||||
|
sh: "[ 1 = 2 ]"
|
||||||
|
msg: "1 is not 2"
|
||||||
|
`,
|
||||||
|
&taskfile.Precondition{},
|
||||||
|
&taskfile.Precondition{Sh: "[ 1 = 2 ]", Msg: "1 is not 2"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
err := yaml.Unmarshal([]byte(test.content), test.v)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, test.expected, test.v)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,19 +7,21 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/go-task/task/internal/taskfile"
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
|
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrIncludedTaskfilesCantHaveIncludes is returned when a included Taskfile contains includes
|
var (
|
||||||
var ErrIncludedTaskfilesCantHaveIncludes = errors.New("task: Included Taskfiles can't have includes. Please, move the include to the main Taskfile")
|
// ErrIncludedTaskfilesCantHaveIncludes is returned when a included Taskfile contains includes
|
||||||
|
ErrIncludedTaskfilesCantHaveIncludes = errors.New("task: Included Taskfiles can't have includes. Please, move the include to the main Taskfile")
|
||||||
|
)
|
||||||
|
|
||||||
// Taskfile reads a Taskfile for a given directory
|
// Taskfile reads a Taskfile for a given directory
|
||||||
func Taskfile(dir string) (*taskfile.Taskfile, error) {
|
func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
||||||
path := filepath.Join(dir, "Taskfile.yml")
|
path := filepath.Join(dir, entrypoint)
|
||||||
if _, err := os.Stat(path); err != nil {
|
if _, err := os.Stat(path); err != nil {
|
||||||
return nil, fmt.Errorf(`No Taskfile.yml found. Use "task --init" to create a new one`)
|
return nil, fmt.Errorf(`task: No Taskfile found on "%s". Use "task --init" to create a new one`, path)
|
||||||
}
|
}
|
||||||
t, err := readTaskfile(path)
|
t, err := readTaskfile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/go-task/task/internal/taskfile"
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
|
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,22 +1,24 @@
|
|||||||
package taskfile
|
package taskfile
|
||||||
|
|
||||||
// Tasks representas a group of tasks
|
// Tasks represents a group of tasks
|
||||||
type Tasks map[string]*Task
|
type Tasks map[string]*Task
|
||||||
|
|
||||||
// Task represents a task
|
// Task represents a task
|
||||||
type Task struct {
|
type Task struct {
|
||||||
Task string
|
Task string
|
||||||
Cmds []*Cmd
|
Cmds []*Cmd
|
||||||
Deps []*Dep
|
Deps []*Dep
|
||||||
Desc string
|
Desc string
|
||||||
Sources []string
|
Summary string
|
||||||
Generates []string
|
Sources []string
|
||||||
Status []string
|
Generates []string
|
||||||
Dir string
|
Status []string
|
||||||
Vars Vars
|
Preconditions []*Precondition
|
||||||
Env Vars
|
Dir string
|
||||||
Silent bool
|
Vars Vars
|
||||||
Method string
|
Env Vars
|
||||||
Prefix string
|
Silent bool
|
||||||
IgnoreError bool `yaml:"ignore_error"`
|
Method string
|
||||||
|
Prefix string
|
||||||
|
IgnoreError bool `yaml:"ignore_error"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ type Taskfile struct {
|
|||||||
Output string
|
Output string
|
||||||
Includes map[string]string
|
Includes map[string]string
|
||||||
Vars Vars
|
Vars Vars
|
||||||
|
Env Vars
|
||||||
Tasks Tasks
|
Tasks Tasks
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,6 +24,7 @@ func (tf *Taskfile) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|||||||
Output string
|
Output string
|
||||||
Includes map[string]string
|
Includes map[string]string
|
||||||
Vars Vars
|
Vars Vars
|
||||||
|
Env Vars
|
||||||
Tasks Tasks
|
Tasks Tasks
|
||||||
}
|
}
|
||||||
if err := unmarshal(&taskfile); err != nil {
|
if err := unmarshal(&taskfile); err != nil {
|
||||||
@@ -33,9 +35,13 @@ func (tf *Taskfile) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|||||||
tf.Output = taskfile.Output
|
tf.Output = taskfile.Output
|
||||||
tf.Includes = taskfile.Includes
|
tf.Includes = taskfile.Includes
|
||||||
tf.Vars = taskfile.Vars
|
tf.Vars = taskfile.Vars
|
||||||
|
tf.Env = taskfile.Env
|
||||||
tf.Tasks = taskfile.Tasks
|
tf.Tasks = taskfile.Tasks
|
||||||
if tf.Expansions <= 0 {
|
if tf.Expansions <= 0 {
|
||||||
tf.Expansions = 2
|
tf.Expansions = 2
|
||||||
}
|
}
|
||||||
|
if tf.Vars == nil {
|
||||||
|
tf.Vars = make(Vars)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package taskfile_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-task/task/internal/taskfile"
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
package version
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/Masterminds/semver"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
v1 = mustVersion("1")
|
|
||||||
v2 = mustVersion("2")
|
|
||||||
v21 = mustVersion("2.1")
|
|
||||||
v22 = mustVersion("2.2")
|
|
||||||
v23 = mustVersion("2.3")
|
|
||||||
)
|
|
||||||
|
|
||||||
// IsV1 returns if is a given Taskfile version is version 1
|
|
||||||
func IsV1(v *semver.Constraints) bool {
|
|
||||||
return v.Check(v1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsV2 returns if is a given Taskfile version is at least version 2
|
|
||||||
func IsV2(v *semver.Constraints) bool {
|
|
||||||
return v.Check(v2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsV21 returns if is a given Taskfile version is at least version 2.1
|
|
||||||
func IsV21(v *semver.Constraints) bool {
|
|
||||||
return v.Check(v21)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsV22 returns if is a given Taskfile version is at least version 2.2
|
|
||||||
func IsV22(v *semver.Constraints) bool {
|
|
||||||
return v.Check(v22)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsV23 returns if is a given Taskfile version is at least version 2.3
|
|
||||||
func IsV23(v *semver.Constraints) bool {
|
|
||||||
return v.Check(v23)
|
|
||||||
}
|
|
||||||
|
|
||||||
func mustVersion(s string) *semver.Version {
|
|
||||||
v, err := semver.NewVersion(s)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/go-task/task/internal/taskfile"
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Templater is a help struct that allow us to call "replaceX" funcs multiple
|
// Templater is a help struct that allow us to call "replaceX" funcs multiple
|
||||||
|
|||||||
31
precondition.go
Normal file
31
precondition.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package task
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v2/internal/execext"
|
||||||
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrPreconditionFailed is returned when a precondition fails
|
||||||
|
ErrPreconditionFailed = errors.New("task: precondition not met")
|
||||||
|
)
|
||||||
|
|
||||||
|
func (e *Executor) areTaskPreconditionsMet(ctx context.Context, t *taskfile.Task) (bool, error) {
|
||||||
|
for _, p := range t.Preconditions {
|
||||||
|
err := execext.RunCommand(ctx, &execext.RunCommandOptions{
|
||||||
|
Command: p.Sh,
|
||||||
|
Dir: t.Dir,
|
||||||
|
Env: getEnviron(t),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
e.Logger.Errf("task: %s", p.Msg)
|
||||||
|
return false, ErrPreconditionFailed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
34
status.go
34
status.go
@@ -4,19 +4,19 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/go-task/task/internal/execext"
|
"github.com/go-task/task/v2/internal/execext"
|
||||||
"github.com/go-task/task/internal/status"
|
"github.com/go-task/task/v2/internal/status"
|
||||||
"github.com/go-task/task/internal/taskfile"
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Status returns an error if any the of given tasks is not up-to-date
|
// Status returns an error if any the of given tasks is not up-to-date
|
||||||
func (e *Executor) Status(calls ...taskfile.Call) error {
|
func (e *Executor) Status(ctx context.Context, calls ...taskfile.Call) error {
|
||||||
for _, call := range calls {
|
for _, call := range calls {
|
||||||
t, err := e.CompiledTask(call)
|
t, err := e.CompiledTask(call)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
isUpToDate, err := isTaskUpToDate(e.Context, t)
|
isUpToDate, err := e.isTaskUpToDate(ctx, t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -27,12 +27,12 @@ func (e *Executor) Status(calls ...taskfile.Call) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func isTaskUpToDate(ctx context.Context, t *taskfile.Task) (bool, error) {
|
func (e *Executor) isTaskUpToDate(ctx context.Context, t *taskfile.Task) (bool, error) {
|
||||||
if len(t.Status) > 0 {
|
if len(t.Status) > 0 {
|
||||||
return isTaskUpToDateStatus(ctx, t)
|
return e.isTaskUpToDateStatus(ctx, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
checker, err := getStatusChecker(t)
|
checker, err := e.getStatusChecker(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@@ -40,15 +40,15 @@ func isTaskUpToDate(ctx context.Context, t *taskfile.Task) (bool, error) {
|
|||||||
return checker.IsUpToDate()
|
return checker.IsUpToDate()
|
||||||
}
|
}
|
||||||
|
|
||||||
func statusOnError(t *taskfile.Task) error {
|
func (e *Executor) statusOnError(t *taskfile.Task) error {
|
||||||
checker, err := getStatusChecker(t)
|
checker, err := e.getStatusChecker(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return checker.OnError()
|
return checker.OnError()
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStatusChecker(t *taskfile.Task) (status.Checker, error) {
|
func (e *Executor) getStatusChecker(t *taskfile.Task) (status.Checker, error) {
|
||||||
switch t.Method {
|
switch t.Method {
|
||||||
case "", "timestamp":
|
case "", "timestamp":
|
||||||
return &status.Timestamp{
|
return &status.Timestamp{
|
||||||
@@ -58,9 +58,11 @@ func getStatusChecker(t *taskfile.Task) (status.Checker, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
case "checksum":
|
case "checksum":
|
||||||
return &status.Checksum{
|
return &status.Checksum{
|
||||||
Dir: t.Dir,
|
Dir: t.Dir,
|
||||||
Task: t.Task,
|
Task: t.Task,
|
||||||
Sources: t.Sources,
|
Sources: t.Sources,
|
||||||
|
Generates: t.Generates,
|
||||||
|
Dry: e.Dry,
|
||||||
}, nil
|
}, nil
|
||||||
case "none":
|
case "none":
|
||||||
return status.None{}, nil
|
return status.None{}, nil
|
||||||
@@ -69,7 +71,7 @@ func getStatusChecker(t *taskfile.Task) (status.Checker, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isTaskUpToDateStatus(ctx context.Context, t *taskfile.Task) (bool, error) {
|
func (e *Executor) isTaskUpToDateStatus(ctx context.Context, t *taskfile.Task) (bool, error) {
|
||||||
for _, s := range t.Status {
|
for _, s := range t.Status {
|
||||||
err := execext.RunCommand(ctx, &execext.RunCommandOptions{
|
err := execext.RunCommand(ctx, &execext.RunCommandOptions{
|
||||||
Command: s,
|
Command: s,
|
||||||
@@ -77,8 +79,10 @@ func isTaskUpToDateStatus(ctx context.Context, t *taskfile.Task) (bool, error) {
|
|||||||
Env: getEnviron(t),
|
Env: getEnviron(t),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
e.Logger.VerboseOutf("task: status command %s exited non-zero: %s", s, err)
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
e.Logger.VerboseOutf("task: status command %s exited zero", s)
|
||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|||||||
179
task.go
179
task.go
@@ -2,22 +2,24 @@ package task
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/go-task/task/internal/compiler"
|
"github.com/go-task/task/v2/internal/compiler"
|
||||||
compilerv1 "github.com/go-task/task/internal/compiler/v1"
|
compilerv1 "github.com/go-task/task/v2/internal/compiler/v1"
|
||||||
compilerv2 "github.com/go-task/task/internal/compiler/v2"
|
compilerv2 "github.com/go-task/task/v2/internal/compiler/v2"
|
||||||
"github.com/go-task/task/internal/execext"
|
"github.com/go-task/task/v2/internal/execext"
|
||||||
"github.com/go-task/task/internal/logger"
|
"github.com/go-task/task/v2/internal/logger"
|
||||||
"github.com/go-task/task/internal/output"
|
"github.com/go-task/task/v2/internal/output"
|
||||||
"github.com/go-task/task/internal/taskfile"
|
"github.com/go-task/task/v2/internal/summary"
|
||||||
"github.com/go-task/task/internal/taskfile/read"
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
"github.com/go-task/task/internal/taskfile/version"
|
"github.com/go-task/task/v2/internal/taskfile/read"
|
||||||
|
|
||||||
"github.com/Masterminds/semver"
|
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,30 +32,33 @@ const (
|
|||||||
// Executor executes a Taskfile
|
// Executor executes a Taskfile
|
||||||
type Executor struct {
|
type Executor struct {
|
||||||
Taskfile *taskfile.Taskfile
|
Taskfile *taskfile.Taskfile
|
||||||
Dir string
|
|
||||||
Force bool
|
|
||||||
Watch bool
|
|
||||||
Verbose bool
|
|
||||||
Silent bool
|
|
||||||
Dry bool
|
|
||||||
|
|
||||||
Context context.Context
|
Dir string
|
||||||
|
Entrypoint string
|
||||||
|
Force bool
|
||||||
|
Watch bool
|
||||||
|
Verbose bool
|
||||||
|
Silent bool
|
||||||
|
Dry bool
|
||||||
|
Summary bool
|
||||||
|
|
||||||
Stdin io.Reader
|
Stdin io.Reader
|
||||||
Stdout io.Writer
|
Stdout io.Writer
|
||||||
Stderr io.Writer
|
Stderr io.Writer
|
||||||
|
|
||||||
Logger *logger.Logger
|
Logger *logger.Logger
|
||||||
Compiler compiler.Compiler
|
Compiler compiler.Compiler
|
||||||
Output output.Output
|
Output output.Output
|
||||||
|
OutputStyle string
|
||||||
|
|
||||||
taskvars taskfile.Vars
|
taskvars taskfile.Vars
|
||||||
|
|
||||||
taskCallCount map[string]*int32
|
taskCallCount map[string]*int32
|
||||||
|
mkdirMutexMap map[string]*sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run runs Task
|
// Run runs Task
|
||||||
func (e *Executor) Run(calls ...taskfile.Call) error {
|
func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error {
|
||||||
// check if given tasks exist
|
// check if given tasks exist
|
||||||
for _, c := range calls {
|
for _, c := range calls {
|
||||||
if _, ok := e.Taskfile.Tasks[c.Task]; !ok {
|
if _, ok := e.Taskfile.Tasks[c.Task]; !ok {
|
||||||
@@ -63,12 +68,17 @@ func (e *Executor) Run(calls ...taskfile.Call) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if e.Summary {
|
||||||
|
summary.PrintTasks(e.Logger, e.Taskfile, calls)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if e.Watch {
|
if e.Watch {
|
||||||
return e.watchTasks(calls...)
|
return e.watchTasks(calls...)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range calls {
|
for _, c := range calls {
|
||||||
if err := e.RunTask(e.Context, c); err != nil {
|
if err := e.RunTask(ctx, c); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,8 +87,12 @@ func (e *Executor) Run(calls ...taskfile.Call) error {
|
|||||||
|
|
||||||
// Setup setups Executor's internal state
|
// Setup setups Executor's internal state
|
||||||
func (e *Executor) Setup() error {
|
func (e *Executor) Setup() error {
|
||||||
|
if e.Entrypoint == "" {
|
||||||
|
e.Entrypoint = "Taskfile.yml"
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
e.Taskfile, err = read.Taskfile(e.Dir)
|
e.Taskfile, err = read.Taskfile(e.Dir, e.Entrypoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -87,14 +101,6 @@ func (e *Executor) Setup() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err := semver.NewConstraint(e.Taskfile.Version)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf(`task: could not parse taskfile version "%s": %v`, e.Taskfile.Version, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if e.Context == nil {
|
|
||||||
e.Context = context.Background()
|
|
||||||
}
|
|
||||||
if e.Stdin == nil {
|
if e.Stdin == nil {
|
||||||
e.Stdin = os.Stdin
|
e.Stdin = os.Stdin
|
||||||
}
|
}
|
||||||
@@ -109,14 +115,30 @@ func (e *Executor) Setup() error {
|
|||||||
Stderr: e.Stderr,
|
Stderr: e.Stderr,
|
||||||
Verbose: e.Verbose,
|
Verbose: e.Verbose,
|
||||||
}
|
}
|
||||||
switch {
|
|
||||||
case version.IsV1(v):
|
v, err := strconv.ParseFloat(e.Taskfile.Version, 64)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(`task: Could not parse taskfile version "%s": %v`, e.Taskfile.Version, err)
|
||||||
|
}
|
||||||
|
// consider as equal to the greater version if round
|
||||||
|
if v == 2.0 {
|
||||||
|
v = 2.6
|
||||||
|
}
|
||||||
|
|
||||||
|
if v < 1 {
|
||||||
|
return fmt.Errorf(`task: Taskfile version should be greater or equal to v1`)
|
||||||
|
}
|
||||||
|
if v > 2.6 {
|
||||||
|
return fmt.Errorf(`task: Taskfile versions greater than v2.6 not implemented in the version of Task`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v < 2 {
|
||||||
e.Compiler = &compilerv1.CompilerV1{
|
e.Compiler = &compilerv1.CompilerV1{
|
||||||
Dir: e.Dir,
|
Dir: e.Dir,
|
||||||
Vars: e.taskvars,
|
Vars: e.taskvars,
|
||||||
Logger: e.Logger,
|
Logger: e.Logger,
|
||||||
}
|
}
|
||||||
case version.IsV2(v), version.IsV21(v), version.IsV22(v):
|
} else { // v >= 2
|
||||||
e.Compiler = &compilerv2.CompilerV2{
|
e.Compiler = &compilerv2.CompilerV2{
|
||||||
Dir: e.Dir,
|
Dir: e.Dir,
|
||||||
Taskvars: e.taskvars,
|
Taskvars: e.taskvars,
|
||||||
@@ -124,16 +146,18 @@ func (e *Executor) Setup() error {
|
|||||||
Expansions: e.Taskfile.Expansions,
|
Expansions: e.Taskfile.Expansions,
|
||||||
Logger: e.Logger,
|
Logger: e.Logger,
|
||||||
}
|
}
|
||||||
case version.IsV23(v):
|
|
||||||
return fmt.Errorf(`task: Taskfile versions greater than v2.3 not implemented in the version of Task`)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !version.IsV21(v) && e.Taskfile.Output != "" {
|
if v < 2.1 && e.Taskfile.Output != "" {
|
||||||
return fmt.Errorf(`task: Taskfile option "output" is only available starting on Taskfile version v2.1`)
|
return fmt.Errorf(`task: Taskfile option "output" is only available starting on Taskfile version v2.1`)
|
||||||
}
|
}
|
||||||
if !version.IsV22(v) && len(e.Taskfile.Includes) > 0 {
|
if v < 2.2 && len(e.Taskfile.Includes) > 0 {
|
||||||
return fmt.Errorf(`task: Including Taskfiles is only available starting on Taskfile version v2.2`)
|
return fmt.Errorf(`task: Including Taskfiles is only available starting on Taskfile version v2.2`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if e.OutputStyle != "" {
|
||||||
|
e.Taskfile.Output = e.OutputStyle
|
||||||
|
}
|
||||||
switch e.Taskfile.Output {
|
switch e.Taskfile.Output {
|
||||||
case "", "interleaved":
|
case "", "interleaved":
|
||||||
e.Output = output.Interleaved{}
|
e.Output = output.Interleaved{}
|
||||||
@@ -145,8 +169,8 @@ func (e *Executor) Setup() error {
|
|||||||
return fmt.Errorf(`task: output option "%s" not recognized`, e.Taskfile.Output)
|
return fmt.Errorf(`task: output option "%s" not recognized`, e.Taskfile.Output)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !version.IsV21(v) {
|
if v <= 2.1 {
|
||||||
err := fmt.Errorf(`task: Taskfile option "ignore_error" is only available starting on Taskfile version v2.1`)
|
err := errors.New(`task: Taskfile option "ignore_error" is only available starting on Taskfile version v2.1`)
|
||||||
|
|
||||||
for _, task := range e.Taskfile.Tasks {
|
for _, task := range e.Taskfile.Tasks {
|
||||||
if task.IgnoreError {
|
if task.IgnoreError {
|
||||||
@@ -160,9 +184,19 @@ func (e *Executor) Setup() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v < 2.6 {
|
||||||
|
for _, task := range e.Taskfile.Tasks {
|
||||||
|
if len(task.Preconditions) > 0 {
|
||||||
|
return errors.New(`task: Task option "preconditions" is only available starting on Taskfile version v2.6`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
e.taskCallCount = make(map[string]*int32, len(e.Taskfile.Tasks))
|
e.taskCallCount = make(map[string]*int32, len(e.Taskfile.Tasks))
|
||||||
|
e.mkdirMutexMap = make(map[string]*sync.Mutex, len(e.Taskfile.Tasks))
|
||||||
for k := range e.Taskfile.Tasks {
|
for k := range e.Taskfile.Tasks {
|
||||||
e.taskCallCount[k] = new(int32)
|
e.taskCallCount[k] = new(int32)
|
||||||
|
e.mkdirMutexMap[k] = &sync.Mutex{}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -182,11 +216,17 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !e.Force {
|
if !e.Force {
|
||||||
upToDate, err := isTaskUpToDate(ctx, t)
|
preCondMet, err := e.areTaskPreconditionsMet(ctx, t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if upToDate {
|
|
||||||
|
upToDate, err := e.isTaskUpToDate(ctx, t)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if upToDate && preCondMet {
|
||||||
if !e.Silent {
|
if !e.Silent {
|
||||||
e.Logger.Errf(`task: Task "%s" is up to date`, t.Task)
|
e.Logger.Errf(`task: Task "%s" is up to date`, t.Task)
|
||||||
}
|
}
|
||||||
@@ -194,9 +234,13 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := e.mkdir(t); err != nil {
|
||||||
|
e.Logger.Errf("task: cannot make directory %q: %v", t.Dir, err)
|
||||||
|
}
|
||||||
|
|
||||||
for i := range t.Cmds {
|
for i := range t.Cmds {
|
||||||
if err := e.runCommand(ctx, t, call, i); err != nil {
|
if err := e.runCommand(ctx, t, call, i); err != nil {
|
||||||
if err2 := statusOnError(t); err2 != nil {
|
if err2 := e.statusOnError(t); err2 != nil {
|
||||||
e.Logger.VerboseErrf("task: error cleaning status on error: %v", err2)
|
e.Logger.VerboseErrf("task: error cleaning status on error: %v", err2)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,6 +255,23 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Executor) mkdir(t *taskfile.Task) error {
|
||||||
|
if t.Dir == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex := e.mkdirMutexMap[t.Task]
|
||||||
|
mutex.Lock()
|
||||||
|
defer mutex.Unlock()
|
||||||
|
|
||||||
|
if _, err := os.Stat(t.Dir); os.IsNotExist(err) {
|
||||||
|
if err := os.MkdirAll(t.Dir, 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (e *Executor) runDeps(ctx context.Context, t *taskfile.Task) error {
|
func (e *Executor) runDeps(ctx context.Context, t *taskfile.Task) error {
|
||||||
g, ctx := errgroup.WithContext(ctx)
|
g, ctx := errgroup.WithContext(ctx)
|
||||||
|
|
||||||
@@ -218,7 +279,11 @@ func (e *Executor) runDeps(ctx context.Context, t *taskfile.Task) error {
|
|||||||
d := d
|
d := d
|
||||||
|
|
||||||
g.Go(func() error {
|
g.Go(func() error {
|
||||||
return e.RunTask(ctx, taskfile.Call{Task: d.Task, Vars: d.Vars})
|
err := e.RunTask(ctx, taskfile.Call{Task: d.Task, Vars: d.Vars})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +295,11 @@ func (e *Executor) runCommand(ctx context.Context, t *taskfile.Task, call taskfi
|
|||||||
|
|
||||||
switch {
|
switch {
|
||||||
case cmd.Task != "":
|
case cmd.Task != "":
|
||||||
return e.RunTask(ctx, taskfile.Call{Task: cmd.Task, Vars: cmd.Vars})
|
err := e.RunTask(ctx, taskfile.Call{Task: cmd.Task, Vars: cmd.Vars})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
case cmd.Cmd != "":
|
case cmd.Cmd != "":
|
||||||
if e.Verbose || (!cmd.Silent && !t.Silent && !e.Silent) {
|
if e.Verbose || (!cmd.Silent && !t.Silent && !e.Silent) {
|
||||||
e.Logger.Errf(cmd.Cmd)
|
e.Logger.Errf(cmd.Cmd)
|
||||||
@@ -242,8 +311,18 @@ func (e *Executor) runCommand(ctx context.Context, t *taskfile.Task, call taskfi
|
|||||||
|
|
||||||
stdOut := e.Output.WrapWriter(e.Stdout, t.Prefix)
|
stdOut := e.Output.WrapWriter(e.Stdout, t.Prefix)
|
||||||
stdErr := e.Output.WrapWriter(e.Stderr, t.Prefix)
|
stdErr := e.Output.WrapWriter(e.Stderr, t.Prefix)
|
||||||
defer stdOut.Close()
|
defer func() {
|
||||||
defer stdErr.Close()
|
if _, ok := stdOut.(*os.File); !ok {
|
||||||
|
if closer, ok := stdOut.(io.Closer); ok {
|
||||||
|
closer.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, ok := stdErr.(*os.File); !ok {
|
||||||
|
if closer, ok := stdErr.(io.Closer); ok {
|
||||||
|
closer.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
err := execext.RunCommand(ctx, &execext.RunCommandOptions{
|
err := execext.RunCommand(ctx, &execext.RunCommandOptions{
|
||||||
Command: cmd.Cmd,
|
Command: cmd.Cmd,
|
||||||
@@ -268,9 +347,9 @@ func getEnviron(t *taskfile.Task) []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
envs := os.Environ()
|
environ := os.Environ()
|
||||||
for k, v := range t.Env.ToStringMap() {
|
for k, v := range t.Env.ToStringMap() {
|
||||||
envs = append(envs, fmt.Sprintf("%s=%s", k, v))
|
environ = append(environ, fmt.Sprintf("%s=%s", k, v))
|
||||||
}
|
}
|
||||||
return envs
|
return environ
|
||||||
}
|
}
|
||||||
|
|||||||
265
task_test.go
265
task_test.go
@@ -2,17 +2,18 @@ package task_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-task/task"
|
"github.com/go-task/task/v2"
|
||||||
"github.com/go-task/task/internal/taskfile"
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
|
|
||||||
"github.com/mitchellh/go-homedir"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -40,7 +41,7 @@ func (fct fileContentTest) Run(t *testing.T) {
|
|||||||
Stderr: ioutil.Discard,
|
Stderr: ioutil.Discard,
|
||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup(), "e.Setup()")
|
assert.NoError(t, e.Setup(), "e.Setup()")
|
||||||
assert.NoError(t, e.Run(taskfile.Call{Task: fct.Target}), "e.Run(target)")
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: fct.Target}), "e.Run(target)")
|
||||||
|
|
||||||
for name, expectContent := range fct.Files {
|
for name, expectContent := range fct.Files {
|
||||||
t.Run(fct.name(name), func(t *testing.T) {
|
t.Run(fct.name(name), func(t *testing.T) {
|
||||||
@@ -61,7 +62,8 @@ func TestEnv(t *testing.T) {
|
|||||||
Target: "default",
|
Target: "default",
|
||||||
TrimSpace: false,
|
TrimSpace: false,
|
||||||
Files: map[string]string{
|
Files: map[string]string{
|
||||||
"env.txt": "GOOS='linux' GOARCH='amd64' CGO_ENABLED='0'\n",
|
"local.txt": "GOOS='linux' GOARCH='amd64' CGO_ENABLED='0'\n",
|
||||||
|
"global.txt": "FOO='foo' BAR='overriden' BAZ='baz'\n",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
tt.Run(t)
|
tt.Run(t)
|
||||||
@@ -177,7 +179,7 @@ func TestVarsInvalidTmpl(t *testing.T) {
|
|||||||
Stderr: ioutil.Discard,
|
Stderr: ioutil.Discard,
|
||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup(), "e.Setup()")
|
assert.NoError(t, e.Setup(), "e.Setup()")
|
||||||
assert.EqualError(t, e.Run(taskfile.Call{Task: target}), expectError, "e.Run(target)")
|
assert.EqualError(t, e.Run(context.Background(), taskfile.Call{Task: target}), expectError, "e.Run(target)")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParams(t *testing.T) {
|
func TestParams(t *testing.T) {
|
||||||
@@ -229,12 +231,12 @@ func TestDeps(t *testing.T) {
|
|||||||
Stderr: ioutil.Discard,
|
Stderr: ioutil.Discard,
|
||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup())
|
assert.NoError(t, e.Setup())
|
||||||
assert.NoError(t, e.Run(taskfile.Call{Task: "default"}))
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "default"}))
|
||||||
|
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
f = filepath.Join(dir, f)
|
f = filepath.Join(dir, f)
|
||||||
if _, err := os.Stat(f); err != nil {
|
if _, err := os.Stat(f); err != nil {
|
||||||
t.Errorf("File %s should exists", f)
|
t.Errorf("File %s should exist", f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,7 +248,7 @@ func TestStatus(t *testing.T) {
|
|||||||
_ = os.Remove(file)
|
_ = os.Remove(file)
|
||||||
|
|
||||||
if _, err := os.Stat(file); err == nil {
|
if _, err := os.Stat(file); err == nil {
|
||||||
t.Errorf("File should not exists: %v", err)
|
t.Errorf("File should not exist: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var buff bytes.Buffer
|
var buff bytes.Buffer
|
||||||
@@ -257,35 +259,79 @@ func TestStatus(t *testing.T) {
|
|||||||
Silent: true,
|
Silent: true,
|
||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup())
|
assert.NoError(t, e.Setup())
|
||||||
assert.NoError(t, e.Run(taskfile.Call{Task: "gen-foo"}))
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "gen-foo"}))
|
||||||
|
|
||||||
if _, err := os.Stat(file); err != nil {
|
if _, err := os.Stat(file); err != nil {
|
||||||
t.Errorf("File should exists: %v", err)
|
t.Errorf("File should exist: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Silent = false
|
e.Silent = false
|
||||||
assert.NoError(t, e.Run(taskfile.Call{Task: "gen-foo"}))
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "gen-foo"}))
|
||||||
|
|
||||||
if buff.String() != `task: Task "gen-foo" is up to date`+"\n" {
|
if buff.String() != `task: Task "gen-foo" is up to date`+"\n" {
|
||||||
t.Errorf("Wrong output message: %s", buff.String())
|
t.Errorf("Wrong output message: %s", buff.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPrecondition(t *testing.T) {
|
||||||
|
const dir = "testdata/precondition"
|
||||||
|
|
||||||
|
var buff bytes.Buffer
|
||||||
|
e := &task.Executor{
|
||||||
|
Dir: dir,
|
||||||
|
Stdout: &buff,
|
||||||
|
Stderr: &buff,
|
||||||
|
}
|
||||||
|
|
||||||
|
// A precondition that has been met
|
||||||
|
assert.NoError(t, e.Setup())
|
||||||
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "foo"}))
|
||||||
|
if buff.String() != "" {
|
||||||
|
t.Errorf("Got Output when none was expected: %s", buff.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// A precondition that was not met
|
||||||
|
assert.Error(t, e.Run(context.Background(), taskfile.Call{Task: "impossible"}))
|
||||||
|
|
||||||
|
if buff.String() != "task: 1 != 0 obviously!\n" {
|
||||||
|
t.Errorf("Wrong output message: %s", buff.String())
|
||||||
|
}
|
||||||
|
buff.Reset()
|
||||||
|
|
||||||
|
// Calling a task with a precondition in a dependency fails the task
|
||||||
|
assert.Error(t, e.Run(context.Background(), taskfile.Call{Task: "depends_on_impossible"}))
|
||||||
|
|
||||||
|
if buff.String() != "task: 1 != 0 obviously!\n" {
|
||||||
|
t.Errorf("Wrong output message: %s", buff.String())
|
||||||
|
}
|
||||||
|
buff.Reset()
|
||||||
|
|
||||||
|
// Calling a task with a precondition in a cmd fails the task
|
||||||
|
assert.Error(t, e.Run(context.Background(), taskfile.Call{Task: "executes_failing_task_as_cmd"}))
|
||||||
|
if buff.String() != "task: 1 != 0 obviously!\n" {
|
||||||
|
t.Errorf("Wrong output message: %s", buff.String())
|
||||||
|
}
|
||||||
|
buff.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
func TestGenerates(t *testing.T) {
|
func TestGenerates(t *testing.T) {
|
||||||
var srcTask = "sub/src.txt"
|
const (
|
||||||
var relTask = "rel.txt"
|
srcTask = "sub/src.txt"
|
||||||
var absTask = "abs.txt"
|
relTask = "rel.txt"
|
||||||
|
absTask = "abs.txt"
|
||||||
|
fileWithSpaces = "my text file.txt"
|
||||||
|
)
|
||||||
|
|
||||||
// This test does not work with a relative dir.
|
// This test does not work with a relative dir.
|
||||||
dir, err := filepath.Abs("testdata/generates")
|
dir, err := filepath.Abs("testdata/generates")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
var srcFile = filepath.Join(dir, srcTask)
|
var srcFile = filepath.Join(dir, srcTask)
|
||||||
|
|
||||||
for _, task := range []string{srcTask, relTask, absTask} {
|
for _, task := range []string{srcTask, relTask, absTask, fileWithSpaces} {
|
||||||
path := filepath.Join(dir, task)
|
path := filepath.Join(dir, task)
|
||||||
_ = os.Remove(path)
|
_ = os.Remove(path)
|
||||||
if _, err := os.Stat(path); err == nil {
|
if _, err := os.Stat(path); err == nil {
|
||||||
t.Errorf("File should not exists: %v", err)
|
t.Errorf("File should not exist: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,19 +343,19 @@ func TestGenerates(t *testing.T) {
|
|||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup())
|
assert.NoError(t, e.Setup())
|
||||||
|
|
||||||
for _, theTask := range []string{relTask, absTask} {
|
for _, theTask := range []string{relTask, absTask, fileWithSpaces} {
|
||||||
var destFile = filepath.Join(dir, theTask)
|
var destFile = filepath.Join(dir, theTask)
|
||||||
var upToDate = fmt.Sprintf("task: Task \"%s\" is up to date\n", srcTask) +
|
var upToDate = fmt.Sprintf("task: Task \"%s\" is up to date\n", srcTask) +
|
||||||
fmt.Sprintf("task: Task \"%s\" is up to date\n", theTask)
|
fmt.Sprintf("task: Task \"%s\" is up to date\n", theTask)
|
||||||
|
|
||||||
// Run task for the first time.
|
// Run task for the first time.
|
||||||
assert.NoError(t, e.Run(taskfile.Call{Task: theTask}))
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: theTask}))
|
||||||
|
|
||||||
if _, err := os.Stat(srcFile); err != nil {
|
if _, err := os.Stat(srcFile); err != nil {
|
||||||
t.Errorf("File should exists: %v", err)
|
t.Errorf("File should exist: %v", err)
|
||||||
}
|
}
|
||||||
if _, err := os.Stat(destFile); err != nil {
|
if _, err := os.Stat(destFile); err != nil {
|
||||||
t.Errorf("File should exists: %v", err)
|
t.Errorf("File should exist: %v", err)
|
||||||
}
|
}
|
||||||
// Ensure task was not incorrectly found to be up-to-date on first run.
|
// Ensure task was not incorrectly found to be up-to-date on first run.
|
||||||
if buff.String() == upToDate {
|
if buff.String() == upToDate {
|
||||||
@@ -318,7 +364,7 @@ func TestGenerates(t *testing.T) {
|
|||||||
buff.Reset()
|
buff.Reset()
|
||||||
|
|
||||||
// Re-run task to ensure it's now found to be up-to-date.
|
// Re-run task to ensure it's now found to be up-to-date.
|
||||||
assert.NoError(t, e.Run(taskfile.Call{Task: theTask}))
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: theTask}))
|
||||||
if buff.String() != upToDate {
|
if buff.String() != upToDate {
|
||||||
t.Errorf("Wrong output message: %s", buff.String())
|
t.Errorf("Wrong output message: %s", buff.String())
|
||||||
}
|
}
|
||||||
@@ -349,14 +395,14 @@ func TestStatusChecksum(t *testing.T) {
|
|||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup())
|
assert.NoError(t, e.Setup())
|
||||||
|
|
||||||
assert.NoError(t, e.Run(taskfile.Call{Task: "build"}))
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "build"}))
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
_, err := os.Stat(filepath.Join(dir, f))
|
_, err := os.Stat(filepath.Join(dir, f))
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
buff.Reset()
|
buff.Reset()
|
||||||
assert.NoError(t, e.Run(taskfile.Call{Task: "build"}))
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "build"}))
|
||||||
assert.Equal(t, `task: Task "build" is up to date`+"\n", buff.String())
|
assert.Equal(t, `task: Task "build" is up to date`+"\n", buff.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,7 +412,7 @@ func TestInit(t *testing.T) {
|
|||||||
|
|
||||||
_ = os.Remove(file)
|
_ = os.Remove(file)
|
||||||
if _, err := os.Stat(file); err == nil {
|
if _, err := os.Stat(file); err == nil {
|
||||||
t.Errorf("Taskfile.yml should not exists")
|
t.Errorf("Taskfile.yml should not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := task.InitTaskfile(ioutil.Discard, dir); err != nil {
|
if err := task.InitTaskfile(ioutil.Discard, dir); err != nil {
|
||||||
@@ -374,7 +420,7 @@ func TestInit(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, err := os.Stat(file); err != nil {
|
if _, err := os.Stat(file); err != nil {
|
||||||
t.Errorf("Taskfile.yml should exists")
|
t.Errorf("Taskfile.yml should exist")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,7 +433,7 @@ func TestCyclicDep(t *testing.T) {
|
|||||||
Stderr: ioutil.Discard,
|
Stderr: ioutil.Discard,
|
||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup())
|
assert.NoError(t, e.Setup())
|
||||||
assert.IsType(t, &task.MaximumTaskCallExceededError{}, e.Run(taskfile.Call{Task: "task-1"}))
|
assert.IsType(t, &task.MaximumTaskCallExceededError{}, e.Run(context.Background(), taskfile.Call{Task: "task-1"}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTaskVersion(t *testing.T) {
|
func TestTaskVersion(t *testing.T) {
|
||||||
@@ -423,16 +469,16 @@ func TestTaskIgnoreErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup())
|
assert.NoError(t, e.Setup())
|
||||||
|
|
||||||
assert.NoError(t, e.Run(taskfile.Call{Task: "task-should-pass"}))
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "task-should-pass"}))
|
||||||
assert.Error(t, e.Run(taskfile.Call{Task: "task-should-fail"}))
|
assert.Error(t, e.Run(context.Background(), taskfile.Call{Task: "task-should-fail"}))
|
||||||
assert.NoError(t, e.Run(taskfile.Call{Task: "cmd-should-pass"}))
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "cmd-should-pass"}))
|
||||||
assert.Error(t, e.Run(taskfile.Call{Task: "cmd-should-fail"}))
|
assert.Error(t, e.Run(context.Background(), taskfile.Call{Task: "cmd-should-fail"}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExpand(t *testing.T) {
|
func TestExpand(t *testing.T) {
|
||||||
const dir = "testdata/expand"
|
const dir = "testdata/expand"
|
||||||
|
|
||||||
home, err := homedir.Dir()
|
home, err := os.UserHomeDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Couldn't get $HOME: %v", err)
|
t.Errorf("Couldn't get $HOME: %v", err)
|
||||||
}
|
}
|
||||||
@@ -444,7 +490,7 @@ func TestExpand(t *testing.T) {
|
|||||||
Stderr: &buff,
|
Stderr: &buff,
|
||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup())
|
assert.NoError(t, e.Setup())
|
||||||
assert.NoError(t, e.Run(taskfile.Call{Task: "pwd"}))
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "pwd"}))
|
||||||
assert.Equal(t, home, strings.TrimSpace(buff.String()))
|
assert.Equal(t, home, strings.TrimSpace(buff.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,7 +509,7 @@ func TestDry(t *testing.T) {
|
|||||||
Dry: true,
|
Dry: true,
|
||||||
}
|
}
|
||||||
assert.NoError(t, e.Setup())
|
assert.NoError(t, e.Setup())
|
||||||
assert.NoError(t, e.Run(taskfile.Call{Task: "build"}))
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "build"}))
|
||||||
|
|
||||||
assert.Equal(t, "touch file.txt", strings.TrimSpace(buff.String()))
|
assert.Equal(t, "touch file.txt", strings.TrimSpace(buff.String()))
|
||||||
if _, err := os.Stat(file); err == nil {
|
if _, err := os.Stat(file); err == nil {
|
||||||
@@ -471,6 +517,32 @@ func TestDry(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestDryChecksum tests if the checksum file is not being written to disk
|
||||||
|
// if the dry mode is enabled.
|
||||||
|
func TestDryChecksum(t *testing.T) {
|
||||||
|
const dir = "testdata/dry_checksum"
|
||||||
|
|
||||||
|
checksumFile := filepath.Join(dir, ".task/checksum/default")
|
||||||
|
_ = os.Remove(checksumFile)
|
||||||
|
|
||||||
|
e := task.Executor{
|
||||||
|
Dir: dir,
|
||||||
|
Stdout: ioutil.Discard,
|
||||||
|
Stderr: ioutil.Discard,
|
||||||
|
Dry: true,
|
||||||
|
}
|
||||||
|
assert.NoError(t, e.Setup())
|
||||||
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "default"}))
|
||||||
|
|
||||||
|
_, err := os.Stat(checksumFile)
|
||||||
|
assert.Error(t, err, "checksum file should not exist")
|
||||||
|
|
||||||
|
e.Dry = false
|
||||||
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "default"}))
|
||||||
|
_, err = os.Stat(checksumFile)
|
||||||
|
assert.NoError(t, err, "checksum file should exist")
|
||||||
|
}
|
||||||
|
|
||||||
func TestIncludes(t *testing.T) {
|
func TestIncludes(t *testing.T) {
|
||||||
tt := fileContentTest{
|
tt := fileContentTest{
|
||||||
Dir: "testdata/includes",
|
Dir: "testdata/includes",
|
||||||
@@ -484,3 +556,128 @@ func TestIncludes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
tt.Run(t)
|
tt.Run(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIncludesEmptyMain(t *testing.T) {
|
||||||
|
tt := fileContentTest{
|
||||||
|
Dir: "testdata/includes_empty",
|
||||||
|
Target: "included:default",
|
||||||
|
TrimSpace: true,
|
||||||
|
Files: map[string]string{
|
||||||
|
"file.txt": "default",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
tt.Run(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIncludesDependencies(t *testing.T) {
|
||||||
|
tt := fileContentTest{
|
||||||
|
Dir: "testdata/includes_deps",
|
||||||
|
Target: "default",
|
||||||
|
TrimSpace: true,
|
||||||
|
Files: map[string]string{
|
||||||
|
"default.txt": "default",
|
||||||
|
"called_dep.txt": "called_dep",
|
||||||
|
"called_task.txt": "called_task",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
tt.Run(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIncludesCallingRoot(t *testing.T) {
|
||||||
|
tt := fileContentTest{
|
||||||
|
Dir: "testdata/includes_call_root_task",
|
||||||
|
Target: "included:call-root",
|
||||||
|
TrimSpace: true,
|
||||||
|
Files: map[string]string{
|
||||||
|
"root_task.txt": "root task",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
tt.Run(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSummary(t *testing.T) {
|
||||||
|
const dir = "testdata/summary"
|
||||||
|
|
||||||
|
var buff bytes.Buffer
|
||||||
|
e := task.Executor{
|
||||||
|
Dir: dir,
|
||||||
|
Stdout: &buff,
|
||||||
|
Stderr: &buff,
|
||||||
|
Summary: true,
|
||||||
|
Silent: true,
|
||||||
|
}
|
||||||
|
assert.NoError(t, e.Setup())
|
||||||
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "task-with-summary"}, taskfile.Call{Task: "other-task-with-summary"}))
|
||||||
|
|
||||||
|
data, err := ioutil.ReadFile(filepath.Join(dir, "task-with-summary.txt"))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
expectedOutput := string(data)
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
expectedOutput = strings.Replace(expectedOutput, "\r\n", "\n", -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, expectedOutput, buff.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWhenNoDirAttributeItRunsInSameDirAsTaskfile(t *testing.T) {
|
||||||
|
const expected = "dir"
|
||||||
|
const dir = "testdata/" + expected
|
||||||
|
var out bytes.Buffer
|
||||||
|
e := &task.Executor{
|
||||||
|
Dir: dir,
|
||||||
|
Stdout: &out,
|
||||||
|
Stderr: &out,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NoError(t, e.Setup())
|
||||||
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "whereami"}))
|
||||||
|
|
||||||
|
// got should be the "dir" part of "testdata/dir"
|
||||||
|
got := strings.TrimSuffix(filepath.Base(out.String()), "\n")
|
||||||
|
assert.Equal(t, expected, got, "Mismatch in the working directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWhenDirAttributeAndDirExistsItRunsInThatDir(t *testing.T) {
|
||||||
|
const expected = "exists"
|
||||||
|
const dir = "testdata/dir/explicit_exists"
|
||||||
|
var out bytes.Buffer
|
||||||
|
e := &task.Executor{
|
||||||
|
Dir: dir,
|
||||||
|
Stdout: &out,
|
||||||
|
Stderr: &out,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NoError(t, e.Setup())
|
||||||
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "whereami"}))
|
||||||
|
|
||||||
|
got := strings.TrimSuffix(filepath.Base(out.String()), "\n")
|
||||||
|
assert.Equal(t, expected, got, "Mismatch in the working directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWhenDirAttributeItCreatesMissingAndRunsInThatDir(t *testing.T) {
|
||||||
|
const expected = "createme"
|
||||||
|
const dir = "testdata/dir/explicit_doesnt_exist/"
|
||||||
|
const toBeCreated = dir + expected
|
||||||
|
const target = "whereami"
|
||||||
|
var out bytes.Buffer
|
||||||
|
e := &task.Executor{
|
||||||
|
Dir: dir,
|
||||||
|
Stdout: &out,
|
||||||
|
Stderr: &out,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the directory to be created doesn't actually exist.
|
||||||
|
_ = os.Remove(toBeCreated)
|
||||||
|
if _, err := os.Stat(toBeCreated); err == nil {
|
||||||
|
t.Errorf("Directory should not exist: %v", err)
|
||||||
|
}
|
||||||
|
assert.NoError(t, e.Setup())
|
||||||
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: target}))
|
||||||
|
|
||||||
|
got := strings.TrimSuffix(filepath.Base(out.String()), "\n")
|
||||||
|
assert.Equal(t, expected, got, "Mismatch in the working directory")
|
||||||
|
|
||||||
|
// Clean-up after ourselves only if no error.
|
||||||
|
_ = os.Remove(toBeCreated)
|
||||||
|
}
|
||||||
|
|||||||
7
testdata/dir/Taskfile.yml
vendored
Normal file
7
testdata/dir/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
version: '2'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
whereami:
|
||||||
|
cmds:
|
||||||
|
- pwd
|
||||||
|
silent: true
|
||||||
8
testdata/dir/explicit_doesnt_exist/Taskfile.yml
vendored
Normal file
8
testdata/dir/explicit_doesnt_exist/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
version: '2'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
whereami:
|
||||||
|
dir: createme
|
||||||
|
cmds:
|
||||||
|
- pwd
|
||||||
|
silent: true
|
||||||
8
testdata/dir/explicit_exists/Taskfile.yml
vendored
Normal file
8
testdata/dir/explicit_exists/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
version: '2'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
whereami:
|
||||||
|
dir: exists
|
||||||
|
cmds:
|
||||||
|
- pwd
|
||||||
|
silent: true
|
||||||
0
testdata/dir/explicit_exists/exists/.keep
vendored
Normal file
0
testdata/dir/explicit_exists/exists/.keep
vendored
Normal file
9
testdata/dry_checksum/Taskfile.yml
vendored
Normal file
9
testdata/dry_checksum/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
version: '2'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default:
|
||||||
|
cmds:
|
||||||
|
- echo "Working..."
|
||||||
|
sources:
|
||||||
|
- source.txt
|
||||||
|
method: checksum
|
||||||
1
testdata/dry_checksum/source.txt
vendored
Normal file
1
testdata/dry_checksum/source.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Something...
|
||||||
2
testdata/env/.gitignore
vendored
2
testdata/env/.gitignore
vendored
@@ -1 +1 @@
|
|||||||
env.txt
|
*.txt
|
||||||
|
|||||||
43
testdata/env/Taskfile.yml
vendored
43
testdata/env/Taskfile.yml
vendored
@@ -1,10 +1,33 @@
|
|||||||
default:
|
version: '2'
|
||||||
vars:
|
|
||||||
AMD64: amd64
|
vars:
|
||||||
env:
|
BAZ:
|
||||||
GOOS: linux
|
sh: echo baz
|
||||||
GOARCH: "{{.AMD64}}"
|
|
||||||
CGO_ENABLED:
|
env:
|
||||||
sh: echo '0'
|
FOO: foo
|
||||||
cmds:
|
BAR: bar
|
||||||
- echo "GOOS='$GOOS' GOARCH='$GOARCH' CGO_ENABLED='$CGO_ENABLED'" > env.txt
|
BAZ: "{{.BAZ}}"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default:
|
||||||
|
cmds:
|
||||||
|
- task: local
|
||||||
|
- task: global
|
||||||
|
|
||||||
|
local:
|
||||||
|
vars:
|
||||||
|
AMD64: amd64
|
||||||
|
env:
|
||||||
|
GOOS: linux
|
||||||
|
GOARCH: "{{.AMD64}}"
|
||||||
|
CGO_ENABLED:
|
||||||
|
sh: echo '0'
|
||||||
|
cmds:
|
||||||
|
- echo "GOOS='$GOOS' GOARCH='$GOARCH' CGO_ENABLED='$CGO_ENABLED'" > local.txt
|
||||||
|
|
||||||
|
global:
|
||||||
|
env:
|
||||||
|
BAR: overriden
|
||||||
|
cmds:
|
||||||
|
- echo "FOO='$FOO' BAR='$BAR' BAZ='$BAZ'" > global.txt
|
||||||
|
|||||||
10
testdata/generates/Taskfile.yml
vendored
10
testdata/generates/Taskfile.yml
vendored
@@ -29,3 +29,13 @@ sub/src.txt:
|
|||||||
- echo "hello world" > sub/src.txt
|
- echo "hello world" > sub/src.txt
|
||||||
status:
|
status:
|
||||||
- test -f sub/src.txt
|
- test -f sub/src.txt
|
||||||
|
|
||||||
|
'my text file.txt':
|
||||||
|
desc: generate file with spaces in the name
|
||||||
|
deps: [sub/src.txt]
|
||||||
|
cmds:
|
||||||
|
- cat sub/src.txt > 'my text file.txt'
|
||||||
|
sources:
|
||||||
|
- sub/src.txt
|
||||||
|
generates:
|
||||||
|
- 'my text file.txt'
|
||||||
|
|||||||
1
testdata/includes_call_root_task/.gitignore
vendored
Normal file
1
testdata/includes_call_root_task/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.txt
|
||||||
9
testdata/includes_call_root_task/Taskfile.yml
vendored
Normal file
9
testdata/includes_call_root_task/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
version: '2'
|
||||||
|
|
||||||
|
includes:
|
||||||
|
included: Taskfile2.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
root-task:
|
||||||
|
cmds:
|
||||||
|
- echo "root task" > root_task.txt
|
||||||
6
testdata/includes_call_root_task/Taskfile2.yml
vendored
Normal file
6
testdata/includes_call_root_task/Taskfile2.yml
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
version: '2'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
call-root:
|
||||||
|
cmds:
|
||||||
|
- task: :root-task
|
||||||
1
testdata/includes_deps/.gitignore
vendored
Normal file
1
testdata/includes_deps/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.txt
|
||||||
9
testdata/includes_deps/Taskfile.yml
vendored
Normal file
9
testdata/includes_deps/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
version: '2'
|
||||||
|
|
||||||
|
includes:
|
||||||
|
included: Taskfile2.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default:
|
||||||
|
cmds:
|
||||||
|
- task: included:default
|
||||||
16
testdata/includes_deps/Taskfile2.yml
vendored
Normal file
16
testdata/includes_deps/Taskfile2.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
version: '2'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default:
|
||||||
|
deps: [called_dep]
|
||||||
|
cmds:
|
||||||
|
- echo "default" > default.txt
|
||||||
|
- task: called_task
|
||||||
|
|
||||||
|
called_dep:
|
||||||
|
cmds:
|
||||||
|
- echo "called_dep" > called_dep.txt
|
||||||
|
|
||||||
|
called_task:
|
||||||
|
cmds:
|
||||||
|
- echo "called_task" > called_task.txt
|
||||||
1
testdata/includes_empty/.gitignore
vendored
Normal file
1
testdata/includes_empty/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
file.txt
|
||||||
4
testdata/includes_empty/Taskfile.yml
vendored
Normal file
4
testdata/includes_empty/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
version: '2'
|
||||||
|
|
||||||
|
includes:
|
||||||
|
included: Taskfile2.yml
|
||||||
10
testdata/includes_empty/Taskfile2.yml
vendored
Normal file
10
testdata/includes_empty/Taskfile2.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
version: '2'
|
||||||
|
|
||||||
|
vars:
|
||||||
|
FILE: file.txt
|
||||||
|
CONTENT: default
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default:
|
||||||
|
cmds:
|
||||||
|
- echo "{{.CONTENT}}" > {{.FILE}}
|
||||||
19
testdata/precondition/Taskfile.yml
vendored
Normal file
19
testdata/precondition/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
version: '2'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
foo:
|
||||||
|
preconditions:
|
||||||
|
- test -f foo.txt
|
||||||
|
|
||||||
|
impossible:
|
||||||
|
preconditions:
|
||||||
|
- sh: "[ 1 = 0 ]"
|
||||||
|
msg: "1 != 0 obviously!"
|
||||||
|
|
||||||
|
depends_on_impossible:
|
||||||
|
deps:
|
||||||
|
- impossible
|
||||||
|
|
||||||
|
executes_failing_task_as_cmd:
|
||||||
|
cmds:
|
||||||
|
- task: impossible
|
||||||
0
testdata/precondition/foo.txt
vendored
Normal file
0
testdata/precondition/foo.txt
vendored
Normal file
26
testdata/summary/Taskfile.yml
vendored
Normal file
26
testdata/summary/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
version: 2
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
task-with-summary:
|
||||||
|
deps: [dependend-task-1, dependend-task-2]
|
||||||
|
summary: |
|
||||||
|
summary of task-with-summary - line 1
|
||||||
|
line 2
|
||||||
|
line 3
|
||||||
|
cmds:
|
||||||
|
- echo 'task-with-summary was executed'
|
||||||
|
- echo 'another command'
|
||||||
|
- exit 0
|
||||||
|
|
||||||
|
other-task-with-summary:
|
||||||
|
summary: summary of other-task-with-summary
|
||||||
|
cmds:
|
||||||
|
- echo 'other-task-with-summary was executed'
|
||||||
|
|
||||||
|
dependend-task-1:
|
||||||
|
cmds:
|
||||||
|
- echo 'dependend-task-1 was executed'
|
||||||
|
|
||||||
|
dependend-task-2:
|
||||||
|
cmds:
|
||||||
|
- echo 'dependend-task-2 was executed'
|
||||||
22
testdata/summary/task-with-summary.txt
vendored
Normal file
22
testdata/summary/task-with-summary.txt
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
task: task-with-summary
|
||||||
|
|
||||||
|
summary of task-with-summary - line 1
|
||||||
|
line 2
|
||||||
|
line 3
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- dependend-task-1
|
||||||
|
- dependend-task-2
|
||||||
|
|
||||||
|
commands:
|
||||||
|
- echo 'task-with-summary was executed'
|
||||||
|
- echo 'another command'
|
||||||
|
- exit 0
|
||||||
|
|
||||||
|
|
||||||
|
task: other-task-with-summary
|
||||||
|
|
||||||
|
summary of other-task-with-summary
|
||||||
|
|
||||||
|
commands:
|
||||||
|
- echo 'other-task-with-summary was executed'
|
||||||
29
variables.go
29
variables.go
@@ -3,10 +3,9 @@ package task
|
|||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/go-task/task/internal/taskfile"
|
"github.com/go-task/task/v2/internal/execext"
|
||||||
"github.com/go-task/task/internal/templater"
|
"github.com/go-task/task/v2/internal/taskfile"
|
||||||
|
"github.com/go-task/task/v2/internal/templater"
|
||||||
"mvdan.cc/sh/shell"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CompiledTask returns a copy of a task, but replacing variables in almost all
|
// CompiledTask returns a copy of a task, but replacing variables in almost all
|
||||||
@@ -31,13 +30,13 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) {
|
|||||||
Status: r.ReplaceSlice(origTask.Status),
|
Status: r.ReplaceSlice(origTask.Status),
|
||||||
Dir: r.Replace(origTask.Dir),
|
Dir: r.Replace(origTask.Dir),
|
||||||
Vars: nil,
|
Vars: nil,
|
||||||
Env: r.ReplaceVars(origTask.Env),
|
Env: nil,
|
||||||
Silent: origTask.Silent,
|
Silent: origTask.Silent,
|
||||||
Method: r.Replace(origTask.Method),
|
Method: r.Replace(origTask.Method),
|
||||||
Prefix: r.Replace(origTask.Prefix),
|
Prefix: r.Replace(origTask.Prefix),
|
||||||
IgnoreError: origTask.IgnoreError,
|
IgnoreError: origTask.IgnoreError,
|
||||||
}
|
}
|
||||||
new.Dir, err = shell.Expand(new.Dir, nil)
|
new.Dir, err = execext.Expand(new.Dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -47,6 +46,14 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) {
|
|||||||
if new.Prefix == "" {
|
if new.Prefix == "" {
|
||||||
new.Prefix = new.Task
|
new.Prefix = new.Task
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new.Env = make(taskfile.Vars, len(e.Taskfile.Env)+len(origTask.Env))
|
||||||
|
for k, v := range r.ReplaceVars(e.Taskfile.Env) {
|
||||||
|
new.Env[k] = v
|
||||||
|
}
|
||||||
|
for k, v := range r.ReplaceVars(origTask.Env) {
|
||||||
|
new.Env[k] = v
|
||||||
|
}
|
||||||
for k, v := range new.Env {
|
for k, v := range new.Env {
|
||||||
static, err := e.Compiler.HandleDynamicVar(v)
|
static, err := e.Compiler.HandleDynamicVar(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -77,5 +84,15 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(origTask.Preconditions) > 0 {
|
||||||
|
new.Preconditions = make([]*taskfile.Precondition, len(origTask.Preconditions))
|
||||||
|
for i, precond := range origTask.Preconditions {
|
||||||
|
new.Preconditions[i] = &taskfile.Precondition{
|
||||||
|
Sh: r.Replace(precond.Sh),
|
||||||
|
Msg: r.Replace(precond.Msg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &new, r.Err()
|
return &new, r.Err()
|
||||||
}
|
}
|
||||||
|
|||||||
27
vendor/github.com/Masterminds/semver/.travis.yml
generated
vendored
Normal file
27
vendor/github.com/Masterminds/semver/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.6.x
|
||||||
|
- 1.7.x
|
||||||
|
- 1.8.x
|
||||||
|
- 1.9.x
|
||||||
|
- 1.10.x
|
||||||
|
- tip
|
||||||
|
|
||||||
|
# Setting sudo access to false will let Travis CI use containers rather than
|
||||||
|
# VMs to run the tests. For more details see:
|
||||||
|
# - http://docs.travis-ci.com/user/workers/container-based-infrastructure/
|
||||||
|
# - http://docs.travis-ci.com/user/workers/standard-infrastructure/
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
script:
|
||||||
|
- make setup
|
||||||
|
- make test
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
webhooks:
|
||||||
|
urls:
|
||||||
|
- https://webhooks.gitter.im/e/06e3328629952dabe3e0
|
||||||
|
on_success: change # options: [always|never|change] default: always
|
||||||
|
on_failure: always # options: [always|never|change] default: always
|
||||||
|
on_start: never # options: [always|never|change] default: always
|
||||||
86
vendor/github.com/Masterminds/semver/CHANGELOG.md
generated
vendored
Normal file
86
vendor/github.com/Masterminds/semver/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# 1.4.2 (2018-04-10)
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
- #72: Updated the docs to point to vert for a console appliaction
|
||||||
|
- #71: Update the docs on pre-release comparator handling
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- #70: Fix the handling of pre-releases and the 0.0.0 release edge case
|
||||||
|
|
||||||
|
# 1.4.1 (2018-04-02)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- Fixed #64: Fix pre-release precedence issue (thanks @uudashr)
|
||||||
|
|
||||||
|
# 1.4.0 (2017-10-04)
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
- #61: Update NewVersion to parse ints with a 64bit int size (thanks @zknill)
|
||||||
|
|
||||||
|
# 1.3.1 (2017-07-10)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- Fixed #57: number comparisons in prerelease sometimes inaccurate
|
||||||
|
|
||||||
|
# 1.3.0 (2017-05-02)
|
||||||
|
|
||||||
|
## Added
|
||||||
|
- #45: Added json (un)marshaling support (thanks @mh-cbon)
|
||||||
|
- Stability marker. See https://masterminds.github.io/stability/
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- #51: Fix handling of single digit tilde constraint (thanks @dgodd)
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
- #55: The godoc icon moved from png to svg
|
||||||
|
|
||||||
|
# 1.2.3 (2017-04-03)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- #46: Fixed 0.x.x and 0.0.x in constraints being treated as *
|
||||||
|
|
||||||
|
# Release 1.2.2 (2016-12-13)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- #34: Fixed issue where hyphen range was not working with pre-release parsing.
|
||||||
|
|
||||||
|
# Release 1.2.1 (2016-11-28)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- #24: Fixed edge case issue where constraint "> 0" does not handle "0.0.1-alpha"
|
||||||
|
properly.
|
||||||
|
|
||||||
|
# Release 1.2.0 (2016-11-04)
|
||||||
|
|
||||||
|
## Added
|
||||||
|
- #20: Added MustParse function for versions (thanks @adamreese)
|
||||||
|
- #15: Added increment methods on versions (thanks @mh-cbon)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
- Issue #21: Per the SemVer spec (section 9) a pre-release is unstable and
|
||||||
|
might not satisfy the intended compatibility. The change here ignores pre-releases
|
||||||
|
on constraint checks (e.g., ~ or ^) when a pre-release is not part of the
|
||||||
|
constraint. For example, `^1.2.3` will ignore pre-releases while
|
||||||
|
`^1.2.3-alpha` will include them.
|
||||||
|
|
||||||
|
# Release 1.1.1 (2016-06-30)
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
- Issue #9: Speed up version comparison performance (thanks @sdboyer)
|
||||||
|
- Issue #8: Added benchmarks (thanks @sdboyer)
|
||||||
|
- Updated Go Report Card URL to new location
|
||||||
|
- Updated Readme to add code snippet formatting (thanks @mh-cbon)
|
||||||
|
- Updating tagging to v[SemVer] structure for compatibility with other tools.
|
||||||
|
|
||||||
|
# Release 1.1.0 (2016-03-11)
|
||||||
|
|
||||||
|
- Issue #2: Implemented validation to provide reasons a versions failed a
|
||||||
|
constraint.
|
||||||
|
|
||||||
|
# Release 1.0.1 (2015-12-31)
|
||||||
|
|
||||||
|
- Fixed #1: * constraint failing on valid versions.
|
||||||
|
|
||||||
|
# Release 1.0.0 (2015-10-20)
|
||||||
|
|
||||||
|
- Initial release
|
||||||
36
vendor/github.com/Masterminds/semver/Makefile
generated
vendored
Normal file
36
vendor/github.com/Masterminds/semver/Makefile
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
.PHONY: setup
|
||||||
|
setup:
|
||||||
|
go get -u gopkg.in/alecthomas/gometalinter.v1
|
||||||
|
gometalinter.v1 --install
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: validate lint
|
||||||
|
@echo "==> Running tests"
|
||||||
|
go test -v
|
||||||
|
|
||||||
|
.PHONY: validate
|
||||||
|
validate:
|
||||||
|
@echo "==> Running static validations"
|
||||||
|
@gometalinter.v1 \
|
||||||
|
--disable-all \
|
||||||
|
--enable deadcode \
|
||||||
|
--severity deadcode:error \
|
||||||
|
--enable gofmt \
|
||||||
|
--enable gosimple \
|
||||||
|
--enable ineffassign \
|
||||||
|
--enable misspell \
|
||||||
|
--enable vet \
|
||||||
|
--tests \
|
||||||
|
--vendor \
|
||||||
|
--deadline 60s \
|
||||||
|
./... || exit_code=1
|
||||||
|
|
||||||
|
.PHONY: lint
|
||||||
|
lint:
|
||||||
|
@echo "==> Running linters"
|
||||||
|
@gometalinter.v1 \
|
||||||
|
--disable-all \
|
||||||
|
--enable golint \
|
||||||
|
--vendor \
|
||||||
|
--deadline 60s \
|
||||||
|
./... || :
|
||||||
165
vendor/github.com/Masterminds/semver/README.md
generated
vendored
Normal file
165
vendor/github.com/Masterminds/semver/README.md
generated
vendored
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
# SemVer
|
||||||
|
|
||||||
|
The `semver` package provides the ability to work with [Semantic Versions](http://semver.org) in Go. Specifically it provides the ability to:
|
||||||
|
|
||||||
|
* Parse semantic versions
|
||||||
|
* Sort semantic versions
|
||||||
|
* Check if a semantic version fits within a set of constraints
|
||||||
|
* Optionally work with a `v` prefix
|
||||||
|
|
||||||
|
[](https://masterminds.github.io/stability/active.html)
|
||||||
|
[](https://travis-ci.org/Masterminds/semver) [](https://ci.appveyor.com/project/mattfarina/semver/branch/master) [](https://godoc.org/github.com/Masterminds/semver) [](https://goreportcard.com/report/github.com/Masterminds/semver)
|
||||||
|
|
||||||
|
## Parsing Semantic Versions
|
||||||
|
|
||||||
|
To parse a semantic version use the `NewVersion` function. For example,
|
||||||
|
|
||||||
|
```go
|
||||||
|
v, err := semver.NewVersion("1.2.3-beta.1+build345")
|
||||||
|
```
|
||||||
|
|
||||||
|
If there is an error the version wasn't parseable. The version object has methods
|
||||||
|
to get the parts of the version, compare it to other versions, convert the
|
||||||
|
version back into a string, and get the original string. For more details
|
||||||
|
please see the [documentation](https://godoc.org/github.com/Masterminds/semver).
|
||||||
|
|
||||||
|
## Sorting Semantic Versions
|
||||||
|
|
||||||
|
A set of versions can be sorted using the [`sort`](https://golang.org/pkg/sort/)
|
||||||
|
package from the standard library. For example,
|
||||||
|
|
||||||
|
```go
|
||||||
|
raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",}
|
||||||
|
vs := make([]*semver.Version, len(raw))
|
||||||
|
for i, r := range raw {
|
||||||
|
v, err := semver.NewVersion(r)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error parsing version: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
vs[i] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Sort(semver.Collection(vs))
|
||||||
|
```
|
||||||
|
|
||||||
|
## Checking Version Constraints
|
||||||
|
|
||||||
|
Checking a version against version constraints is one of the most featureful
|
||||||
|
parts of the package.
|
||||||
|
|
||||||
|
```go
|
||||||
|
c, err := semver.NewConstraint(">= 1.2.3")
|
||||||
|
if err != nil {
|
||||||
|
// Handle constraint not being parseable.
|
||||||
|
}
|
||||||
|
|
||||||
|
v, _ := semver.NewVersion("1.3")
|
||||||
|
if err != nil {
|
||||||
|
// Handle version not being parseable.
|
||||||
|
}
|
||||||
|
// Check if the version meets the constraints. The a variable will be true.
|
||||||
|
a := c.Check(v)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Basic Comparisons
|
||||||
|
|
||||||
|
There are two elements to the comparisons. First, a comparison string is a list
|
||||||
|
of comma separated and comparisons. These are then separated by || separated or
|
||||||
|
comparisons. For example, `">= 1.2, < 3.0.0 || >= 4.2.3"` is looking for a
|
||||||
|
comparison that's greater than or equal to 1.2 and less than 3.0.0 or is
|
||||||
|
greater than or equal to 4.2.3.
|
||||||
|
|
||||||
|
The basic comparisons are:
|
||||||
|
|
||||||
|
* `=`: equal (aliased to no operator)
|
||||||
|
* `!=`: not equal
|
||||||
|
* `>`: greater than
|
||||||
|
* `<`: less than
|
||||||
|
* `>=`: greater than or equal to
|
||||||
|
* `<=`: less than or equal to
|
||||||
|
|
||||||
|
_Note, according to the Semantic Version specification pre-releases may not be
|
||||||
|
API compliant with their release counterpart. It says,_
|
||||||
|
|
||||||
|
> _A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version._
|
||||||
|
|
||||||
|
_SemVer comparisons without a pre-release value will skip pre-release versions.
|
||||||
|
For example, `>1.2.3` will skip pre-releases when looking at a list of values
|
||||||
|
while `>1.2.3-alpha.1` will evaluate pre-releases._
|
||||||
|
|
||||||
|
## Hyphen Range Comparisons
|
||||||
|
|
||||||
|
There are multiple methods to handle ranges and the first is hyphens ranges.
|
||||||
|
These look like:
|
||||||
|
|
||||||
|
* `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5`
|
||||||
|
* `2.3.4 - 4.5` which is equivalent to `>= 2.3.4, <= 4.5`
|
||||||
|
|
||||||
|
## Wildcards In Comparisons
|
||||||
|
|
||||||
|
The `x`, `X`, and `*` characters can be used as a wildcard character. This works
|
||||||
|
for all comparison operators. When used on the `=` operator it falls
|
||||||
|
back to the pack level comparison (see tilde below). For example,
|
||||||
|
|
||||||
|
* `1.2.x` is equivalent to `>= 1.2.0, < 1.3.0`
|
||||||
|
* `>= 1.2.x` is equivalent to `>= 1.2.0`
|
||||||
|
* `<= 2.x` is equivalent to `<= 3`
|
||||||
|
* `*` is equivalent to `>= 0.0.0`
|
||||||
|
|
||||||
|
## Tilde Range Comparisons (Patch)
|
||||||
|
|
||||||
|
The tilde (`~`) comparison operator is for patch level ranges when a minor
|
||||||
|
version is specified and major level changes when the minor number is missing.
|
||||||
|
For example,
|
||||||
|
|
||||||
|
* `~1.2.3` is equivalent to `>= 1.2.3, < 1.3.0`
|
||||||
|
* `~1` is equivalent to `>= 1, < 2`
|
||||||
|
* `~2.3` is equivalent to `>= 2.3, < 2.4`
|
||||||
|
* `~1.2.x` is equivalent to `>= 1.2.0, < 1.3.0`
|
||||||
|
* `~1.x` is equivalent to `>= 1, < 2`
|
||||||
|
|
||||||
|
## Caret Range Comparisons (Major)
|
||||||
|
|
||||||
|
The caret (`^`) comparison operator is for major level changes. This is useful
|
||||||
|
when comparisons of API versions as a major change is API breaking. For example,
|
||||||
|
|
||||||
|
* `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0`
|
||||||
|
* `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0`
|
||||||
|
* `^2.3` is equivalent to `>= 2.3, < 3`
|
||||||
|
* `^2.x` is equivalent to `>= 2.0.0, < 3`
|
||||||
|
|
||||||
|
# Validation
|
||||||
|
|
||||||
|
In addition to testing a version against a constraint, a version can be validated
|
||||||
|
against a constraint. When validation fails a slice of errors containing why a
|
||||||
|
version didn't meet the constraint is returned. For example,
|
||||||
|
|
||||||
|
```go
|
||||||
|
c, err := semver.NewConstraint("<= 1.2.3, >= 1.4")
|
||||||
|
if err != nil {
|
||||||
|
// Handle constraint not being parseable.
|
||||||
|
}
|
||||||
|
|
||||||
|
v, _ := semver.NewVersion("1.3")
|
||||||
|
if err != nil {
|
||||||
|
// Handle version not being parseable.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate a version against a constraint.
|
||||||
|
a, msgs := c.Validate(v)
|
||||||
|
// a is false
|
||||||
|
for _, m := range msgs {
|
||||||
|
fmt.Println(m)
|
||||||
|
|
||||||
|
// Loops over the errors which would read
|
||||||
|
// "1.3 is greater than 1.2.3"
|
||||||
|
// "1.3 is less than 1.4"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Contribute
|
||||||
|
|
||||||
|
If you find an issue or want to contribute please file an [issue](https://github.com/Masterminds/semver/issues)
|
||||||
|
or [create a pull request](https://github.com/Masterminds/semver/pulls).
|
||||||
44
vendor/github.com/Masterminds/semver/appveyor.yml
generated
vendored
Normal file
44
vendor/github.com/Masterminds/semver/appveyor.yml
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
version: build-{build}.{branch}
|
||||||
|
|
||||||
|
clone_folder: C:\gopath\src\github.com\Masterminds\semver
|
||||||
|
shallow_clone: true
|
||||||
|
|
||||||
|
environment:
|
||||||
|
GOPATH: C:\gopath
|
||||||
|
|
||||||
|
platform:
|
||||||
|
- x64
|
||||||
|
|
||||||
|
install:
|
||||||
|
- go version
|
||||||
|
- go env
|
||||||
|
- go get -u gopkg.in/alecthomas/gometalinter.v1
|
||||||
|
- set PATH=%PATH%;%GOPATH%\bin
|
||||||
|
- gometalinter.v1.exe --install
|
||||||
|
|
||||||
|
build_script:
|
||||||
|
- go install -v ./...
|
||||||
|
|
||||||
|
test_script:
|
||||||
|
- "gometalinter.v1 \
|
||||||
|
--disable-all \
|
||||||
|
--enable deadcode \
|
||||||
|
--severity deadcode:error \
|
||||||
|
--enable gofmt \
|
||||||
|
--enable gosimple \
|
||||||
|
--enable ineffassign \
|
||||||
|
--enable misspell \
|
||||||
|
--enable vet \
|
||||||
|
--tests \
|
||||||
|
--vendor \
|
||||||
|
--deadline 60s \
|
||||||
|
./... || exit_code=1"
|
||||||
|
- "gometalinter.v1 \
|
||||||
|
--disable-all \
|
||||||
|
--enable golint \
|
||||||
|
--vendor \
|
||||||
|
--deadline 60s \
|
||||||
|
./... || :"
|
||||||
|
- go test -v
|
||||||
|
|
||||||
|
deploy: off
|
||||||
20
vendor/github.com/Masterminds/semver/constraints.go
generated
vendored
20
vendor/github.com/Masterminds/semver/constraints.go
generated
vendored
@@ -233,6 +233,12 @@ func constraintNotEqual(v *Version, c *constraint) bool {
|
|||||||
|
|
||||||
func constraintGreaterThan(v *Version, c *constraint) bool {
|
func constraintGreaterThan(v *Version, c *constraint) bool {
|
||||||
|
|
||||||
|
// An edge case the constraint is 0.0.0 and the version is 0.0.0-someprerelease
|
||||||
|
// exists. This that case.
|
||||||
|
if !isNonZero(c.con) && isNonZero(v) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// If there is a pre-release on the version but the constraint isn't looking
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
// for them assume that pre-releases are not compatible. See issue 21 for
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
// more details.
|
// more details.
|
||||||
@@ -265,6 +271,11 @@ func constraintLessThan(v *Version, c *constraint) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func constraintGreaterThanEqual(v *Version, c *constraint) bool {
|
func constraintGreaterThanEqual(v *Version, c *constraint) bool {
|
||||||
|
// An edge case the constraint is 0.0.0 and the version is 0.0.0-someprerelease
|
||||||
|
// exists. This that case.
|
||||||
|
if !isNonZero(c.con) && isNonZero(v) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// If there is a pre-release on the version but the constraint isn't looking
|
// If there is a pre-release on the version but the constraint isn't looking
|
||||||
// for them assume that pre-releases are not compatible. See issue 21 for
|
// for them assume that pre-releases are not compatible. See issue 21 for
|
||||||
@@ -404,3 +415,12 @@ func rewriteRange(i string) string {
|
|||||||
|
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Detect if a version is not zero (0.0.0)
|
||||||
|
func isNonZero(v *Version) bool {
|
||||||
|
if v.Major() != 0 || v.Minor() != 0 || v.Patch() != 0 || v.Prerelease() != "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
2
vendor/github.com/Masterminds/semver/doc.go
generated
vendored
2
vendor/github.com/Masterminds/semver/doc.go
generated
vendored
@@ -47,7 +47,7 @@ parts of the package.
|
|||||||
// Handle constraint not being parseable.
|
// Handle constraint not being parseable.
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err := semver.NewVersion("1.3")
|
v, _ := semver.NewVersion("1.3")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Handle version not being parseable.
|
// Handle version not being parseable.
|
||||||
}
|
}
|
||||||
|
|||||||
2
vendor/github.com/Masterminds/semver/version.go
generated
vendored
2
vendor/github.com/Masterminds/semver/version.go
generated
vendored
@@ -106,7 +106,7 @@ func MustParse(v string) *Version {
|
|||||||
// Note, if the original version contained a leading v this version will not.
|
// Note, if the original version contained a leading v this version will not.
|
||||||
// See the Original() method to retrieve the original value. Semantic Versions
|
// See the Original() method to retrieve the original value. Semantic Versions
|
||||||
// don't contain a leading v per the spec. Instead it's optional on
|
// don't contain a leading v per the spec. Instead it's optional on
|
||||||
// implementation.
|
// impelementation.
|
||||||
func (v *Version) String() string {
|
func (v *Version) String() string {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
|||||||
2
vendor/github.com/Masterminds/sprig/.gitignore
generated
vendored
Normal file
2
vendor/github.com/Masterminds/sprig/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
vendor/
|
||||||
|
/.glide
|
||||||
24
vendor/github.com/Masterminds/sprig/.travis.yml
generated
vendored
Normal file
24
vendor/github.com/Masterminds/sprig/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.9.x
|
||||||
|
- 1.10.x
|
||||||
|
- 1.11.x
|
||||||
|
- tip
|
||||||
|
|
||||||
|
# Setting sudo access to false will let Travis CI use containers rather than
|
||||||
|
# VMs to run the tests. For more details see:
|
||||||
|
# - http://docs.travis-ci.com/user/workers/container-based-infrastructure/
|
||||||
|
# - http://docs.travis-ci.com/user/workers/standard-infrastructure/
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
script:
|
||||||
|
- make setup test
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
webhooks:
|
||||||
|
urls:
|
||||||
|
- https://webhooks.gitter.im/e/06e3328629952dabe3e0
|
||||||
|
on_success: change # options: [always|never|change] default: always
|
||||||
|
on_failure: always # options: [always|never|change] default: always
|
||||||
|
on_start: never # options: [always|never|change] default: always
|
||||||
153
vendor/github.com/Masterminds/sprig/CHANGELOG.md
generated
vendored
Normal file
153
vendor/github.com/Masterminds/sprig/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
## Release 2.15.0 (2018-04-02)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- #68 and #69: Add json helpers to docs (thanks @arunvelsriram)
|
||||||
|
- #66: Add ternary function (thanks @binoculars)
|
||||||
|
- #67: Allow keys function to take multiple dicts (thanks @binoculars)
|
||||||
|
- #89: Added sha1sum to crypto function (thanks @benkeil)
|
||||||
|
- #81: Allow customizing Root CA that used by genSignedCert (thanks @chenzhiwei)
|
||||||
|
- #92: Add travis testing for go 1.10
|
||||||
|
- #93: Adding appveyor config for windows testing
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- #90: Updating to more recent dependencies
|
||||||
|
- #73: replace satori/go.uuid with google/uuid (thanks @petterw)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- #76: Fixed documentation typos (thanks @Thiht)
|
||||||
|
- Fixed rounding issue on the `ago` function. Note, the removes support for Go 1.8 and older
|
||||||
|
|
||||||
|
## Release 2.14.1 (2017-12-01)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- #60: Fix typo in function name documentation (thanks @neil-ca-moore)
|
||||||
|
- #61: Removing line with {{ due to blocking github pages genertion
|
||||||
|
- #64: Update the list functions to handle int, string, and other slices for compatibility
|
||||||
|
|
||||||
|
## Release 2.14.0 (2017-10-06)
|
||||||
|
|
||||||
|
This new version of Sprig adds a set of functions for generating and working with SSL certificates.
|
||||||
|
|
||||||
|
- `genCA` generates an SSL Certificate Authority
|
||||||
|
- `genSelfSignedCert` generates an SSL self-signed certificate
|
||||||
|
- `genSignedCert` generates an SSL certificate and key based on a given CA
|
||||||
|
|
||||||
|
## Release 2.13.0 (2017-09-18)
|
||||||
|
|
||||||
|
This release adds new functions, including:
|
||||||
|
|
||||||
|
- `regexMatch`, `regexFindAll`, `regexFind`, `regexReplaceAll`, `regexReplaceAllLiteral`, and `regexSplit` to work with regular expressions
|
||||||
|
- `floor`, `ceil`, and `round` math functions
|
||||||
|
- `toDate` converts a string to a date
|
||||||
|
- `nindent` is just like `indent` but also prepends a new line
|
||||||
|
- `ago` returns the time from `time.Now`
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- #40: Added basic regex functionality (thanks @alanquillin)
|
||||||
|
- #41: Added ceil floor and round functions (thanks @alanquillin)
|
||||||
|
- #48: Added toDate function (thanks @andreynering)
|
||||||
|
- #50: Added nindent function (thanks @binoculars)
|
||||||
|
- #46: Added ago function (thanks @slayer)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- #51: Updated godocs to include new string functions (thanks @curtisallen)
|
||||||
|
- #49: Added ability to merge multiple dicts (thanks @binoculars)
|
||||||
|
|
||||||
|
## Release 2.12.0 (2017-05-17)
|
||||||
|
|
||||||
|
- `snakecase`, `camelcase`, and `shuffle` are three new string functions
|
||||||
|
- `fail` allows you to bail out of a template render when conditions are not met
|
||||||
|
|
||||||
|
## Release 2.11.0 (2017-05-02)
|
||||||
|
|
||||||
|
- Added `toJson` and `toPrettyJson`
|
||||||
|
- Added `merge`
|
||||||
|
- Refactored documentation
|
||||||
|
|
||||||
|
## Release 2.10.0 (2017-03-15)
|
||||||
|
|
||||||
|
- Added `semver` and `semverCompare` for Semantic Versions
|
||||||
|
- `list` replaces `tuple`
|
||||||
|
- Fixed issue with `join`
|
||||||
|
- Added `first`, `last`, `intial`, `rest`, `prepend`, `append`, `toString`, `toStrings`, `sortAlpha`, `reverse`, `coalesce`, `pluck`, `pick`, `compact`, `keys`, `omit`, `uniq`, `has`, `without`
|
||||||
|
|
||||||
|
## Release 2.9.0 (2017-02-23)
|
||||||
|
|
||||||
|
- Added `splitList` to split a list
|
||||||
|
- Added crypto functions of `genPrivateKey` and `derivePassword`
|
||||||
|
|
||||||
|
## Release 2.8.0 (2016-12-21)
|
||||||
|
|
||||||
|
- Added access to several path functions (`base`, `dir`, `clean`, `ext`, and `abs`)
|
||||||
|
- Added functions for _mutating_ dictionaries (`set`, `unset`, `hasKey`)
|
||||||
|
|
||||||
|
## Release 2.7.0 (2016-12-01)
|
||||||
|
|
||||||
|
- Added `sha256sum` to generate a hash of an input
|
||||||
|
- Added functions to convert a numeric or string to `int`, `int64`, `float64`
|
||||||
|
|
||||||
|
## Release 2.6.0 (2016-10-03)
|
||||||
|
|
||||||
|
- Added a `uuidv4` template function for generating UUIDs inside of a template.
|
||||||
|
|
||||||
|
## Release 2.5.0 (2016-08-19)
|
||||||
|
|
||||||
|
- New `trimSuffix`, `trimPrefix`, `hasSuffix`, and `hasPrefix` functions
|
||||||
|
- New aliases have been added for a few functions that didn't follow the naming conventions (`trimAll` and `abbrevBoth`)
|
||||||
|
- `trimall` and `abbrevboth` (notice the case) are deprecated and will be removed in 3.0.0
|
||||||
|
|
||||||
|
## Release 2.4.0 (2016-08-16)
|
||||||
|
|
||||||
|
- Adds two functions: `until` and `untilStep`
|
||||||
|
|
||||||
|
## Release 2.3.0 (2016-06-21)
|
||||||
|
|
||||||
|
- cat: Concatenate strings with whitespace separators.
|
||||||
|
- replace: Replace parts of a string: `replace " " "-" "Me First"` renders "Me-First"
|
||||||
|
- plural: Format plurals: `len "foo" | plural "one foo" "many foos"` renders "many foos"
|
||||||
|
- indent: Indent blocks of text in a way that is sensitive to "\n" characters.
|
||||||
|
|
||||||
|
## Release 2.2.0 (2016-04-21)
|
||||||
|
|
||||||
|
- Added a `genPrivateKey` function (Thanks @bacongobbler)
|
||||||
|
|
||||||
|
## Release 2.1.0 (2016-03-30)
|
||||||
|
|
||||||
|
- `default` now prints the default value when it does not receive a value down the pipeline. It is much safer now to do `{{.Foo | default "bar"}}`.
|
||||||
|
- Added accessors for "hermetic" functions. These return only functions that, when given the same input, produce the same output.
|
||||||
|
|
||||||
|
## Release 2.0.0 (2016-03-29)
|
||||||
|
|
||||||
|
Because we switched from `int` to `int64` as the return value for all integer math functions, the library's major version number has been incremented.
|
||||||
|
|
||||||
|
- `min` complements `max` (formerly `biggest`)
|
||||||
|
- `empty` indicates that a value is the empty value for its type
|
||||||
|
- `tuple` creates a tuple inside of a template: `{{$t := tuple "a", "b" "c"}}`
|
||||||
|
- `dict` creates a dictionary inside of a template `{{$d := dict "key1" "val1" "key2" "val2"}}`
|
||||||
|
- Date formatters have been added for HTML dates (as used in `date` input fields)
|
||||||
|
- Integer math functions can convert from a number of types, including `string` (via `strconv.ParseInt`).
|
||||||
|
|
||||||
|
## Release 1.2.0 (2016-02-01)
|
||||||
|
|
||||||
|
- Added quote and squote
|
||||||
|
- Added b32enc and b32dec
|
||||||
|
- add now takes varargs
|
||||||
|
- biggest now takes varargs
|
||||||
|
|
||||||
|
## Release 1.1.0 (2015-12-29)
|
||||||
|
|
||||||
|
- Added #4: Added contains function. strings.Contains, but with the arguments
|
||||||
|
switched to simplify common pipelines. (thanks krancour)
|
||||||
|
- Added Travis-CI testing support
|
||||||
|
|
||||||
|
## Release 1.0.0 (2015-12-23)
|
||||||
|
|
||||||
|
- Initial release
|
||||||
13
vendor/github.com/Masterminds/sprig/Makefile
generated
vendored
Normal file
13
vendor/github.com/Masterminds/sprig/Makefile
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
HAS_GLIDE := $(shell command -v glide;)
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test:
|
||||||
|
go test -v .
|
||||||
|
|
||||||
|
.PHONY: setup
|
||||||
|
setup:
|
||||||
|
ifndef HAS_GLIDE
|
||||||
|
go get -u github.com/Masterminds/glide
|
||||||
|
endif
|
||||||
|
glide install
|
||||||
81
vendor/github.com/Masterminds/sprig/README.md
generated
vendored
Normal file
81
vendor/github.com/Masterminds/sprig/README.md
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
# Sprig: Template functions for Go templates
|
||||||
|
[](https://masterminds.github.io/stability/sustained.html)
|
||||||
|
[](https://travis-ci.org/Masterminds/sprig)
|
||||||
|
|
||||||
|
The Go language comes with a [built-in template
|
||||||
|
language](http://golang.org/pkg/text/template/), but not
|
||||||
|
very many template functions. This library provides a group of commonly
|
||||||
|
used template functions.
|
||||||
|
|
||||||
|
It is inspired by the template functions found in
|
||||||
|
[Twig](http://twig.sensiolabs.org/documentation) and also in various
|
||||||
|
JavaScript libraries, such as [underscore.js](http://underscorejs.org/).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Template developers can read the [Sprig function documentation](http://masterminds.github.io/sprig/) to
|
||||||
|
learn about the >100 template functions available.
|
||||||
|
|
||||||
|
For Go developers wishing to include Sprig as a library in their programs,
|
||||||
|
API documentation is available [at GoDoc.org](http://godoc.org/github.com/Masterminds/sprig), but
|
||||||
|
read on for standard usage.
|
||||||
|
|
||||||
|
### Load the Sprig library
|
||||||
|
|
||||||
|
To load the Sprig `FuncMap`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/Masterminds/sprig"
|
||||||
|
"html/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This example illustrates that the FuncMap *must* be set before the
|
||||||
|
// templates themselves are loaded.
|
||||||
|
tpl := template.Must(
|
||||||
|
template.New("base").Funcs(sprig.FuncMap()).ParseGlob("*.html")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Call the functions inside of templates
|
||||||
|
|
||||||
|
By convention, all functions are lowercase. This seems to follow the Go
|
||||||
|
idiom for template functions (as opposed to template methods, which are
|
||||||
|
TitleCase).
|
||||||
|
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
{{ "hello!" | upper | repeat 5 }}
|
||||||
|
```
|
||||||
|
|
||||||
|
Produces:
|
||||||
|
|
||||||
|
```
|
||||||
|
HELLO!HELLO!HELLO!HELLO!HELLO!
|
||||||
|
```
|
||||||
|
|
||||||
|
## Principles:
|
||||||
|
|
||||||
|
The following principles were used in deciding on which functions to add, and
|
||||||
|
determining how to implement them.
|
||||||
|
|
||||||
|
- Template functions should be used to build layout. Therefore, the following
|
||||||
|
types of operations are within the domain of template functions:
|
||||||
|
- Formatting
|
||||||
|
- Layout
|
||||||
|
- Simple type conversions
|
||||||
|
- Utilities that assist in handling common formatting and layout needs (e.g. arithmetic)
|
||||||
|
- Template functions should not return errors unless there is no way to print
|
||||||
|
a sensible value. For example, converting a string to an integer should not
|
||||||
|
produce an error if conversion fails. Instead, it should display a default
|
||||||
|
value that can be displayed.
|
||||||
|
- Simple math is necessary for grid layouts, pagers, and so on. Complex math
|
||||||
|
(anything other than arithmetic) should be done outside of templates.
|
||||||
|
- Template functions only deal with the data passed into them. They never retrieve
|
||||||
|
data from a source.
|
||||||
|
- Finally, do not override core Go template functions.
|
||||||
26
vendor/github.com/Masterminds/sprig/appveyor.yml
generated
vendored
Normal file
26
vendor/github.com/Masterminds/sprig/appveyor.yml
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
version: build-{build}.{branch}
|
||||||
|
|
||||||
|
clone_folder: C:\gopath\src\github.com\Masterminds\sprig
|
||||||
|
shallow_clone: true
|
||||||
|
|
||||||
|
environment:
|
||||||
|
GOPATH: C:\gopath
|
||||||
|
|
||||||
|
platform:
|
||||||
|
- x64
|
||||||
|
|
||||||
|
install:
|
||||||
|
- go get -u github.com/Masterminds/glide
|
||||||
|
- set PATH=%GOPATH%\bin;%PATH%
|
||||||
|
- go version
|
||||||
|
- go env
|
||||||
|
|
||||||
|
build_script:
|
||||||
|
- glide install
|
||||||
|
- go install ./...
|
||||||
|
|
||||||
|
test_script:
|
||||||
|
- go test -v
|
||||||
|
|
||||||
|
deploy: off
|
||||||
217
vendor/github.com/Masterminds/sprig/doc.go
generated
vendored
217
vendor/github.com/Masterminds/sprig/doc.go
generated
vendored
@@ -14,221 +14,6 @@ Note that you should add the function map before you parse any template files.
|
|||||||
appear in the standard library. This is to make it easier to pipe
|
appear in the standard library. This is to make it easier to pipe
|
||||||
arguments into functions.
|
arguments into functions.
|
||||||
|
|
||||||
Date Functions
|
See http://masterminds.github.io/sprig/ for more detailed documentation on each of the available functions.
|
||||||
|
|
||||||
- date FORMAT TIME: Format a date, where a date is an integer type or a time.Time type, and
|
|
||||||
format is a time.Format formatting string.
|
|
||||||
- dateModify: Given a date, modify it with a duration: `date_modify "-1.5h" now`. If the duration doesn't
|
|
||||||
parse, it returns the time unaltered. See `time.ParseDuration` for info on duration strings.
|
|
||||||
- now: Current time.Time, for feeding into date-related functions.
|
|
||||||
- htmlDate TIME: Format a date for use in the value field of an HTML "date" form element.
|
|
||||||
- dateInZone FORMAT TIME TZ: Like date, but takes three arguments: format, timestamp,
|
|
||||||
timezone.
|
|
||||||
- htmlDateInZone TIME TZ: Like htmlDate, but takes two arguments: timestamp,
|
|
||||||
timezone.
|
|
||||||
|
|
||||||
String Functions
|
|
||||||
|
|
||||||
- abbrev: Truncate a string with ellipses. `abbrev 5 "hello world"` yields "he..."
|
|
||||||
- abbrevboth: Abbreviate from both sides, yielding "...lo wo..."
|
|
||||||
- trunc: Truncate a string (no suffix). `trunc 5 "Hello World"` yields "hello".
|
|
||||||
- trim: strings.TrimSpace
|
|
||||||
- trimAll: strings.Trim, but with the argument order reversed `trimAll "$" "$5.00"` or `"$5.00 | trimAll "$"`
|
|
||||||
- trimSuffix: strings.TrimSuffix, but with the argument order reversed: `trimSuffix "-" "ends-with-"`
|
|
||||||
- trimPrefix: strings.TrimPrefix, but with the argument order reversed `trimPrefix "$" "$5"`
|
|
||||||
- upper: strings.ToUpper
|
|
||||||
- lower: strings.ToLower
|
|
||||||
- nospace: Remove all space characters from a string. `nospace "h e l l o"` becomes "hello"
|
|
||||||
- title: strings.Title
|
|
||||||
- untitle: Remove title casing
|
|
||||||
- repeat: strings.Repeat, but with the arguments switched: `repeat count str`. (This simplifies common pipelines)
|
|
||||||
- substr: Given string, start, and length, return a substr.
|
|
||||||
- initials: Given a multi-word string, return the initials. `initials "Matt Butcher"` returns "MB"
|
|
||||||
- randAlphaNum: Given a length, generate a random alphanumeric sequence
|
|
||||||
- randAlpha: Given a length, generate an alphabetic string
|
|
||||||
- randAscii: Given a length, generate a random ASCII string (symbols included)
|
|
||||||
- randNumeric: Given a length, generate a string of digits.
|
|
||||||
- swapcase: SwapCase swaps the case of a string using a word based algorithm. see https://godoc.org/github.com/Masterminds/goutils#SwapCase
|
|
||||||
- shuffle: Shuffle randomizes runes in a string and returns the result. It uses default random source in `math/rand`
|
|
||||||
- snakecase: convert all upper case characters in a string to underscore format.
|
|
||||||
- camelcase: convert all lower case characters behind underscores to upper case character
|
|
||||||
- wrap: Force a line wrap at the given width. `wrap 80 "imagine a longer string"`
|
|
||||||
- wrapWith: Wrap a line at the given length, but using 'sep' instead of a newline. `wrapWith 50, "<br>", $html`
|
|
||||||
- contains: strings.Contains, but with the arguments switched: `contains substr str`. (This simplifies common pipelines)
|
|
||||||
- hasPrefix: strings.hasPrefix, but with the arguments switched
|
|
||||||
- hasSuffix: strings.hasSuffix, but with the arguments switched
|
|
||||||
- quote: Wrap string(s) in double quotation marks, escape the contents by adding '\' before '"'.
|
|
||||||
- squote: Wrap string(s) in double quotation marks, does not escape content.
|
|
||||||
- cat: Concatenate strings, separating them by spaces. `cat $a $b $c`.
|
|
||||||
- indent: Indent a string using space characters. `indent 4 "foo\nbar"` produces " foo\n bar"
|
|
||||||
- nindent: Indent a string using space characters and prepend a new line. `indent 4 "foo\nbar"` produces "\n foo\n bar"
|
|
||||||
- replace: Replace an old with a new in a string: `$name | replace " " "-"`
|
|
||||||
- plural: Choose singular or plural based on length: `len $fish | plural "one anchovy" "many anchovies"`
|
|
||||||
- sha256sum: Generate a hex encoded sha256 hash of the input
|
|
||||||
- toString: Convert something to a string
|
|
||||||
|
|
||||||
String Slice Functions:
|
|
||||||
|
|
||||||
- join: strings.Join, but as `join SEP SLICE`
|
|
||||||
- split: strings.Split, but as `split SEP STRING`. The results are returned
|
|
||||||
as a map with the indexes set to _N, where N is an integer starting from 0.
|
|
||||||
Use it like this: `{{$v := "foo/bar/baz" | split "/"}}{{$v._0}}` (Prints `foo`)
|
|
||||||
- splitList: strings.Split, but as `split SEP STRING`. The results are returned
|
|
||||||
as an array.
|
|
||||||
- toStrings: convert a list to a list of strings. 'list 1 2 3 | toStrings' produces '["1" "2" "3"]'
|
|
||||||
- sortAlpha: sort a list lexicographically.
|
|
||||||
|
|
||||||
Integer Slice Functions:
|
|
||||||
|
|
||||||
- until: Given an integer, returns a slice of counting integers from 0 to one
|
|
||||||
less than the given integer: `range $i, $e := until 5`
|
|
||||||
- untilStep: Given start, stop, and step, return an integer slice starting at
|
|
||||||
'start', stopping at `stop`, and incrementing by 'step. This is the same
|
|
||||||
as Python's long-form of 'range'.
|
|
||||||
|
|
||||||
Conversions:
|
|
||||||
|
|
||||||
- atoi: Convert a string to an integer. 0 if the integer could not be parsed.
|
|
||||||
- int64: Convert a string or another numeric type to an int64.
|
|
||||||
- int: Convert a string or another numeric type to an int.
|
|
||||||
- float64: Convert a string or another numeric type to a float64.
|
|
||||||
|
|
||||||
Defaults:
|
|
||||||
|
|
||||||
- default: Give a default value. Used like this: trim " "| default "empty".
|
|
||||||
Since trim produces an empty string, the default value is returned. For
|
|
||||||
things with a length (strings, slices, maps), len(0) will trigger the default.
|
|
||||||
For numbers, the value 0 will trigger the default. For booleans, false will
|
|
||||||
trigger the default. For structs, the default is never returned (there is
|
|
||||||
no clear empty condition). For everything else, nil value triggers a default.
|
|
||||||
- empty: Return true if the given value is the zero value for its type.
|
|
||||||
Caveats: structs are always non-empty. This should match the behavior of
|
|
||||||
{{if pipeline}}, but can be used inside of a pipeline.
|
|
||||||
- coalesce: Given a list of items, return the first non-empty one.
|
|
||||||
This follows the same rules as 'empty'. '{{ coalesce .someVal 0 "hello" }}`
|
|
||||||
will return `.someVal` if set, or else return "hello". The 0 is skipped
|
|
||||||
because it is an empty value.
|
|
||||||
- compact: Return a copy of a list with all of the empty values removed.
|
|
||||||
'list 0 1 2 "" | compact' will return '[1 2]'
|
|
||||||
- ternary: Given a value,'true | ternary "b" "c"' will return "b".
|
|
||||||
'false | ternary "b" "c"' will return '"c"'. Similar to the JavaScript ternary
|
|
||||||
operator.
|
|
||||||
|
|
||||||
OS:
|
|
||||||
- env: Resolve an environment variable
|
|
||||||
- expandenv: Expand a string through the environment
|
|
||||||
|
|
||||||
File Paths:
|
|
||||||
- base: Return the last element of a path. https://golang.org/pkg/path#Base
|
|
||||||
- dir: Remove the last element of a path. https://golang.org/pkg/path#Dir
|
|
||||||
- clean: Clean a path to the shortest equivalent name. (e.g. remove "foo/.."
|
|
||||||
from "foo/../bar.html") https://golang.org/pkg/path#Clean
|
|
||||||
- ext: https://golang.org/pkg/path#Ext
|
|
||||||
- isAbs: https://golang.org/pkg/path#IsAbs
|
|
||||||
|
|
||||||
Encoding:
|
|
||||||
- b64enc: Base 64 encode a string.
|
|
||||||
- b64dec: Base 64 decode a string.
|
|
||||||
|
|
||||||
Reflection:
|
|
||||||
|
|
||||||
- typeOf: Takes an interface and returns a string representation of the type.
|
|
||||||
For pointers, this will return a type prefixed with an asterisk(`*`). So
|
|
||||||
a pointer to type `Foo` will be `*Foo`.
|
|
||||||
- typeIs: Compares an interface with a string name, and returns true if they match.
|
|
||||||
Note that a pointer will not match a reference. For example `*Foo` will not
|
|
||||||
match `Foo`.
|
|
||||||
- typeIsLike: Compares an interface with a string name and returns true if
|
|
||||||
the interface is that `name` or that `*name`. In other words, if the given
|
|
||||||
value matches the given type or is a pointer to the given type, this returns
|
|
||||||
true.
|
|
||||||
- kindOf: Takes an interface and returns a string representation of its kind.
|
|
||||||
- kindIs: Returns true if the given string matches the kind of the given interface.
|
|
||||||
|
|
||||||
Note: None of these can test whether or not something implements a given
|
|
||||||
interface, since doing so would require compiling the interface in ahead of
|
|
||||||
time.
|
|
||||||
|
|
||||||
Data Structures:
|
|
||||||
|
|
||||||
- tuple: Takes an arbitrary list of items and returns a slice of items. Its
|
|
||||||
tuple-ish properties are mainly gained through the template idiom, and not
|
|
||||||
through an API provided here. WARNING: The implementation of tuple will
|
|
||||||
change in the future.
|
|
||||||
- list: An arbitrary ordered list of items. (This is prefered over tuple.)
|
|
||||||
- dict: Takes a list of name/values and returns a map[string]interface{}.
|
|
||||||
The first parameter is converted to a string and stored as a key, the
|
|
||||||
second parameter is treated as the value. And so on, with odds as keys and
|
|
||||||
evens as values. If the function call ends with an odd, the last key will
|
|
||||||
be assigned the empty string. Non-string keys are converted to strings as
|
|
||||||
follows: []byte are converted, fmt.Stringers will have String() called.
|
|
||||||
errors will have Error() called. All others will be passed through
|
|
||||||
fmt.Sprintf("%v").
|
|
||||||
|
|
||||||
Lists Functions:
|
|
||||||
|
|
||||||
These are used to manipulate lists: '{{ list 1 2 3 | reverse | first }}'
|
|
||||||
|
|
||||||
- first: Get the first item in a 'list'. 'list 1 2 3 | first' prints '1'
|
|
||||||
- last: Get the last item in a 'list': 'list 1 2 3 | last ' prints '3'
|
|
||||||
- rest: Get all but the first item in a list: 'list 1 2 3 | rest' returns '[2 3]'
|
|
||||||
- initial: Get all but the last item in a list: 'list 1 2 3 | initial' returns '[1 2]'
|
|
||||||
- append: Add an item to the end of a list: 'append $list 4' adds '4' to the end of '$list'
|
|
||||||
- prepend: Add an item to the beginning of a list: 'prepend $list 4' puts 4 at the beginning of the list.
|
|
||||||
- reverse: Reverse the items in a list.
|
|
||||||
- uniq: Remove duplicates from a list.
|
|
||||||
- without: Return a list with the given values removed: 'without (list 1 2 3) 1' would return '[2 3]'
|
|
||||||
- has: Return 'true' if the item is found in the list: 'has "foo" $list' will return 'true' if the list contains "foo"
|
|
||||||
|
|
||||||
Dict Functions:
|
|
||||||
|
|
||||||
These are used to manipulate dicts.
|
|
||||||
|
|
||||||
- set: Takes a dict, a key, and a value, and sets that key/value pair in
|
|
||||||
the dict. `set $dict $key $value`. For convenience, it returns the dict,
|
|
||||||
even though the dict was modified in place.
|
|
||||||
- unset: Takes a dict and a key, and deletes that key/value pair from the
|
|
||||||
dict. `unset $dict $key`. This returns the dict for convenience.
|
|
||||||
- hasKey: Takes a dict and a key, and returns boolean true if the key is in
|
|
||||||
the dict.
|
|
||||||
- pluck: Given a key and one or more maps, get all of the values for that key.
|
|
||||||
- keys: Get an array of all of the keys in one or more dicts.
|
|
||||||
- pick: Select just the given keys out of the dict, and return a new dict.
|
|
||||||
- omit: Return a dict without the given keys.
|
|
||||||
- values: Returns a list (interface{}) of all dictionary values.
|
|
||||||
|
|
||||||
Math Functions:
|
|
||||||
|
|
||||||
Integer functions will convert integers of any width to `int64`. If a
|
|
||||||
string is passed in, functions will attempt to convert with
|
|
||||||
`strconv.ParseInt(s, 1064)`. If this fails, the value will be treated as 0.
|
|
||||||
|
|
||||||
- add1: Increment an integer by 1
|
|
||||||
- add: Sum an arbitrary number of integers
|
|
||||||
- sub: Subtract the second integer from the first
|
|
||||||
- div: Divide the first integer by the second
|
|
||||||
- mod: Module of first integer divided by second
|
|
||||||
- mul: Multiply integers
|
|
||||||
- max: Return the biggest of a series of one or more integers
|
|
||||||
- min: Return the smallest of a series of one or more integers
|
|
||||||
- biggest: DEPRECATED. Return the biggest of a series of one or more integers
|
|
||||||
|
|
||||||
Crypto Functions:
|
|
||||||
|
|
||||||
- genPrivateKey: Generate a private key for the given cryptosystem. If no
|
|
||||||
argument is supplied, by default it will generate a private key using
|
|
||||||
the RSA algorithm. Accepted values are `rsa`, `dsa`, and `ecdsa`.
|
|
||||||
- derivePassword: Derive a password from the given parameters according to the ["Master Password" algorithm](http://masterpasswordapp.com/algorithm.html)
|
|
||||||
Given parameters (in order) are:
|
|
||||||
`counter` (starting with 1), `password_type` (maximum, long, medium, short, basic, or pin), `password`,
|
|
||||||
`user`, and `site`
|
|
||||||
|
|
||||||
SemVer Functions:
|
|
||||||
|
|
||||||
These functions provide version parsing and comparisons for SemVer 2 version
|
|
||||||
strings.
|
|
||||||
|
|
||||||
- semver: Parse a semantic version and return a Version object.
|
|
||||||
- semverCompare: Compare a SemVer range to a particular version.
|
|
||||||
*/
|
*/
|
||||||
package sprig
|
package sprig
|
||||||
|
|||||||
33
vendor/github.com/Masterminds/sprig/glide.lock
generated
vendored
Normal file
33
vendor/github.com/Masterminds/sprig/glide.lock
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
hash: 770b6a1132b743dadf6a0bb5fb8bf7083b1a5209f6d6c07826234ab2a97aade9
|
||||||
|
updated: 2018-04-02T23:08:56.947456531+02:00
|
||||||
|
imports:
|
||||||
|
- name: github.com/aokoli/goutils
|
||||||
|
version: 9c37978a95bd5c709a15883b6242714ea6709e64
|
||||||
|
- name: github.com/google/uuid
|
||||||
|
version: 064e2069ce9c359c118179501254f67d7d37ba24
|
||||||
|
- name: github.com/huandu/xstrings
|
||||||
|
version: 3959339b333561bf62a38b424fd41517c2c90f40
|
||||||
|
- name: github.com/imdario/mergo
|
||||||
|
version: 7fe0c75c13abdee74b09fcacef5ea1c6bba6a874
|
||||||
|
- name: github.com/Masterminds/goutils
|
||||||
|
version: 3391d3790d23d03408670993e957e8f408993c34
|
||||||
|
- name: github.com/Masterminds/semver
|
||||||
|
version: 59c29afe1a994eacb71c833025ca7acf874bb1da
|
||||||
|
- name: github.com/stretchr/testify
|
||||||
|
version: e3a8ff8ce36581f87a15341206f205b1da467059
|
||||||
|
subpackages:
|
||||||
|
- assert
|
||||||
|
- name: golang.org/x/crypto
|
||||||
|
version: d172538b2cfce0c13cee31e647d0367aa8cd2486
|
||||||
|
subpackages:
|
||||||
|
- pbkdf2
|
||||||
|
- scrypt
|
||||||
|
testImports:
|
||||||
|
- name: github.com/davecgh/go-spew
|
||||||
|
version: 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d
|
||||||
|
subpackages:
|
||||||
|
- spew
|
||||||
|
- name: github.com/pmezard/go-difflib
|
||||||
|
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
|
||||||
|
subpackages:
|
||||||
|
- difflib
|
||||||
15
vendor/github.com/Masterminds/sprig/glide.yaml
generated
vendored
Normal file
15
vendor/github.com/Masterminds/sprig/glide.yaml
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package: github.com/Masterminds/sprig
|
||||||
|
import:
|
||||||
|
- package: github.com/Masterminds/goutils
|
||||||
|
version: ^1.0.0
|
||||||
|
- package: github.com/google/uuid
|
||||||
|
version: ^0.2
|
||||||
|
- package: golang.org/x/crypto
|
||||||
|
subpackages:
|
||||||
|
- scrypt
|
||||||
|
- package: github.com/Masterminds/semver
|
||||||
|
version: v1.2.2
|
||||||
|
- package: github.com/stretchr/testify
|
||||||
|
- package: github.com/imdario/mergo
|
||||||
|
version: ~0.2.2
|
||||||
|
- package: github.com/huandu/xstrings
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user