Compare commits

...

15 Commits

Author SHA1 Message Date
Andrey Nering
b9aea8c5ec v3.3.0 2021-03-20 13:21:00 -03:00
Andrey Nering
897619a961 Upgrade github.com/spf13/pflag to v1.0.5 2021-03-20 12:00:39 -03:00
Andrey Nering
e6c4706b73 Add support for delegating CLI arguments with "--" and a special CLI_ARGS variable
Closes #327
2021-03-20 11:58:45 -03:00
Andrey Nering
8994c50d34 Upgrade mvdan.cc/sh to v3.2.4 2021-03-20 10:38:13 -03:00
Andrey Nering
55b62e47eb Upgrade mvdan.cc/sh to v3.2.2 2021-03-07 15:32:22 -03:00
Ross Hammermeister
c6ecf70377 Adding a --concurrency (-C) flag 2021-03-07 09:49:57 -03:00
Andrey Nering
f0cd7d27fb Taskfile: Set CGO_ENABLED=0 globally
We want that also for running tests, and not only for building it.
2021-03-07 09:30:33 -03:00
Andrey Nering
f923bb499b CHANGELOG: Fix wrong year in release date 2021-02-16 17:53:28 -03:00
Andrey Nering
aa3a29fed2 CHANGELOG: Add missing release dates 2021-02-16 17:52:32 -03:00
Andrey Nering
47d3011c85 v3.2.2 2021-01-12 13:21:36 -03:00
Andrey Nering
cec713a47a Update CHANGELOG 2021-01-12 12:09:03 -03:00
Andrey Nering
bf6d0c0a74 Improve performance of --list and --summary flags
Closes #332
2021-01-12 12:03:04 -03:00
Andrey Nering
c11672fca3 Envs should be overridable
System-wide environment variable should have priority. That's how it
works for .env files, so this is consistent.

Closes #425
2021-01-12 11:32:49 -03:00
Andrey Nering
e086b654aa Environment from .env file should be available as variables
Fixes #379
2021-01-12 11:11:40 -03:00
Andrey Nering
1107f691ea Update install script
Closes #428

Co-authored-by: odidev <odidev@puresoftware.com>
2021-01-12 10:43:45 -03:00
23 changed files with 355 additions and 152 deletions

View File

@@ -1,13 +1,35 @@
# Changelog # Changelog
## v3.2.1 ## v3.3.0 - 2021-03-20
- Add support for delegating CLI arguments to commands with `--` and a
special `CLI_ARGS` variable
([#327](https://github.com/go-task/task/issues/327)).
- Add a `--concurrency` (alias `-C`) flag, to limit the number of tasks that
run concurrently. This is useful for heavy workloads.
([#345](https://github.com/go-task/task/pull/345)).
## v3.2.2 - 2021-01-12
- Improve performance of `--list` and `--summary` by skipping running shell
variables for these flags
([#332](https://github.com/go-task/task/issues/332)).
- Fixed a bug where an environment in a Taskfile was not always overridable
by the system environment
([#425](https://github.com/go-task/task/issues/425)).
- Fixed environment from .env files not being available as variables
([#379](https://github.com/go-task/task/issues/379)).
- The install script is now working for ARM platforms
([#428](https://github.com/go-task/task/pull/428)).
## v3.2.1 - 2021-01-09
- Fixed some bugs and regressions regarding dynamic variables and directories - Fixed some bugs and regressions regarding dynamic variables and directories
([#426](https://github.com/go-task/task/issues/426)). ([#426](https://github.com/go-task/task/issues/426)).
- The [slim-sprig](https://github.com/go-task/slim-sprig) package was updated - The [slim-sprig](https://github.com/go-task/slim-sprig) package was updated
with the upstream [sprig](https://github.com/Masterminds/sprig). with the upstream [sprig](https://github.com/Masterminds/sprig).
## v3.2.0 ## v3.2.0 - 2021-01-07
- Fix the `.task` directory being created in the task directory instead of the - Fix the `.task` directory being created in the task directory instead of the
Taskfile directory Taskfile directory
@@ -20,7 +42,7 @@
should be more stable now should be more stable now
([#423](https://github.com/go-task/task/pull/423), [#365](https://github.com/go-task/task/issues/365)). ([#423](https://github.com/go-task/task/pull/423), [#365](https://github.com/go-task/task/issues/365)).
## v3.1.0 ## v3.1.0 - 2021-01-03
- Fix a bug when the checksum up-to-date resolution is used by a task - Fix a bug when the checksum up-to-date resolution is used by a task
with a custom `label:` attribute with a custom `label:` attribute
@@ -36,7 +58,7 @@
sentence was in the last line sentence was in the last line
([#403](https://github.com/go-task/task/issues/403)). ([#403](https://github.com/go-task/task/issues/403)).
## v3.0.1 ## v3.0.1 - 2020-12-26
- Allow use as a library by moving the required packages out of the `internal` - Allow use as a library by moving the required packages out of the `internal`
directory directory
@@ -46,7 +68,7 @@
- Fix panic when you have empty tasks in your Taskfile - Fix panic when you have empty tasks in your Taskfile
([#338](https://github.com/go-task/task/issues/338), [#362](https://github.com/go-task/task/pull/362)). ([#338](https://github.com/go-task/task/issues/338), [#362](https://github.com/go-task/task/pull/362)).
## v3.0.0 ## v3.0.0 - 2020-08-16
- On `v3`, all CLI variables will be considered global variables - On `v3`, all CLI variables will be considered global variables
([#336](https://github.com/go-task/task/issues/336), [#341](https://github.com/go-task/task/pull/341)) ([#336](https://github.com/go-task/task/issues/336), [#341](https://github.com/go-task/task/pull/341))
@@ -89,7 +111,7 @@
commands are green, errors are red, etc commands are green, errors are red, etc
([#207](https://github.com/go-task/task/pull/207)). ([#207](https://github.com/go-task/task/pull/207)).
## v2.8.1 - 2019-05-20 ## v2.8.1 - 2020-05-20
- Fix error code for the `--help` flag - Fix error code for the `--help` flag
([#300](https://github.com/go-task/task/issues/300), [#330](https://github.com/go-task/task/pull/330)). ([#300](https://github.com/go-task/task/issues/300), [#330](https://github.com/go-task/task/pull/330)).

View File

@@ -12,6 +12,9 @@ vars:
GO_PACKAGES: GO_PACKAGES:
sh: go list ./... sh: go list ./...
env:
CGO_ENABLED: '0'
tasks: tasks:
default: default:
cmds: cmds:
@@ -21,8 +24,6 @@ tasks:
desc: Installs Task desc: Installs Task
cmds: cmds:
- go install -v -ldflags="-w -s -X main.version={{.GIT_COMMIT}}" ./cmd/task - go install -v -ldflags="-w -s -X main.version={{.GIT_COMMIT}}" ./cmd/task
env:
CGO_ENABLED: '0'
mod: mod:
desc: Downloads and tidy Go modules desc: Downloads and tidy Go modules

View File

@@ -9,7 +9,7 @@ import (
// ParseV3 parses command line argument: tasks and global variables // ParseV3 parses command line argument: tasks and global variables
func ParseV3(args ...string) ([]taskfile.Call, *taskfile.Vars) { func ParseV3(args ...string) ([]taskfile.Call, *taskfile.Vars) {
var calls []taskfile.Call var calls []taskfile.Call
var globals *taskfile.Vars var globals = &taskfile.Vars{}
for _, arg := range args { for _, arg := range args {
if !strings.Contains(arg, "=") { if !strings.Contains(arg, "=") {
@@ -17,9 +17,6 @@ func ParseV3(args ...string) ([]taskfile.Call, *taskfile.Vars) {
continue continue
} }
if globals == nil {
globals = &taskfile.Vars{}
}
name, value := splitVar(arg) name, value := splitVar(arg)
globals.Set(name, taskfile.Var{Static: value}) globals.Set(name, taskfile.Var{Static: value})
} }
@@ -34,7 +31,7 @@ func ParseV3(args ...string) ([]taskfile.Call, *taskfile.Vars) {
// ParseV2 parses command line argument: tasks and vars of each task // ParseV2 parses command line argument: tasks and vars of each task
func ParseV2(args ...string) ([]taskfile.Call, *taskfile.Vars) { func ParseV2(args ...string) ([]taskfile.Call, *taskfile.Vars) {
var calls []taskfile.Call var calls []taskfile.Call
var globals *taskfile.Vars var globals = &taskfile.Vars{}
for _, arg := range args { for _, arg := range args {
if !strings.Contains(arg, "=") { if !strings.Contains(arg, "=") {
@@ -43,9 +40,6 @@ func ParseV2(args ...string) ([]taskfile.Call, *taskfile.Vars) {
} }
if len(calls) < 1 { if len(calls) < 1 {
if globals == nil {
globals = &taskfile.Vars{}
}
name, value := splitVar(arg) name, value := splitVar(arg)
globals.Set(name, taskfile.Var{Static: value}) globals.Set(name, taskfile.Var{Static: value})
} else { } else {

View File

@@ -96,7 +96,9 @@ func TestArgsV3(t *testing.T) {
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, globals := args.ParseV3(test.Args...) calls, globals := args.ParseV3(test.Args...)
assert.Equal(t, test.ExpectedCalls, calls) assert.Equal(t, test.ExpectedCalls, calls)
if test.ExpectedGlobals.Len() > 0 || globals.Len() > 0 {
assert.Equal(t, test.ExpectedGlobals, globals) assert.Equal(t, test.ExpectedGlobals, globals)
}
}) })
} }
} }
@@ -198,7 +200,10 @@ func TestArgsV2(t *testing.T) {
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, globals := args.ParseV2(test.Args...) calls, globals := args.ParseV2(test.Args...)
assert.Equal(t, test.ExpectedCalls, calls) assert.Equal(t, test.ExpectedCalls, calls)
if test.ExpectedGlobals.Len() > 0 || globals.Len() > 0 {
assert.Equal(t, test.ExpectedGlobals, globals) assert.Equal(t, test.ExpectedGlobals, globals)
}
}) })
} }
} }

View File

@@ -7,6 +7,7 @@ import (
"os" "os"
"os/signal" "os/signal"
"path/filepath" "path/filepath"
"strings"
"syscall" "syscall"
"github.com/spf13/pflag" "github.com/spf13/pflag"
@@ -65,6 +66,7 @@ func main() {
dry bool dry bool
summary bool summary bool
parallel bool parallel bool
concurrency int
dir string dir string
entrypoint string entrypoint string
output string output string
@@ -87,6 +89,7 @@ func main() {
pflag.StringVarP(&entrypoint, "taskfile", "t", "", `choose which Taskfile to run. Defaults to "Taskfile.yml"`) 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.StringVarP(&output, "output", "o", "", "sets output style: [interleaved|group|prefixed]")
pflag.BoolVarP(&color, "color", "c", true, "colored output") pflag.BoolVarP(&color, "color", "c", true, "colored output")
pflag.IntVarP(&concurrency, "concurrency", "C", 0, "limit number tasks to run concurrently")
pflag.Parse() pflag.Parse()
if versionFlag { if versionFlag {
@@ -132,6 +135,7 @@ func main() {
Summary: summary, Summary: summary,
Parallel: parallel, Parallel: parallel,
Color: color, Color: color,
Concurrency: concurrency,
Stdin: os.Stdin, Stdin: os.Stdin,
Stdout: os.Stdout, Stdout: os.Stdout,
@@ -156,12 +160,16 @@ func main() {
var ( var (
calls []taskfile.Call calls []taskfile.Call
globals *taskfile.Vars globals *taskfile.Vars
tasksAndVars, cliArgs = getArgs()
) )
if v >= 3.0 { if v >= 3.0 {
calls, globals = args.ParseV3(pflag.Args()...) calls, globals = args.ParseV3(tasksAndVars...)
} else { } else {
calls, globals = args.ParseV2(pflag.Args()...) calls, globals = args.ParseV2(tasksAndVars...)
} }
globals.Set("CLI_ARGS", taskfile.Var{Static: strings.Join(cliArgs, " ")})
e.Taskfile.Vars.Merge(globals) e.Taskfile.Vars.Merge(globals)
ctx := context.Background() ctx := context.Background()
@@ -182,6 +190,22 @@ func main() {
} }
} }
func getArgs() (tasksAndVars, cliArgs []string) {
var (
args = pflag.Args()
doubleDashPos = pflag.CommandLine.ArgsLenAtDash()
)
if doubleDashPos != -1 {
tasksAndVars = args[:doubleDashPos]
cliArgs = args[doubleDashPos:]
} else {
tasksAndVars = args
}
return
}
func getSignalContext() context.Context { func getSignalContext() context.Context {
ch := make(chan os.Signal, 1) ch := make(chan os.Signal, 1)
signal.Notify(ch, os.Interrupt, os.Kill, syscall.SIGTERM) signal.Notify(ch, os.Interrupt, os.Kill, syscall.SIGTERM)

25
concurrency.go Normal file
View File

@@ -0,0 +1,25 @@
package task
func (e *Executor) acquireConcurrencyLimit() func() {
if e.concurrencySemaphore == nil {
return emptyFunc
}
e.concurrencySemaphore <- struct{}{}
return func() {
<-e.concurrencySemaphore
}
}
func (e *Executor) releaseConcurrencyLimit() func() {
if e.concurrencySemaphore == nil {
return emptyFunc
}
<-e.concurrencySemaphore
return func() {
e.concurrencySemaphore <- struct{}{}
}
}
func emptyFunc() {}

View File

@@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
set -e set -e
# Code generated by godownloader on 2018-04-07T17:47:38Z. DO NOT EDIT. # Code generated by godownloader on 2021-01-12T13:40:40Z. DO NOT EDIT.
# #
usage() { usage() {
@@ -27,11 +27,12 @@ parse_args() {
# over-ridden by flag below # over-ridden by flag below
BINDIR=${BINDIR:-./bin} BINDIR=${BINDIR:-./bin}
while getopts "b:dh?" arg; do while getopts "b:dh?x" arg; do
case "$arg" in case "$arg" in
b) BINDIR="$OPTARG" ;; b) BINDIR="$OPTARG" ;;
d) log_set_priority 10 ;; d) log_set_priority 10 ;;
h | \?) usage "$0" ;; h | \?) usage "$0" ;;
x) set -x ;;
esac esac
done done
shift $((OPTIND - 1)) shift $((OPTIND - 1))
@@ -42,46 +43,41 @@ parse_args() {
# network, either nothing will happen or will syntax error # network, either nothing will happen or will syntax error
# out preventing half-done work # out preventing half-done work
execute() { execute() {
tmpdir=$(mktmpdir) tmpdir=$(mktemp -d)
log_debug "downloading files into ${tmpdir}" log_debug "downloading files into ${tmpdir}"
http_download "${tmpdir}/${TARBALL}" "${TARBALL_URL}" http_download "${tmpdir}/${TARBALL}" "${TARBALL_URL}"
http_download "${tmpdir}/${CHECKSUM}" "${CHECKSUM_URL}" http_download "${tmpdir}/${CHECKSUM}" "${CHECKSUM_URL}"
hash_sha256_verify "${tmpdir}/${TARBALL}" "${tmpdir}/${CHECKSUM}" hash_sha256_verify "${tmpdir}/${TARBALL}" "${tmpdir}/${CHECKSUM}"
srcdir="${tmpdir}" srcdir="${tmpdir}"
(cd "${tmpdir}" && untar "${TARBALL}") (cd "${tmpdir}" && untar "${TARBALL}")
install -d "${BINDIR}" test ! -d "${BINDIR}" && install -d "${BINDIR}"
for binexe in "task" ; do for binexe in $BINARIES; do
if [ "$OS" = "windows" ]; then if [ "$OS" = "windows" ]; then
binexe="${binexe}.exe" binexe="${binexe}.exe"
fi fi
install "${srcdir}/${binexe}" "${BINDIR}/" install "${srcdir}/${binexe}" "${BINDIR}/"
log_info "installed ${BINDIR}/${binexe}" log_info "installed ${BINDIR}/${binexe}"
done done
rm -rf "${tmpdir}"
} }
is_supported_platform() { get_binaries() {
platform=$1 case "$PLATFORM" in
found=1 darwin/amd64) BINARIES="task" ;;
case "$platform" in darwin/arm64) BINARIES="task" ;;
windows/386) found=0 ;; darwin/armv6) BINARIES="task" ;;
windows/amd64) found=0 ;; linux/386) BINARIES="task" ;;
darwin/386) found=0 ;; linux/amd64) BINARIES="task" ;;
darwin/amd64) found=0 ;; linux/arm64) BINARIES="task" ;;
linux/386) found=0 ;; linux/armv6) BINARIES="task" ;;
linux/amd64) found=0 ;; windows/386) BINARIES="task" ;;
esac windows/amd64) BINARIES="task" ;;
case "$platform" in windows/arm64) BINARIES="task" ;;
darwin/386) found=1 ;; windows/armv6) BINARIES="task" ;;
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" 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 exit 1
fi ;;
esac
} }
tag_to_version() { tag_to_version() {
if [ -z "${TAG}" ]; then if [ -z "${TAG}" ]; then
@@ -99,8 +95,8 @@ tag_to_version() {
VERSION=${TAG#v} VERSION=${TAG#v}
} }
adjust_format() { adjust_format() {
# change format (tar.gz or zip) based on ARCH # change format (tar.gz or zip) based on OS
case ${ARCH} in case ${OS} in
windows) FORMAT=zip ;; windows) FORMAT=zip ;;
esac esac
true true
@@ -174,7 +170,9 @@ log_crit() {
uname_os() { uname_os() {
os=$(uname -s | tr '[:upper:]' '[:lower:]') os=$(uname -s | tr '[:upper:]' '[:lower:]')
case "$os" in case "$os" in
msys_nt) os="windows" ;; cygwin_nt*) os="windows" ;;
mingw*) os="windows" ;;
msys_nt*) os="windows" ;;
esac esac
echo "$os" echo "$os"
} }
@@ -186,9 +184,9 @@ uname_arch() {
i686) arch="386" ;; i686) arch="386" ;;
i386) arch="386" ;; i386) arch="386" ;;
aarch64) arch="arm64" ;; aarch64) arch="arm64" ;;
armv5*) arch="arm5" ;; armv5*) arch="armv5" ;;
armv6*) arch="arm6" ;; armv6*) arch="armv6" ;;
armv7*) arch="arm7" ;; armv7*) arch="armv7" ;;
esac esac
echo ${arch} echo ${arch}
} }
@@ -234,8 +232,8 @@ uname_arch_check() {
untar() { untar() {
tarball=$1 tarball=$1
case "${tarball}" in case "${tarball}" in
*.tar.gz | *.tgz) tar -xzf "${tarball}" ;; *.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" ;;
*.tar) tar -xf "${tarball}" ;; *.tar) tar --no-same-owner -xf "${tarball}" ;;
*.zip) unzip "${tarball}" ;; *.zip) unzip "${tarball}" ;;
*) *)
log_err "untar unknown archive format for ${tarball}" log_err "untar unknown archive format for ${tarball}"
@@ -243,11 +241,6 @@ untar() {
;; ;;
esac esac
} }
mktmpdir() {
test -z "$TMPDIR" && TMPDIR="$(mktemp -d)"
mkdir -p "${TMPDIR}"
echo "${TMPDIR}"
}
http_download_curl() { http_download_curl() {
local_file=$1 local_file=$1
source_url=$2 source_url=$2
@@ -368,7 +361,7 @@ uname_arch_check "$ARCH"
parse_args "$@" parse_args "$@"
check_platform get_binaries
tag_to_version tag_to_version

View File

@@ -520,6 +520,27 @@ tasks:
This works for all types of variables. This works for all types of variables.
## Forwarding CLI arguments to commands
If `--` is given in the CLI, all following paramaters are added to a
special `.CLI_ARGS` variable. This is useful to forward arguments to another
command.
The below example will run `yarn install`.
```bash
$ task yarn -- install
```
```yaml
version: '3'
tasks:
yarn:
cmds:
- yarn {{.CLI_ARGS}}
```
## Go's template engine ## Go's template engine
Task parse commands as [Go's template engine][gotemplate] before executing Task parse commands as [Go's template engine][gotemplate] before executing

4
go.mod
View File

@@ -7,11 +7,11 @@ require (
github.com/mattn/go-colorable v0.1.2 // indirect github.com/mattn/go-colorable v0.1.2 // indirect
github.com/mattn/go-zglob v0.0.1 github.com/mattn/go-zglob v0.0.1
github.com/radovskyb/watcher v1.0.5 github.com/radovskyb/watcher v1.0.5
github.com/spf13/pflag v1.0.3 github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.5.1 github.com/stretchr/testify v1.5.1
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
mvdan.cc/sh/v3 v3.2.1 mvdan.cc/sh/v3 v3.2.4
) )
go 1.13 go 1.13

11
go.sum
View File

@@ -13,7 +13,6 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg78
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
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/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
@@ -33,10 +32,9 @@ github.com/radovskyb/watcher v1.0.5 h1:wqt7gb+HjGacvFoLTKeT44C+XVPxu7bvHvKT1IvZ7
github.com/radovskyb/watcher v1.0.5/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg= github.com/radovskyb/watcher v1.0.5/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg=
github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= 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.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 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= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
@@ -48,7 +46,6 @@ golang.org/x/sys v0.0.0-20201029080932-201ba4db2418 h1:HlFl4V6pEMziuLXyRkm5BIYq1
golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20191110171634-ad39bd3f0407 h1:5zh5atpUEdIc478E/ebrIaHLKcfVvG6dL/fGv7BcMoM= golang.org/x/term v0.0.0-20191110171634-ad39bd3f0407 h1:5zh5atpUEdIc478E/ebrIaHLKcfVvG6dL/fGv7BcMoM=
golang.org/x/term v0.0.0-20191110171634-ad39bd3f0407/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20191110171634-ad39bd3f0407/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
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 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 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-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -58,5 +55,5 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
mvdan.cc/editorconfig v0.1.1-0.20200121172147-e40951bde157/go.mod h1:Ge4atmRUYqueGppvJ7JNrtqpqokoJEFxYbP0Z+WeKS8= mvdan.cc/editorconfig v0.1.1-0.20200121172147-e40951bde157/go.mod h1:Ge4atmRUYqueGppvJ7JNrtqpqokoJEFxYbP0Z+WeKS8=
mvdan.cc/sh/v3 v3.2.1 h1:uQBpiGM+rEuHse3Q+W7ajuJUeOtFVJUN/6GeX4/dUWE= mvdan.cc/sh/v3 v3.2.4 h1:+fZaWcXWRjYAvqzEKoDhDM3DkxdDUykU2iw0VMKFe9s=
mvdan.cc/sh/v3 v3.2.1/go.mod h1:fPQmabBpREM/XQ9YXSU5ZFZ/Sm+PmKP9/vkFHgYKJEI= mvdan.cc/sh/v3 v3.2.4/go.mod h1:fPQmabBpREM/XQ9YXSU5ZFZ/Sm+PmKP9/vkFHgYKJEI=

View File

@@ -30,7 +30,7 @@ func (e *Executor) tasksWithDesc() (tasks []*taskfile.Task) {
tasks = make([]*taskfile.Task, 0, len(e.Taskfile.Tasks)) tasks = make([]*taskfile.Task, 0, len(e.Taskfile.Tasks))
for _, task := range e.Taskfile.Tasks { for _, task := range e.Taskfile.Tasks {
if task.Desc != "" { if task.Desc != "" {
compiledTask, err := e.CompiledTask(taskfile.Call{Task: task.Task}) compiledTask, err := e.FastCompiledTask(taskfile.Call{Task: task.Task})
if err == nil { if err == nil {
task = compiledTask task = compiledTask
} }

View File

@@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
set -e set -e
# Code generated by godownloader on 2018-04-07T17:47:38Z. DO NOT EDIT. # Code generated by godownloader on 2021-01-12T13:40:40Z. DO NOT EDIT.
# #
usage() { usage() {
@@ -27,11 +27,12 @@ parse_args() {
# over-ridden by flag below # over-ridden by flag below
BINDIR=${BINDIR:-./bin} BINDIR=${BINDIR:-./bin}
while getopts "b:dh?" arg; do while getopts "b:dh?x" arg; do
case "$arg" in case "$arg" in
b) BINDIR="$OPTARG" ;; b) BINDIR="$OPTARG" ;;
d) log_set_priority 10 ;; d) log_set_priority 10 ;;
h | \?) usage "$0" ;; h | \?) usage "$0" ;;
x) set -x ;;
esac esac
done done
shift $((OPTIND - 1)) shift $((OPTIND - 1))
@@ -42,46 +43,41 @@ parse_args() {
# network, either nothing will happen or will syntax error # network, either nothing will happen or will syntax error
# out preventing half-done work # out preventing half-done work
execute() { execute() {
tmpdir=$(mktmpdir) tmpdir=$(mktemp -d)
log_debug "downloading files into ${tmpdir}" log_debug "downloading files into ${tmpdir}"
http_download "${tmpdir}/${TARBALL}" "${TARBALL_URL}" http_download "${tmpdir}/${TARBALL}" "${TARBALL_URL}"
http_download "${tmpdir}/${CHECKSUM}" "${CHECKSUM_URL}" http_download "${tmpdir}/${CHECKSUM}" "${CHECKSUM_URL}"
hash_sha256_verify "${tmpdir}/${TARBALL}" "${tmpdir}/${CHECKSUM}" hash_sha256_verify "${tmpdir}/${TARBALL}" "${tmpdir}/${CHECKSUM}"
srcdir="${tmpdir}" srcdir="${tmpdir}"
(cd "${tmpdir}" && untar "${TARBALL}") (cd "${tmpdir}" && untar "${TARBALL}")
install -d "${BINDIR}" test ! -d "${BINDIR}" && install -d "${BINDIR}"
for binexe in "task" ; do for binexe in $BINARIES; do
if [ "$OS" = "windows" ]; then if [ "$OS" = "windows" ]; then
binexe="${binexe}.exe" binexe="${binexe}.exe"
fi fi
install "${srcdir}/${binexe}" "${BINDIR}/" install "${srcdir}/${binexe}" "${BINDIR}/"
log_info "installed ${BINDIR}/${binexe}" log_info "installed ${BINDIR}/${binexe}"
done done
rm -rf "${tmpdir}"
} }
is_supported_platform() { get_binaries() {
platform=$1 case "$PLATFORM" in
found=1 darwin/amd64) BINARIES="task" ;;
case "$platform" in darwin/arm64) BINARIES="task" ;;
windows/386) found=0 ;; darwin/armv6) BINARIES="task" ;;
windows/amd64) found=0 ;; linux/386) BINARIES="task" ;;
darwin/386) found=0 ;; linux/amd64) BINARIES="task" ;;
darwin/amd64) found=0 ;; linux/arm64) BINARIES="task" ;;
linux/386) found=0 ;; linux/armv6) BINARIES="task" ;;
linux/amd64) found=0 ;; windows/386) BINARIES="task" ;;
esac windows/amd64) BINARIES="task" ;;
case "$platform" in windows/arm64) BINARIES="task" ;;
darwin/386) found=1 ;; windows/armv6) BINARIES="task" ;;
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" 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 exit 1
fi ;;
esac
} }
tag_to_version() { tag_to_version() {
if [ -z "${TAG}" ]; then if [ -z "${TAG}" ]; then
@@ -99,8 +95,8 @@ tag_to_version() {
VERSION=${TAG#v} VERSION=${TAG#v}
} }
adjust_format() { adjust_format() {
# change format (tar.gz or zip) based on ARCH # change format (tar.gz or zip) based on OS
case ${ARCH} in case ${OS} in
windows) FORMAT=zip ;; windows) FORMAT=zip ;;
esac esac
true true
@@ -174,7 +170,9 @@ log_crit() {
uname_os() { uname_os() {
os=$(uname -s | tr '[:upper:]' '[:lower:]') os=$(uname -s | tr '[:upper:]' '[:lower:]')
case "$os" in case "$os" in
msys_nt) os="windows" ;; cygwin_nt*) os="windows" ;;
mingw*) os="windows" ;;
msys_nt*) os="windows" ;;
esac esac
echo "$os" echo "$os"
} }
@@ -186,9 +184,9 @@ uname_arch() {
i686) arch="386" ;; i686) arch="386" ;;
i386) arch="386" ;; i386) arch="386" ;;
aarch64) arch="arm64" ;; aarch64) arch="arm64" ;;
armv5*) arch="arm5" ;; armv5*) arch="armv5" ;;
armv6*) arch="arm6" ;; armv6*) arch="armv6" ;;
armv7*) arch="arm7" ;; armv7*) arch="armv7" ;;
esac esac
echo ${arch} echo ${arch}
} }
@@ -234,8 +232,8 @@ uname_arch_check() {
untar() { untar() {
tarball=$1 tarball=$1
case "${tarball}" in case "${tarball}" in
*.tar.gz | *.tgz) tar -xzf "${tarball}" ;; *.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" ;;
*.tar) tar -xf "${tarball}" ;; *.tar) tar --no-same-owner -xf "${tarball}" ;;
*.zip) unzip "${tarball}" ;; *.zip) unzip "${tarball}" ;;
*) *)
log_err "untar unknown archive format for ${tarball}" log_err "untar unknown archive format for ${tarball}"
@@ -243,11 +241,6 @@ untar() {
;; ;;
esac esac
} }
mktmpdir() {
test -z "$TMPDIR" && TMPDIR="$(mktemp -d)"
mkdir -p "${TMPDIR}"
echo "${TMPDIR}"
}
http_download_curl() { http_download_curl() {
local_file=$1 local_file=$1
source_url=$2 source_url=$2
@@ -368,7 +361,7 @@ uname_arch_check "$ARCH"
parse_args "$@" parse_args "$@"
check_platform get_binaries
tag_to_version tag_to_version

View File

@@ -8,6 +8,7 @@ import (
// E.g. variable merger, template processing, etc. // E.g. variable merger, template processing, etc.
type Compiler interface { type Compiler interface {
GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error)
FastGetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error)
HandleDynamicVar(v taskfile.Var, dir string) (string, error) HandleDynamicVar(v taskfile.Var, dir string) (string, error)
ResetCache() ResetCache()
} }

View File

@@ -30,6 +30,11 @@ type CompilerV2 struct {
muDynamicCache sync.Mutex muDynamicCache sync.Mutex
} }
// FastGetVariables is a no-op on v2
func (c *CompilerV2) FastGetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) {
return c.GetVariables(t, call)
}
// GetVariables returns fully resolved variables following the priority order: // GetVariables returns fully resolved variables following the priority order:
// 1. Task variables // 1. Task variables
// 2. Call variables // 2. Call variables

View File

@@ -20,6 +20,7 @@ var _ compiler.Compiler = &CompilerV3{}
type CompilerV3 struct { type CompilerV3 struct {
Dir string Dir string
TaskfileEnv *taskfile.Vars
TaskfileVars *taskfile.Vars TaskfileVars *taskfile.Vars
Logger *logger.Logger Logger *logger.Logger
@@ -29,6 +30,14 @@ type CompilerV3 struct {
} }
func (c *CompilerV3) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) { func (c *CompilerV3) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) {
return c.getVariables(t, call, true)
}
func (c *CompilerV3) FastGetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) {
return c.getVariables(t, call, false)
}
func (c *CompilerV3) getVariables(t *taskfile.Task, call taskfile.Call, evaluateShVars bool) (*taskfile.Vars, error) {
result := compiler.GetEnviron() result := compiler.GetEnviron()
result.Set("TASK", taskfile.Var{Static: t.Task}) result.Set("TASK", taskfile.Var{Static: t.Task})
@@ -36,6 +45,11 @@ func (c *CompilerV3) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfi
return func(k string, v taskfile.Var) error { return func(k string, v taskfile.Var) error {
tr := templater.Templater{Vars: result, RemoveNoValue: true} tr := templater.Templater{Vars: result, RemoveNoValue: true}
if !evaluateShVars {
result.Set(k, taskfile.Var{Static: tr.Replace(v.Static)})
return nil
}
v = taskfile.Var{ v = taskfile.Var{
Static: tr.Replace(v.Static), Static: tr.Replace(v.Static),
Sh: tr.Replace(v.Sh), Sh: tr.Replace(v.Sh),
@@ -54,6 +68,9 @@ func (c *CompilerV3) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfi
} }
rangeFunc := getRangeFunc(c.Dir) rangeFunc := getRangeFunc(c.Dir)
if err := c.TaskfileEnv.Range(rangeFunc); err != nil {
return nil, err
}
if err := c.TaskfileVars.Range(rangeFunc); err != nil { if err := c.TaskfileVars.Range(rangeFunc); err != nil {
return nil, err return nil, err
} }

View File

@@ -63,7 +63,7 @@ func (r *Templater) ReplaceSlice(strs []string) []string {
} }
func (r *Templater) ReplaceVars(vars *taskfile.Vars) *taskfile.Vars { func (r *Templater) ReplaceVars(vars *taskfile.Vars) *taskfile.Vars {
if r.err != nil || vars == nil || len(vars.Keys) == 0 { if r.err != nil || vars.Len() == 0 {
return nil return nil
} }

31
task.go
View File

@@ -42,6 +42,7 @@ type Executor struct {
Summary bool Summary bool
Parallel bool Parallel bool
Color bool Color bool
Concurrency int
Stdin io.Reader Stdin io.Reader
Stdout io.Writer Stdout io.Writer
@@ -54,6 +55,7 @@ type Executor struct {
taskvars *taskfile.Vars taskvars *taskfile.Vars
concurrencySemaphore chan struct{}
taskCallCount map[string]*int32 taskCallCount map[string]*int32
mkdirMutexMap map[string]*sync.Mutex mkdirMutexMap map[string]*sync.Mutex
} }
@@ -71,7 +73,7 @@ func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error {
if e.Summary { if e.Summary {
for i, c := range calls { for i, c := range calls {
compiledTask, err := e.CompiledTask(c) compiledTask, err := e.FastCompiledTask(c)
if err != nil { if err != nil {
return nil return nil
} }
@@ -168,6 +170,7 @@ func (e *Executor) Setup() error {
} else { } else {
e.Compiler = &compilerv3.CompilerV3{ e.Compiler = &compilerv3.CompilerV3{
Dir: e.Dir, Dir: e.Dir,
TaskfileEnv: e.Taskfile.Env,
TaskfileVars: e.Taskfile.Vars, TaskfileVars: e.Taskfile.Vars,
Logger: e.Logger, Logger: e.Logger,
} }
@@ -246,6 +249,10 @@ func (e *Executor) Setup() error {
e.taskCallCount[k] = new(int32) e.taskCallCount[k] = new(int32)
e.mkdirMutexMap[k] = &sync.Mutex{} e.mkdirMutexMap[k] = &sync.Mutex{}
} }
if e.Concurrency > 0 {
e.concurrencySemaphore = make(chan struct{}, e.Concurrency)
}
return nil return nil
} }
@@ -259,6 +266,9 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
return &MaximumTaskCallExceededError{task: call.Task} return &MaximumTaskCallExceededError{task: call.Task}
} }
release := e.acquireConcurrencyLimit()
defer release()
if err := e.runDeps(ctx, t); err != nil { if err := e.runDeps(ctx, t); err != nil {
return err return err
} }
@@ -323,6 +333,9 @@ func (e *Executor) mkdir(t *taskfile.Task) error {
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)
reacquire := e.releaseConcurrencyLimit()
defer reacquire()
for _, d := range t.Deps { for _, d := range t.Deps {
d := d d := d
@@ -343,6 +356,9 @@ func (e *Executor) runCommand(ctx context.Context, t *taskfile.Task, call taskfi
switch { switch {
case cmd.Task != "": case cmd.Task != "":
reacquire := e.releaseConcurrencyLimit()
defer reacquire()
err := 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 { if err != nil {
return err return err
@@ -396,10 +412,19 @@ func getEnviron(t *taskfile.Task) []string {
} }
environ := os.Environ() environ := os.Environ()
for k, v := range t.Env.ToCacheMap() { for k, v := range t.Env.ToCacheMap() {
if s, ok := v.(string); ok { str, isString := v.(string)
environ = append(environ, fmt.Sprintf("%s=%s", k, s)) if !isString {
continue
} }
if _, alreadySet := os.LookupEnv(k); alreadySet {
continue
} }
environ = append(environ, fmt.Sprintf("%s=%s", k, str))
}
return environ return environ
} }

View File

@@ -126,6 +126,7 @@ func TestVarsV3(t *testing.T) {
"var-order.txt": "ABCDEF\n", "var-order.txt": "ABCDEF\n",
"dependent-sh.txt": "123456\n", "dependent-sh.txt": "123456\n",
"with-call.txt": "Hi, ABC123!\n", "with-call.txt": "Hi, ABC123!\n",
"from-dot-env.txt": "From .env file\n",
}, },
} }
tt.Run(t) tt.Run(t)
@@ -170,6 +171,22 @@ func TestVarsInvalidTmpl(t *testing.T) {
assert.EqualError(t, e.Run(context.Background(), taskfile.Call{Task: target}), expectError, "e.Run(target)") assert.EqualError(t, e.Run(context.Background(), taskfile.Call{Task: target}), expectError, "e.Run(target)")
} }
func TestConcurrency(t *testing.T) {
const (
dir = "testdata/concurrency"
target = "default"
)
e := &task.Executor{
Dir: dir,
Stdout: ioutil.Discard,
Stderr: ioutil.Discard,
Concurrency: 1,
}
assert.NoError(t, e.Setup(), "e.Setup()")
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: target}), "e.Run(target)")
}
func TestParams(t *testing.T) { func TestParams(t *testing.T) {
tt := fileContentTest{ tt := fileContentTest{
Dir: "testdata/params", Dir: "testdata/params",

View File

@@ -75,7 +75,7 @@ func (vs *Vars) Range(yield func(key string, value Var) error) error {
// ToCacheMap converts Vars to a map containing only the static // ToCacheMap converts Vars to a map containing only the static
// variables // variables
func (vs *Vars) ToCacheMap() (m map[string]interface{}) { func (vs *Vars) ToCacheMap() (m map[string]interface{}) {
m = make(map[string]interface{}, len(vs.Keys)) m = make(map[string]interface{}, vs.Len())
vs.Range(func(k string, v Var) error { vs.Range(func(k string, v Var) error {
if v.Sh != "" { if v.Sh != "" {
// Dynamic variable is not yet resolved; trigger // Dynamic variable is not yet resolved; trigger
@@ -93,6 +93,14 @@ func (vs *Vars) ToCacheMap() (m map[string]interface{}) {
return return
} }
// Len returns the size of the map
func (vs *Vars) Len() int {
if vs == nil {
return 0
}
return len(vs.Keys)
}
// Var represents either a static or dynamic variable. // Var represents either a static or dynamic variable.
type Var struct { type Var struct {
Static string Static string

32
testdata/concurrency/Taskfile.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
version: '2'
tasks:
default:
deps:
- t1
t1:
deps:
- t3
- t4
cmds:
- task: t2
- echo done 1
t2:
deps:
- t5
- t6
cmds:
- echo done 2
t3:
cmds:
- echo done 3
t4:
cmds:
- echo done 4
t5:
cmds:
- echo done 5
t6:
cmds:
- echo done 6

1
testdata/vars/v3/.env vendored Normal file
View File

@@ -0,0 +1 @@
DOT_ENV_VAR=From .env file

View File

@@ -1,5 +1,7 @@
version: '3' version: '3'
dotenv: [.env]
vars: vars:
VAR_A: A VAR_A: A
VAR_B: '{{.VAR_A}}B' VAR_B: '{{.VAR_A}}B'
@@ -15,6 +17,7 @@ tasks:
- task: var-order - task: var-order
- task: dependent-sh - task: dependent-sh
- task: with-call - task: with-call
- task: from-dot-env
missing-var: echo '{{.NON_EXISTING_VAR}}' > missing-var.txt missing-var: echo '{{.NON_EXISTING_VAR}}' > missing-var.txt
@@ -44,3 +47,5 @@ tasks:
MESSAGE: Hi, {{.ABC123}}! MESSAGE: Hi, {{.ABC123}}!
cmds: cmds:
- echo "{{.MESSAGE}}" > with-call.txt - echo "{{.MESSAGE}}" > with-call.txt
from-dot-env: echo '{{.DOT_ENV_VAR}}' > from-dot-env.txt

View File

@@ -13,12 +13,27 @@ import (
// 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
// properties using the Go template package. // properties using the Go template package.
func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) { func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) {
return e.compiledTask(call, true)
}
// FastCompiledTask is like CompiledTask, but it skippes dynamic variables.
func (e *Executor) FastCompiledTask(call taskfile.Call) (*taskfile.Task, error) {
return e.compiledTask(call, false)
}
func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskfile.Task, error) {
origTask, ok := e.Taskfile.Tasks[call.Task] origTask, ok := e.Taskfile.Tasks[call.Task]
if !ok { if !ok {
return nil, &taskNotFoundError{call.Task} return nil, &taskNotFoundError{call.Task}
} }
vars, err := e.Compiler.GetVariables(origTask, call) var vars *taskfile.Vars
var err error
if evaluateShVars {
vars, err = e.Compiler.GetVariables(origTask, call)
} else {
vars, err = e.Compiler.FastGetVariables(origTask, call)
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -59,6 +74,7 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) {
new.Env = &taskfile.Vars{} new.Env = &taskfile.Vars{}
new.Env.Merge(r.ReplaceVars(e.Taskfile.Env)) new.Env.Merge(r.ReplaceVars(e.Taskfile.Env))
new.Env.Merge(r.ReplaceVars(origTask.Env)) new.Env.Merge(r.ReplaceVars(origTask.Env))
if evaluateShVars {
err = new.Env.Range(func(k string, v taskfile.Var) error { err = new.Env.Range(func(k string, v taskfile.Var) error {
static, err := e.Compiler.HandleDynamicVar(v, new.Dir) static, err := e.Compiler.HandleDynamicVar(v, new.Dir)
if err != nil { if err != nil {
@@ -70,6 +86,7 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
}
if len(origTask.Cmds) > 0 { if len(origTask.Cmds) > 0 {
new.Cmds = make([]*taskfile.Cmd, len(origTask.Cmds)) new.Cmds = make([]*taskfile.Cmd, len(origTask.Cmds))