mirror of
https://github.com/go-task/task.git
synced 2026-06-28 07:04:33 +00:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f2abc13ce2 | ||
|
|
0f4621fb02 | ||
|
|
c6ff641f6d | ||
|
|
350f74a53d | ||
|
|
41cd7acc87 | ||
|
|
c6eea26660 | ||
|
|
61c5718663 | ||
|
|
9897f4b527 | ||
|
|
978a6e5ecb | ||
|
|
a018997ddc | ||
|
|
de09843467 | ||
|
|
78a57fdb4b | ||
|
|
0bc2fd72f0 | ||
|
|
dda5164efd | ||
|
|
3df2396b63 | ||
|
|
d3da84e724 | ||
|
|
eb61015477 | ||
|
|
40c644f006 | ||
|
|
c9aa0180a8 | ||
|
|
a06e46885d | ||
|
|
60fa6e6c0a | ||
|
|
2f18f7927d | ||
|
|
292cf75836 | ||
|
|
fc95061f4c | ||
|
|
1f1275255c | ||
|
|
7cdf0000d9 | ||
|
|
13606e5e00 | ||
|
|
35af240faa | ||
|
|
0ac56f8973 | ||
|
|
6e5f8b1fb0 | ||
|
|
15e831c0b0 | ||
|
|
d3e2fbf1e2 | ||
|
|
66748ab5e5 | ||
|
|
c73a2c8f84 | ||
|
|
4bbcd99b8b | ||
|
|
02e7ff27c7 |
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: 1.17.x
|
go-version: 1.18.x
|
||||||
|
|
||||||
- name: Run GoReleaser
|
- name: Run GoReleaser
|
||||||
uses: goreleaser/goreleaser-action@v2
|
uses: goreleaser/goreleaser-action@v2
|
||||||
|
|||||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -5,7 +5,7 @@ jobs:
|
|||||||
name: Test
|
name: Test
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
go-version: [1.16.x, 1.17.x]
|
go-version: [1.17.x, 1.18.x]
|
||||||
platform: [ubuntu-latest, macos-latest, windows-latest]
|
platform: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
runs-on: ${{matrix.platform}}
|
runs-on: ${{matrix.platform}}
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
16
CHANGELOG.md
16
CHANGELOG.md
@@ -1,6 +1,20 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## v3.11.0 - 2022-01-19
|
## v3.12.0 - 2022-03-31
|
||||||
|
|
||||||
|
- The `--list` and `--list-all` flags can now be combined with the `--silent`
|
||||||
|
flag to print the task names only, without their description
|
||||||
|
([#691](https://github.com/go-task/task/pull/691)).
|
||||||
|
- Added support for multi-level inclusion of Taskfiles. This means that
|
||||||
|
included Taskfiles can also include other Taskfiles. Before this was limited
|
||||||
|
to one level
|
||||||
|
([#390](https://github.com/go-task/task/issues/390), [#623](https://github.com/go-task/task/discussions/623), [#656](https://github.com/go-task/task/pull/656)).
|
||||||
|
- Add ability to specify vars when including a Taskfile.
|
||||||
|
[Check out the documentation](https://taskfile.dev/#/usage?id=vars-of-included-taskfiles)
|
||||||
|
for more information.
|
||||||
|
([#677](https://github.com/go-task/task/pull/677)).
|
||||||
|
|
||||||
|
## v3.11.0 - 2022-02-19
|
||||||
|
|
||||||
- Task now supports printing begin and end messages when using the `group`
|
- Task now supports printing begin and end messages when using the `group`
|
||||||
output mode, useful for grouping tasks in CI systems.
|
output mode, useful for grouping tasks in CI systems.
|
||||||
|
|||||||
@@ -158,6 +158,12 @@ func main() {
|
|||||||
|
|
||||||
OutputStyle: output,
|
OutputStyle: output,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (list || listAll) && silent {
|
||||||
|
e.ListTaskNames(listAll)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if err := e.Setup(); err != nil {
|
if err := e.Setup(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,60 @@
|
|||||||
#compdef task
|
#compdef task
|
||||||
|
|
||||||
# Listing commands from Taskfile.yml
|
local context state state_descr line
|
||||||
function __list() {
|
typeset -A opt_args
|
||||||
local -a scripts
|
|
||||||
|
|
||||||
if [ -f Taskfile.yml ] || [ -f Taskfile.yaml ]; then
|
# Listing commands from Taskfile.yml
|
||||||
scripts=($(task -l | sed '1d' | sed 's/^\* //' | awk '{ print $1 }' | sed 's/:$//' | sed 's/:/\\:/g'))
|
function __task_list() {
|
||||||
_describe 'script' scripts
|
local -a scripts cmd
|
||||||
|
local -i enabled=0
|
||||||
|
local taskfile item task desc
|
||||||
|
|
||||||
|
cmd=(task)
|
||||||
|
taskfile="${(v)opt_args[(i)-t|--taskfile]}"
|
||||||
|
|
||||||
|
if [[ -n "$taskfile" && -f "$taskfile" ]]; then
|
||||||
|
enabled=1
|
||||||
|
cmd+=(--taskfile "$taskfile")
|
||||||
|
else
|
||||||
|
for taskfile in Taskfile{,.dist}.{yaml,yml}; do
|
||||||
|
if [[ -f "$taskfile" ]]; then
|
||||||
|
enabled=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
(( enabled )) || return 0
|
||||||
|
|
||||||
|
scripts=()
|
||||||
|
for item in "${(@)${(f)$("${cmd[@]}" --list)}[2,-1]#\* }"; do
|
||||||
|
task="${item%%:[[:space:]]*}"
|
||||||
|
desc="${item##[^[:space:]]##[[:space:]]##}"
|
||||||
|
scripts+=( "${task//:/\\:}:$desc" )
|
||||||
|
done
|
||||||
|
_describe 'Task to run' scripts
|
||||||
}
|
}
|
||||||
|
|
||||||
_arguments \
|
_arguments \
|
||||||
'(-d --dir)'{-d,--dir}': :_files' \
|
'(-C --concurrency)'{-C,--concurrency}'[limit number of concurrent tasks]: ' \
|
||||||
'(--dry)'--dry \
|
'(-p --parallel)'{-p,--parallel}'[run command-line tasks in parallel]' \
|
||||||
'(-f --force)'{-f,--force} \
|
'(-f --force)'{-f,--force}'[run even if task is up-to-date]' \
|
||||||
'(-i --init)'{-i,--init} \
|
'(-c --color)'{-c,--color}'[colored output]' \
|
||||||
'(-l --list)'{-l,--list} \
|
'(-d --dir)'{-d,--dir}'[dir to run in]:execution dir:_dirs' \
|
||||||
'(-s --silent)'{-s,--silent} \
|
'(--dry)--dry[dry-run mode, compile and print tasks only]' \
|
||||||
'(--status)'--status \
|
'(-o --output)'{-o,--output}'[set output style]:style:(interleaved group prefixed)' \
|
||||||
'(-v --verbose)'{-v,--verbose} \
|
'(--output-group-begin)--output-group-begin[message template before grouped output]:template text: ' \
|
||||||
'(--version)'--version \
|
'(--output-group-end)--output-group-end[message template after grouped output]:template text: ' \
|
||||||
'(-w --watch)'{-w,--watch} \
|
'(-s --silent)'{-s,--silent}'[disable echoing]' \
|
||||||
'(- *)'{-h,--help} \
|
'(--status)--status[exit non-zero if supplied tasks not up-to-date]' \
|
||||||
'*: :__list' \
|
'(--summary)--summary[show summary\: field from tasks instead of running them]' \
|
||||||
|
'(-t --taskfile)'{-t,--taskfile}'[specify a different taskfile]:taskfile:_files' \
|
||||||
|
'(-v --verbose)'{-v,--verbose}'[verbose mode]' \
|
||||||
|
'(-w --watch)'{-w,--watch}'[watch-mode for given tasks, re-run when inputs change]' \
|
||||||
|
+ '(operation)' \
|
||||||
|
{-l,--list}'[list describable tasks]' \
|
||||||
|
{-a,--list-all}'[list all tasks]' \
|
||||||
|
{-i,--init}'[create new Taskfile.yaml]' \
|
||||||
|
'(-*)'{-h,--help}'[show help]' \
|
||||||
|
'(-*)--version[show version and exit]' \
|
||||||
|
'*: :__task_list'
|
||||||
|
|||||||
@@ -25,6 +25,18 @@ right:
|
|||||||
sudo snap install task --classic
|
sudo snap install task --classic
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### **Chocolatey**
|
||||||
|
|
||||||
|
If you're on Windows and have [Chocolatey][choco] installed, getting
|
||||||
|
Task is as simple as running:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
choco install go-task
|
||||||
|
```
|
||||||
|
|
||||||
|
This installation method is community owned.
|
||||||
|
|
||||||
|
|
||||||
#### **Scoop**
|
#### **Scoop**
|
||||||
|
|
||||||
If you're on Windows and have [Scoop][scoop] installed, use `extras` bucket
|
If you're on Windows and have [Scoop][scoop] installed, use `extras` bucket
|
||||||
@@ -150,4 +162,5 @@ env GO111MODULE=on go get -u github.com/go-task/task/v3/cmd/task@latest
|
|||||||
[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
|
||||||
|
[choco]: https://chocolatey.org/
|
||||||
[scoop]: https://scoop.sh/
|
[scoop]: https://scoop.sh/
|
||||||
|
|||||||
@@ -164,10 +164,6 @@ includes:
|
|||||||
> The included Taskfiles must be using the same schema version the main
|
> The included Taskfiles must be using the same schema version the main
|
||||||
> Taskfile uses.
|
> Taskfile uses.
|
||||||
|
|
||||||
> Also, for now included Taskfiles can't include other Taskfiles.
|
|
||||||
> This was a deliberate decision to keep use and implementation simple.
|
|
||||||
> If you disagree, open an GitHub issue and explain your use case. =)
|
|
||||||
|
|
||||||
### Optional includes
|
### Optional includes
|
||||||
|
|
||||||
Includes marked as optional will allow Task to continue execution as normal if
|
Includes marked as optional will allow Task to continue execution as normal if
|
||||||
@@ -187,6 +183,31 @@ tasks:
|
|||||||
- echo "This command can still be successfully executed if ./tests/Taskfile.yml does not exist"
|
- echo "This command can still be successfully executed if ./tests/Taskfile.yml does not exist"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Vars of included Taskfiles
|
||||||
|
|
||||||
|
You can also specify variables when including a Taskfile. This may be useful
|
||||||
|
for having reusable Taskfile that can be tweaked or even included more than once:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '3'
|
||||||
|
|
||||||
|
includes:
|
||||||
|
backend:
|
||||||
|
taskfile: ./taskfiles/Docker.yml
|
||||||
|
vars:
|
||||||
|
DOCKER_IMAGE: backend_image
|
||||||
|
|
||||||
|
frontend:
|
||||||
|
taskfile: ./taskfiles/Docker.yml
|
||||||
|
vars:
|
||||||
|
DOCKER_IMAGE: frontend_image
|
||||||
|
```
|
||||||
|
|
||||||
|
> NOTE: Vars declared in the included Taskfile have preference over the
|
||||||
|
included ones! If you want a variable in an included Taskfile to be overridable
|
||||||
|
use the [default function](https://go-task.github.io/slim-sprig/defaults.html):
|
||||||
|
`MY_VAR: '{{.MY_VAR | default "my-default-value"}}'`.
|
||||||
|
|
||||||
## Task directory
|
## Task directory
|
||||||
|
|
||||||
By default, tasks will be executed in the directory where the Taskfile is
|
By default, tasks will be executed in the directory where the Taskfile is
|
||||||
@@ -535,6 +556,8 @@ They are listed below in order of importance (e.g. most important first):
|
|||||||
- Variables declared in the task definition
|
- 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 of the [included Taskfile](#including-other-taskfiles) (when the task is included)
|
||||||
|
- Variables of the [inclusion of the Taskfile](#vars-of-included-taskfiles) (when the task is included)
|
||||||
- Global variables (those declared in the `vars:` option in the Taskfile)
|
- Global variables (those declared in the `vars:` option in the Taskfile)
|
||||||
- Environment variables
|
- Environment variables
|
||||||
|
|
||||||
|
|||||||
13
go.mod
13
go.mod
@@ -8,10 +8,19 @@ require (
|
|||||||
github.com/mitchellh/hashstructure/v2 v2.0.2
|
github.com/mitchellh/hashstructure/v2 v2.0.2
|
||||||
github.com/radovskyb/watcher v1.0.7
|
github.com/radovskyb/watcher v1.0.7
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.1
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
|
||||||
mvdan.cc/sh/v3 v3.4.3
|
mvdan.cc/sh/v3 v3.4.3
|
||||||
)
|
)
|
||||||
|
|
||||||
go 1.16
|
require (
|
||||||
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.9 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20210925032602-92d5a993a665 // indirect
|
||||||
|
golang.org/x/term v0.0.0-20210916214954-140adaaadfaf // indirect
|
||||||
|
)
|
||||||
|
|
||||||
|
go 1.17
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -46,8 +46,8 @@ 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/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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|||||||
34
help.go
34
help.go
@@ -2,7 +2,11 @@ package task
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/internal/logger"
|
"github.com/go-task/task/v3/internal/logger"
|
||||||
@@ -70,3 +74,33 @@ func (e *Executor) tasksWithDesc() (tasks []*taskfile.Task) {
|
|||||||
sort.Slice(tasks, func(i, j int) bool { return tasks[i].Task < tasks[j].Task })
|
sort.Slice(tasks, func(i, j int) bool { return tasks[i].Task < tasks[j].Task })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PrintTaskNames prints only the task names in a Taskfile.
|
||||||
|
// Only tasks with a non-empty description are printed if allTasks is false.
|
||||||
|
// Otherwise, all task names are printed.
|
||||||
|
func (e *Executor) ListTaskNames(allTasks bool) {
|
||||||
|
// if called from cmd/task.go, e.Taskfile has not yet been parsed
|
||||||
|
if e.Taskfile == nil {
|
||||||
|
if err := e.readTaskfile(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// use stdout if no output defined
|
||||||
|
var w io.Writer = os.Stdout
|
||||||
|
if e.Stdout != nil {
|
||||||
|
w = e.Stdout
|
||||||
|
}
|
||||||
|
// create a string slice from all map values (*taskfile.Task)
|
||||||
|
s := make([]string, 0, len(e.Taskfile.Tasks))
|
||||||
|
for _, t := range e.Taskfile.Tasks {
|
||||||
|
if allTasks || t.Desc != "" {
|
||||||
|
s = append(s, strings.TrimRight(t.Task, ":"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// sort and print all task names
|
||||||
|
sort.Strings(s)
|
||||||
|
for _, t := range s {
|
||||||
|
fmt.Fprintln(w, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -74,12 +74,35 @@ func (c *CompilerV3) getVariables(t *taskfile.Task, call *taskfile.Call, evaluat
|
|||||||
}
|
}
|
||||||
rangeFunc := getRangeFunc(c.Dir)
|
rangeFunc := getRangeFunc(c.Dir)
|
||||||
|
|
||||||
|
var taskRangeFunc func(k string, v taskfile.Var) error
|
||||||
|
if t != 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 := c.TaskfileEnv.Range(rangeFunc); err != nil {
|
if err := c.TaskfileEnv.Range(rangeFunc); err != nil {
|
||||||
return nil, err
|
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
|
||||||
}
|
}
|
||||||
|
if t != nil {
|
||||||
|
if err := t.IncludedTaskfileVars.Range(taskRangeFunc); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := t.IncludeVars.Range(rangeFunc); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if t == nil || call == nil {
|
if t == nil || call == nil {
|
||||||
return result, nil
|
return result, nil
|
||||||
@@ -88,19 +111,6 @@ func (c *CompilerV3) getVariables(t *taskfile.Task, call *taskfile.Call, evaluat
|
|||||||
if err := call.Vars.Range(rangeFunc); err != nil {
|
if err := call.Vars.Range(rangeFunc); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 {
|
if err := t.Vars.Range(taskRangeFunc); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
15
task.go
15
task.go
@@ -104,10 +104,21 @@ func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error {
|
|||||||
return g.Wait()
|
return g.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// readTaskfile selects and parses the entrypoint.
|
||||||
|
func (e *Executor) readTaskfile() error {
|
||||||
|
var err error
|
||||||
|
e.Taskfile, err = read.Taskfile(&read.ReaderNode{
|
||||||
|
Dir: e.Dir,
|
||||||
|
Entrypoint: e.Entrypoint,
|
||||||
|
Parent: nil,
|
||||||
|
Optional: false,
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Setup setups Executor's internal state
|
// Setup setups Executor's internal state
|
||||||
func (e *Executor) Setup() error {
|
func (e *Executor) Setup() error {
|
||||||
var err error
|
err := e.readTaskfile()
|
||||||
e.Taskfile, err = read.Taskfile(e.Dir, e.Entrypoint)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
58
task_test.go
58
task_test.go
@@ -753,6 +753,35 @@ func TestIncludes(t *testing.T) {
|
|||||||
tt.Run(t)
|
tt.Run(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIncludesMultiLevel(t *testing.T) {
|
||||||
|
tt := fileContentTest{
|
||||||
|
Dir: "testdata/includes_multi_level",
|
||||||
|
Target: "default",
|
||||||
|
TrimSpace: true,
|
||||||
|
Files: map[string]string{
|
||||||
|
"called_one.txt": "one",
|
||||||
|
"called_two.txt": "two",
|
||||||
|
"called_three.txt": "three",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
tt.Run(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIncludeCycle(t *testing.T) {
|
||||||
|
const dir = "testdata/includes_cycle"
|
||||||
|
expectedError := "task: include cycle detected between testdata/includes_cycle/Taskfile.yml <--> testdata/includes_cycle/one/two/Taskfile.yml"
|
||||||
|
|
||||||
|
var buff bytes.Buffer
|
||||||
|
e := task.Executor{
|
||||||
|
Dir: dir,
|
||||||
|
Stdout: &buff,
|
||||||
|
Stderr: &buff,
|
||||||
|
Silent: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.EqualError(t, e.Setup(), expectedError)
|
||||||
|
}
|
||||||
|
|
||||||
func TestIncorrectVersionIncludes(t *testing.T) {
|
func TestIncorrectVersionIncludes(t *testing.T) {
|
||||||
const dir = "testdata/incorrect_includes"
|
const dir = "testdata/incorrect_includes"
|
||||||
expectedError := "task: Import with additional parameters is only available starting on Taskfile version v3"
|
expectedError := "task: Import with additional parameters is only available starting on Taskfile version v3"
|
||||||
@@ -1218,3 +1247,32 @@ Bye!
|
|||||||
t.Log(buff.String())
|
t.Log(buff.String())
|
||||||
assert.Equal(t, strings.TrimSpace(buff.String()), expectedOutputOrder)
|
assert.Equal(t, strings.TrimSpace(buff.String()), expectedOutputOrder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIncludedVars(t *testing.T) {
|
||||||
|
const dir = "testdata/include_with_vars"
|
||||||
|
var buff bytes.Buffer
|
||||||
|
e := task.Executor{
|
||||||
|
Dir: dir,
|
||||||
|
Stdout: &buff,
|
||||||
|
Stderr: &buff,
|
||||||
|
}
|
||||||
|
assert.NoError(t, e.Setup())
|
||||||
|
|
||||||
|
expectedOutputOrder := strings.TrimSpace(`
|
||||||
|
task: [included1:task1] echo "VAR_1 is included1-var1"
|
||||||
|
VAR_1 is included1-var1
|
||||||
|
task: [included1:task1] echo "VAR_2 is included-default-var2"
|
||||||
|
VAR_2 is included-default-var2
|
||||||
|
task: [included2:task1] echo "VAR_1 is included2-var1"
|
||||||
|
VAR_1 is included2-var1
|
||||||
|
task: [included2:task1] echo "VAR_2 is included-default-var2"
|
||||||
|
VAR_2 is included-default-var2
|
||||||
|
task: [included3:task1] echo "VAR_1 is included-default-var1"
|
||||||
|
VAR_1 is included-default-var1
|
||||||
|
task: [included3:task1] echo "VAR_2 is included-default-var2"
|
||||||
|
VAR_2 is included-default-var2
|
||||||
|
`)
|
||||||
|
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "task1"}))
|
||||||
|
t.Log(buff.String())
|
||||||
|
assert.Equal(t, strings.TrimSpace(buff.String()), expectedOutputOrder)
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ type IncludedTaskfile struct {
|
|||||||
Dir string
|
Dir string
|
||||||
Optional bool
|
Optional bool
|
||||||
AdvancedImport bool
|
AdvancedImport bool
|
||||||
|
Vars *Vars
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncludedTaskfiles represents information about included tasksfiles
|
// IncludedTaskfiles represents information about included tasksfiles
|
||||||
@@ -94,6 +95,7 @@ func (it *IncludedTaskfile) UnmarshalYAML(unmarshal func(interface{}) error) err
|
|||||||
Taskfile string
|
Taskfile string
|
||||||
Dir string
|
Dir string
|
||||||
Optional bool
|
Optional bool
|
||||||
|
Vars *Vars
|
||||||
}
|
}
|
||||||
if err := unmarshal(&includedTaskfile); err != nil {
|
if err := unmarshal(&includedTaskfile); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -102,5 +104,6 @@ func (it *IncludedTaskfile) UnmarshalYAML(unmarshal func(interface{}) error) err
|
|||||||
it.Dir = includedTaskfile.Dir
|
it.Dir = includedTaskfile.Dir
|
||||||
it.Optional = includedTaskfile.Optional
|
it.Optional = includedTaskfile.Optional
|
||||||
it.AdvancedImport = true
|
it.AdvancedImport = true
|
||||||
|
it.Vars = includedTaskfile.Vars
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// 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")
|
|
||||||
// ErrIncludedTaskfilesCantHaveDotenvs is returned when a included Taskfile contains dotenvs
|
// ErrIncludedTaskfilesCantHaveDotenvs is returned when a included Taskfile contains dotenvs
|
||||||
ErrIncludedTaskfilesCantHaveDotenvs = errors.New("task: Included Taskfiles can't have dotenv declarations. Please, move the dotenv declaration to the main Taskfile")
|
ErrIncludedTaskfilesCantHaveDotenvs = errors.New("task: Included Taskfiles can't have dotenv declarations. Please, move the dotenv declaration to the main Taskfile")
|
||||||
|
|
||||||
@@ -28,21 +26,29 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ReaderNode struct {
|
||||||
|
Dir string
|
||||||
|
Entrypoint string
|
||||||
|
Optional bool
|
||||||
|
Parent *ReaderNode
|
||||||
|
}
|
||||||
|
|
||||||
// Taskfile reads a Taskfile for a given directory
|
// Taskfile reads a Taskfile for a given directory
|
||||||
// Uses current dir when dir is left empty. Uses Taskfile.yml
|
// Uses current dir when dir is left empty. Uses Taskfile.yml
|
||||||
// or Taskfile.yaml when entrypoint is left empty
|
// or Taskfile.yaml when entrypoint is left empty
|
||||||
func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
func Taskfile(readerNode *ReaderNode) (*taskfile.Taskfile, error) {
|
||||||
if dir == "" {
|
if readerNode.Dir == "" {
|
||||||
d, err := os.Getwd()
|
d, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dir = d
|
readerNode.Dir = d
|
||||||
}
|
}
|
||||||
path, err := exists(filepath.Join(dir, entrypoint))
|
path, err := exists(filepath.Join(readerNode.Dir, readerNode.Entrypoint))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
readerNode.Entrypoint = filepath.Base(path)
|
||||||
|
|
||||||
t, err := readTaskfile(path)
|
t, err := readTaskfile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -62,6 +68,7 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
|||||||
Dir: tr.Replace(includedTask.Dir),
|
Dir: tr.Replace(includedTask.Dir),
|
||||||
Optional: includedTask.Optional,
|
Optional: includedTask.Optional,
|
||||||
AdvancedImport: includedTask.AdvancedImport,
|
AdvancedImport: includedTask.AdvancedImport,
|
||||||
|
Vars: includedTask.Vars,
|
||||||
}
|
}
|
||||||
if err := tr.Err(); err != nil {
|
if err := tr.Err(); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -73,9 +80,8 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !filepath.IsAbs(path) {
|
if !filepath.IsAbs(path) {
|
||||||
path = filepath.Join(dir, path)
|
path = filepath.Join(readerNode.Dir, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
path, err = exists(path)
|
path, err = exists(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if includedTask.Optional {
|
if includedTask.Optional {
|
||||||
@@ -84,12 +90,23 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
includedTaskfile, err := readTaskfile(path)
|
includeReaderNode := &ReaderNode{
|
||||||
if err != nil {
|
Dir: filepath.Dir(path),
|
||||||
|
Entrypoint: filepath.Base(path),
|
||||||
|
Parent: readerNode,
|
||||||
|
Optional: includedTask.Optional,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := checkCircularIncludes(includeReaderNode); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if includedTaskfile.Includes.Len() > 0 {
|
|
||||||
return ErrIncludedTaskfilesCantHaveIncludes
|
includedTaskfile, err := Taskfile(includeReaderNode)
|
||||||
|
if err != nil {
|
||||||
|
if includedTask.Optional {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if v >= 3.0 && len(includedTaskfile.Dotenv) > 0 {
|
if v >= 3.0 && len(includedTaskfile.Dotenv) > 0 {
|
||||||
@@ -99,12 +116,12 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
|||||||
if includedTask.AdvancedImport {
|
if includedTask.AdvancedImport {
|
||||||
for k, v := range includedTaskfile.Vars.Mapping {
|
for k, v := range includedTaskfile.Vars.Mapping {
|
||||||
o := v
|
o := v
|
||||||
o.Dir = filepath.Join(dir, includedTask.Dir)
|
o.Dir = filepath.Join(readerNode.Dir, includedTask.Dir)
|
||||||
includedTaskfile.Vars.Mapping[k] = o
|
includedTaskfile.Vars.Mapping[k] = o
|
||||||
}
|
}
|
||||||
for k, v := range includedTaskfile.Env.Mapping {
|
for k, v := range includedTaskfile.Env.Mapping {
|
||||||
o := v
|
o := v
|
||||||
o.Dir = filepath.Join(dir, includedTask.Dir)
|
o.Dir = filepath.Join(readerNode.Dir, includedTask.Dir)
|
||||||
includedTaskfile.Env.Mapping[k] = o
|
includedTaskfile.Env.Mapping[k] = o
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +129,8 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
|||||||
if !filepath.IsAbs(task.Dir) {
|
if !filepath.IsAbs(task.Dir) {
|
||||||
task.Dir = filepath.Join(includedTask.Dir, task.Dir)
|
task.Dir = filepath.Join(includedTask.Dir, task.Dir)
|
||||||
}
|
}
|
||||||
|
task.IncludeVars = includedTask.Vars
|
||||||
|
task.IncludedTaskfileVars = includedTaskfile.Vars
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +144,7 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if v < 3.0 {
|
if v < 3.0 {
|
||||||
path = filepath.Join(dir, fmt.Sprintf("Taskfile_%s.yml", runtime.GOOS))
|
path = filepath.Join(readerNode.Dir, fmt.Sprintf("Taskfile_%s.yml", runtime.GOOS))
|
||||||
if _, err = os.Stat(path); err == nil {
|
if _, err = os.Stat(path); err == nil {
|
||||||
osTaskfile, err := readTaskfile(path)
|
osTaskfile, err := readTaskfile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -175,3 +194,25 @@ func exists(path string) (string, error) {
|
|||||||
|
|
||||||
return "", fmt.Errorf(`task: No Taskfile found in "%s". Use "task --init" to create a new one`, path)
|
return "", fmt.Errorf(`task: No Taskfile found in "%s". Use "task --init" to create a new one`, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkCircularIncludes(node *ReaderNode) error {
|
||||||
|
if node == nil {
|
||||||
|
return errors.New("task: failed to check for include cycle: node was nil")
|
||||||
|
}
|
||||||
|
if node.Parent == nil {
|
||||||
|
return errors.New("task: failed to check for include cycle: node.Parent was nil")
|
||||||
|
}
|
||||||
|
var curNode = node
|
||||||
|
var basePath = filepath.Join(node.Dir, node.Entrypoint)
|
||||||
|
for curNode.Parent != nil {
|
||||||
|
curNode = curNode.Parent
|
||||||
|
curPath := filepath.Join(curNode.Dir, curNode.Entrypoint)
|
||||||
|
if curPath == basePath {
|
||||||
|
return fmt.Errorf("task: include cycle detected between %s <--> %s",
|
||||||
|
curPath,
|
||||||
|
filepath.Join(node.Parent.Dir, node.Parent.Entrypoint),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,25 +5,27 @@ 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
|
||||||
Label string
|
Label string
|
||||||
Desc string
|
Desc string
|
||||||
Summary string
|
Summary string
|
||||||
Sources []string
|
Sources []string
|
||||||
Generates []string
|
Generates []string
|
||||||
Status []string
|
Status []string
|
||||||
Preconditions []*Precondition
|
Preconditions []*Precondition
|
||||||
Dir string
|
Dir string
|
||||||
Vars *Vars
|
Vars *Vars
|
||||||
Env *Vars
|
Env *Vars
|
||||||
Silent bool
|
Silent bool
|
||||||
Interactive bool
|
Interactive bool
|
||||||
Method string
|
Method string
|
||||||
Prefix string
|
Prefix string
|
||||||
IgnoreError bool
|
IgnoreError bool
|
||||||
Run string
|
Run string
|
||||||
|
IncludeVars *Vars
|
||||||
|
IncludedTaskfileVars *Vars
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Task) Name() string {
|
func (t *Task) Name() string {
|
||||||
|
|||||||
20
testdata/include_with_vars/Taskfile.yml
vendored
Normal file
20
testdata/include_with_vars/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
version: "3"
|
||||||
|
|
||||||
|
includes:
|
||||||
|
included1:
|
||||||
|
taskfile: include/Taskfile.include.yml
|
||||||
|
vars:
|
||||||
|
VAR_1: included1-var1
|
||||||
|
included2:
|
||||||
|
taskfile: include/Taskfile.include.yml
|
||||||
|
vars:
|
||||||
|
VAR_1: included2-var1
|
||||||
|
included3:
|
||||||
|
taskfile: include/Taskfile.include.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
task1:
|
||||||
|
cmds:
|
||||||
|
- task: included1:task1
|
||||||
|
- task: included2:task1
|
||||||
|
- task: included3:task1
|
||||||
11
testdata/include_with_vars/include/Taskfile.include.yml
vendored
Normal file
11
testdata/include_with_vars/include/Taskfile.include.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
version: "3"
|
||||||
|
|
||||||
|
vars:
|
||||||
|
VAR_1: '{{.VAR_1 | default "included-default-var1"}}'
|
||||||
|
VAR_2: '{{.VAR_2 | default "included-default-var2"}}'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
task1:
|
||||||
|
cmds:
|
||||||
|
- echo "VAR_1 is {{.VAR_1}}"
|
||||||
|
- echo "VAR_2 is {{.VAR_2}}"
|
||||||
12
testdata/includes_cycle/Taskfile.yml
vendored
Normal file
12
testdata/includes_cycle/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
includes:
|
||||||
|
'one': ./one/Taskfile.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default:
|
||||||
|
cmds:
|
||||||
|
- echo "called_dep" > called_dep.txt
|
||||||
|
level1:
|
||||||
|
cmds:
|
||||||
|
- echo "hello level 1"
|
||||||
9
testdata/includes_cycle/one/Taskfile.yml
vendored
Normal file
9
testdata/includes_cycle/one/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
includes:
|
||||||
|
'two': ./two/Taskfile.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
level2:
|
||||||
|
cmds:
|
||||||
|
- echo "hello level 2"
|
||||||
9
testdata/includes_cycle/one/two/Taskfile.yml
vendored
Normal file
9
testdata/includes_cycle/one/two/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
includes:
|
||||||
|
bad: "../../Taskfile.yml"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
level3:
|
||||||
|
cmds:
|
||||||
|
- echo "hello level 3"
|
||||||
11
testdata/includes_multi_level/Taskfile.yml
vendored
Normal file
11
testdata/includes_multi_level/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
includes:
|
||||||
|
'one': ./one/
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default:
|
||||||
|
cmds:
|
||||||
|
- task: one:default
|
||||||
|
- task: one:two:default
|
||||||
|
- task: one:two:three:default
|
||||||
1
testdata/includes_multi_level/called_one.txt
vendored
Normal file
1
testdata/includes_multi_level/called_one.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
one
|
||||||
1
testdata/includes_multi_level/called_three.txt
vendored
Normal file
1
testdata/includes_multi_level/called_three.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
three
|
||||||
1
testdata/includes_multi_level/called_two.txt
vendored
Normal file
1
testdata/includes_multi_level/called_two.txt
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
two
|
||||||
7
testdata/includes_multi_level/one/Taskfile.yml
vendored
Normal file
7
testdata/includes_multi_level/one/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
includes:
|
||||||
|
'two': ./two/
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default: echo one > called_one.txt
|
||||||
7
testdata/includes_multi_level/one/two/Taskfile.yml
vendored
Normal file
7
testdata/includes_multi_level/one/two/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
includes:
|
||||||
|
'three': ./three/Taskfile.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default: echo two > called_two.txt
|
||||||
4
testdata/includes_multi_level/one/two/three/Taskfile.yml
vendored
Normal file
4
testdata/includes_multi_level/one/two/three/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default: echo three > called_three.txt
|
||||||
32
variables.go
32
variables.go
@@ -46,21 +46,23 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf
|
|||||||
r := templater.Templater{Vars: vars, RemoveNoValue: v >= 3.0}
|
r := templater.Templater{Vars: vars, RemoveNoValue: v >= 3.0}
|
||||||
|
|
||||||
new := taskfile.Task{
|
new := taskfile.Task{
|
||||||
Task: origTask.Task,
|
Task: origTask.Task,
|
||||||
Label: r.Replace(origTask.Label),
|
Label: r.Replace(origTask.Label),
|
||||||
Desc: r.Replace(origTask.Desc),
|
Desc: r.Replace(origTask.Desc),
|
||||||
Summary: r.Replace(origTask.Summary),
|
Summary: r.Replace(origTask.Summary),
|
||||||
Sources: r.ReplaceSlice(origTask.Sources),
|
Sources: r.ReplaceSlice(origTask.Sources),
|
||||||
Generates: r.ReplaceSlice(origTask.Generates),
|
Generates: r.ReplaceSlice(origTask.Generates),
|
||||||
Dir: r.Replace(origTask.Dir),
|
Dir: r.Replace(origTask.Dir),
|
||||||
Vars: nil,
|
Vars: nil,
|
||||||
Env: nil,
|
Env: nil,
|
||||||
Silent: origTask.Silent,
|
Silent: origTask.Silent,
|
||||||
Interactive: origTask.Interactive,
|
Interactive: origTask.Interactive,
|
||||||
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,
|
||||||
Run: r.Replace(origTask.Run),
|
Run: r.Replace(origTask.Run),
|
||||||
|
IncludeVars: origTask.IncludeVars,
|
||||||
|
IncludedTaskfileVars: origTask.IncludedTaskfileVars,
|
||||||
}
|
}
|
||||||
new.Dir, err = execext.Expand(new.Dir)
|
new.Dir, err = execext.Expand(new.Dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user