Compare commits

...

71 Commits

Author SHA1 Message Date
Andrey Nering
5d22cf4327 v3.16.0 2022-09-29 22:01:16 -03:00
Andrey Nering
219d3ad193 Website: Fix link to file 2022-09-29 21:38:26 -03:00
Andrey Nering
e72157e26a Merge pull request #871 from go-task/release-to-npm
Add package.json to allow users to install Task using npm
2022-09-29 21:34:39 -03:00
Andrey Nering
50a377a7c4 Add package.json to allow users to install Task using npm
Closes #870
2022-09-29 21:27:30 -03:00
Andrey Nering
9d7ddff60c README: Add more links 2022-09-29 13:33:20 -03:00
Andrey Nering
081d878f86 Website > Installation: Update Arch Linux installation method
Package and maintainer changed. See #869.
2022-09-20 13:05:18 -03:00
Andrey Nering
a95191d29e Website: Improve syntax highlighting 2022-09-17 13:51:54 -03:00
Andrey Nering
111f6e7f18 Add CHANGELOG entry and API documentation for #818 2022-09-17 13:11:16 -03:00
Andrey Nering
4a5c1e9ec4 Merge branch 'internal-tasks' of https://github.com/pd93/task into pd93-internal-tasks 2022-09-17 12:59:19 -03:00
Andrey Nering
8f0893b5f7 Website: Adjustments to Carbon 2022-09-17 11:11:02 -03:00
Andrey Nering
b16e705a6c Website: Update Open Graph image 2022-09-15 11:17:01 -03:00
Andrey Nering
3cad318b70 v3.15.2
I pushed v3.15.1 tagged in a commit in a detached branch by mistake.

Repushing as v3.15.2
2022-09-08 21:26:18 -03:00
Andrey Nering
8c6002cae6 v3.15.1 2022-09-08 21:22:19 -03:00
Andrey Nering
0355bbaf3b Merge pull request #861 from cdaguerre/feat/make-zsh-completion-configurable
Make zsh completion list configurable
2022-09-08 21:01:04 -03:00
Andrey Nering
2ba083a650 Merge pull request #863 from MarioSchwalbe/bash-completion
Fix handling of CLI_ARGS
2022-09-08 20:59:16 -03:00
Andrey Nering
c79ea5a257 Merge pull request #866 from pd93/fix-read-dotenv
fix: ignore empty dotfile file names
2022-09-08 20:58:25 -03:00
Pete Davison
44706f4957 fix: ignore empty dotfile file names 2022-09-08 18:51:39 +00:00
Mario Schwalbe
a1b3bb03ed * Fix handling of CLI_ARGS 2022-09-08 19:03:29 +02:00
Christian Daguerre
76caa16909 Make zsh completion list configurable 2022-09-07 10:33:55 +02:00
Andrey Nering
160b788198 Merge pull request #859 from jfhovinne/docs-reprobuilds
Document how to reproduce release binaries
2022-09-05 14:29:42 -03:00
jfhovinne
eada62f62c Document how to reproduce executables 2022-09-05 19:08:37 +02:00
Andrey Nering
bd9419e6db Website: Use "Roboto" as the main font
This is to add consistency between different operating systems, specially
Windows which used "Segoe UI" before this commit.
2022-09-04 17:38:29 -03:00
Andrey Nering
bdd9de3001 CHANGELOG: Add extra link 2022-09-03 18:28:24 -03:00
Andrey Nering
200ba4ed04 v3.15.0 2022-09-03 18:21:40 -03:00
Andrey Nering
1e8939dd58 Merge pull request #857 from go-task/feature/add-dir-special-variables
Add ROOT_DIR and TASKFILE_DIR special variables
2022-09-03 18:18:43 -03:00
Andrey Nering
f45dd11e53 Add ROOT_DIR and TASKFILE_DIR special variables
Closes #215
2022-09-03 18:14:54 -03:00
Andrey Nering
1a0cc1d64d Update favicon.ico 2022-08-31 13:21:43 -03:00
Wes McNamee
421cb522d9 Merge pull request #846 from rootulp/patch-1
fix: grammar in docs
2022-08-24 22:07:23 -07:00
Rootul Patel
1b18b041d6 fix: grammar in docs 2022-08-24 20:30:21 -04:00
Andrey Nering
8788703ac6 CHANGELOG for #831
Closes #826
2022-08-23 18:43:04 -03:00
Andrey Nering
b6c25e3ad9 Mention #844 on CHANGELOG 2022-08-23 18:40:34 -03:00
Andrey Nering
73eaa68cd1 Merge pull request #844 from MarioSchwalbe/bash-completion
Use --silent to get the list of tasks (bash completion)
2022-08-23 18:39:47 -03:00
Andrey Nering
beb927f7b4 Merge pull request #831 from ilewin/check_path_for_symlinks_issue_826
Attempt to fix Task not following symlinks
2022-08-23 18:38:17 -03:00
ilewin
cdc969cd4e Added test to check if symlinks are evaluated for task source files 2022-08-23 18:36:19 +02:00
ilewin
2a67499f12 Issue #826. Replaced zglob.Glob func with GlobFollowSymlinks to evaluate symlinks 2022-08-23 18:25:11 +02:00
Mario Schwalbe
6a3cc79daa * Use --silent to get list of tasks 2022-08-23 18:03:15 +02:00
Andrey Nering
97d4a947ee Merge pull request #838 from pcgeek86/patch-1
Update releasing.md
2022-08-17 20:50:18 -03:00
Wes McNamee
e0e47ad9a0 Merge pull request #841 from cristaloleg/fix-linter
Fix go-critic suggestions
2022-08-17 12:38:12 -07:00
Oleg Kovalov
b08eac58e9 Fix go-critic suggestions 2022-08-17 19:37:58 +02:00
Pete Davison
11409ccf21 fix: list + silent flags shouldn't display internal tasks 2022-08-16 17:07:05 +00:00
Pete Davison
e3b6c97c3b fix: the merged task should be internal if the task OR the taskfile are internal 2022-08-16 17:07:05 +00:00
Pete Davison
d3da086ebf docs: added usage 2022-08-16 17:07:05 +00:00
Pete Davison
3507fa40f1 feat: add internal to included files 2022-08-16 17:07:05 +00:00
Pete Davison
6f8f1f1409 feat(task): tasks can be internal (not accessible from cli) 2022-08-16 17:06:25 +00:00
Trevor Sullivan
c2148a359d Update releasing.md 2022-08-16 04:33:54 -06:00
Andrey Nering
c172185a24 Update CHANGELOG 2022-08-15 09:55:11 -03:00
Andrey Nering
1140a5c4ae Merge pull request #835 from MarioSchwalbe/bash-completion
Improved bash completion
2022-08-15 09:52:07 -03:00
Mario Schwalbe
3cc378c960 * Convert indentation to 2 spaces 2022-08-13 21:55:35 +02:00
Andrey Nering
9b3a961303 Merge pull request #832 from jfhovinne/reprobuilds
Modify goreleaser defaults for reproducible builds
2022-08-13 12:04:27 -03:00
Mario Schwalbe
d048555149 Improved bash completion for task 2022-08-11 20:48:41 +02:00
jfhovinne
7533858a52 Modify goreleaser defaults for reproducible builds 2022-08-10 15:33:17 +02:00
Andrey Nering
c4e10ef0aa Refactor: Add SmartJoin to handle IsAbs automatically 2022-08-06 18:19:07 -03:00
Andrey Nering
c20842e7cd v3.14.1: Add CHANGELOG to website 2022-08-03 22:26:39 -03:00
Andrey Nering
6cfdb21313 v3.14.1 2022-08-03 22:08:17 -03:00
Bevan Arps
e396f4d06f Resolve relative include paths relative to the including Taskfile
Closes #823
Closes #822
2022-08-03 21:59:17 -03:00
Andrey Nering
47c1bb6a5b Merge pull request #816 from go-task/dependabot/npm_and_yarn/docs/terser-5.14.2
Bump terser from 5.13.1 to 5.14.2 in /docs
2022-08-03 21:00:52 -03:00
Andrey Nering
adfb0b513e Merge pull request #827 from go-task/go-1-19
Upgrade to Go v1.19
2022-08-03 21:00:44 -03:00
Andrey Nering
98d78b9d8a Upgrade to Go v1.19 2022-08-03 20:58:06 -03:00
Wes McNamee
a1c32a56ea Merge pull request #817 from white-gecko/patch-1
Resolve contradiction.
2022-07-27 23:36:25 -07:00
Natanael Arndt
6584bcf87f Resolve contradiction. 2022-07-21 14:30:51 +02:00
dependabot[bot]
7ac75af622 Bump terser from 5.13.1 to 5.14.2 in /docs
Bumps [terser](https://github.com/terser/terser) from 5.13.1 to 5.14.2.
- [Release notes](https://github.com/terser/terser/releases)
- [Changelog](https://github.com/terser/terser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/terser/terser/commits)

---
updated-dependencies:
- dependency-name: terser
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-21 05:16:51 +00:00
Andrey Nering
b3c283b282 Merge pull request #814 from abner-chenc/master
go.mod: update to current golang.org/x/sys revision
2022-07-18 10:30:57 -03:00
Guoqi Chen
c2615dd746 go.mod: update to current golang.org/x/sys revision
go get -d golang.org/x/sys@c0bba94af5f85fbad9f6dc2e04ed5b8fac9696cf
go mod tidy

This brings in linux/loong64 support.
2022-07-18 10:11:48 +08:00
Andrey Nering
789518f70d Merge pull request #811 from go-task/imgbot
[ImgBot] Optimize images
2022-07-16 23:28:31 -03:00
ImgBotApp
ad3008d855 [ImgBot] Optimize images
*Total -- 61.47kb -> 34.61kb (43.69%)

/docs/static/img/pix.png -- 12.63kb -> 1.25kb (90.13%)
/docs/static/img/logo.png -- 21.79kb -> 13.21kb (39.38%)
/docs/static/img/og-image.png -- 26.26kb -> 19.38kb (26.2%)
/docs/static/img/logo.svg -- 0.44kb -> 0.42kb (2.47%)
/docs/static/img/logo_mono.svg -- 0.36kb -> 0.35kb (1.37%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>
2022-07-17 02:23:22 +00:00
Andrey Nering
3da426603f Website: Improve "Install Script" documentation
Add note about common installation paths.

Closes #775
2022-07-16 22:55:57 -03:00
Andrey Nering
8d26e34b0a Use --list-all to PowerShell completion + Add CHANGELOG to #803 2022-07-16 22:07:24 -03:00
Andrey Nering
110d1d7245 Merge pull request #803 from carlsmedstad/zsh-completion
Fix Zsh completion for tasks without description
2022-07-16 21:38:50 -03:00
Andrey Nering
f7384623df Merge pull request #802 from nokome/patch-1
Update api_reference.md
2022-07-16 21:37:19 -03:00
Carl Smedstad
5d24e166ab Fix Zsh completion for tasks without description
Use --list-all instead of --list in order include tasks without
description in the auto-completion.
2022-07-10 01:52:38 +02:00
Nokome Bentley
f787937a30 Update api_reference.md
Using `cmd` (singular) with a single string is valid syntax also.
2022-07-08 14:01:41 +12:00
68 changed files with 1079 additions and 238 deletions

View File

@@ -14,7 +14,7 @@ jobs:
steps: steps:
- uses: actions/setup-go@v3 - uses: actions/setup-go@v3
with: with:
go-version: 1.18 go-version: 1.18.x
- uses: actions/checkout@v3 - uses: actions/checkout@v3

View File

@@ -15,7 +15,7 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: 1.18.x go-version: 1.19.x
- name: Run GoReleaser - name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2 uses: goreleaser/goreleaser-action@v2

View File

@@ -13,7 +13,7 @@ jobs:
name: Test name: Test
strategy: strategy:
matrix: matrix:
go-version: [1.17.x, 1.18.x] go-version: [1.18.x, 1.19.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:

1
.gitignore vendored
View File

@@ -30,3 +30,4 @@ tags
!/bin/.keep !/bin/.keep
/testdata/vars/v1 /testdata/vars/v1
/tmp /tmp
node_modules

View File

@@ -17,6 +17,9 @@ build:
goarch: 386 goarch: 386
env: env:
- CGO_ENABLED=0 - CGO_ENABLED=0
mod_timestamp: '{{ .CommitTimestamp }}'
flags:
- -trimpath
ldflags: ldflags:
- -s -w # Don't set main.version. - -s -w # Don't set main.version.

View File

@@ -1,5 +1,41 @@
# Changelog # Changelog
## v3.16.0 - 2022-09-29
- Add `npm` as new installation method: `npm i -g @go-task/cli`
([#870](https://github.com/go-task/task/issues/870), [#871](https://github.com/go-task/task/pull/871), [npm package](https://www.npmjs.com/package/@go-task/cli)).
- Add support to marking tasks and includes as internal, which will hide them
from `--list` and `--list-all`
([#818](https://github.com/go-task/task/pull/818)).
## v3.15.2 - 2022-09-08
- Fix error when using variable in `env:` introduced in the previous release
([#858](https://github.com/go-task/task/issues/858), [#866](https://github.com/go-task/task/pull/866)).
- Fix handling of `CLI_ARGS` (`--`) in Bash completion
([#863](https://github.com/go-task/task/pull/863)).
- On zsh completion, add ability to replace `--list-all` with `--list` as
already possible on the Bash completion
([#861](https://github.com/go-task/task/pull/861)).
## v3.15.0 - 2022-09-03
- Add new special variables `ROOT_DIR` and `TASKFILE_DIR`. This was a highly
requested feature
([#215](https://github.com/go-task/task/issues/215), [#857](https://github.com/go-task/task/pull/857), [Documentation](https://taskfile.dev/api/#special-variables)).
- Follow symlinks on `sources`
([#826](https://github.com/go-task/task/issues/826), [#831](https://github.com/go-task/task/pull/831)).
- Improvements and fixes to Bash completion
([#835](https://github.com/go-task/task/pull/835), [#844](https://github.com/go-task/task/pull/844)).
## v3.14.1 - 2022-08-03
- Always resolve relative include paths relative to the including Taskfile
([#822](https://github.com/go-task/task/issues/822), [#823](https://github.com/go-task/task/pull/823)).
- Fix ZSH and PowerShell completions to consider all tasks instead of just the
public ones (those with descriptions)
([#803](https://github.com/go-task/task/pull/803)).
## v3.14.0 - 2022-07-08 ## v3.14.0 - 2022-07-08
- Add ability to override the `.task` directory location with the - Add ability to override the `.task` directory location with the

View File

@@ -10,6 +10,6 @@
</p> </p>
<p> <p>
See <a href="https://taskfile.dev">taskfile.dev</a> for the documentation. <a href="https://taskfile.dev/installation/">Installation</a> | <a href="https://taskfile.dev/usage/">Documentation</a> | <a href="https://twitter.com/taskfiledev">Twitter</a> | <a href="https://discord.gg/6TY36E39UK">Discord</a>
</p> </p>
</div> </div>

View File

@@ -80,6 +80,24 @@ tasks:
cmds: cmds:
- goreleaser --snapshot --rm-dist - goreleaser --snapshot --rm-dist
docs:changelog:
desc: Copy CHANGELOG.md to the documentation website
vars:
FILE: docs/docs/changelog.md
cmds:
- rm {{.FILE}}
- 'echo "---" >> {{.FILE}}'
- 'echo "slug: /changelog/" >> {{.FILE}}'
- 'echo "sidebar_position: 6" >> {{.FILE}}'
- 'echo "---" >> {{.FILE}}'
- 'echo "" >> {{.FILE}}'
- 'cat CHANGELOG.md >> {{.FILE}}'
npm:publish:
desc: Publish release to npm
cmds:
- npm publish --access=public
packages: packages:
cmds: cmds:
- echo '{{.GO_PACKAGES}}' - echo '{{.GO_PACKAGES}}'

View File

@@ -1,26 +1,55 @@
#!/bin/bash # vim: set tabstop=2 shiftwidth=2 expandtab:
GO_TASK_PROGNAME=task _GO_TASK_COMPLETION_LIST_OPTION='--list-all'
_go_task_completion() function _task()
{ {
local cur local cur prev words cword
_get_comp_words_by_ref -n : cur _init_completion -n : || return
case "$cur" in # Check for `--` within command-line and quit or strip suffix.
--*) local i
local options for i in "${!words[@]}"; do
options="$(_parse_help task)" if [ "${words[$i]}" == "--" ]; then
mapfile -t COMPREPLY < <(compgen -W "$options" -- "$cur") # Do not complete words following `--` passed to CLI_ARGS.
[ $cword -gt $i ] && return
# Remove the words following `--` to not put --list in CLI_ARGS.
words=( "${words[@]:0:$i}" )
break
fi
done
# Handle special arguments of options.
case "$prev" in
-d|--dir)
_filedir -d
return $?
;; ;;
*) -t|--taskfile)
local tasks _filedir yaml || return $?
tasks="$($GO_TASK_PROGNAME --list-all 2> /dev/null | awk 'NR>1 { sub(/:$/,"",$2); print $2 }')" _filedir yml
mapfile -t COMPREPLY < <(compgen -W "$tasks" -- "$cur") return $?
;;
-o|--output)
COMPREPLY=( $( compgen -W "interleaved group prefixed" -- $cur ) )
return 0
;; ;;
esac esac
# Handle normal options.
case "$cur" in
-*)
COMPREPLY=( $( compgen -W "$(_parse_help $1)" -- $cur ) )
return 0
;;
esac
# Prepare task name completions.
local tasks=( $( "${words[@]}" --silent $_GO_TASK_COMPLETION_LIST_OPTION 2> /dev/null ) )
COMPREPLY=( $( compgen -W "${tasks[*]}" -- "$cur" ) )
# Post-process because task names might contain colons.
__ltrim_colon_completions "$cur" __ltrim_colon_completions "$cur"
} }
complete -F _go_task_completion $GO_TASK_PROGNAME complete -F _task task

View File

@@ -3,7 +3,7 @@ $scriptBlock = {
$curReg = "task{.exe}? (.*?)$" $curReg = "task{.exe}? (.*?)$"
$startsWith = $wordToComplete | Select-String $curReg -AllMatches | ForEach-Object { $_.Matches.Groups[1].Value } $startsWith = $wordToComplete | Select-String $curReg -AllMatches | ForEach-Object { $_.Matches.Groups[1].Value }
$reg = "\* ($startsWith.+?):" $reg = "\* ($startsWith.+?):"
$listOutput = $(task -l) $listOutput = $(task --list-all)
$listOutput | Select-String $reg -AllMatches | ForEach-Object { $_.Matches.Groups[1].Value + " " } $listOutput | Select-String $reg -AllMatches | ForEach-Object { $_.Matches.Groups[1].Value + " " }
} }

View File

@@ -3,6 +3,8 @@
local context state state_descr line local context state state_descr line
typeset -A opt_args typeset -A opt_args
_GO_TASK_COMPLETION_LIST_OPTION="${GO_TASK_COMPLETION_LIST_OPTION:---list-all}"
# Listing commands from Taskfile.yml # Listing commands from Taskfile.yml
function __task_list() { function __task_list() {
local -a scripts cmd local -a scripts cmd
@@ -27,7 +29,7 @@ function __task_list() {
(( enabled )) || return 0 (( enabled )) || return 0
scripts=() scripts=()
for item in "${(@)${(f)$("${cmd[@]}" --list)}[2,-1]#\* }"; do for item in "${(@)${(f)$("${cmd[@]}" $_GO_TASK_COMPLETION_LIST_OPTION)}[2,-1]#\* }"; do
task="${item%%:[[:space:]]*}" task="${item%%:[[:space:]]*}"
desc="${item##[^[:space:]]##[[:space:]]##}" desc="${item##[^[:space:]]##[[:space:]]##}"
scripts+=( "${task//:/\\:}:$desc" ) scripts+=( "${task//:/\\:}:$desc" )

View File

@@ -9,9 +9,10 @@ tasks:
start: start:
desc: Start website desc: Start website
vars: vars:
HOST: '{{default "localhost" .HOST}}'
PORT: '{{default "3001" .PORT}}' PORT: '{{default "3001" .PORT}}'
cmds: cmds:
- npx docusaurus start --no-open --port={{.PORT}} - npx docusaurus start --no-open --host={{.HOST}} --port={{.PORT}}
build: build:
desc: Build website desc: Build website

View File

@@ -44,6 +44,19 @@ variable
| | `--version` | `bool` | `false` | Show Task version. | | | `--version` | `bool` | `false` | Show Task version. |
| `-w` | `--watch` | `bool` | `false` | Enables watch of the given task. | | `-w` | `--watch` | `bool` | `false` | Enables watch of the given task. |
## Special Variables
There are some special variables that is available on the templating system:
| Var | Description |
| - | - |
| `CLI_ARGS` | Contain all extra arguments passed after `--` when calling Task through the CLI. |
| `TASK` | The name of the current task. |
| `ROOT_DIR` | The absolute path of the root Taskfile. |
| `TASKFILE_DIR` | The absolute path of the included Taskfile. |
| `CHECKSUM` | The checksum of the files listed in `sources`. Only available within the `status` prop and if method is set to `checksum`. |
| `TIMESTAMP` | The date object of the greatest timestamp of the files listes in `sources`. Only available within the `status` prop and if method is set to `timestamp`. |
## ENV ## ENV
Some environment variables can be overriden to adjust Task behavior. Some environment variables can be overriden to adjust Task behavior.
@@ -81,9 +94,10 @@ Some environment variables can be overriden to adjust Task behavior.
| Attribute | Type | Default | Description | | Attribute | Type | Default | Description |
| - | - | - | - | | - | - | - | - |
| `taskfile` | `string` | | The path for the Taskfile or directory to be included. If a directory, Task will look for files named `Taskfile.yml` or `Taskfile.yaml` inside that directory. | | `taskfile` | `string` | | The path for the Taskfile or directory to be included. If a directory, Task will look for files named `Taskfile.yml` or `Taskfile.yaml` inside that directory. If a relative path, resolved relative to the directory containing the including Taskfile. |
| `dir` | `string` | The parent Taskfile directory | The working directory of the included tasks when run. | | `dir` | `string` | The parent Taskfile directory | The working directory of the included tasks when run. |
| `optional` | `bool` | `false` | If `true`, no errors will be thrown if the specified file does not exist. | | `optional` | `bool` | `false` | If `true`, no errors will be thrown if the specified file does not exist. |
| `internal` | `bool` | `false` | If `true`, tasks will be omitted from both `--list` and `--list-all`. |
:::info :::info
@@ -106,6 +120,7 @@ includes:
| `dir` | `string` | | The current directory which this task should run. | | `dir` | `string` | | The current directory which this task should run. |
| `method` | `string` | `checksum` | Method used by this task. Default to the one declared globally or `checksum`. Available options: `checksum`, `timestamp` and `none` | | `method` | `string` | `checksum` | Method used by this task. Default to the one declared globally or `checksum`. Available options: `checksum`, `timestamp` and `none` |
| `silent` | `bool` | `false` | Skips some output for this task. Note that STDOUT and STDERR of the commands will still be redirected. | | `silent` | `bool` | `false` | Skips some output for this task. Note that STDOUT and STDERR of the commands will still be redirected. |
| `internal` | `bool` | `false` | If `true`, omit this task from both `--list` and `--list-all`. |
| `run` | `string` | The one declared globally in the Taskfile or `always` | Specifies whether the task should run again or not if called more than once. Available options: `always`, `once` and `when_changed`. | | `run` | `string` | The one declared globally in the Taskfile or `always` | Specifies whether the task should run again or not if called more than once. Available options: `always`, `once` and `when_changed`. |
| `prefix` | `string` | | Allows to override the prefix print before the STDOUT. Only relevant when using the `prefixed` output mode. | | `prefix` | `string` | | Allows to override the prefix print before the STDOUT. Only relevant when using the `prefixed` output mode. |
| `ignore_error` | `bool` | `false` | Continue execution if errors happen while executing the commands. | | `ignore_error` | `bool` | `false` | Continue execution if errors happen while executing the commands. |
@@ -129,6 +144,9 @@ tasks:
foobar: foobar:
- echo "foo" - echo "foo"
- echo "bar" - echo "bar"
baz:
cmd: echo "baz"
``` ```
::: :::

View File

@@ -5,6 +5,42 @@ sidebar_position: 6
# Changelog # Changelog
## v3.16.0 - 2022-09-29
- Add `npm` as new installation method: `npm i -g @go-task/cli`
([#870](https://github.com/go-task/task/issues/870), [#871](https://github.com/go-task/task/pull/871), [npm package](https://www.npmjs.com/package/@go-task/cli)).
- Add support to marking tasks and includes as internal, which will hide them
from `--list` and `--list-all`
([#818](https://github.com/go-task/task/pull/818)).
## v3.15.2 - 2022-09-08
- Fix error when using variable in `env:` introduced in the previous release
([#858](https://github.com/go-task/task/issues/858), [#866](https://github.com/go-task/task/pull/866)).
- Fix handling of `CLI_ARGS` (`--`) in Bash completion
([#863](https://github.com/go-task/task/pull/863)).
- On zsh completion, add ability to replace `--list-all` with `--list` as
already possible on the Bash completion
([#861](https://github.com/go-task/task/pull/861)).
## v3.15.0 - 2022-09-03
- Add new special variables `ROOT_DIR` and `TASKFILE_DIR`. This was a highly
requested feature
([#215](https://github.com/go-task/task/issues/215), [#857](https://github.com/go-task/task/pull/857), [Documentation](https://taskfile.dev/api/#special-variables)).
- Follow symlinks on `sources`
([#826](https://github.com/go-task/task/issues/826), [#831](https://github.com/go-task/task/pull/831)).
- Improvements and fixes to Bash completion
([#835](https://github.com/go-task/task/pull/835), [#844](https://github.com/go-task/task/pull/844)).
## v3.14.1 - 2022-08-03
- Always resolve relative include paths relative to the including Taskfile
([#822](https://github.com/go-task/task/issues/822), [#823](https://github.com/go-task/task/pull/823)).
- Fix ZSH and PowerShell completions to consider all tasks instead of just the
public ones (those with descriptions)
([#803](https://github.com/go-task/task/pull/803)).
## v3.14.0 - 2022-07-08 ## v3.14.0 - 2022-07-08
- Add ability to override the `.task` directory location with the - Add ability to override the `.task` directory location with the

View File

@@ -46,8 +46,8 @@ Some installation methods are maintained by third party:
- [GitHub Actions](https://github.com/arduino/setup-task) - [GitHub Actions](https://github.com/arduino/setup-task)
by [@arduino](https://github.com/arduino) by [@arduino](https://github.com/arduino)
- [AUR](https://aur.archlinux.org/packages/taskfile-git) - [AUR](https://aur.archlinux.org/packages/go-task-bin)
by [@kovetskiy](https://github.com/kovetskiy) by [@carlsmedstad](https://github.com/carlsmedstad)
- [Scoop](https://github.com/lukesampson/scoop-extras/blob/master/bucket/task.json) - [Scoop](https://github.com/lukesampson/scoop-extras/blob/master/bucket/task.json)
- [Fedora](https://packages.fedoraproject.org/pkgs/golang-github-task/go-task/) - [Fedora](https://packages.fedoraproject.org/pkgs/golang-github-task/go-task/)
- [NixOS](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/tools/go-task/default.nix) - [NixOS](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/tools/go-task/default.nix)

View File

@@ -55,15 +55,23 @@ may take some time until it's available on Scoop.
### AUR ### AUR
If you're on Arch Linux you can install Task from If you're on Arch Linux you can install Task from
[AUR](https://aur.archlinux.org/packages/taskfile-git) using your favorite [AUR](https://aur.archlinux.org/packages/go-task-bin) using your favorite
package manager such as `yay`, `pacaur` or `yaourt`: package manager such as `yay`, `pacaur` or `yaourt`:
```cmd ```cmd
yay -S taskfile-git yay -S go-task-bin
``` ```
This installation method is community owned, but since it's `-git` version of Alternatively, there's
the package, it's always latest available version based on the Git repository. [this package](https://aur.archlinux.org/packages/go-task) which installs from
the source code instead of downloading the binary from the
[releases page](https://github.com/go-task/task/releases):
```cmd
yay -S go-task
```
This installation method is community owned.
### Fedora ### Fedora
@@ -89,6 +97,15 @@ nix-env -iA nixpkgs.go-task
This installation method is community owned. After a new release of Task, it This installation method is community owned. After a new release of Task, it
may take some time until it's available in [nixpkgs](https://github.com/NixOS/nixpkgs). may take some time until it's available in [nixpkgs](https://github.com/NixOS/nixpkgs).
### npm
You can also use Node and npm to install Task by installing
[this package](https://www.npmjs.com/package/@go-task/cli).
```bash
npm install -g @go-task/cli
```
## Get The Binary ## Get The Binary
### Binary ### Binary
@@ -106,19 +123,25 @@ We also have an [install script][installscript] which is very useful in
scenarios like CI. Many thanks to [GoDownloader][godownloader] for enabling the scenarios like CI. Many thanks to [GoDownloader][godownloader] for enabling the
easy generation of this script. easy generation of this script.
By default, it installs on the `./bin` directory relative to the working
directory:
```bash ```bash
# For Default Installation to ./bin with debug logging
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d
# For Installation To /usr/local/bin for userwide access with debug logging
# May require sudo sh
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin
``` ```
:::info It is possible to override the installation directory with the `-b` parameter.
On Linux, common choices are `~/.local/bin` and `~/bin` to install for the
current user or `/usr/local/bin` to install for all users:
This method will download the binary on the local `./bin` directory by default. ```bash
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b ~/.local/bin
```
:::caution
On macOS and Windows, `~/.local/bin` and `~/bin` are not added to `$PATH` by
default.
::: :::

View File

@@ -41,7 +41,7 @@ guide to check the full schema documentation and Task features.
`$PATH` and you're done! Or you can also install using [Homebrew][homebrew], `$PATH` and you're done! Or you can also install using [Homebrew][homebrew],
[Snapcraft][snapcraft], or [Scoop][scoop] if you want. [Snapcraft][snapcraft], or [Scoop][scoop] if you want.
- Available on CIs: by adding [this simple command](installation.md#install-script) - Available on CIs: by adding [this simple command](installation.md#install-script)
to install on your CI script and you're done to use Task as part of your CI pipeline; to install on your CI script and you're ready to use Task as part of your CI pipeline;
- Truly cross-platform: while most build tools only work well on Linux or macOS, - Truly cross-platform: while most build tools only work well on Linux or macOS,
Task also supports Windows thanks to [this shell interpreter for Go][sh]. Task also supports Windows thanks to [this shell interpreter for Go][sh].
- Great for code generation: you can easily [prevent a task from running](/usage#prevent-unnecessary-work) - Great for code generation: you can easily [prevent a task from running](/usage#prevent-unnecessary-work)

View File

@@ -13,17 +13,25 @@ the `test-release` task of the Taskfile.
artifacts automatically when a new Git tag is pushed to master artifacts automatically when a new Git tag is pushed to master
(raw executables and DEB and RPM packages). (raw executables and DEB and RPM packages).
Since v3.15.0, raw executables can also be reproduced and verified locally by
checking out a specific tag and calling `goreleaser build`, using the Go version
defined in the above GitHub Actions.
# Homebrew # Homebrew
To release a new version on the [Homebrew tap][homebrewtap] edit the Goreleaser will automatically push a new commit to the
[Formula/go-task.rb][gotaskrb] file, updating with the new version, download [Formula/go-task.rb][gotaskrb] file in the [Homebrew tap][homebrewtap]
URL and sha256. repository to release the new version.
# npm
To release to npm update the version in the [`package.json`][packagejson] file
and then run `task npm:publish` to push it.
# Snapcraft # Snapcraft
The exception is the publishing of a new version of the The [snap package][snappackage] requires to manual steps to release a new
[snap package][snappackage]. This current require two steps after publishing version:
the binaries:
* Updating the current version on [snapcraft.yaml][snapcraftyaml]. * Updating the current version on [snapcraft.yaml][snapcraftyaml].
* Moving both `amd64`, `armhf` and `arm64` new artifacts to the stable channel on * Moving both `amd64`, `armhf` and `arm64` new artifacts to the stable channel on
@@ -31,9 +39,9 @@ the [Snapcraft dashboard][snapcraftdashboard].
# Scoop # Scoop
Scoop is a community owned installation method. Scoop owners usually take care Scoop is a command-line package manager for the Windows operating system.
of updating versions there by editing Scoop package manifests are maintained by the community.
[this file](https://github.com/lukesampson/scoop-extras/blob/master/bucket/task.json). Scoop owners usually take care of updating versions there by editing [this file](https://github.com/lukesampson/scoop-extras/blob/master/bucket/task.json).
If you think its Task version is outdated, open an issue to let us know. If you think its Task version is outdated, open an issue to let us know.
# Nix # Nix
@@ -46,6 +54,7 @@ If you think its Task version is outdated, open an issue to let us know.
[goreleaser]: https://goreleaser.com/ [goreleaser]: https://goreleaser.com/
[homebrewtap]: https://github.com/go-task/homebrew-tap [homebrewtap]: https://github.com/go-task/homebrew-tap
[gotaskrb]: https://github.com/go-task/homebrew-tap/blob/master/Formula/go-task.rb [gotaskrb]: https://github.com/go-task/homebrew-tap/blob/master/Formula/go-task.rb
[packagejson]: https://github.com/go-task/task/blob/master/package.json#L3
[snappackage]: https://github.com/go-task/snap [snappackage]: https://github.com/go-task/snap
[snapcraftyaml]: https://github.com/go-task/snap/blob/master/snap/snapcraft.yaml#L2 [snapcraftyaml]: https://github.com/go-task/snap/blob/master/snap/snapcraft.yaml#L2
[snapcraftdashboard]: https://snapcraft.io/task/releases [snapcraftdashboard]: https://snapcraft.io/task/releases

View File

@@ -136,6 +136,8 @@ namespace. So, you'd call `task docs:serve` to run the `serve` task from
`documentation/Taskfile.yml` or `task docker:build` to run the `build` task `documentation/Taskfile.yml` or `task docker:build` to run the `build` task
from the `DockerTasks.yml` file. from the `DockerTasks.yml` file.
Relative paths are resolved relative to the directory containing the including Taskfile.
### OS-specific Taskfiles ### OS-specific Taskfiles
With `version: '2'`, task automatically includes any `Taskfile_{{OS}}.yml` With `version: '2'`, task automatically includes any `Taskfile_{{OS}}.yml`
@@ -192,6 +194,22 @@ 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"
``` ```
### Internal includes
Includes marked as internal will set all the tasks of the included file to be
internal as well (see the [Internal tasks](#internal-tasks) section below).
This is useful when including utility tasks that are not intended to be used
directly by the user.
```yaml
version: '3'
includes:
tests:
taskfile: ./taskfiles/Utils.yml
internal: true
```
### Vars of included Taskfiles ### Vars of included Taskfiles
You can also specify variables when including a Taskfile. This may be useful You can also specify variables when including a Taskfile. This may be useful
@@ -215,12 +233,35 @@ includes:
:::info :::info
Vars declared in the included Taskfile have preference over the Vars declared in the included Taskfile have preference over the
included ones! If you want a variable in an included Taskfile to be overridable, variables in the including Taskfile! 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): use the [default function](https://go-task.github.io/slim-sprig/defaults.html):
`MY_VAR: '{{.MY_VAR | default "my-default-value"}}'`. `MY_VAR: '{{.MY_VAR | default "my-default-value"}}'`.
::: :::
## Internal tasks
Internal tasks are tasks that cannot be called directly by the user. They will
not appear in the output when running `task --list|--list-all`. Other tasks may
call internal tasks in the usual way. This is useful for creating reusable,
function-like tasks that have no useful purpose on the command line.
```yaml
version: '3'
tasks:
build-image-1:
cmds:
- task: build-image
vars:
DOCKER_IMAGE: image-1
build-image:
internal: true
cmds:
- docker build -t {{.DOCKER_IMAGE}} .
```
## 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

View File

@@ -1,8 +1,8 @@
// @ts-check // @ts-check
// Note: type annotations allow type checking and IDEs autocompletion // Note: type annotations allow type checking and IDEs autocompletion
const lightCodeTheme = require('prism-react-renderer/themes/github'); const lightCodeTheme = require('./src/themes/prismLight');
const darkCodeTheme = require('prism-react-renderer/themes/dracula'); const darkCodeTheme = require('./src/themes/prismDark');
const GITHUB_URL = 'https://github.com/go-task/task'; const GITHUB_URL = 'https://github.com/go-task/task';
const TWITTER_URL = 'https://twitter.com/taskfiledev'; const TWITTER_URL = 'https://twitter.com/taskfiledev';

View File

@@ -1,4 +1,9 @@
@import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,400;0,700;1,400;1,700&family=Roboto:ital,wght@0,400;0,700;1,400;1,700&display=swap');
:root { :root {
--ifm-font-family-base: Roboto, system-ui, -apple-system, Segoe UI, Ubuntu, Cantarell, Noto Sans, sans-serif, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
--ifm-font-family-monospace: 'Roboto Mono', SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
--ifm-color-primary: #43ABA2 ; --ifm-color-primary: #43ABA2 ;
--ifm-color-primary-dark: #3AB2A6; --ifm-color-primary-dark: #3AB2A6;
--ifm-color-primary-darker: #32B8AB; --ifm-color-primary-darker: #32B8AB;
@@ -11,13 +16,6 @@
} }
[data-theme='dark'] { [data-theme='dark'] {
--ifm-color-primary: #43ABA2 ;
--ifm-color-primary-dark: #3AB2A6;
--ifm-color-primary-darker: #32B8AB;
--ifm-color-primary-darkest: #29BEB0;
--ifm-color-primary-light: #4CA59D;
--ifm-color-primary-lighter: #559F98;
--ifm-color-primary-lightest: #5D9993;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
} }

View File

@@ -0,0 +1,79 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const darkTheme = require('prism-react-renderer/themes/vsDark/index.cjs.js');
module.exports = {
plain: {
color: '#D4D4D4',
backgroundColor: '#212121'
},
styles: [
...darkTheme.styles,
{
types: ['title'],
style: {
color: '#569CD6',
fontWeight: 'bold'
}
},
{
types: ['property', 'parameter'],
style: {
color: '#9CDCFE'
}
},
{
types: ['script'],
style: {
color: '#D4D4D4'
}
},
{
types: ['boolean', 'arrow', 'atrule', 'tag'],
style: {
color: '#569CD6'
}
},
{
types: ['number', 'color', 'unit'],
style: {
color: '#B5CEA8'
}
},
{
types: ['font-matter'],
style: {
color: '#CE9178'
}
},
{
types: ['keyword', 'rule'],
style: {
color: '#C586C0'
}
},
{
types: ['regex'],
style: {
color: '#D16969'
}
},
{
types: ['maybe-class-name'],
style: {
color: '#4EC9B0'
}
},
{
types: ['constant'],
style: {
color: '#4FC1FF'
}
}
]
};

View File

@@ -0,0 +1,100 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const lightTheme = require('prism-react-renderer/themes/github/index.cjs.js');
module.exports = {
...lightTheme,
styles: [
...lightTheme.styles,
{
types: ['title'],
style: {
color: '#0550AE',
fontWeight: 'bold'
}
},
{
types: ['parameter'],
style: {
color: '#953800'
}
},
{
types: ['boolean', 'rule', 'color', 'number', 'constant', 'property'],
style: {
color: '#005CC5'
}
},
{
types: ['atrule', 'tag'],
style: {
color: '#22863A'
}
},
{
types: ['script'],
style: {
color: '#24292E'
}
},
{
types: ['operator', 'unit', 'rule'],
style: {
color: '#D73A49'
}
},
{
types: ['font-matter', 'string', 'attr-value'],
style: {
color: '#C6105F'
}
},
{
types: ['class-name'],
style: {
color: '#116329'
}
},
{
types: ['attr-name'],
style: {
color: '#0550AE'
}
},
{
types: ['keyword'],
style: {
color: '#CF222E'
}
},
{
types: ['function'],
style: {
color: '#8250DF'
}
},
{
types: ['selector'],
style: {
color: '#6F42C1'
}
},
{
types: ['variable'],
style: {
color: '#E36209'
}
},
{
types: ['comment'],
style: {
color: '#6B6B6B'
}
}
]
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -1,5 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 375 375" width="500" height="500"> <svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" viewBox="0 0 375 375"><path fill="#29beb0" d="M 187.570312 190.933594 L 187.570312 375 L 30.070312 279.535156 L 30.070312 95.464844 Z"/><path fill="#69d2c8" d="M 187.570312 190.933594 L 187.570312 375 L 345.070312 279.535156 L 345.070312 95.464844 Z"/><path fill="#94dfd8" d="M 187.570312 190.933594 L 30.070312 95.464844 L 187.570312 0 L 345.070312 95.464844 Z"/></svg>
<path fill="#29beb0" d="M 187.570312 190.933594 L 187.570312 375 L 30.070312 279.535156 L 30.070312 95.464844 Z"/>
<path fill="#69d2c8" d="M 187.570312 190.933594 L 187.570312 375 L 345.070312 279.535156 L 345.070312 95.464844 Z"/>
<path fill="#94dfd8" d="M 187.570312 190.933594 L 30.070312 95.464844 L 187.570312 0 L 345.070312 95.464844 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 446 B

After

Width:  |  Height:  |  Size: 435 B

View File

@@ -1,3 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 375 375" width="500" height="500"> <svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" viewBox="0 0 375 375"><path d="M 29.021972 281.445466 L 183.370289 375 L 183.370289 194.622441 L 29.021972 101.064089 Z M 345.978037 281.445466 L 345.978037 101.064079 L 191.629731 194.622431 L 191.629731 375 Z M 342.140723 93.731759 L 187.5 0 L 32.859297 93.731759 L 187.5 187.467349 Z"/></svg>
<path d="M 29.021972 281.445466 L 183.370289 375 L 183.370289 194.622441 L 29.021972 101.064089 Z M 345.978037 281.445466 L 345.978037 101.064079 L 191.629731 194.622431 L 191.629731 375 Z M 342.140723 93.731759 L 187.5 0 L 32.859297 93.731759 L 187.5 187.467349 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 365 B

After

Width:  |  Height:  |  Size: 360 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,6 +1,6 @@
(function () { (function () {
function attachAd() { function attachAd() {
const el = document.createElement('script'); var el = document.createElement('script');
el.setAttribute('type', 'text/javascript'); el.setAttribute('type', 'text/javascript');
el.setAttribute('id', '_carbonads_js'); el.setAttribute('id', '_carbonads_js');
el.setAttribute( el.setAttribute(
@@ -9,7 +9,7 @@
); );
el.setAttribute('async', 'async'); el.setAttribute('async', 'async');
const wrapper = document.getElementById('sidebar-ads'); var wrapper = document.getElementById('sidebar-ads');
wrapper.innerHTML = ''; wrapper.innerHTML = '';
wrapper.appendChild(el); wrapper.appendChild(el);
} }
@@ -17,8 +17,13 @@
setTimeout(function () { setTimeout(function () {
attachAd(); attachAd();
window.addEventListener('popstate', function () { var currentPath = window.location.pathname;
attachAd();
}); setInterval(function () {
if (currentPath !== window.location.pathname) {
currentPath = window.location.pathname;
attachAd();
}
}, 1000);
}, 1000); }, 1000);
})(); })();

View File

@@ -1577,33 +1577,46 @@
"@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/sourcemap-codec" "^1.4.10"
"@jridgewell/gen-mapping@^0.3.0": "@jridgewell/gen-mapping@^0.3.0":
version "0.3.1" version "0.3.2"
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz#cf92a983c83466b8c0ce9124fadeaf09f7c66ea9" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9"
integrity sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg== integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==
dependencies: dependencies:
"@jridgewell/set-array" "^1.0.0" "@jridgewell/set-array" "^1.0.1"
"@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/sourcemap-codec" "^1.4.10"
"@jridgewell/trace-mapping" "^0.3.9" "@jridgewell/trace-mapping" "^0.3.9"
"@jridgewell/resolve-uri@^3.0.3": "@jridgewell/resolve-uri@^3.0.3":
version "3.0.7" version "3.1.0"
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA== integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
"@jridgewell/set-array@^1.0.0": "@jridgewell/set-array@^1.0.0":
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.1.tgz#36a6acc93987adcf0ba50c66908bd0b70de8afea" resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.1.tgz#36a6acc93987adcf0ba50c66908bd0b70de8afea"
integrity sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ== integrity sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==
"@jridgewell/set-array@^1.0.1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
"@jridgewell/source-map@^0.3.2":
version "0.3.2"
resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb"
integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==
dependencies:
"@jridgewell/gen-mapping" "^0.3.0"
"@jridgewell/trace-mapping" "^0.3.9"
"@jridgewell/sourcemap-codec@^1.4.10": "@jridgewell/sourcemap-codec@^1.4.10":
version "1.4.13" version "1.4.14"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w== integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
"@jridgewell/trace-mapping@^0.3.9": "@jridgewell/trace-mapping@^0.3.9":
version "0.3.13" version "0.3.14"
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed"
integrity sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w== integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==
dependencies: dependencies:
"@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/resolve-uri" "^3.0.3"
"@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/sourcemap-codec" "^1.4.10"
@@ -4960,11 +4973,6 @@ lodash.some@^4.4.0:
resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d"
integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0= integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=
lodash.sortby@^4.7.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
lodash.uniq@4.5.0, lodash.uniq@^4.5.0: lodash.uniq@4.5.0, lodash.uniq@^4.5.0:
version "4.5.0" version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
@@ -6815,13 +6823,6 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
source-map@~0.8.0-beta.0:
version "0.8.0-beta.0"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.8.0-beta.0.tgz#d4c1bb42c3f7ee925f005927ba10709e0d1d1f11"
integrity sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==
dependencies:
whatwg-url "^7.0.0"
space-separated-tokens@^1.0.0: space-separated-tokens@^1.0.0:
version "1.1.5" version "1.1.5"
resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899"
@@ -7036,13 +7037,13 @@ terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.1:
terser "^5.7.2" terser "^5.7.2"
terser@^5.10.0, terser@^5.7.2: terser@^5.10.0, terser@^5.7.2:
version "5.13.1" version "5.14.2"
resolved "https://registry.yarnpkg.com/terser/-/terser-5.13.1.tgz#66332cdc5a01b04a224c9fad449fc1a18eaa1799" resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.2.tgz#9ac9f22b06994d736174f4091aa368db896f1c10"
integrity sha512-hn4WKOfwnwbYfe48NgrQjqNOH9jzLqRcIfbYytOXCOv46LBfWr9bDS17MQqOi+BWGD0sJK3Sj5NC/gJjiojaoA== integrity sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==
dependencies: dependencies:
"@jridgewell/source-map" "^0.3.2"
acorn "^8.5.0" acorn "^8.5.0"
commander "^2.20.0" commander "^2.20.0"
source-map "~0.8.0-beta.0"
source-map-support "~0.5.20" source-map-support "~0.5.20"
text-table@^0.2.0: text-table@^0.2.0:
@@ -7092,13 +7093,6 @@ totalist@^1.0.0:
resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df"
integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==
tr46@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=
dependencies:
punycode "^2.1.0"
tr46@~0.0.3: tr46@~0.0.3:
version "0.0.3" version "0.0.3"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
@@ -7437,11 +7431,6 @@ webidl-conversions@^3.0.0:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=
webidl-conversions@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
webpack-bundle-analyzer@^4.5.0: webpack-bundle-analyzer@^4.5.0:
version "4.5.0" version "4.5.0"
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz#1b0eea2947e73528754a6f9af3e91b2b6e0f79d5" resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz#1b0eea2947e73528754a6f9af3e91b2b6e0f79d5"
@@ -7585,15 +7574,6 @@ whatwg-url@^5.0.0:
tr46 "~0.0.3" tr46 "~0.0.3"
webidl-conversions "^3.0.0" webidl-conversions "^3.0.0"
whatwg-url@^7.0.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==
dependencies:
lodash.sortby "^4.7.0"
tr46 "^1.0.1"
webidl-conversions "^4.0.2"
which@^1.3.1: which@^1.3.1:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"

View File

@@ -17,7 +17,15 @@ type taskNotFoundError struct {
} }
func (err *taskNotFoundError) Error() string { func (err *taskNotFoundError) Error() string {
return fmt.Sprintf(`task: Task "%s" not found`, err.taskName) return fmt.Sprintf(`task: Task %q not found`, err.taskName)
}
type taskInternalError struct {
taskName string
}
func (err *taskInternalError) Error() string {
return fmt.Sprintf(`task: Task "%s" is internal`, err.taskName)
} }
type TaskRunError struct { type TaskRunError struct {
@@ -26,7 +34,7 @@ type TaskRunError struct {
} }
func (err *TaskRunError) Error() string { func (err *TaskRunError) Error() string {
return fmt.Sprintf(`task: Failed to run task "%s": %v`, err.taskName, err.err) return fmt.Sprintf(`task: Failed to run task %q: %v`, err.taskName, err.err)
} }
func (err *TaskRunError) ExitCode() int { func (err *TaskRunError) ExitCode() int {
@@ -46,7 +54,7 @@ type MaximumTaskCallExceededError struct {
func (e *MaximumTaskCallExceededError) Error() string { func (e *MaximumTaskCallExceededError) Error() string {
return fmt.Sprintf( return fmt.Sprintf(
`task: maximum task call exceeded (%d) for task "%s": probably an cyclic dep or infinite loop`, `task: maximum task call exceeded (%d) for task %q: probably an cyclic dep or infinite loop`,
MaximumTaskCall, MaximumTaskCall,
e.task, e.task,
) )

4
go.mod
View File

@@ -19,9 +19,9 @@ require (
github.com/mattn/go-colorable v0.1.9 // indirect github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-isatty v0.0.14 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
) )
go 1.17 go 1.18

25
go.sum
View File

@@ -1,30 +1,17 @@
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI=
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss=
github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= 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/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/renameio v1.0.1/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk=
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
@@ -34,14 +21,11 @@ github.com/mattn/go-zglob v0.0.3 h1:6Ry4EYsScDyt5di4OI6xw1bYhOqfE5S33Z1OPy+d+To=
github.com/mattn/go-zglob v0.0.3/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/mattn/go-zglob v0.0.3/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/radovskyb/watcher v1.0.7 h1:AYePLih6dpmS32vlHfhCeli8127LzkIgwJGcwwe8tUE= github.com/radovskyb/watcher v1.0.7 h1:AYePLih6dpmS32vlHfhCeli8127LzkIgwJGcwwe8tUE=
github.com/radovskyb/watcher v1.0.7/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg= github.com/radovskyb/watcher v1.0.7/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 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=
@@ -54,23 +38,18 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cO
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=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
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=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
mvdan.cc/editorconfig v0.2.0/go.mod h1:lvnnD3BNdBYkhq+B4uBuFFKatfp02eB6HixDvEz91C0=
mvdan.cc/sh/v3 v3.6.0-0.dev.0.20220704111049-a6e3029cd899 h1:nwm4t5PtLlFd/H342GP50CtYf7vyMCOZkPx3g9shO0c= mvdan.cc/sh/v3 v3.6.0-0.dev.0.20220704111049-a6e3029cd899 h1:nwm4t5PtLlFd/H342GP50CtYf7vyMCOZkPx3g9shO0c=
mvdan.cc/sh/v3 v3.6.0-0.dev.0.20220704111049-a6e3029cd899/go.mod h1:1JcoyAKm1lZw/2bZje/iYKWicU/KMd0rsyJeKHnsK4E= mvdan.cc/sh/v3 v3.6.0-0.dev.0.20220704111049-a6e3029cd899/go.mod h1:1JcoyAKm1lZw/2bZje/iYKWicU/KMd0rsyJeKHnsK4E=

View File

@@ -52,7 +52,9 @@ func (e *Executor) printTasks(listAll bool) {
func (e *Executor) allTaskNames() (tasks []*taskfile.Task) { func (e *Executor) allTaskNames() (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 {
tasks = append(tasks, task) if !task.Internal {
tasks = append(tasks, 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
@@ -61,7 +63,7 @@ func (e *Executor) allTaskNames() (tasks []*taskfile.Task) {
func (e *Executor) tasksWithDesc() (tasks []*taskfile.Task) { 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.Internal && task.Desc != "" {
compiledTask, err := e.FastCompiledTask(taskfile.Call{Task: task.Task}) compiledTask, err := e.FastCompiledTask(taskfile.Call{Task: task.Task})
if err == nil { if err == nil {
task = compiledTask task = compiledTask
@@ -92,7 +94,7 @@ func (e *Executor) ListTaskNames(allTasks bool) {
// create a string slice from all map values (*taskfile.Task) // create a string slice from all map values (*taskfile.Task)
s := make([]string, 0, len(e.Taskfile.Tasks)) s := make([]string, 0, len(e.Taskfile.Tasks))
for _, t := range e.Taskfile.Tasks { for _, t := range e.Taskfile.Tasks {
if allTasks || t.Desc != "" { if (allTasks || t.Desc != "") && !t.Internal {
s = append(s, strings.TrimRight(t.Task, ":")) s = append(s, strings.TrimRight(t.Task, ":"))
} }
} }

View File

@@ -4,7 +4,8 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"path/filepath"
"github.com/go-task/task/v3/internal/filepathext"
) )
const defaultTaskfile = `# https://taskfile.dev const defaultTaskfile = `# https://taskfile.dev
@@ -23,13 +24,13 @@ tasks:
// InitTaskfile Taskfile creates a new Taskfile // InitTaskfile Taskfile creates a new Taskfile
func InitTaskfile(w io.Writer, dir string) error { func InitTaskfile(w io.Writer, dir string) error {
f := filepath.Join(dir, "Taskfile.yaml") f := filepathext.SmartJoin(dir, "Taskfile.yaml")
if _, err := os.Stat(f); err == nil { if _, err := os.Stat(f); err == nil {
return ErrTaskfileAlreadyExists return ErrTaskfileAlreadyExists
} }
if err := os.WriteFile(f, []byte(defaultTaskfile), 0644); err != nil { if err := os.WriteFile(f, []byte(defaultTaskfile), 0o644); err != nil {
return err return err
} }
fmt.Fprintf(w, "Taskfile.yaml created in the current directory\n") fmt.Fprintf(w, "Taskfile.yaml created in the current directory\n")

View File

@@ -4,12 +4,12 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
"path/filepath"
"strings" "strings"
"sync" "sync"
"github.com/go-task/task/v3/internal/compiler" "github.com/go-task/task/v3/internal/compiler"
"github.com/go-task/task/v3/internal/execext" "github.com/go-task/task/v3/internal/execext"
"github.com/go-task/task/v3/internal/filepathext"
"github.com/go-task/task/v3/internal/logger" "github.com/go-task/task/v3/internal/logger"
"github.com/go-task/task/v3/internal/templater" "github.com/go-task/task/v3/internal/templater"
"github.com/go-task/task/v3/taskfile" "github.com/go-task/task/v3/taskfile"
@@ -44,7 +44,13 @@ func (c *CompilerV3) FastGetVariables(t *taskfile.Task, call taskfile.Call) (*ta
func (c *CompilerV3) getVariables(t *taskfile.Task, call *taskfile.Call, evaluateShVars bool) (*taskfile.Vars, error) { func (c *CompilerV3) getVariables(t *taskfile.Task, call *taskfile.Call, evaluateShVars bool) (*taskfile.Vars, error) {
result := compiler.GetEnviron() result := compiler.GetEnviron()
if t != nil { if t != nil {
result.Set("TASK", taskfile.Var{Static: t.Task}) specialVars, err := c.getSpecialVars(t)
if err != nil {
return nil, err
}
for k, v := range specialVars {
result.Set(k, taskfile.Var{Static: v})
}
} }
getRangeFunc := func(dir string) func(k string, v taskfile.Var) error { getRangeFunc := func(dir string) func(k string, v taskfile.Var) error {
@@ -83,9 +89,7 @@ func (c *CompilerV3) getVariables(t *taskfile.Task, call *taskfile.Call, evaluat
if err := tr.Err(); err != nil { if err := tr.Err(); err != nil {
return nil, err return nil, err
} }
if !filepath.IsAbs(dir) { dir = filepathext.SmartJoin(c.Dir, dir)
dir = filepath.Join(c.Dir, dir)
}
taskRangeFunc = getRangeFunc(dir) taskRangeFunc = getRangeFunc(dir)
} }
@@ -167,3 +171,23 @@ func (c *CompilerV3) ResetCache() {
c.dynamicCache = nil c.dynamicCache = nil
} }
func (c *CompilerV3) getSpecialVars(t *taskfile.Task) (map[string]string, error) {
taskfileDir, err := c.getTaskfileDir(t)
if err != nil {
return nil, err
}
return map[string]string{
"TASK": t.Task,
"ROOT_DIR": c.Dir,
"TASKFILE_DIR": taskfileDir,
}, nil
}
func (c *CompilerV3) getTaskfileDir(t *taskfile.Task) (string, error) {
if t.IncludedTaskfile != nil {
return t.IncludedTaskfile.FullDirPath()
}
return c.Dir, nil
}

View File

@@ -73,7 +73,7 @@ func IsExitError(err error) bool {
// if available. // if available.
func Expand(s string) (string, error) { func Expand(s string) (string, error) {
s = filepath.ToSlash(s) s = filepath.ToSlash(s)
s = strings.Replace(s, " ", `\ `, -1) s = strings.ReplaceAll(s, " ", `\ `)
fields, err := shell.Fields(s, nil) fields, err := shell.Fields(s, nil)
if err != nil { if err != nil {
return "", err return "", err

View File

@@ -0,0 +1,14 @@
package filepathext
import (
"path/filepath"
)
// SmartJoin joins two paths, but only if the second is not already an
// absolute path.
func SmartJoin(a, b string) string {
if filepath.IsAbs(b) {
return b
}
return filepath.Join(a, b)
}

View File

@@ -8,6 +8,8 @@ import (
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings" "strings"
"github.com/go-task/task/v3/internal/filepathext"
) )
// Checksum validades if a task is up to date by calculating its source // Checksum validades if a task is up to date by calculating its source
@@ -43,8 +45,8 @@ func (c *Checksum) IsUpToDate() (bool, error) {
} }
if !c.Dry { if !c.Dry {
_ = os.MkdirAll(filepath.Join(c.TempDir, "checksum"), 0755) _ = os.MkdirAll(filepathext.SmartJoin(c.TempDir, "checksum"), 0o755)
if err = os.WriteFile(checksumFile, []byte(newMd5+"\n"), 0644); err != nil { if err = os.WriteFile(checksumFile, []byte(newMd5+"\n"), 0o644); err != nil {
return false, err return false, err
} }
} }

View File

@@ -2,12 +2,12 @@ package status
import ( import (
"os" "os"
"path/filepath"
"sort" "sort"
"github.com/mattn/go-zglob" "github.com/mattn/go-zglob"
"github.com/go-task/task/v3/internal/execext" "github.com/go-task/task/v3/internal/execext"
"github.com/go-task/task/v3/internal/filepathext"
) )
func globs(dir string, globs []string) ([]string, error) { func globs(dir string, globs []string) ([]string, error) {
@@ -25,17 +25,18 @@ func globs(dir string, globs []string) ([]string, error) {
func Glob(dir string, g string) ([]string, error) { func Glob(dir string, g string) ([]string, error) {
files := make([]string, 0) files := make([]string, 0)
if !filepath.IsAbs(g) { g = filepathext.SmartJoin(dir, g)
g = filepath.Join(dir, g)
}
g, err := execext.Expand(g) g, err := execext.Expand(g)
if err != nil { if err != nil {
return nil, err return nil, err
} }
fs, err := zglob.Glob(g)
fs, err := zglob.GlobFollowSymlinks(g)
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, f := range fs { for _, f := range fs {
info, err := os.Stat(f) info, err := os.Stat(f)
if err != nil { if err != nil {

View File

@@ -19,11 +19,11 @@ func init() {
"OS": func() string { return runtime.GOOS }, "OS": func() string { return runtime.GOOS },
"ARCH": func() string { return runtime.GOARCH }, "ARCH": func() string { return runtime.GOARCH },
"catLines": func(s string) string { "catLines": func(s string) string {
s = strings.Replace(s, "\r\n", " ", -1) s = strings.ReplaceAll(s, "\r\n", " ")
return strings.Replace(s, "\n", " ", -1) return strings.ReplaceAll(s, "\n", " ")
}, },
"splitLines": func(s string) []string { "splitLines": func(s string) []string {
s = strings.Replace(s, "\r\n", "\n", -1) s = strings.ReplaceAll(s, "\r\n", "\n")
return strings.Split(s, "\n") return strings.Split(s, "\n")
}, },
"fromSlash": func(path string) string { "fromSlash": func(path string) string {

32
package-lock.json generated Normal file
View File

@@ -0,0 +1,32 @@
{
"name": "@go-task/cli",
"version": "3.16.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@go-task/cli",
"version": "3.16.0",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@go-task/go-npm": "^0.1.15"
}
},
"node_modules/@go-task/go-npm": {
"version": "0.1.15",
"resolved": "https://registry.npmjs.org/@go-task/go-npm/-/go-npm-0.1.15.tgz",
"integrity": "sha512-xG+6SsSQsa6MzWML1CABWHTwHrCrBqXc/D1POoMDGIgjsRE/PB1noSBGLFhvU5DWHdPksqbAt/w9VOjbqlXpYw==",
"bin": {
"go-npm": "bin/index.js"
}
}
},
"dependencies": {
"@go-task/go-npm": {
"version": "0.1.15",
"resolved": "https://registry.npmjs.org/@go-task/go-npm/-/go-npm-0.1.15.tgz",
"integrity": "sha512-xG+6SsSQsa6MzWML1CABWHTwHrCrBqXc/D1POoMDGIgjsRE/PB1noSBGLFhvU5DWHdPksqbAt/w9VOjbqlXpYw=="
}
}
}

34
package.json Normal file
View File

@@ -0,0 +1,34 @@
{
"name": "@go-task/cli",
"version": "3.16.0",
"description": "A task runner / simpler Make alternative written in Go",
"scripts": {
"postinstall": "go-npm install",
"preuninstall": "go-npm uninstall"
},
"goBinary": {
"name": "task",
"path": "./bin",
"url": "https://github.com/go-task/task/releases/download/v{{version}}/task_{{platform}}_{{arch}}{{archive_ext}}"
},
"files": [],
"repository": {
"type": "git",
"url": "https://github.com/go-task/task.git"
},
"keywords": [
"task",
"taskfile",
"build-tool",
"task-runner"
],
"author": "Andrey Nering",
"license": "MIT",
"bugs": {
"url": "https://github.com/go-task/task/issues"
},
"homepage": "https://taskfile.dev",
"dependencies": {
"@go-task/go-npm": "^0.1.15"
}
}

View File

@@ -12,6 +12,7 @@ import (
compilerv2 "github.com/go-task/task/v3/internal/compiler/v2" compilerv2 "github.com/go-task/task/v3/internal/compiler/v2"
compilerv3 "github.com/go-task/task/v3/internal/compiler/v3" compilerv3 "github.com/go-task/task/v3/internal/compiler/v3"
"github.com/go-task/task/v3/internal/execext" "github.com/go-task/task/v3/internal/execext"
"github.com/go-task/task/v3/internal/filepathext"
"github.com/go-task/task/v3/internal/logger" "github.com/go-task/task/v3/internal/logger"
"github.com/go-task/task/v3/internal/output" "github.com/go-task/task/v3/internal/output"
"github.com/go-task/task/v3/taskfile" "github.com/go-task/task/v3/taskfile"
@@ -19,6 +20,10 @@ import (
) )
func (e *Executor) Setup() error { func (e *Executor) Setup() error {
if err := e.setCurrentDir(); err != nil {
return err
}
if err := e.readTaskfile(); err != nil { if err := e.readTaskfile(); err != nil {
return err return err
} }
@@ -52,6 +57,23 @@ func (e *Executor) Setup() error {
return nil return nil
} }
func (e *Executor) setCurrentDir() error {
if e.Dir == "" {
wd, err := os.Getwd()
if err != nil {
return err
}
e.Dir = wd
} else if !filepath.IsAbs(e.Dir) {
abs, err := filepath.Abs(e.Dir)
if err != nil {
return err
}
e.Dir = abs
}
return nil
}
func (e *Executor) readTaskfile() error { func (e *Executor) readTaskfile() error {
var err error var err error
e.Taskfile, err = read.Taskfile(&read.ReaderNode{ e.Taskfile, err = read.Taskfile(&read.ReaderNode{
@@ -69,7 +91,7 @@ func (e *Executor) setupTempDir() error {
} }
if os.Getenv("TASK_TEMP_DIR") == "" { if os.Getenv("TASK_TEMP_DIR") == "" {
e.TempDir = filepath.Join(e.Dir, ".task") e.TempDir = filepathext.SmartJoin(e.Dir, ".task")
} else if filepath.IsAbs(os.Getenv("TASK_TEMP_DIR")) || strings.HasPrefix(os.Getenv("TASK_TEMP_DIR"), "~") { } else if filepath.IsAbs(os.Getenv("TASK_TEMP_DIR")) || strings.HasPrefix(os.Getenv("TASK_TEMP_DIR"), "~") {
tempDir, err := execext.Expand(os.Getenv("TASK_TEMP_DIR")) tempDir, err := execext.Expand(os.Getenv("TASK_TEMP_DIR"))
if err != nil { if err != nil {
@@ -77,9 +99,9 @@ func (e *Executor) setupTempDir() error {
} }
projectDir, _ := filepath.Abs(e.Dir) projectDir, _ := filepath.Abs(e.Dir)
projectName := filepath.Base(projectDir) projectName := filepath.Base(projectDir)
e.TempDir = filepath.Join(tempDir, projectName) e.TempDir = filepathext.SmartJoin(tempDir, projectName)
} else { } else {
e.TempDir = filepath.Join(e.Dir, os.Getenv("TASK_TEMP_DIR")) e.TempDir = filepathext.SmartJoin(e.Dir, os.Getenv("TASK_TEMP_DIR"))
} }
return nil return nil

View File

@@ -9,7 +9,7 @@ import (
) )
// NOTE(@andreynering): This function intercepts SIGINT and SIGTERM signals // NOTE(@andreynering): This function intercepts SIGINT and SIGTERM signals
// so the Task process is not killed immediatelly and processes running have // so the Task process is not killed immediately and processes running have
// time to do cleanup work. // time to do cleanup work.
func (e *Executor) InterceptInterruptSignals() { func (e *Executor) InterceptInterruptSignals() {
ch := make(chan os.Signal, 3) ch := make(chan os.Signal, 3)

View File

@@ -64,11 +64,16 @@ type Executor struct {
func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error { func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error {
// check if given tasks exist // check if given tasks exist
for _, c := range calls { for _, c := range calls {
if _, ok := e.Taskfile.Tasks[c.Task]; !ok { t, ok := e.Taskfile.Tasks[c.Task]
if !ok {
// FIXME: move to the main package // FIXME: move to the main package
e.ListTasksWithDesc() e.ListTasksWithDesc()
return &taskNotFoundError{taskName: c.Task} return &taskNotFoundError{taskName: c.Task}
} }
if t.Internal {
e.ListTasksWithDesc()
return &taskInternalError{taskName: c.Task}
}
} }
if e.Summary { if e.Summary {
@@ -181,7 +186,7 @@ func (e *Executor) mkdir(t *taskfile.Task) error {
defer mutex.Unlock() defer mutex.Unlock()
if _, err := os.Stat(t.Dir); os.IsNotExist(err) { if _, err := os.Stat(t.Dir); os.IsNotExist(err) {
if err := os.MkdirAll(t.Dir, 0755); err != nil { if err := os.MkdirAll(t.Dir, 0o755); err != nil {
return err return err
} }
} }

View File

@@ -14,6 +14,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/go-task/task/v3" "github.com/go-task/task/v3"
"github.com/go-task/task/v3/internal/filepathext"
"github.com/go-task/task/v3/taskfile" "github.com/go-task/task/v3/taskfile"
) )
@@ -37,12 +38,12 @@ func (fct fileContentTest) name(file string) string {
func (fct fileContentTest) Run(t *testing.T) { func (fct fileContentTest) Run(t *testing.T) {
for f := range fct.Files { for f := range fct.Files {
_ = os.Remove(filepath.Join(fct.Dir, f)) _ = os.Remove(filepathext.SmartJoin(fct.Dir, f))
} }
e := &task.Executor{ e := &task.Executor{
Dir: fct.Dir, Dir: fct.Dir,
TempDir: filepath.Join(fct.Dir, ".task"), TempDir: filepathext.SmartJoin(fct.Dir, ".task"),
Entrypoint: fct.Entrypoint, Entrypoint: fct.Entrypoint,
Stdout: io.Discard, Stdout: io.Discard,
Stderr: io.Discard, Stderr: io.Discard,
@@ -52,13 +53,14 @@ func (fct fileContentTest) Run(t *testing.T) {
for name, expectContent := range fct.Files { for name, expectContent := range fct.Files {
t.Run(fct.name(name), func(t *testing.T) { t.Run(fct.name(name), func(t *testing.T) {
b, err := os.ReadFile(filepath.Join(fct.Dir, name)) path := filepathext.SmartJoin(fct.Dir, name)
b, err := os.ReadFile(path)
assert.NoError(t, err, "Error reading file") assert.NoError(t, err, "Error reading file")
s := string(b) s := string(b)
if fct.TrimSpace { if fct.TrimSpace {
s = strings.TrimSpace(s) s = strings.TrimSpace(s)
} }
assert.Equal(t, expectContent, s, "unexpected file content") assert.Equal(t, expectContent, s, "unexpected file content in %s", path)
}) })
} }
} }
@@ -162,6 +164,39 @@ func TestMultilineVars(t *testing.T) {
} }
} }
func TestSpecialVars(t *testing.T) {
const dir = "testdata/special_vars"
const target = "default"
var buff bytes.Buffer
e := &task.Executor{
Dir: dir,
Stdout: &buff,
Stderr: &buff,
Silent: true,
}
assert.NoError(t, e.Setup())
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: target}))
toAbs := func(rel string) string {
abs, err := filepath.Abs(rel)
assert.NoError(t, err)
return abs
}
output := buff.String()
// Root Taskfile
assert.Contains(t, output, "root/TASK=print")
assert.Contains(t, output, "root/ROOT_DIR="+toAbs("testdata/special_vars"))
assert.Contains(t, output, "root/TASKFILE_DIR="+toAbs("testdata/special_vars"))
// Included Taskfile
assert.Contains(t, output, "included/TASK=included:print")
assert.Contains(t, output, "included/ROOT_DIR="+toAbs("testdata/special_vars"))
assert.Contains(t, output, "included/TASKFILE_DIR="+toAbs("testdata/special_vars/included"))
}
func TestVarsInvalidTmpl(t *testing.T) { func TestVarsInvalidTmpl(t *testing.T) {
const ( const (
dir = "testdata/vars/v2" dir = "testdata/vars/v2"
@@ -234,7 +269,7 @@ func TestDeps(t *testing.T) {
} }
for _, f := range files { for _, f := range files {
_ = os.Remove(filepath.Join(dir, f)) _ = os.Remove(filepathext.SmartJoin(dir, f))
} }
e := &task.Executor{ e := &task.Executor{
@@ -246,7 +281,7 @@ func TestDeps(t *testing.T) {
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "default"})) assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "default"}))
for _, f := range files { for _, f := range files {
f = filepath.Join(dir, f) f = filepathext.SmartJoin(dir, f)
if _, err := os.Stat(f); err != nil { if _, err := os.Stat(f); err != nil {
t.Errorf("File %s should exist", f) t.Errorf("File %s should exist", f)
} }
@@ -262,7 +297,7 @@ func TestStatus(t *testing.T) {
} }
for _, f := range files { for _, f := range files {
path := filepath.Join(dir, f) path := filepathext.SmartJoin(dir, f)
_ = os.Remove(path) _ = os.Remove(path)
if _, err := os.Stat(path); err == nil { if _, err := os.Stat(path); err == nil {
t.Errorf("File should not exist: %v", err) t.Errorf("File should not exist: %v", err)
@@ -272,7 +307,7 @@ func TestStatus(t *testing.T) {
var buff bytes.Buffer var buff bytes.Buffer
e := &task.Executor{ e := &task.Executor{
Dir: dir, Dir: dir,
TempDir: filepath.Join(dir, ".task"), TempDir: filepathext.SmartJoin(dir, ".task"),
Stdout: &buff, Stdout: &buff,
Stderr: &buff, Stderr: &buff,
Silent: true, Silent: true,
@@ -282,7 +317,7 @@ func TestStatus(t *testing.T) {
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "gen-bar"})) assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "gen-bar"}))
for _, f := range files { for _, f := range files {
if _, err := os.Stat(filepath.Join(dir, f)); err != nil { if _, err := os.Stat(filepathext.SmartJoin(dir, f)); err != nil {
t.Errorf("File should exist: %v", err) t.Errorf("File should exist: %v", err)
} }
} }
@@ -359,10 +394,10 @@ func TestGenerates(t *testing.T) {
fileWithSpaces = "my text file.txt" fileWithSpaces = "my text file.txt"
) )
var srcFile = filepath.Join(dir, srcTask) var srcFile = filepathext.SmartJoin(dir, srcTask)
for _, task := range []string{srcTask, relTask, absTask, fileWithSpaces} { for _, task := range []string{srcTask, relTask, absTask, fileWithSpaces} {
path := filepath.Join(dir, task) path := filepathext.SmartJoin(dir, task)
_ = os.Remove(path) _ = os.Remove(path)
if _, err := os.Stat(path); err == nil { if _, err := os.Stat(path); err == nil {
t.Errorf("File should not exist: %v", err) t.Errorf("File should not exist: %v", err)
@@ -378,7 +413,7 @@ func TestGenerates(t *testing.T) {
assert.NoError(t, e.Setup()) assert.NoError(t, e.Setup())
for _, theTask := range []string{relTask, absTask, fileWithSpaces} { for _, theTask := range []string{relTask, absTask, fileWithSpaces} {
var destFile = filepath.Join(dir, theTask) var destFile = filepathext.SmartJoin(dir, theTask)
var upToDate = fmt.Sprintf("task: Task \"%s\" is up to date\n", srcTask) + var upToDate = fmt.Sprintf("task: Task \"%s\" is up to date\n", srcTask) +
fmt.Sprintf("task: Task \"%s\" is up to date\n", theTask) fmt.Sprintf("task: Task \"%s\" is up to date\n", theTask)
@@ -415,16 +450,16 @@ func TestStatusChecksum(t *testing.T) {
} }
for _, f := range files { for _, f := range files {
_ = os.Remove(filepath.Join(dir, f)) _ = os.Remove(filepathext.SmartJoin(dir, f))
_, err := os.Stat(filepath.Join(dir, f)) _, err := os.Stat(filepathext.SmartJoin(dir, f))
assert.Error(t, err) assert.Error(t, err)
} }
var buff bytes.Buffer var buff bytes.Buffer
e := task.Executor{ e := task.Executor{
Dir: dir, Dir: dir,
TempDir: filepath.Join(dir, ".task"), TempDir: filepathext.SmartJoin(dir, ".task"),
Stdout: &buff, Stdout: &buff,
Stderr: &buff, Stderr: &buff,
} }
@@ -432,7 +467,7 @@ func TestStatusChecksum(t *testing.T) {
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "build"})) assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "build"}))
for _, f := range files { for _, f := range files {
_, err := os.Stat(filepath.Join(dir, f)) _, err := os.Stat(filepathext.SmartJoin(dir, f))
assert.NoError(t, err) assert.NoError(t, err)
} }
@@ -576,13 +611,13 @@ func TestListCanListDescOnly(t *testing.T) {
func TestStatusVariables(t *testing.T) { func TestStatusVariables(t *testing.T) {
const dir = "testdata/status_vars" const dir = "testdata/status_vars"
_ = os.RemoveAll(filepath.Join(dir, ".task")) _ = os.RemoveAll(filepathext.SmartJoin(dir, ".task"))
_ = os.Remove(filepath.Join(dir, "generated.txt")) _ = os.Remove(filepathext.SmartJoin(dir, "generated.txt"))
var buff bytes.Buffer var buff bytes.Buffer
e := task.Executor{ e := task.Executor{
Dir: dir, Dir: dir,
TempDir: filepath.Join(dir, ".task"), TempDir: filepathext.SmartJoin(dir, ".task"),
Stdout: &buff, Stdout: &buff,
Stderr: &buff, Stderr: &buff,
Silent: false, Silent: false,
@@ -593,7 +628,7 @@ func TestStatusVariables(t *testing.T) {
assert.Contains(t, buff.String(), "d41d8cd98f00b204e9800998ecf8427e") assert.Contains(t, buff.String(), "d41d8cd98f00b204e9800998ecf8427e")
inf, err := os.Stat(filepath.Join(dir, "source.txt")) inf, err := os.Stat(filepathext.SmartJoin(dir, "source.txt"))
assert.NoError(t, err) assert.NoError(t, err)
ts := fmt.Sprintf("%d", inf.ModTime().Unix()) ts := fmt.Sprintf("%d", inf.ModTime().Unix())
tf := inf.ModTime().String() tf := inf.ModTime().String()
@@ -604,7 +639,7 @@ func TestStatusVariables(t *testing.T) {
func TestInit(t *testing.T) { func TestInit(t *testing.T) {
const dir = "testdata/init" const dir = "testdata/init"
var file = filepath.Join(dir, "Taskfile.yaml") var file = filepathext.SmartJoin(dir, "Taskfile.yaml")
_ = os.Remove(file) _ = os.Remove(file)
if _, err := os.Stat(file); err == nil { if _, err := os.Stat(file); err == nil {
@@ -693,7 +728,7 @@ func TestExpand(t *testing.T) {
func TestDry(t *testing.T) { func TestDry(t *testing.T) {
const dir = "testdata/dry" const dir = "testdata/dry"
file := filepath.Join(dir, "file.txt") file := filepathext.SmartJoin(dir, "file.txt")
_ = os.Remove(file) _ = os.Remove(file)
var buff bytes.Buffer var buff bytes.Buffer
@@ -718,12 +753,12 @@ func TestDry(t *testing.T) {
func TestDryChecksum(t *testing.T) { func TestDryChecksum(t *testing.T) {
const dir = "testdata/dry_checksum" const dir = "testdata/dry_checksum"
checksumFile := filepath.Join(dir, ".task/checksum/default") checksumFile := filepathext.SmartJoin(dir, ".task/checksum/default")
_ = os.Remove(checksumFile) _ = os.Remove(checksumFile)
e := task.Executor{ e := task.Executor{
Dir: dir, Dir: dir,
TempDir: filepath.Join(dir, ".task"), TempDir: filepathext.SmartJoin(dir, ".task"),
Stdout: io.Discard, Stdout: io.Discard,
Stderr: io.Discard, Stderr: io.Discard,
Dry: true, Dry: true,
@@ -774,7 +809,6 @@ func TestIncludesMultiLevel(t *testing.T) {
func TestIncludeCycle(t *testing.T) { func TestIncludeCycle(t *testing.T) {
const dir = "testdata/includes_cycle" 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 var buff bytes.Buffer
e := task.Executor{ e := task.Executor{
@@ -784,7 +818,9 @@ func TestIncludeCycle(t *testing.T) {
Silent: true, Silent: true,
} }
assert.EqualError(t, e.Setup(), expectedError) err := e.Setup()
assert.Error(t, err)
assert.Contains(t, err.Error(), "task: include cycle detected between")
} }
func TestIncorrectVersionIncludes(t *testing.T) { func TestIncorrectVersionIncludes(t *testing.T) {
@@ -852,27 +888,39 @@ func TestIncludesOptional(t *testing.T) {
} }
func TestIncludesOptionalImplicitFalse(t *testing.T) { func TestIncludesOptionalImplicitFalse(t *testing.T) {
const dir = "testdata/includes_optional_implicit_false"
wd, _ := os.Getwd()
message := "stat %s/%s/TaskfileOptional.yml: no such file or directory"
expected := fmt.Sprintf(message, wd, dir)
e := task.Executor{ e := task.Executor{
Dir: "testdata/includes_optional_implicit_false", Dir: dir,
Stdout: io.Discard, Stdout: io.Discard,
Stderr: io.Discard, Stderr: io.Discard,
} }
err := e.Setup() err := e.Setup()
assert.Error(t, err) assert.Error(t, err)
assert.Equal(t, "stat testdata/includes_optional_implicit_false/TaskfileOptional.yml: no such file or directory", err.Error()) assert.Equal(t, expected, err.Error())
} }
func TestIncludesOptionalExplicitFalse(t *testing.T) { func TestIncludesOptionalExplicitFalse(t *testing.T) {
const dir = "testdata/includes_optional_explicit_false"
wd, _ := os.Getwd()
message := "stat %s/%s/TaskfileOptional.yml: no such file or directory"
expected := fmt.Sprintf(message, wd, dir)
e := task.Executor{ e := task.Executor{
Dir: "testdata/includes_optional_explicit_false", Dir: dir,
Stdout: io.Discard, Stdout: io.Discard,
Stderr: io.Discard, Stderr: io.Discard,
} }
err := e.Setup() err := e.Setup()
assert.Error(t, err) assert.Error(t, err)
assert.Equal(t, "stat testdata/includes_optional_explicit_false/TaskfileOptional.yml: no such file or directory", err.Error()) assert.Equal(t, expected, err.Error())
} }
func TestIncludesFromCustomTaskfile(t *testing.T) { func TestIncludesFromCustomTaskfile(t *testing.T) {
@@ -890,6 +938,106 @@ func TestIncludesFromCustomTaskfile(t *testing.T) {
tt.Run(t) tt.Run(t)
} }
func TestIncludesRelativePath(t *testing.T) {
const dir = "testdata/includes_rel_path"
var buff bytes.Buffer
e := task.Executor{
Dir: dir,
Stdout: &buff,
Stderr: &buff,
}
assert.NoError(t, e.Setup())
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "common:pwd"}))
assert.Contains(t, buff.String(), "testdata/includes_rel_path/common")
buff.Reset()
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "included:common:pwd"}))
assert.Contains(t, buff.String(), "testdata/includes_rel_path/common")
}
func TestIncludesInternal(t *testing.T) {
const dir = "testdata/internal_task"
tests := []struct {
name string
task string
expectedErr bool
expectedOutput string
}{
{"included internal task via task", "task-1", false, "Hello, World!\n"},
{"included internal task via dep", "task-2", false, "Hello, World!\n"},
{
"included internal direct",
"included:task-3",
true,
"task: No tasks with description available. Try --list-all to list all tasks\n",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
var buff bytes.Buffer
e := task.Executor{
Dir: dir,
Stdout: &buff,
Stderr: &buff,
Silent: true,
}
assert.NoError(t, e.Setup())
err := e.Run(context.Background(), taskfile.Call{Task: test.task})
if test.expectedErr {
assert.Error(t, err, test.expectedErr)
} else {
assert.NoError(t, err)
}
assert.Equal(t, test.expectedOutput, buff.String())
})
}
}
func TestInternalTask(t *testing.T) {
const dir = "testdata/internal_task"
tests := []struct {
name string
task string
expectedErr bool
expectedOutput string
}{
{"internal task via task", "task-1", false, "Hello, World!\n"},
{"internal task via dep", "task-2", false, "Hello, World!\n"},
{
"internal direct",
"task-3",
true,
"task: No tasks with description available. Try --list-all to list all tasks\n",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
var buff bytes.Buffer
e := task.Executor{
Dir: dir,
Stdout: &buff,
Stderr: &buff,
Silent: true,
}
assert.NoError(t, e.Setup())
err := e.Run(context.Background(), taskfile.Call{Task: test.task})
if test.expectedErr {
assert.Error(t, err, test.expectedErr)
} else {
assert.NoError(t, err)
}
assert.Equal(t, test.expectedOutput, buff.String())
})
}
}
func TestSupportedFileNames(t *testing.T) { func TestSupportedFileNames(t *testing.T) {
fileNames := []string{ fileNames := []string{
"Taskfile.yml", "Taskfile.yml",
@@ -926,12 +1074,12 @@ func TestSummary(t *testing.T) {
assert.NoError(t, e.Setup()) assert.NoError(t, e.Setup())
assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "task-with-summary"}, taskfile.Call{Task: "other-task-with-summary"})) assert.NoError(t, e.Run(context.Background(), taskfile.Call{Task: "task-with-summary"}, taskfile.Call{Task: "other-task-with-summary"}))
data, err := os.ReadFile(filepath.Join(dir, "task-with-summary.txt")) data, err := os.ReadFile(filepathext.SmartJoin(dir, "task-with-summary.txt"))
assert.NoError(t, err) assert.NoError(t, err)
expectedOutput := string(data) expectedOutput := string(data)
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
expectedOutput = strings.Replace(expectedOutput, "\r\n", "\n", -1) expectedOutput = strings.ReplaceAll(expectedOutput, "\r\n", "\n")
} }
assert.Equal(t, expectedOutput, buff.String()) assert.Equal(t, expectedOutput, buff.String())
@@ -1299,3 +1447,36 @@ func TestErrorCode(t *testing.T) {
assert.True(t, ok, "cannot cast returned error to *task.TaskRunError") assert.True(t, ok, "cannot cast returned error to *task.TaskRunError")
assert.Equal(t, 42, casted.ExitCode(), "unexpected exit code from task") assert.Equal(t, 42, casted.ExitCode(), "unexpected exit code from task")
} }
func TestEvaluateSymlinksInPaths(t *testing.T) {
const dir = "testdata/evaluate_symlinks_in_paths"
var buff bytes.Buffer
e := &task.Executor{
Dir: dir,
Stdout: &buff,
Stderr: &buff,
Silent: false,
}
assert.NoError(t, e.Setup())
err := e.Run(context.Background(), taskfile.Call{Task: "default"})
assert.NoError(t, err)
assert.NotEqual(t, `task: Task "default" is up to date`, strings.TrimSpace(buff.String()))
buff.Reset()
err = e.Run(context.Background(), taskfile.Call{Task: "test-sym"})
assert.NoError(t, err)
assert.NotEqual(t, `task: Task "test-sym" is up to date`, strings.TrimSpace(buff.String()))
buff.Reset()
err = e.Run(context.Background(), taskfile.Call{Task: "default"})
assert.NoError(t, err)
assert.NotEqual(t, `task: Task "default" is up to date`, strings.TrimSpace(buff.String()))
buff.Reset()
err = e.Run(context.Background(), taskfile.Call{Task: "default"})
assert.NoError(t, err)
assert.Equal(t, `task: Task "default" is up to date`, strings.TrimSpace(buff.String()))
buff.Reset()
err = e.Run(context.Background(), taskfile.Call{Task: "reset"})
assert.NoError(t, err)
buff.Reset()
err = os.RemoveAll(dir + "/.task")
assert.NoError(t, err)
}

View File

@@ -2,17 +2,24 @@ package taskfile
import ( import (
"errors" "errors"
"fmt"
"path/filepath"
"github.com/go-task/task/v3/internal/execext"
"github.com/go-task/task/v3/internal/filepathext"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
// IncludedTaskfile represents information about included tasksfile // IncludedTaskfile represents information about included taskfiles
type IncludedTaskfile struct { type IncludedTaskfile struct {
Taskfile string Taskfile string
Dir string Dir string
Optional bool Optional bool
Internal bool
AdvancedImport bool AdvancedImport bool
Vars *Vars Vars *Vars
BaseDir string // The directory from which the including taskfile was loaded; used to resolve relative paths
} }
// IncludedTaskfiles represents information about included tasksfiles // IncludedTaskfiles represents information about included tasksfiles
@@ -95,6 +102,7 @@ func (it *IncludedTaskfile) UnmarshalYAML(unmarshal func(interface{}) error) err
Taskfile string Taskfile string
Dir string Dir string
Optional bool Optional bool
Internal bool
Vars *Vars Vars *Vars
} }
if err := unmarshal(&includedTaskfile); err != nil { if err := unmarshal(&includedTaskfile); err != nil {
@@ -103,7 +111,36 @@ func (it *IncludedTaskfile) UnmarshalYAML(unmarshal func(interface{}) error) err
it.Taskfile = includedTaskfile.Taskfile it.Taskfile = includedTaskfile.Taskfile
it.Dir = includedTaskfile.Dir it.Dir = includedTaskfile.Dir
it.Optional = includedTaskfile.Optional it.Optional = includedTaskfile.Optional
it.Internal = includedTaskfile.Internal
it.AdvancedImport = true it.AdvancedImport = true
it.Vars = includedTaskfile.Vars it.Vars = includedTaskfile.Vars
return nil return nil
} }
// FullTaskfilePath returns the fully qualified path to the included taskfile
func (it *IncludedTaskfile) FullTaskfilePath() (string, error) {
return it.resolvePath(it.Taskfile)
}
// FullDirPath returns the fully qualified path to the included taskfile's working directory
func (it *IncludedTaskfile) FullDirPath() (string, error) {
return it.resolvePath(it.Dir)
}
func (it *IncludedTaskfile) resolvePath(path string) (string, error) {
path, err := execext.Expand(path)
if err != nil {
return "", err
}
if filepath.IsAbs(path) {
return path, nil
}
result, err := filepath.Abs(filepathext.SmartJoin(it.BaseDir, path))
if err != nil {
return "", fmt.Errorf("task: error resolving path %s relative to %s: %w", path, it.BaseDir, err)
}
return result, nil
}

View File

@@ -9,7 +9,7 @@ import (
const NamespaceSeparator = ":" const NamespaceSeparator = ":"
// Merge merges the second Taskfile into the first // Merge merges the second Taskfile into the first
func Merge(t1, t2 *Taskfile, namespaces ...string) error { func Merge(t1, t2 *Taskfile, internal bool, namespaces ...string) error {
if t1.Version != t2.Version { if t1.Version != t2.Version {
return fmt.Errorf(`task: Taskfiles versions should match. First is "%s" but second is "%s"`, t1.Version, t2.Version) return fmt.Errorf(`task: Taskfiles versions should match. First is "%s" but second is "%s"`, t1.Version, t2.Version)
} }
@@ -43,6 +43,8 @@ func Merge(t1, t2 *Taskfile, namespaces ...string) error {
// have serious side-effects in the future, since we're editing // have serious side-effects in the future, since we're editing
// the original references instead of deep copying them. // the original references instead of deep copying them.
v.Internal = v.Internal || internal
t1.Tasks[taskNameWithNamespace(k, namespaces...)] = v t1.Tasks[taskNameWithNamespace(k, namespaces...)] = v
for _, dep := range v.Deps { for _, dep := range v.Deps {

View File

@@ -2,11 +2,11 @@ package read
import ( import (
"os" "os"
"path/filepath"
"github.com/joho/godotenv" "github.com/joho/godotenv"
"github.com/go-task/task/v3/internal/compiler" "github.com/go-task/task/v3/internal/compiler"
"github.com/go-task/task/v3/internal/filepathext"
"github.com/go-task/task/v3/internal/templater" "github.com/go-task/task/v3/internal/templater"
"github.com/go-task/task/v3/taskfile" "github.com/go-task/task/v3/taskfile"
) )
@@ -27,10 +27,11 @@ func Dotenv(c compiler.Compiler, tf *taskfile.Taskfile, dir string) (*taskfile.V
for _, dotEnvPath := range tf.Dotenv { for _, dotEnvPath := range tf.Dotenv {
dotEnvPath = tr.Replace(dotEnvPath) dotEnvPath = tr.Replace(dotEnvPath)
if dotEnvPath == "" {
if !filepath.IsAbs(dotEnvPath) { continue
dotEnvPath = filepath.Join(dir, dotEnvPath)
} }
dotEnvPath = filepathext.SmartJoin(dir, dotEnvPath)
if _, err := os.Stat(dotEnvPath); os.IsNotExist(err) { if _, err := os.Stat(dotEnvPath); os.IsNotExist(err) {
continue continue
} }

View File

@@ -9,7 +9,7 @@ import (
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"github.com/go-task/task/v3/internal/execext" "github.com/go-task/task/v3/internal/filepathext"
"github.com/go-task/task/v3/internal/templater" "github.com/go-task/task/v3/internal/templater"
"github.com/go-task/task/v3/taskfile" "github.com/go-task/task/v3/taskfile"
) )
@@ -44,7 +44,8 @@ func Taskfile(readerNode *ReaderNode) (*taskfile.Taskfile, error) {
} }
readerNode.Dir = d readerNode.Dir = d
} }
path, err := exists(filepath.Join(readerNode.Dir, readerNode.Entrypoint))
path, err := exists(filepathext.SmartJoin(readerNode.Dir, readerNode.Entrypoint))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -60,6 +61,16 @@ func Taskfile(readerNode *ReaderNode) (*taskfile.Taskfile, error) {
return nil, err return nil, err
} }
// Annotate any included Taskfile reference with a base directory for resolving relative paths
_ = t.Includes.Range(func(key string, includedFile taskfile.IncludedTaskfile) error {
// Set the base directory for resolving relative paths, but only if not already set
if includedFile.BaseDir == "" {
includedFile.BaseDir = readerNode.Dir
t.Includes.Set(key, includedFile)
}
return nil
})
err = t.Includes.Range(func(namespace string, includedTask taskfile.IncludedTaskfile) error { err = t.Includes.Range(func(namespace string, includedTask taskfile.IncludedTaskfile) error {
if v >= 3.0 { if v >= 3.0 {
tr := templater.Templater{Vars: &taskfile.Vars{}, RemoveNoValue: true} tr := templater.Templater{Vars: &taskfile.Vars{}, RemoveNoValue: true}
@@ -67,21 +78,21 @@ func Taskfile(readerNode *ReaderNode) (*taskfile.Taskfile, error) {
Taskfile: tr.Replace(includedTask.Taskfile), Taskfile: tr.Replace(includedTask.Taskfile),
Dir: tr.Replace(includedTask.Dir), Dir: tr.Replace(includedTask.Dir),
Optional: includedTask.Optional, Optional: includedTask.Optional,
Internal: includedTask.Internal,
AdvancedImport: includedTask.AdvancedImport, AdvancedImport: includedTask.AdvancedImport,
Vars: includedTask.Vars, Vars: includedTask.Vars,
BaseDir: includedTask.BaseDir,
} }
if err := tr.Err(); err != nil { if err := tr.Err(); err != nil {
return err return err
} }
} }
path, err := execext.Expand(includedTask.Taskfile) path, err := includedTask.FullTaskfilePath()
if err != nil { if err != nil {
return err return err
} }
if !filepath.IsAbs(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 {
@@ -114,27 +125,31 @@ func Taskfile(readerNode *ReaderNode) (*taskfile.Taskfile, error) {
} }
if includedTask.AdvancedImport { if includedTask.AdvancedImport {
dir, err := includedTask.FullDirPath()
if err != nil {
return err
}
for k, v := range includedTaskfile.Vars.Mapping { for k, v := range includedTaskfile.Vars.Mapping {
o := v o := v
o.Dir = filepath.Join(readerNode.Dir, includedTask.Dir) o.Dir = 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(readerNode.Dir, includedTask.Dir) o.Dir = dir
includedTaskfile.Env.Mapping[k] = o includedTaskfile.Env.Mapping[k] = o
} }
for _, task := range includedTaskfile.Tasks { for _, task := range includedTaskfile.Tasks {
if !filepath.IsAbs(task.Dir) { task.Dir = filepathext.SmartJoin(dir, task.Dir)
task.Dir = filepath.Join(includedTask.Dir, task.Dir)
}
task.IncludeVars = includedTask.Vars task.IncludeVars = includedTask.Vars
task.IncludedTaskfileVars = includedTaskfile.Vars task.IncludedTaskfileVars = includedTaskfile.Vars
task.IncludedTaskfile = &includedTask
} }
} }
if err = taskfile.Merge(t, includedTaskfile, namespace); err != nil { if err = taskfile.Merge(t, includedTaskfile, includedTask.Internal, namespace); err != nil {
return err return err
} }
return nil return nil
@@ -144,13 +159,13 @@ func Taskfile(readerNode *ReaderNode) (*taskfile.Taskfile, error) {
} }
if v < 3.0 { if v < 3.0 {
path = filepath.Join(readerNode.Dir, fmt.Sprintf("Taskfile_%s.yml", runtime.GOOS)) path = filepathext.SmartJoin(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 {
return nil, err return nil, err
} }
if err = taskfile.Merge(t, osTaskfile); err != nil { if err = taskfile.Merge(t, osTaskfile, false); err != nil {
return nil, err return nil, err
} }
} }
@@ -186,7 +201,7 @@ func exists(path string) (string, error) {
} }
for _, n := range defaultTaskfiles { for _, n := range defaultTaskfiles {
fpath := filepath.Join(path, n) fpath := filepathext.SmartJoin(path, n)
if _, err := os.Stat(fpath); err == nil { if _, err := os.Stat(fpath); err == nil {
return fpath, nil return fpath, nil
} }
@@ -203,14 +218,14 @@ func checkCircularIncludes(node *ReaderNode) error {
return errors.New("task: failed to check for include cycle: node.Parent was nil") return errors.New("task: failed to check for include cycle: node.Parent was nil")
} }
var curNode = node var curNode = node
var basePath = filepath.Join(node.Dir, node.Entrypoint) var basePath = filepathext.SmartJoin(node.Dir, node.Entrypoint)
for curNode.Parent != nil { for curNode.Parent != nil {
curNode = curNode.Parent curNode = curNode.Parent
curPath := filepath.Join(curNode.Dir, curNode.Entrypoint) curPath := filepathext.SmartJoin(curNode.Dir, curNode.Entrypoint)
if curPath == basePath { if curPath == basePath {
return fmt.Errorf("task: include cycle detected between %s <--> %s", return fmt.Errorf("task: include cycle detected between %s <--> %s",
curPath, curPath,
filepath.Join(node.Parent.Dir, node.Parent.Entrypoint), filepathext.SmartJoin(node.Parent.Dir, node.Parent.Entrypoint),
) )
} }
} }

View File

@@ -3,11 +3,11 @@ package read
import ( import (
"fmt" "fmt"
"os" "os"
"path/filepath"
"runtime" "runtime"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"github.com/go-task/task/v3/internal/filepathext"
"github.com/go-task/task/v3/taskfile" "github.com/go-task/task/v3/taskfile"
) )
@@ -15,7 +15,7 @@ import (
func Taskvars(dir string) (*taskfile.Vars, error) { func Taskvars(dir string) (*taskfile.Vars, error) {
vars := &taskfile.Vars{} vars := &taskfile.Vars{}
path := filepath.Join(dir, "Taskvars.yml") path := filepathext.SmartJoin(dir, "Taskvars.yml")
if _, err := os.Stat(path); err == nil { if _, err := os.Stat(path); err == nil {
vars, err = readTaskvars(path) vars, err = readTaskvars(path)
if err != nil { if err != nil {
@@ -23,7 +23,7 @@ func Taskvars(dir string) (*taskfile.Vars, error) {
} }
} }
path = filepath.Join(dir, fmt.Sprintf("Taskvars_%s.yml", runtime.GOOS)) path = filepathext.SmartJoin(dir, fmt.Sprintf("Taskvars_%s.yml", runtime.GOOS))
if _, err := os.Stat(path); err == nil { if _, err := os.Stat(path); err == nil {
osVars, err := readTaskvars(path) osVars, err := readTaskvars(path)
if err != nil { if err != nil {

View File

@@ -20,12 +20,14 @@ type Task struct {
Env *Vars Env *Vars
Silent bool Silent bool
Interactive bool Interactive bool
Internal bool
Method string Method string
Prefix string Prefix string
IgnoreError bool IgnoreError bool
Run string Run string
IncludeVars *Vars IncludeVars *Vars
IncludedTaskfileVars *Vars IncludedTaskfileVars *Vars
IncludedTaskfile *IncludedTaskfile
} }
func (t *Task) Name() string { func (t *Task) Name() string {
@@ -63,6 +65,7 @@ func (t *Task) UnmarshalYAML(unmarshal func(interface{}) error) error {
Env *Vars Env *Vars
Silent bool Silent bool
Interactive bool Interactive bool
Internal bool
Method string Method string
Prefix string Prefix string
IgnoreError bool `yaml:"ignore_error"` IgnoreError bool `yaml:"ignore_error"`
@@ -85,6 +88,7 @@ func (t *Task) UnmarshalYAML(unmarshal func(interface{}) error) error {
t.Env = task.Env t.Env = task.Env
t.Silent = task.Silent t.Silent = task.Silent
t.Interactive = task.Interactive t.Interactive = task.Interactive
t.Internal = task.Internal
t.Method = task.Method t.Method = task.Method
t.Prefix = task.Prefix t.Prefix = task.Prefix
t.IgnoreError = task.IgnoreError t.IgnoreError = task.IgnoreError

View File

@@ -0,0 +1,17 @@
version: '3'
tasks:
default:
sources:
- src/**/*
cmds:
- echo "some job"
test-sym:
cmds:
- echo "shared file source changed" > src/shared/b
reset:
cmds:
- echo "shared file source" > src/shared/b
- echo "file source" > src/a

View File

@@ -0,0 +1 @@
shared file source

View File

@@ -0,0 +1 @@
inner shared file source

View File

@@ -0,0 +1 @@
file source

View File

@@ -0,0 +1 @@
../shared

15
testdata/includes_internal/Taskfile.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
version: '3'
includes:
included:
taskfile: Taskfile2.yml
internal: true
tasks:
task-1:
cmds:
- task: included:default
task-2:
deps:
- included:default

View File

@@ -0,0 +1,6 @@
version: '3'
tasks:
task-3:
cmds:
- echo "Hello, World!"

10
testdata/includes_rel_path/Taskfile.yml vendored Normal file
View File

@@ -0,0 +1,10 @@
version: '3'
includes:
included:
taskfile: ./included
dir: ./included
common:
taskfile: ./common
dir: ./common

View File

@@ -0,0 +1,4 @@
version: '3'
tasks:
pwd: pwd

View File

@@ -0,0 +1,6 @@
version: '3'
includes:
common:
taskfile: ../common
dir: ../common

15
testdata/internal_task/Taskfile.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
version: '3'
tasks:
task-1:
cmds:
- task: task-3
task-2:
deps:
- task-3
task-3:
internal: true
cmds:
- echo "Hello, World!"

18
testdata/special_vars/Taskfile.yml vendored Normal file
View File

@@ -0,0 +1,18 @@
version: '3'
includes:
included:
taskfile: ./included
dir: ./included
tasks:
default:
cmds:
- task: print
- task: included:print
print:
cmds:
- echo root/TASK={{.TASK}}
- echo root/ROOT_DIR={{.ROOT_DIR}}
- echo root/TASKFILE_DIR={{.TASKFILE_DIR}}

View File

@@ -0,0 +1,8 @@
version: '3'
tasks:
print:
cmds:
- echo included/TASK={{.TASK}}
- echo included/ROOT_DIR={{.ROOT_DIR}}
- echo included/TASKFILE_DIR={{.TASKFILE_DIR}}

View File

@@ -1,10 +1,10 @@
package task package task
import ( import (
"path/filepath"
"strings" "strings"
"github.com/go-task/task/v3/internal/execext" "github.com/go-task/task/v3/internal/execext"
"github.com/go-task/task/v3/internal/filepathext"
"github.com/go-task/task/v3/internal/status" "github.com/go-task/task/v3/internal/status"
"github.com/go-task/task/v3/internal/templater" "github.com/go-task/task/v3/internal/templater"
"github.com/go-task/task/v3/taskfile" "github.com/go-task/task/v3/taskfile"
@@ -57,6 +57,7 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf
Env: nil, Env: nil,
Silent: origTask.Silent, Silent: origTask.Silent,
Interactive: origTask.Interactive, Interactive: origTask.Interactive,
Internal: origTask.Internal,
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,
@@ -68,8 +69,8 @@ func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskf
if err != nil { if err != nil {
return nil, err return nil, err
} }
if e.Dir != "" && !filepath.IsAbs(new.Dir) { if e.Dir != "" {
new.Dir = filepath.Join(e.Dir, new.Dir) new.Dir = filepathext.SmartJoin(e.Dir, new.Dir)
} }
if new.Prefix == "" { if new.Prefix == "" {
new.Prefix = new.Task new.Prefix = new.Task