mirror of
https://github.com/go-task/task.git
synced 2026-06-12 02:11:37 +00:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9aea8c5ec | ||
|
|
897619a961 | ||
|
|
e6c4706b73 | ||
|
|
8994c50d34 | ||
|
|
55b62e47eb | ||
|
|
c6ecf70377 | ||
|
|
f0cd7d27fb | ||
|
|
f923bb499b | ||
|
|
aa3a29fed2 | ||
|
|
47d3011c85 | ||
|
|
cec713a47a | ||
|
|
bf6d0c0a74 | ||
|
|
c11672fca3 | ||
|
|
e086b654aa | ||
|
|
1107f691ea | ||
|
|
b095ca5756 | ||
|
|
4afc0e8ed0 | ||
|
|
141b377b4e | ||
|
|
402a478785 | ||
|
|
73680584f3 |
39
CHANGELOG.md
39
CHANGELOG.md
@@ -1,6 +1,35 @@
|
||||
# Changelog
|
||||
|
||||
## v3.2.0
|
||||
## 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
|
||||
([#426](https://github.com/go-task/task/issues/426)).
|
||||
- The [slim-sprig](https://github.com/go-task/slim-sprig) package was updated
|
||||
with the upstream [sprig](https://github.com/Masterminds/sprig).
|
||||
|
||||
## v3.2.0 - 2021-01-07
|
||||
|
||||
- Fix the `.task` directory being created in the task directory instead of the
|
||||
Taskfile directory
|
||||
@@ -13,7 +42,7 @@
|
||||
should be more stable now
|
||||
([#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
|
||||
with a custom `label:` attribute
|
||||
@@ -29,7 +58,7 @@
|
||||
sentence was in the last line
|
||||
([#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`
|
||||
directory
|
||||
@@ -39,7 +68,7 @@
|
||||
- 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)).
|
||||
|
||||
## v3.0.0
|
||||
## v3.0.0 - 2020-08-16
|
||||
|
||||
- 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))
|
||||
@@ -82,7 +111,7 @@
|
||||
commands are green, errors are red, etc
|
||||
([#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
|
||||
([#300](https://github.com/go-task/task/issues/300), [#330](https://github.com/go-task/task/pull/330)).
|
||||
|
||||
@@ -12,6 +12,9 @@ vars:
|
||||
GO_PACKAGES:
|
||||
sh: go list ./...
|
||||
|
||||
env:
|
||||
CGO_ENABLED: '0'
|
||||
|
||||
tasks:
|
||||
default:
|
||||
cmds:
|
||||
@@ -21,8 +24,6 @@ tasks:
|
||||
desc: Installs Task
|
||||
cmds:
|
||||
- go install -v -ldflags="-w -s -X main.version={{.GIT_COMMIT}}" ./cmd/task
|
||||
env:
|
||||
CGO_ENABLED: '0'
|
||||
|
||||
mod:
|
||||
desc: Downloads and tidy Go modules
|
||||
|
||||
10
args/args.go
10
args/args.go
@@ -9,7 +9,7 @@ import (
|
||||
// ParseV3 parses command line argument: tasks and global variables
|
||||
func ParseV3(args ...string) ([]taskfile.Call, *taskfile.Vars) {
|
||||
var calls []taskfile.Call
|
||||
var globals *taskfile.Vars
|
||||
var globals = &taskfile.Vars{}
|
||||
|
||||
for _, arg := range args {
|
||||
if !strings.Contains(arg, "=") {
|
||||
@@ -17,9 +17,6 @@ func ParseV3(args ...string) ([]taskfile.Call, *taskfile.Vars) {
|
||||
continue
|
||||
}
|
||||
|
||||
if globals == nil {
|
||||
globals = &taskfile.Vars{}
|
||||
}
|
||||
name, value := splitVar(arg)
|
||||
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
|
||||
func ParseV2(args ...string) ([]taskfile.Call, *taskfile.Vars) {
|
||||
var calls []taskfile.Call
|
||||
var globals *taskfile.Vars
|
||||
var globals = &taskfile.Vars{}
|
||||
|
||||
for _, arg := range args {
|
||||
if !strings.Contains(arg, "=") {
|
||||
@@ -43,9 +40,6 @@ func ParseV2(args ...string) ([]taskfile.Call, *taskfile.Vars) {
|
||||
}
|
||||
|
||||
if len(calls) < 1 {
|
||||
if globals == nil {
|
||||
globals = &taskfile.Vars{}
|
||||
}
|
||||
name, value := splitVar(arg)
|
||||
globals.Set(name, taskfile.Var{Static: value})
|
||||
} else {
|
||||
|
||||
@@ -96,7 +96,9 @@ func TestArgsV3(t *testing.T) {
|
||||
t.Run(fmt.Sprintf("TestArgs%d", i+1), func(t *testing.T) {
|
||||
calls, globals := args.ParseV3(test.Args...)
|
||||
assert.Equal(t, test.ExpectedCalls, calls)
|
||||
assert.Equal(t, test.ExpectedGlobals, globals)
|
||||
if test.ExpectedGlobals.Len() > 0 || globals.Len() > 0 {
|
||||
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) {
|
||||
calls, globals := args.ParseV2(test.Args...)
|
||||
assert.Equal(t, test.ExpectedCalls, calls)
|
||||
assert.Equal(t, test.ExpectedGlobals, globals)
|
||||
if test.ExpectedGlobals.Len() > 0 || globals.Len() > 0 {
|
||||
assert.Equal(t, test.ExpectedGlobals, globals)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
@@ -65,6 +66,7 @@ func main() {
|
||||
dry bool
|
||||
summary bool
|
||||
parallel bool
|
||||
concurrency int
|
||||
dir string
|
||||
entrypoint 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(&output, "output", "o", "", "sets output style: [interleaved|group|prefixed]")
|
||||
pflag.BoolVarP(&color, "color", "c", true, "colored output")
|
||||
pflag.IntVarP(&concurrency, "concurrency", "C", 0, "limit number tasks to run concurrently")
|
||||
pflag.Parse()
|
||||
|
||||
if versionFlag {
|
||||
@@ -122,16 +125,17 @@ func main() {
|
||||
}
|
||||
|
||||
e := task.Executor{
|
||||
Force: force,
|
||||
Watch: watch,
|
||||
Verbose: verbose,
|
||||
Silent: silent,
|
||||
Dir: dir,
|
||||
Dry: dry,
|
||||
Entrypoint: entrypoint,
|
||||
Summary: summary,
|
||||
Parallel: parallel,
|
||||
Color: color,
|
||||
Force: force,
|
||||
Watch: watch,
|
||||
Verbose: verbose,
|
||||
Silent: silent,
|
||||
Dir: dir,
|
||||
Dry: dry,
|
||||
Entrypoint: entrypoint,
|
||||
Summary: summary,
|
||||
Parallel: parallel,
|
||||
Color: color,
|
||||
Concurrency: concurrency,
|
||||
|
||||
Stdin: os.Stdin,
|
||||
Stdout: os.Stdout,
|
||||
@@ -154,14 +158,18 @@ func main() {
|
||||
}
|
||||
|
||||
var (
|
||||
calls []taskfile.Call
|
||||
globals *taskfile.Vars
|
||||
calls []taskfile.Call
|
||||
globals *taskfile.Vars
|
||||
tasksAndVars, cliArgs = getArgs()
|
||||
)
|
||||
|
||||
if v >= 3.0 {
|
||||
calls, globals = args.ParseV3(pflag.Args()...)
|
||||
calls, globals = args.ParseV3(tasksAndVars...)
|
||||
} 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)
|
||||
|
||||
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 {
|
||||
ch := make(chan os.Signal, 1)
|
||||
signal.Notify(ch, os.Interrupt, os.Kill, syscall.SIGTERM)
|
||||
|
||||
25
concurrency.go
Normal file
25
concurrency.go
Normal 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() {}
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
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() {
|
||||
@@ -27,11 +27,12 @@ parse_args() {
|
||||
# over-ridden by flag below
|
||||
|
||||
BINDIR=${BINDIR:-./bin}
|
||||
while getopts "b:dh?" arg; do
|
||||
while getopts "b:dh?x" arg; do
|
||||
case "$arg" in
|
||||
b) BINDIR="$OPTARG" ;;
|
||||
d) log_set_priority 10 ;;
|
||||
h | \?) usage "$0" ;;
|
||||
x) set -x ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
@@ -42,46 +43,41 @@ parse_args() {
|
||||
# network, either nothing will happen or will syntax error
|
||||
# out preventing half-done work
|
||||
execute() {
|
||||
tmpdir=$(mktmpdir)
|
||||
tmpdir=$(mktemp -d)
|
||||
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
|
||||
test ! -d "${BINDIR}" && install -d "${BINDIR}"
|
||||
for binexe in $BINARIES; do
|
||||
if [ "$OS" = "windows" ]; then
|
||||
binexe="${binexe}.exe"
|
||||
fi
|
||||
install "${srcdir}/${binexe}" "${BINDIR}/"
|
||||
log_info "installed ${BINDIR}/${binexe}"
|
||||
done
|
||||
rm -rf "${tmpdir}"
|
||||
}
|
||||
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 ;;
|
||||
get_binaries() {
|
||||
case "$PLATFORM" in
|
||||
darwin/amd64) BINARIES="task" ;;
|
||||
darwin/arm64) BINARIES="task" ;;
|
||||
darwin/armv6) BINARIES="task" ;;
|
||||
linux/386) BINARIES="task" ;;
|
||||
linux/amd64) BINARIES="task" ;;
|
||||
linux/arm64) BINARIES="task" ;;
|
||||
linux/armv6) BINARIES="task" ;;
|
||||
windows/386) BINARIES="task" ;;
|
||||
windows/amd64) BINARIES="task" ;;
|
||||
windows/arm64) BINARIES="task" ;;
|
||||
windows/armv6) BINARIES="task" ;;
|
||||
*)
|
||||
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
|
||||
;;
|
||||
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
|
||||
@@ -99,8 +95,8 @@ tag_to_version() {
|
||||
VERSION=${TAG#v}
|
||||
}
|
||||
adjust_format() {
|
||||
# change format (tar.gz or zip) based on ARCH
|
||||
case ${ARCH} in
|
||||
# change format (tar.gz or zip) based on OS
|
||||
case ${OS} in
|
||||
windows) FORMAT=zip ;;
|
||||
esac
|
||||
true
|
||||
@@ -174,7 +170,9 @@ log_crit() {
|
||||
uname_os() {
|
||||
os=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
case "$os" in
|
||||
msys_nt) os="windows" ;;
|
||||
cygwin_nt*) os="windows" ;;
|
||||
mingw*) os="windows" ;;
|
||||
msys_nt*) os="windows" ;;
|
||||
esac
|
||||
echo "$os"
|
||||
}
|
||||
@@ -186,9 +184,9 @@ uname_arch() {
|
||||
i686) arch="386" ;;
|
||||
i386) arch="386" ;;
|
||||
aarch64) arch="arm64" ;;
|
||||
armv5*) arch="arm5" ;;
|
||||
armv6*) arch="arm6" ;;
|
||||
armv7*) arch="arm7" ;;
|
||||
armv5*) arch="armv5" ;;
|
||||
armv6*) arch="armv6" ;;
|
||||
armv7*) arch="armv7" ;;
|
||||
esac
|
||||
echo ${arch}
|
||||
}
|
||||
@@ -234,8 +232,8 @@ uname_arch_check() {
|
||||
untar() {
|
||||
tarball=$1
|
||||
case "${tarball}" in
|
||||
*.tar.gz | *.tgz) tar -xzf "${tarball}" ;;
|
||||
*.tar) tar -xf "${tarball}" ;;
|
||||
*.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" ;;
|
||||
*.tar) tar --no-same-owner -xf "${tarball}" ;;
|
||||
*.zip) unzip "${tarball}" ;;
|
||||
*)
|
||||
log_err "untar unknown archive format for ${tarball}"
|
||||
@@ -243,11 +241,6 @@ untar() {
|
||||
;;
|
||||
esac
|
||||
}
|
||||
mktmpdir() {
|
||||
test -z "$TMPDIR" && TMPDIR="$(mktemp -d)"
|
||||
mkdir -p "${TMPDIR}"
|
||||
echo "${TMPDIR}"
|
||||
}
|
||||
http_download_curl() {
|
||||
local_file=$1
|
||||
source_url=$2
|
||||
@@ -368,7 +361,7 @@ uname_arch_check "$ARCH"
|
||||
|
||||
parse_args "$@"
|
||||
|
||||
check_platform
|
||||
get_binaries
|
||||
|
||||
tag_to_version
|
||||
|
||||
|
||||
@@ -520,6 +520,27 @@ tasks:
|
||||
|
||||
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
|
||||
|
||||
Task parse commands as [Go's template engine][gotemplate] before executing
|
||||
|
||||
6
go.mod
6
go.mod
@@ -2,16 +2,16 @@ module github.com/go-task/task/v3
|
||||
|
||||
require (
|
||||
github.com/fatih/color v1.7.0
|
||||
github.com/go-task/slim-sprig v0.0.0-20200516131648-f9bac4e523eb
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0
|
||||
github.com/joho/godotenv v1.3.0
|
||||
github.com/mattn/go-colorable v0.1.2 // 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/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.5.1
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
|
||||
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
|
||||
|
||||
15
go.sum
15
go.sum
@@ -8,12 +8,11 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/go-task/slim-sprig v0.0.0-20200516131648-f9bac4e523eb h1:/qbv1F67s6ehqX9mG23cJOeca3FWpOVKgtPfPUMAi0k=
|
||||
github.com/go-task/slim-sprig v0.0.0-20200516131648-f9bac4e523eb/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
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/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.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||
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/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/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
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/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
@@ -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/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=
|
||||
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=
|
||||
@@ -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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
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.1/go.mod h1:fPQmabBpREM/XQ9YXSU5ZFZ/Sm+PmKP9/vkFHgYKJEI=
|
||||
mvdan.cc/sh/v3 v3.2.4 h1:+fZaWcXWRjYAvqzEKoDhDM3DkxdDUykU2iw0VMKFe9s=
|
||||
mvdan.cc/sh/v3 v3.2.4/go.mod h1:fPQmabBpREM/XQ9YXSU5ZFZ/Sm+PmKP9/vkFHgYKJEI=
|
||||
|
||||
2
help.go
2
help.go
@@ -30,7 +30,7 @@ func (e *Executor) tasksWithDesc() (tasks []*taskfile.Task) {
|
||||
tasks = make([]*taskfile.Task, 0, len(e.Taskfile.Tasks))
|
||||
for _, task := range e.Taskfile.Tasks {
|
||||
if task.Desc != "" {
|
||||
compiledTask, err := e.CompiledTask(taskfile.Call{Task: task.Task})
|
||||
compiledTask, err := e.FastCompiledTask(taskfile.Call{Task: task.Task})
|
||||
if err == nil {
|
||||
task = compiledTask
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
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() {
|
||||
@@ -27,11 +27,12 @@ parse_args() {
|
||||
# over-ridden by flag below
|
||||
|
||||
BINDIR=${BINDIR:-./bin}
|
||||
while getopts "b:dh?" arg; do
|
||||
while getopts "b:dh?x" arg; do
|
||||
case "$arg" in
|
||||
b) BINDIR="$OPTARG" ;;
|
||||
d) log_set_priority 10 ;;
|
||||
h | \?) usage "$0" ;;
|
||||
x) set -x ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
@@ -42,46 +43,41 @@ parse_args() {
|
||||
# network, either nothing will happen or will syntax error
|
||||
# out preventing half-done work
|
||||
execute() {
|
||||
tmpdir=$(mktmpdir)
|
||||
tmpdir=$(mktemp -d)
|
||||
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
|
||||
test ! -d "${BINDIR}" && install -d "${BINDIR}"
|
||||
for binexe in $BINARIES; do
|
||||
if [ "$OS" = "windows" ]; then
|
||||
binexe="${binexe}.exe"
|
||||
fi
|
||||
install "${srcdir}/${binexe}" "${BINDIR}/"
|
||||
log_info "installed ${BINDIR}/${binexe}"
|
||||
done
|
||||
rm -rf "${tmpdir}"
|
||||
}
|
||||
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 ;;
|
||||
get_binaries() {
|
||||
case "$PLATFORM" in
|
||||
darwin/amd64) BINARIES="task" ;;
|
||||
darwin/arm64) BINARIES="task" ;;
|
||||
darwin/armv6) BINARIES="task" ;;
|
||||
linux/386) BINARIES="task" ;;
|
||||
linux/amd64) BINARIES="task" ;;
|
||||
linux/arm64) BINARIES="task" ;;
|
||||
linux/armv6) BINARIES="task" ;;
|
||||
windows/386) BINARIES="task" ;;
|
||||
windows/amd64) BINARIES="task" ;;
|
||||
windows/arm64) BINARIES="task" ;;
|
||||
windows/armv6) BINARIES="task" ;;
|
||||
*)
|
||||
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
|
||||
;;
|
||||
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
|
||||
@@ -99,8 +95,8 @@ tag_to_version() {
|
||||
VERSION=${TAG#v}
|
||||
}
|
||||
adjust_format() {
|
||||
# change format (tar.gz or zip) based on ARCH
|
||||
case ${ARCH} in
|
||||
# change format (tar.gz or zip) based on OS
|
||||
case ${OS} in
|
||||
windows) FORMAT=zip ;;
|
||||
esac
|
||||
true
|
||||
@@ -174,7 +170,9 @@ log_crit() {
|
||||
uname_os() {
|
||||
os=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
case "$os" in
|
||||
msys_nt) os="windows" ;;
|
||||
cygwin_nt*) os="windows" ;;
|
||||
mingw*) os="windows" ;;
|
||||
msys_nt*) os="windows" ;;
|
||||
esac
|
||||
echo "$os"
|
||||
}
|
||||
@@ -186,9 +184,9 @@ uname_arch() {
|
||||
i686) arch="386" ;;
|
||||
i386) arch="386" ;;
|
||||
aarch64) arch="arm64" ;;
|
||||
armv5*) arch="arm5" ;;
|
||||
armv6*) arch="arm6" ;;
|
||||
armv7*) arch="arm7" ;;
|
||||
armv5*) arch="armv5" ;;
|
||||
armv6*) arch="armv6" ;;
|
||||
armv7*) arch="armv7" ;;
|
||||
esac
|
||||
echo ${arch}
|
||||
}
|
||||
@@ -234,8 +232,8 @@ uname_arch_check() {
|
||||
untar() {
|
||||
tarball=$1
|
||||
case "${tarball}" in
|
||||
*.tar.gz | *.tgz) tar -xzf "${tarball}" ;;
|
||||
*.tar) tar -xf "${tarball}" ;;
|
||||
*.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" ;;
|
||||
*.tar) tar --no-same-owner -xf "${tarball}" ;;
|
||||
*.zip) unzip "${tarball}" ;;
|
||||
*)
|
||||
log_err "untar unknown archive format for ${tarball}"
|
||||
@@ -243,11 +241,6 @@ untar() {
|
||||
;;
|
||||
esac
|
||||
}
|
||||
mktmpdir() {
|
||||
test -z "$TMPDIR" && TMPDIR="$(mktemp -d)"
|
||||
mkdir -p "${TMPDIR}"
|
||||
echo "${TMPDIR}"
|
||||
}
|
||||
http_download_curl() {
|
||||
local_file=$1
|
||||
source_url=$2
|
||||
@@ -368,7 +361,7 @@ uname_arch_check "$ARCH"
|
||||
|
||||
parse_args "$@"
|
||||
|
||||
check_platform
|
||||
get_binaries
|
||||
|
||||
tag_to_version
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
// E.g. variable merger, template processing, etc.
|
||||
type Compiler interface {
|
||||
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)
|
||||
ResetCache()
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@@ -31,6 +30,11 @@ type CompilerV2 struct {
|
||||
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:
|
||||
// 1. Task variables
|
||||
// 2. Call variables
|
||||
@@ -38,16 +42,8 @@ type CompilerV2 struct {
|
||||
// 4. Taskvars file variables
|
||||
// 5. Environment variables
|
||||
func (c *CompilerV2) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) {
|
||||
// NOTE(@andreynering): We're manually joining these paths here because
|
||||
// this is the raw task, not the compiled one.
|
||||
dir := t.Dir
|
||||
if !filepath.IsAbs(dir) {
|
||||
dir = filepath.Join(c.Dir, dir)
|
||||
}
|
||||
|
||||
vr := varResolver{
|
||||
c: c,
|
||||
dir: dir,
|
||||
vars: compiler.GetEnviron(),
|
||||
}
|
||||
vr.vars.Set("TASK", taskfile.Var{Static: t.Task})
|
||||
@@ -62,7 +58,6 @@ func (c *CompilerV2) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfi
|
||||
|
||||
type varResolver struct {
|
||||
c *CompilerV2
|
||||
dir string
|
||||
vars *taskfile.Vars
|
||||
err error
|
||||
}
|
||||
@@ -77,7 +72,7 @@ func (vr *varResolver) merge(vars *taskfile.Vars) {
|
||||
Static: tr.Replace(v.Static),
|
||||
Sh: tr.Replace(v.Sh),
|
||||
}
|
||||
static, err := vr.c.HandleDynamicVar(v, vr.dir)
|
||||
static, err := vr.c.HandleDynamicVar(v, "")
|
||||
if err != nil {
|
||||
vr.err = err
|
||||
return err
|
||||
@@ -88,7 +83,7 @@ func (vr *varResolver) merge(vars *taskfile.Vars) {
|
||||
vr.err = tr.Err()
|
||||
}
|
||||
|
||||
func (c *CompilerV2) HandleDynamicVar(v taskfile.Var, dir string) (string, error) {
|
||||
func (c *CompilerV2) HandleDynamicVar(v taskfile.Var, _ string) (string, error) {
|
||||
if v.Static != "" || v.Sh == "" {
|
||||
return v.Static, nil
|
||||
}
|
||||
@@ -106,7 +101,6 @@ func (c *CompilerV2) HandleDynamicVar(v taskfile.Var, dir string) (string, error
|
||||
var stdout bytes.Buffer
|
||||
opts := &execext.RunCommandOptions{
|
||||
Command: v.Sh,
|
||||
Dir: dir,
|
||||
Stdout: &stdout,
|
||||
Stderr: c.Logger.Stderr,
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ var _ compiler.Compiler = &CompilerV3{}
|
||||
type CompilerV3 struct {
|
||||
Dir string
|
||||
|
||||
TaskfileEnv *taskfile.Vars
|
||||
TaskfileVars *taskfile.Vars
|
||||
|
||||
Logger *logger.Logger
|
||||
@@ -29,40 +30,67 @@ type CompilerV3 struct {
|
||||
}
|
||||
|
||||
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.Set("TASK", taskfile.Var{Static: t.Task})
|
||||
|
||||
// NOTE(@andreynering): We're manually joining these paths here because
|
||||
// this is the raw task, not the compiled one.
|
||||
dir := t.Dir
|
||||
if !filepath.IsAbs(dir) {
|
||||
dir = filepath.Join(c.Dir, dir)
|
||||
}
|
||||
getRangeFunc := func(dir string) func(k string, v taskfile.Var) error {
|
||||
return func(k string, v taskfile.Var) error {
|
||||
tr := templater.Templater{Vars: result, RemoveNoValue: true}
|
||||
|
||||
rangeFunc := func(k string, v taskfile.Var) error {
|
||||
tr := templater.Templater{Vars: result, RemoveNoValue: true}
|
||||
v = taskfile.Var{
|
||||
Static: tr.Replace(v.Static),
|
||||
Sh: tr.Replace(v.Sh),
|
||||
}
|
||||
if err := tr.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
static, err := c.HandleDynamicVar(v, dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result.Set(k, taskfile.Var{Static: static})
|
||||
return nil
|
||||
}
|
||||
if !evaluateShVars {
|
||||
result.Set(k, taskfile.Var{Static: tr.Replace(v.Static)})
|
||||
return nil
|
||||
}
|
||||
|
||||
v = taskfile.Var{
|
||||
Static: tr.Replace(v.Static),
|
||||
Sh: tr.Replace(v.Sh),
|
||||
Dir: v.Dir,
|
||||
}
|
||||
if err := tr.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
static, err := c.HandleDynamicVar(v, dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result.Set(k, taskfile.Var{Static: static})
|
||||
return nil
|
||||
}
|
||||
}
|
||||
rangeFunc := getRangeFunc(c.Dir)
|
||||
|
||||
if err := c.TaskfileEnv.Range(rangeFunc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.TaskfileVars.Range(rangeFunc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := call.Vars.Range(rangeFunc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := t.Vars.Range(rangeFunc); err != nil {
|
||||
|
||||
// NOTE(@andreynering): We're manually joining these paths here because
|
||||
// this is the raw task, not the compiled one.
|
||||
tr := templater.Templater{Vars: result, RemoveNoValue: true}
|
||||
dir := tr.Replace(t.Dir)
|
||||
if err := tr.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !filepath.IsAbs(dir) {
|
||||
dir = filepath.Join(c.Dir, dir)
|
||||
}
|
||||
taskRangeFunc := getRangeFunc(dir)
|
||||
|
||||
if err := t.Vars.Range(taskRangeFunc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -84,6 +112,11 @@ func (c *CompilerV3) HandleDynamicVar(v taskfile.Var, dir string) (string, error
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// NOTE(@andreynering): If a var have a specific dir, use this instead
|
||||
if v.Dir != "" {
|
||||
dir = v.Dir
|
||||
}
|
||||
|
||||
var stdout bytes.Buffer
|
||||
opts := &execext.RunCommandOptions{
|
||||
Command: v.Sh,
|
||||
|
||||
@@ -63,7 +63,7 @@ func (r *Templater) ReplaceSlice(strs []string) []string {
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
55
task.go
55
task.go
@@ -32,16 +32,17 @@ const (
|
||||
type Executor struct {
|
||||
Taskfile *taskfile.Taskfile
|
||||
|
||||
Dir string
|
||||
Entrypoint string
|
||||
Force bool
|
||||
Watch bool
|
||||
Verbose bool
|
||||
Silent bool
|
||||
Dry bool
|
||||
Summary bool
|
||||
Parallel bool
|
||||
Color bool
|
||||
Dir string
|
||||
Entrypoint string
|
||||
Force bool
|
||||
Watch bool
|
||||
Verbose bool
|
||||
Silent bool
|
||||
Dry bool
|
||||
Summary bool
|
||||
Parallel bool
|
||||
Color bool
|
||||
Concurrency int
|
||||
|
||||
Stdin io.Reader
|
||||
Stdout io.Writer
|
||||
@@ -54,8 +55,9 @@ type Executor struct {
|
||||
|
||||
taskvars *taskfile.Vars
|
||||
|
||||
taskCallCount map[string]*int32
|
||||
mkdirMutexMap map[string]*sync.Mutex
|
||||
concurrencySemaphore chan struct{}
|
||||
taskCallCount map[string]*int32
|
||||
mkdirMutexMap map[string]*sync.Mutex
|
||||
}
|
||||
|
||||
// Run runs Task
|
||||
@@ -71,7 +73,7 @@ func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error {
|
||||
|
||||
if e.Summary {
|
||||
for i, c := range calls {
|
||||
compiledTask, err := e.CompiledTask(c)
|
||||
compiledTask, err := e.FastCompiledTask(c)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -168,6 +170,7 @@ func (e *Executor) Setup() error {
|
||||
} else {
|
||||
e.Compiler = &compilerv3.CompilerV3{
|
||||
Dir: e.Dir,
|
||||
TaskfileEnv: e.Taskfile.Env,
|
||||
TaskfileVars: e.Taskfile.Vars,
|
||||
Logger: e.Logger,
|
||||
}
|
||||
@@ -246,6 +249,10 @@ func (e *Executor) Setup() error {
|
||||
e.taskCallCount[k] = new(int32)
|
||||
e.mkdirMutexMap[k] = &sync.Mutex{}
|
||||
}
|
||||
|
||||
if e.Concurrency > 0 {
|
||||
e.concurrencySemaphore = make(chan struct{}, e.Concurrency)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -259,6 +266,9 @@ func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
|
||||
return &MaximumTaskCallExceededError{task: call.Task}
|
||||
}
|
||||
|
||||
release := e.acquireConcurrencyLimit()
|
||||
defer release()
|
||||
|
||||
if err := e.runDeps(ctx, t); err != nil {
|
||||
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 {
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
|
||||
reacquire := e.releaseConcurrencyLimit()
|
||||
defer reacquire()
|
||||
|
||||
for _, d := range t.Deps {
|
||||
d := d
|
||||
|
||||
@@ -343,6 +356,9 @@ func (e *Executor) runCommand(ctx context.Context, t *taskfile.Task, call taskfi
|
||||
|
||||
switch {
|
||||
case cmd.Task != "":
|
||||
reacquire := e.releaseConcurrencyLimit()
|
||||
defer reacquire()
|
||||
|
||||
err := e.RunTask(ctx, taskfile.Call{Task: cmd.Task, Vars: cmd.Vars})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -396,10 +412,19 @@ func getEnviron(t *taskfile.Task) []string {
|
||||
}
|
||||
|
||||
environ := os.Environ()
|
||||
|
||||
for k, v := range t.Env.ToCacheMap() {
|
||||
if s, ok := v.(string); ok {
|
||||
environ = append(environ, fmt.Sprintf("%s=%s", k, s))
|
||||
str, isString := v.(string)
|
||||
if !isString {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, alreadySet := os.LookupEnv(k); alreadySet {
|
||||
continue
|
||||
}
|
||||
|
||||
environ = append(environ, fmt.Sprintf("%s=%s", k, str))
|
||||
}
|
||||
|
||||
return environ
|
||||
}
|
||||
|
||||
24
task_test.go
24
task_test.go
@@ -126,6 +126,7 @@ func TestVarsV3(t *testing.T) {
|
||||
"var-order.txt": "ABCDEF\n",
|
||||
"dependent-sh.txt": "123456\n",
|
||||
"with-call.txt": "Hi, ABC123!\n",
|
||||
"from-dot-env.txt": "From .env file\n",
|
||||
},
|
||||
}
|
||||
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)")
|
||||
}
|
||||
|
||||
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) {
|
||||
tt := fileContentTest{
|
||||
Dir: "testdata/params",
|
||||
@@ -308,7 +325,7 @@ func TestGenerates(t *testing.T) {
|
||||
const (
|
||||
srcTask = "sub/src.txt"
|
||||
relTask = "rel.txt"
|
||||
absTask = "sub/abs.txt"
|
||||
absTask = "abs.txt"
|
||||
fileWithSpaces = "my text file.txt"
|
||||
)
|
||||
|
||||
@@ -805,7 +822,10 @@ func TestDynamicVariablesShouldRunOnTheTaskDir(t *testing.T) {
|
||||
Target: "default",
|
||||
TrimSpace: false,
|
||||
Files: map[string]string{
|
||||
"subdirectory/dir.txt": "subdirectory\n",
|
||||
"subdirectory/from_root_taskfile.txt": "subdirectory\n",
|
||||
"subdirectory/from_included_taskfile.txt": "subdirectory\n",
|
||||
"subdirectory/from_included_taskfile_task.txt": "subdirectory\n",
|
||||
"subdirectory/from_interpolated_dir.txt": "subdirectory\n",
|
||||
},
|
||||
}
|
||||
tt.Run(t)
|
||||
|
||||
@@ -97,6 +97,17 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
||||
}
|
||||
|
||||
if includedTask.AdvancedImport {
|
||||
for k, v := range includedTaskfile.Vars.Mapping {
|
||||
o := v
|
||||
o.Dir = filepath.Join(dir, includedTask.Dir)
|
||||
includedTaskfile.Vars.Mapping[k] = o
|
||||
}
|
||||
for k, v := range includedTaskfile.Env.Mapping {
|
||||
o := v
|
||||
o.Dir = filepath.Join(dir, includedTask.Dir)
|
||||
includedTaskfile.Env.Mapping[k] = o
|
||||
}
|
||||
|
||||
for _, task := range includedTaskfile.Tasks {
|
||||
if !filepath.IsAbs(task.Dir) {
|
||||
task.Dir = filepath.Join(includedTask.Dir, task.Dir)
|
||||
|
||||
@@ -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
|
||||
// variables
|
||||
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 {
|
||||
if v.Sh != "" {
|
||||
// Dynamic variable is not yet resolved; trigger
|
||||
@@ -93,11 +93,20 @@ func (vs *Vars) ToCacheMap() (m map[string]interface{}) {
|
||||
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.
|
||||
type Var struct {
|
||||
Static string
|
||||
Live interface{}
|
||||
Sh string
|
||||
Dir string
|
||||
}
|
||||
|
||||
// UnmarshalYAML implements yaml.Unmarshaler interface.
|
||||
|
||||
32
testdata/concurrency/Taskfile.yml
vendored
Normal file
32
testdata/concurrency/Taskfile.yml
vendored
Normal 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
|
||||
2
testdata/dir/dynamic_var/.gitignore
vendored
2
testdata/dir/dynamic_var/.gitignore
vendored
@@ -1 +1 @@
|
||||
subdirectory/dir.txt
|
||||
*.txt
|
||||
|
||||
26
testdata/dir/dynamic_var/Taskfile.yml
vendored
26
testdata/dir/dynamic_var/Taskfile.yml
vendored
@@ -1,11 +1,33 @@
|
||||
version: '3'
|
||||
|
||||
includes:
|
||||
sub:
|
||||
taskfile: subdirectory
|
||||
dir: subdirectory
|
||||
|
||||
vars:
|
||||
DIRECTORY: subdirectory
|
||||
|
||||
tasks:
|
||||
default:
|
||||
- task: from-root-taskfile
|
||||
- task: sub:from-included-taskfile
|
||||
- task: sub:from-included-taskfile-task
|
||||
- task: from-interpolated-dir
|
||||
|
||||
from-root-taskfile:
|
||||
cmds:
|
||||
- echo '{{.FOLDER}}' > dir.txt
|
||||
- echo '{{.TASK_DIR}}' > from_root_taskfile.txt
|
||||
dir: subdirectory
|
||||
vars:
|
||||
FOLDER:
|
||||
TASK_DIR:
|
||||
sh: basename $(pwd)
|
||||
silent: true
|
||||
|
||||
from-interpolated-dir:
|
||||
cmds:
|
||||
- echo '{{.INTERPOLATED_DIR}}' > from_interpolated_dir.txt
|
||||
dir: '{{.DIRECTORY}}'
|
||||
vars:
|
||||
INTERPOLATED_DIR:
|
||||
sh: basename $(pwd)
|
||||
|
||||
19
testdata/dir/dynamic_var/subdirectory/Taskfile.yml
vendored
Normal file
19
testdata/dir/dynamic_var/subdirectory/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
version: '3'
|
||||
|
||||
vars:
|
||||
TASKFILE_DIR:
|
||||
sh: basename $(pwd)
|
||||
|
||||
tasks:
|
||||
from-included-taskfile:
|
||||
cmds:
|
||||
- echo '{{.TASKFILE_DIR}}' > from_included_taskfile.txt
|
||||
silent: true
|
||||
|
||||
from-included-taskfile-task:
|
||||
cmds:
|
||||
- echo '{{.TASKFILE_TASK_DIR}}' > from_included_taskfile_task.txt
|
||||
silent: true
|
||||
vars:
|
||||
TASKFILE_TASK_DIR:
|
||||
sh: basename $(pwd)
|
||||
@@ -1 +0,0 @@
|
||||
subdirectory
|
||||
5
testdata/generates/Taskfile.yml
vendored
5
testdata/generates/Taskfile.yml
vendored
@@ -1,10 +1,11 @@
|
||||
version: '3'
|
||||
|
||||
vars:
|
||||
BUILD_DIR: $pwd
|
||||
BUILD_DIR:
|
||||
sh: pwd
|
||||
|
||||
tasks:
|
||||
sub/abs.txt:
|
||||
abs.txt:
|
||||
desc: generates dest file based on absolute paths
|
||||
deps:
|
||||
- sub/src.txt
|
||||
|
||||
1
testdata/vars/v3/.env
vendored
Normal file
1
testdata/vars/v3/.env
vendored
Normal file
@@ -0,0 +1 @@
|
||||
DOT_ENV_VAR=From .env file
|
||||
5
testdata/vars/v3/Taskfile.yml
vendored
5
testdata/vars/v3/Taskfile.yml
vendored
@@ -1,5 +1,7 @@
|
||||
version: '3'
|
||||
|
||||
dotenv: [.env]
|
||||
|
||||
vars:
|
||||
VAR_A: A
|
||||
VAR_B: '{{.VAR_A}}B'
|
||||
@@ -15,6 +17,7 @@ tasks:
|
||||
- task: var-order
|
||||
- task: dependent-sh
|
||||
- task: with-call
|
||||
- task: from-dot-env
|
||||
|
||||
missing-var: echo '{{.NON_EXISTING_VAR}}' > missing-var.txt
|
||||
|
||||
@@ -44,3 +47,5 @@ tasks:
|
||||
MESSAGE: Hi, {{.ABC123}}!
|
||||
cmds:
|
||||
- echo "{{.MESSAGE}}" > with-call.txt
|
||||
|
||||
from-dot-env: echo '{{.DOT_ENV_VAR}}' > from-dot-env.txt
|
||||
|
||||
35
variables.go
35
variables.go
@@ -13,12 +13,27 @@ import (
|
||||
// CompiledTask returns a copy of a task, but replacing variables in almost all
|
||||
// properties using the Go template package.
|
||||
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]
|
||||
if !ok {
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
@@ -59,16 +74,18 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) {
|
||||
new.Env = &taskfile.Vars{}
|
||||
new.Env.Merge(r.ReplaceVars(e.Taskfile.Env))
|
||||
new.Env.Merge(r.ReplaceVars(origTask.Env))
|
||||
err = new.Env.Range(func(k string, v taskfile.Var) error {
|
||||
static, err := e.Compiler.HandleDynamicVar(v, new.Dir)
|
||||
if evaluateShVars {
|
||||
err = new.Env.Range(func(k string, v taskfile.Var) error {
|
||||
static, err := e.Compiler.HandleDynamicVar(v, new.Dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
new.Env.Set(k, taskfile.Var{Static: static})
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
new.Env.Set(k, taskfile.Var{Static: static})
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(origTask.Cmds) > 0 {
|
||||
|
||||
Reference in New Issue
Block a user