mirror of
https://github.com/go-task/task.git
synced 2026-06-23 04:35:52 +00:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47d3011c85 | ||
|
|
cec713a47a | ||
|
|
bf6d0c0a74 | ||
|
|
c11672fca3 | ||
|
|
e086b654aa | ||
|
|
1107f691ea | ||
|
|
b095ca5756 | ||
|
|
4afc0e8ed0 | ||
|
|
141b377b4e | ||
|
|
402a478785 | ||
|
|
73680584f3 | ||
|
|
45dbbcd179 | ||
|
|
83d25bfa00 | ||
|
|
299e27af15 | ||
|
|
ec4cd5ed48 | ||
|
|
59d2733b88 | ||
|
|
cbdd088188 | ||
|
|
2d52485d7b | ||
|
|
d830178ef8 | ||
|
|
049984b4cc | ||
|
|
d261a986ab | ||
|
|
9b2e25735b | ||
|
|
e09e75b0ba | ||
|
|
6630113fef | ||
|
|
b2f08c9c20 | ||
|
|
6a4315b7e7 | ||
|
|
8b3e62ff6d | ||
|
|
f1d3f6740d | ||
|
|
9ccd1d920c | ||
|
|
9674d75ff6 | ||
|
|
22fd74846d | ||
|
|
777645888a | ||
|
|
ac8e344173 | ||
|
|
16fad60833 | ||
|
|
f5eb80759b | ||
|
|
bf88bd5da5 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -27,3 +27,4 @@ tags
|
|||||||
|
|
||||||
/bin
|
/bin
|
||||||
/testdata/vars/v1
|
/testdata/vars/v1
|
||||||
|
/tmp
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ build:
|
|||||||
goarch:
|
goarch:
|
||||||
- 386
|
- 386
|
||||||
- amd64
|
- amd64
|
||||||
|
- arm
|
||||||
|
- arm64
|
||||||
|
goarm:
|
||||||
|
- 6
|
||||||
ignore:
|
ignore:
|
||||||
- goos: darwin
|
- goos: darwin
|
||||||
goarch: 386
|
goarch: 386
|
||||||
|
|||||||
52
CHANGELOG.md
52
CHANGELOG.md
@@ -1,7 +1,59 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v3.2.2
|
||||||
|
|
||||||
|
- Improve performance of `--list` and `--summary` by skipping running shell
|
||||||
|
variables for these flags
|
||||||
|
([#332](https://github.com/go-task/task/issues/332)).
|
||||||
|
- Fixed a bug where an environment in a Taskfile was not always overridable
|
||||||
|
by the system environment
|
||||||
|
([#425](https://github.com/go-task/task/issues/425)).
|
||||||
|
- Fixed environment from .env files not being available as variables
|
||||||
|
([#379](https://github.com/go-task/task/issues/379)).
|
||||||
|
- The install script is now working for ARM platforms
|
||||||
|
([#428](https://github.com/go-task/task/pull/428)).
|
||||||
|
|
||||||
|
## v3.2.1
|
||||||
|
|
||||||
|
- Fixed some bugs and regressions regarding dynamic variables and directories
|
||||||
|
([#426](https://github.com/go-task/task/issues/426)).
|
||||||
|
- The [slim-sprig](https://github.com/go-task/slim-sprig) package was updated
|
||||||
|
with the upstream [sprig](https://github.com/Masterminds/sprig).
|
||||||
|
|
||||||
|
## v3.2.0
|
||||||
|
|
||||||
|
- Fix the `.task` directory being created in the task directory instead of the
|
||||||
|
Taskfile directory
|
||||||
|
([#247](https://github.com/go-task/task/issues/247)).
|
||||||
|
- Fix a bug where dynamic variables (those declared with `sh:`) were not
|
||||||
|
running in the task directory when the task has a custom dir or it was
|
||||||
|
in an included Taskfile
|
||||||
|
([#384](https://github.com/go-task/task/issues/384)).
|
||||||
|
- The watch feature (via the `--watch` flag) got a few different bug fixes and
|
||||||
|
should be more stable now
|
||||||
|
([#423](https://github.com/go-task/task/pull/423), [#365](https://github.com/go-task/task/issues/365)).
|
||||||
|
|
||||||
|
## v3.1.0
|
||||||
|
|
||||||
|
- Fix a bug when the checksum up-to-date resolution is used by a task
|
||||||
|
with a custom `label:` attribute
|
||||||
|
([#412](https://github.com/go-task/task/issues/412)).
|
||||||
|
- Starting from this release, we're releasing official ARMv6 and ARM64 binaries
|
||||||
|
for Linux
|
||||||
|
([#375](https://github.com/go-task/task/issues/375), [#418](https://github.com/go-task/task/issues/418)).
|
||||||
|
- Task now respects the order of declaration of included Taskfiles when
|
||||||
|
evaluating variables declaring by them
|
||||||
|
([#393](https://github.com/go-task/task/issues/393)).
|
||||||
|
- `set -e` is now automatically set on every command. This was done to fix an
|
||||||
|
issue where multiline string commands wouldn't really fail unless the
|
||||||
|
sentence was in the last line
|
||||||
|
([#403](https://github.com/go-task/task/issues/403)).
|
||||||
|
|
||||||
## v3.0.1
|
## v3.0.1
|
||||||
|
|
||||||
|
- Allow use as a library by moving the required packages out of the `internal`
|
||||||
|
directory
|
||||||
|
([#358](https://github.com/go-task/task/pull/358)).
|
||||||
- Do not error if a specified dotenv file does not exist
|
- Do not error if a specified dotenv file does not exist
|
||||||
([#378](https://github.com/go-task/task/issues/378), [#385](https://github.com/go-task/task/pull/385)).
|
([#378](https://github.com/go-task/task/issues/378), [#385](https://github.com/go-task/task/pull/385)).
|
||||||
- Fix panic when you have empty tasks in your Taskfile
|
- Fix panic when you have empty tasks in your Taskfile
|
||||||
|
|||||||
19
README.md
19
README.md
@@ -1,10 +1,15 @@
|
|||||||

|
<div align="center">
|
||||||

|
<a href="https://taskfile.dev">
|
||||||

|
<img src="docs/Logo.png" width="200px" height="200px" />
|
||||||
|
</a>
|
||||||
|
|
||||||
# Task
|
<h1>Task</h1>
|
||||||
|
|
||||||
Task is a task runner / build tool that aims to be simpler and easier to use
|
<p>
|
||||||
than, for example, [GNU Make](https://www.gnu.org/software/make/).
|
Task is a task runner / build tool that aims to be simpler and easier to use than, for example, <a href="https://www.gnu.org/software/make/">GNU Make<a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
See [taskfile.dev](https://taskfile.dev) for the documentation.
|
<p>
|
||||||
|
See <a href="https://taskfile.dev">taskfile.dev</a> for the documentation.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/args"
|
"github.com/go-task/task/v3/args"
|
||||||
"github.com/go-task/task/v3/taskfile"
|
"github.com/go-task/task/v3/taskfile"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestArgsV3(t *testing.T) {
|
func TestArgsV3(t *testing.T) {
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"github.com/go-task/task/v3"
|
"github.com/go-task/task/v3"
|
||||||
"github.com/go-task/task/v3/args"
|
"github.com/go-task/task/v3/args"
|
||||||
"github.com/go-task/task/v3/internal/logger"
|
"github.com/go-task/task/v3/internal/logger"
|
||||||
"github.com/go-task/task/v3/taskfile"
|
"github.com/go-task/task/v3/taskfile"
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
BIN
docs/Logo.png
Normal file
BIN
docs/Logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
@@ -1,5 +1,9 @@
|
|||||||
# Task
|
# Task
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<img id="logo" src="/Logo.png" height="250px" width="250px" />
|
||||||
|
</div>
|
||||||
|
|
||||||
Task is a task runner / build tool that aims to be simpler and easier to use
|
Task is a task runner / build tool that aims to be simpler and easier to use
|
||||||
than, for example, [GNU Make][make].
|
than, for example, [GNU Make][make].
|
||||||
|
|
||||||
|
|||||||
@@ -10,3 +10,8 @@ tasks:
|
|||||||
desc: Serves the documentation site locally
|
desc: Serves the documentation site locally
|
||||||
cmds:
|
cmds:
|
||||||
- docsify serve .
|
- docsify serve .
|
||||||
|
|
||||||
|
ico:
|
||||||
|
desc: Generate favicon.ico from Logo.png
|
||||||
|
cmds:
|
||||||
|
- convert -background transparent "Logo.png" -define icon:auto-resize=16,24,32,48,64,72,96,128,256 "favicon.ico"
|
||||||
|
|||||||
BIN
docs/favicon.ico
BIN
docs/favicon.ico
Binary file not shown.
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 170 KiB |
@@ -8,6 +8,19 @@
|
|||||||
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
||||||
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify-themeable/dist/css/theme-simple.css">
|
<link rel="stylesheet" href="//cdn.jsdelivr.net/npm/docsify-themeable/dist/css/theme-simple.css">
|
||||||
<meta name="google-site-verification" content="VGAYkbdmuaciIDGkBe-eAg9yfZg0C6ostgonbGxxOa0" />
|
<meta name="google-site-verification" content="VGAYkbdmuaciIDGkBe-eAg9yfZg0C6ostgonbGxxOa0" />
|
||||||
|
<style>
|
||||||
|
#logo {
|
||||||
|
transition: all 0.7s ease;
|
||||||
|
}
|
||||||
|
#logo:hover {
|
||||||
|
-webkit-transform: rotateZ(360deg);
|
||||||
|
-ms-transform: rotateZ(360deg);
|
||||||
|
transform: rotateZ(360deg);
|
||||||
|
}
|
||||||
|
.app-name-link img {
|
||||||
|
width: 125px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
@@ -15,7 +28,8 @@
|
|||||||
window.$docsify = {
|
window.$docsify = {
|
||||||
name: 'Task',
|
name: 'Task',
|
||||||
repo: 'go-task/task',
|
repo: 'go-task/task',
|
||||||
themeColor: '#00add8',
|
logo: 'Logo.png',
|
||||||
|
themeColor: '#29beb0',
|
||||||
loadSidebar: true,
|
loadSidebar: true,
|
||||||
auto2top: true,
|
auto2top: true,
|
||||||
maxLevel: 3,
|
maxLevel: 3,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -e
|
set -e
|
||||||
# Code generated by godownloader on 2018-04-07T17:47:38Z. DO NOT EDIT.
|
# Code generated by godownloader on 2021-01-12T13:40:40Z. DO NOT EDIT.
|
||||||
#
|
#
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
@@ -27,11 +27,12 @@ parse_args() {
|
|||||||
# over-ridden by flag below
|
# over-ridden by flag below
|
||||||
|
|
||||||
BINDIR=${BINDIR:-./bin}
|
BINDIR=${BINDIR:-./bin}
|
||||||
while getopts "b:dh?" arg; do
|
while getopts "b:dh?x" arg; do
|
||||||
case "$arg" in
|
case "$arg" in
|
||||||
b) BINDIR="$OPTARG" ;;
|
b) BINDIR="$OPTARG" ;;
|
||||||
d) log_set_priority 10 ;;
|
d) log_set_priority 10 ;;
|
||||||
h | \?) usage "$0" ;;
|
h | \?) usage "$0" ;;
|
||||||
|
x) set -x ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
shift $((OPTIND - 1))
|
shift $((OPTIND - 1))
|
||||||
@@ -42,46 +43,41 @@ parse_args() {
|
|||||||
# network, either nothing will happen or will syntax error
|
# network, either nothing will happen or will syntax error
|
||||||
# out preventing half-done work
|
# out preventing half-done work
|
||||||
execute() {
|
execute() {
|
||||||
tmpdir=$(mktmpdir)
|
tmpdir=$(mktemp -d)
|
||||||
log_debug "downloading files into ${tmpdir}"
|
log_debug "downloading files into ${tmpdir}"
|
||||||
http_download "${tmpdir}/${TARBALL}" "${TARBALL_URL}"
|
http_download "${tmpdir}/${TARBALL}" "${TARBALL_URL}"
|
||||||
http_download "${tmpdir}/${CHECKSUM}" "${CHECKSUM_URL}"
|
http_download "${tmpdir}/${CHECKSUM}" "${CHECKSUM_URL}"
|
||||||
hash_sha256_verify "${tmpdir}/${TARBALL}" "${tmpdir}/${CHECKSUM}"
|
hash_sha256_verify "${tmpdir}/${TARBALL}" "${tmpdir}/${CHECKSUM}"
|
||||||
srcdir="${tmpdir}"
|
srcdir="${tmpdir}"
|
||||||
(cd "${tmpdir}" && untar "${TARBALL}")
|
(cd "${tmpdir}" && untar "${TARBALL}")
|
||||||
install -d "${BINDIR}"
|
test ! -d "${BINDIR}" && install -d "${BINDIR}"
|
||||||
for binexe in "task" ; do
|
for binexe in $BINARIES; do
|
||||||
if [ "$OS" = "windows" ]; then
|
if [ "$OS" = "windows" ]; then
|
||||||
binexe="${binexe}.exe"
|
binexe="${binexe}.exe"
|
||||||
fi
|
fi
|
||||||
install "${srcdir}/${binexe}" "${BINDIR}/"
|
install "${srcdir}/${binexe}" "${BINDIR}/"
|
||||||
log_info "installed ${BINDIR}/${binexe}"
|
log_info "installed ${BINDIR}/${binexe}"
|
||||||
done
|
done
|
||||||
|
rm -rf "${tmpdir}"
|
||||||
}
|
}
|
||||||
is_supported_platform() {
|
get_binaries() {
|
||||||
platform=$1
|
case "$PLATFORM" in
|
||||||
found=1
|
darwin/amd64) BINARIES="task" ;;
|
||||||
case "$platform" in
|
darwin/arm64) BINARIES="task" ;;
|
||||||
windows/386) found=0 ;;
|
darwin/armv6) BINARIES="task" ;;
|
||||||
windows/amd64) found=0 ;;
|
linux/386) BINARIES="task" ;;
|
||||||
darwin/386) found=0 ;;
|
linux/amd64) BINARIES="task" ;;
|
||||||
darwin/amd64) found=0 ;;
|
linux/arm64) BINARIES="task" ;;
|
||||||
linux/386) found=0 ;;
|
linux/armv6) BINARIES="task" ;;
|
||||||
linux/amd64) found=0 ;;
|
windows/386) BINARIES="task" ;;
|
||||||
|
windows/amd64) BINARIES="task" ;;
|
||||||
|
windows/arm64) BINARIES="task" ;;
|
||||||
|
windows/armv6) BINARIES="task" ;;
|
||||||
|
*)
|
||||||
|
log_crit "platform $PLATFORM is not supported. Make sure this script is up-to-date and file request at https://github.com/${PREFIX}/issues/new"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
case "$platform" in
|
|
||||||
darwin/386) found=1 ;;
|
|
||||||
esac
|
|
||||||
return $found
|
|
||||||
}
|
|
||||||
check_platform() {
|
|
||||||
if is_supported_platform "$PLATFORM"; then
|
|
||||||
# optional logging goes here
|
|
||||||
true
|
|
||||||
else
|
|
||||||
log_crit "platform $PLATFORM is not supported. Make sure this script is up-to-date and file request at https://github.com/${PREFIX}/issues/new"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
tag_to_version() {
|
tag_to_version() {
|
||||||
if [ -z "${TAG}" ]; then
|
if [ -z "${TAG}" ]; then
|
||||||
@@ -99,8 +95,8 @@ tag_to_version() {
|
|||||||
VERSION=${TAG#v}
|
VERSION=${TAG#v}
|
||||||
}
|
}
|
||||||
adjust_format() {
|
adjust_format() {
|
||||||
# change format (tar.gz or zip) based on ARCH
|
# change format (tar.gz or zip) based on OS
|
||||||
case ${ARCH} in
|
case ${OS} in
|
||||||
windows) FORMAT=zip ;;
|
windows) FORMAT=zip ;;
|
||||||
esac
|
esac
|
||||||
true
|
true
|
||||||
@@ -174,7 +170,9 @@ log_crit() {
|
|||||||
uname_os() {
|
uname_os() {
|
||||||
os=$(uname -s | tr '[:upper:]' '[:lower:]')
|
os=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||||
case "$os" in
|
case "$os" in
|
||||||
msys_nt) os="windows" ;;
|
cygwin_nt*) os="windows" ;;
|
||||||
|
mingw*) os="windows" ;;
|
||||||
|
msys_nt*) os="windows" ;;
|
||||||
esac
|
esac
|
||||||
echo "$os"
|
echo "$os"
|
||||||
}
|
}
|
||||||
@@ -186,9 +184,9 @@ uname_arch() {
|
|||||||
i686) arch="386" ;;
|
i686) arch="386" ;;
|
||||||
i386) arch="386" ;;
|
i386) arch="386" ;;
|
||||||
aarch64) arch="arm64" ;;
|
aarch64) arch="arm64" ;;
|
||||||
armv5*) arch="arm5" ;;
|
armv5*) arch="armv5" ;;
|
||||||
armv6*) arch="arm6" ;;
|
armv6*) arch="armv6" ;;
|
||||||
armv7*) arch="arm7" ;;
|
armv7*) arch="armv7" ;;
|
||||||
esac
|
esac
|
||||||
echo ${arch}
|
echo ${arch}
|
||||||
}
|
}
|
||||||
@@ -234,8 +232,8 @@ uname_arch_check() {
|
|||||||
untar() {
|
untar() {
|
||||||
tarball=$1
|
tarball=$1
|
||||||
case "${tarball}" in
|
case "${tarball}" in
|
||||||
*.tar.gz | *.tgz) tar -xzf "${tarball}" ;;
|
*.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" ;;
|
||||||
*.tar) tar -xf "${tarball}" ;;
|
*.tar) tar --no-same-owner -xf "${tarball}" ;;
|
||||||
*.zip) unzip "${tarball}" ;;
|
*.zip) unzip "${tarball}" ;;
|
||||||
*)
|
*)
|
||||||
log_err "untar unknown archive format for ${tarball}"
|
log_err "untar unknown archive format for ${tarball}"
|
||||||
@@ -243,11 +241,6 @@ untar() {
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
mktmpdir() {
|
|
||||||
test -z "$TMPDIR" && TMPDIR="$(mktemp -d)"
|
|
||||||
mkdir -p "${TMPDIR}"
|
|
||||||
echo "${TMPDIR}"
|
|
||||||
}
|
|
||||||
http_download_curl() {
|
http_download_curl() {
|
||||||
local_file=$1
|
local_file=$1
|
||||||
source_url=$2
|
source_url=$2
|
||||||
@@ -368,7 +361,7 @@ uname_arch_check "$ARCH"
|
|||||||
|
|
||||||
parse_args "$@"
|
parse_args "$@"
|
||||||
|
|
||||||
check_platform
|
get_binaries
|
||||||
|
|
||||||
tag_to_version
|
tag_to_version
|
||||||
|
|
||||||
|
|||||||
@@ -269,16 +269,16 @@ attribute:
|
|||||||
version: '3'
|
version: '3'
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
main-task:
|
greet:
|
||||||
|
vars:
|
||||||
|
RECIPIENT: '{{default "World" .RECIPIENT}}'
|
||||||
cmds:
|
cmds:
|
||||||
- task: write-file
|
- echo "Hello, {{.RECIPIENT}}!"
|
||||||
vars: {FILE: "hello.txt", CONTENT: "Hello!"}
|
|
||||||
- task: write-file
|
|
||||||
vars: {FILE: "world.txt", CONTENT: "World!"}
|
|
||||||
|
|
||||||
write-file:
|
greet-pessimistically:
|
||||||
cmds:
|
cmds:
|
||||||
- echo "{{.CONTENT}}" > {{.FILE}}
|
- task: greet
|
||||||
|
vars: {RECIPIENT: "Cruel World"}
|
||||||
```
|
```
|
||||||
|
|
||||||
The above syntax is also supported in `deps`.
|
The above syntax is also supported in `deps`.
|
||||||
@@ -865,7 +865,7 @@ $ task default
|
|||||||
## Short task syntax
|
## Short task syntax
|
||||||
|
|
||||||
Starting on Task v3, you can now write tasks with a shorter syntax if they
|
Starting on Task v3, you can now write tasks with a shorter syntax if they
|
||||||
have the default settings (e.g. no custom `env:`, `vars:`, `silent:` , etc):
|
have the default settings (e.g. no custom `env:`, `vars:`, `desc:`, `silent:` , etc):
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
version: '3'
|
version: '3'
|
||||||
@@ -873,7 +873,7 @@ version: '3'
|
|||||||
tasks:
|
tasks:
|
||||||
build: go build -v -o ./app{{exeExt}} .
|
build: go build -v -o ./app{{exeExt}} .
|
||||||
|
|
||||||
build:
|
run:
|
||||||
- task: build
|
- task: build
|
||||||
- ./app{{exeExt}} -h localhost -p 8080
|
- ./app{{exeExt}} -h localhost -p 8080
|
||||||
```
|
```
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -2,7 +2,7 @@ module github.com/go-task/task/v3
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/fatih/color v1.7.0
|
github.com/fatih/color v1.7.0
|
||||||
github.com/go-task/slim-sprig v0.0.0-20200516131648-f9bac4e523eb
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0
|
||||||
github.com/joho/godotenv v1.3.0
|
github.com/joho/godotenv v1.3.0
|
||||||
github.com/mattn/go-colorable v0.1.2 // indirect
|
github.com/mattn/go-colorable v0.1.2 // indirect
|
||||||
github.com/mattn/go-zglob v0.0.1
|
github.com/mattn/go-zglob v0.0.1
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -8,8 +8,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20200516131648-f9bac4e523eb h1:/qbv1F67s6ehqX9mG23cJOeca3FWpOVKgtPfPUMAi0k=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20200516131648-f9bac4e523eb/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
|
||||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||||
|
|||||||
2
help.go
2
help.go
@@ -30,7 +30,7 @@ func (e *Executor) tasksWithDesc() (tasks []*taskfile.Task) {
|
|||||||
tasks = make([]*taskfile.Task, 0, len(e.Taskfile.Tasks))
|
tasks = make([]*taskfile.Task, 0, len(e.Taskfile.Tasks))
|
||||||
for _, task := range e.Taskfile.Tasks {
|
for _, task := range e.Taskfile.Tasks {
|
||||||
if task.Desc != "" {
|
if task.Desc != "" {
|
||||||
compiledTask, err := e.CompiledTask(taskfile.Call{Task: task.Task})
|
compiledTask, err := e.FastCompiledTask(taskfile.Call{Task: task.Task})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
task = compiledTask
|
task = compiledTask
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -e
|
set -e
|
||||||
# Code generated by godownloader on 2018-04-07T17:47:38Z. DO NOT EDIT.
|
# Code generated by godownloader on 2021-01-12T13:40:40Z. DO NOT EDIT.
|
||||||
#
|
#
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
@@ -27,11 +27,12 @@ parse_args() {
|
|||||||
# over-ridden by flag below
|
# over-ridden by flag below
|
||||||
|
|
||||||
BINDIR=${BINDIR:-./bin}
|
BINDIR=${BINDIR:-./bin}
|
||||||
while getopts "b:dh?" arg; do
|
while getopts "b:dh?x" arg; do
|
||||||
case "$arg" in
|
case "$arg" in
|
||||||
b) BINDIR="$OPTARG" ;;
|
b) BINDIR="$OPTARG" ;;
|
||||||
d) log_set_priority 10 ;;
|
d) log_set_priority 10 ;;
|
||||||
h | \?) usage "$0" ;;
|
h | \?) usage "$0" ;;
|
||||||
|
x) set -x ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
shift $((OPTIND - 1))
|
shift $((OPTIND - 1))
|
||||||
@@ -42,46 +43,41 @@ parse_args() {
|
|||||||
# network, either nothing will happen or will syntax error
|
# network, either nothing will happen or will syntax error
|
||||||
# out preventing half-done work
|
# out preventing half-done work
|
||||||
execute() {
|
execute() {
|
||||||
tmpdir=$(mktmpdir)
|
tmpdir=$(mktemp -d)
|
||||||
log_debug "downloading files into ${tmpdir}"
|
log_debug "downloading files into ${tmpdir}"
|
||||||
http_download "${tmpdir}/${TARBALL}" "${TARBALL_URL}"
|
http_download "${tmpdir}/${TARBALL}" "${TARBALL_URL}"
|
||||||
http_download "${tmpdir}/${CHECKSUM}" "${CHECKSUM_URL}"
|
http_download "${tmpdir}/${CHECKSUM}" "${CHECKSUM_URL}"
|
||||||
hash_sha256_verify "${tmpdir}/${TARBALL}" "${tmpdir}/${CHECKSUM}"
|
hash_sha256_verify "${tmpdir}/${TARBALL}" "${tmpdir}/${CHECKSUM}"
|
||||||
srcdir="${tmpdir}"
|
srcdir="${tmpdir}"
|
||||||
(cd "${tmpdir}" && untar "${TARBALL}")
|
(cd "${tmpdir}" && untar "${TARBALL}")
|
||||||
install -d "${BINDIR}"
|
test ! -d "${BINDIR}" && install -d "${BINDIR}"
|
||||||
for binexe in "task" ; do
|
for binexe in $BINARIES; do
|
||||||
if [ "$OS" = "windows" ]; then
|
if [ "$OS" = "windows" ]; then
|
||||||
binexe="${binexe}.exe"
|
binexe="${binexe}.exe"
|
||||||
fi
|
fi
|
||||||
install "${srcdir}/${binexe}" "${BINDIR}/"
|
install "${srcdir}/${binexe}" "${BINDIR}/"
|
||||||
log_info "installed ${BINDIR}/${binexe}"
|
log_info "installed ${BINDIR}/${binexe}"
|
||||||
done
|
done
|
||||||
|
rm -rf "${tmpdir}"
|
||||||
}
|
}
|
||||||
is_supported_platform() {
|
get_binaries() {
|
||||||
platform=$1
|
case "$PLATFORM" in
|
||||||
found=1
|
darwin/amd64) BINARIES="task" ;;
|
||||||
case "$platform" in
|
darwin/arm64) BINARIES="task" ;;
|
||||||
windows/386) found=0 ;;
|
darwin/armv6) BINARIES="task" ;;
|
||||||
windows/amd64) found=0 ;;
|
linux/386) BINARIES="task" ;;
|
||||||
darwin/386) found=0 ;;
|
linux/amd64) BINARIES="task" ;;
|
||||||
darwin/amd64) found=0 ;;
|
linux/arm64) BINARIES="task" ;;
|
||||||
linux/386) found=0 ;;
|
linux/armv6) BINARIES="task" ;;
|
||||||
linux/amd64) found=0 ;;
|
windows/386) BINARIES="task" ;;
|
||||||
|
windows/amd64) BINARIES="task" ;;
|
||||||
|
windows/arm64) BINARIES="task" ;;
|
||||||
|
windows/armv6) BINARIES="task" ;;
|
||||||
|
*)
|
||||||
|
log_crit "platform $PLATFORM is not supported. Make sure this script is up-to-date and file request at https://github.com/${PREFIX}/issues/new"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
case "$platform" in
|
|
||||||
darwin/386) found=1 ;;
|
|
||||||
esac
|
|
||||||
return $found
|
|
||||||
}
|
|
||||||
check_platform() {
|
|
||||||
if is_supported_platform "$PLATFORM"; then
|
|
||||||
# optional logging goes here
|
|
||||||
true
|
|
||||||
else
|
|
||||||
log_crit "platform $PLATFORM is not supported. Make sure this script is up-to-date and file request at https://github.com/${PREFIX}/issues/new"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
tag_to_version() {
|
tag_to_version() {
|
||||||
if [ -z "${TAG}" ]; then
|
if [ -z "${TAG}" ]; then
|
||||||
@@ -99,8 +95,8 @@ tag_to_version() {
|
|||||||
VERSION=${TAG#v}
|
VERSION=${TAG#v}
|
||||||
}
|
}
|
||||||
adjust_format() {
|
adjust_format() {
|
||||||
# change format (tar.gz or zip) based on ARCH
|
# change format (tar.gz or zip) based on OS
|
||||||
case ${ARCH} in
|
case ${OS} in
|
||||||
windows) FORMAT=zip ;;
|
windows) FORMAT=zip ;;
|
||||||
esac
|
esac
|
||||||
true
|
true
|
||||||
@@ -174,7 +170,9 @@ log_crit() {
|
|||||||
uname_os() {
|
uname_os() {
|
||||||
os=$(uname -s | tr '[:upper:]' '[:lower:]')
|
os=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||||
case "$os" in
|
case "$os" in
|
||||||
msys_nt) os="windows" ;;
|
cygwin_nt*) os="windows" ;;
|
||||||
|
mingw*) os="windows" ;;
|
||||||
|
msys_nt*) os="windows" ;;
|
||||||
esac
|
esac
|
||||||
echo "$os"
|
echo "$os"
|
||||||
}
|
}
|
||||||
@@ -186,9 +184,9 @@ uname_arch() {
|
|||||||
i686) arch="386" ;;
|
i686) arch="386" ;;
|
||||||
i386) arch="386" ;;
|
i386) arch="386" ;;
|
||||||
aarch64) arch="arm64" ;;
|
aarch64) arch="arm64" ;;
|
||||||
armv5*) arch="arm5" ;;
|
armv5*) arch="armv5" ;;
|
||||||
armv6*) arch="arm6" ;;
|
armv6*) arch="armv6" ;;
|
||||||
armv7*) arch="arm7" ;;
|
armv7*) arch="armv7" ;;
|
||||||
esac
|
esac
|
||||||
echo ${arch}
|
echo ${arch}
|
||||||
}
|
}
|
||||||
@@ -234,8 +232,8 @@ uname_arch_check() {
|
|||||||
untar() {
|
untar() {
|
||||||
tarball=$1
|
tarball=$1
|
||||||
case "${tarball}" in
|
case "${tarball}" in
|
||||||
*.tar.gz | *.tgz) tar -xzf "${tarball}" ;;
|
*.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" ;;
|
||||||
*.tar) tar -xf "${tarball}" ;;
|
*.tar) tar --no-same-owner -xf "${tarball}" ;;
|
||||||
*.zip) unzip "${tarball}" ;;
|
*.zip) unzip "${tarball}" ;;
|
||||||
*)
|
*)
|
||||||
log_err "untar unknown archive format for ${tarball}"
|
log_err "untar unknown archive format for ${tarball}"
|
||||||
@@ -243,11 +241,6 @@ untar() {
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
mktmpdir() {
|
|
||||||
test -z "$TMPDIR" && TMPDIR="$(mktemp -d)"
|
|
||||||
mkdir -p "${TMPDIR}"
|
|
||||||
echo "${TMPDIR}"
|
|
||||||
}
|
|
||||||
http_download_curl() {
|
http_download_curl() {
|
||||||
local_file=$1
|
local_file=$1
|
||||||
source_url=$2
|
source_url=$2
|
||||||
@@ -368,7 +361,7 @@ uname_arch_check "$ARCH"
|
|||||||
|
|
||||||
parse_args "$@"
|
parse_args "$@"
|
||||||
|
|
||||||
check_platform
|
get_binaries
|
||||||
|
|
||||||
tag_to_version
|
tag_to_version
|
||||||
|
|
||||||
|
|||||||
@@ -8,5 +8,7 @@ import (
|
|||||||
// E.g. variable merger, template processing, etc.
|
// E.g. variable merger, template processing, etc.
|
||||||
type Compiler interface {
|
type Compiler interface {
|
||||||
GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error)
|
GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error)
|
||||||
HandleDynamicVar(v taskfile.Var) (string, error)
|
FastGetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error)
|
||||||
|
HandleDynamicVar(v taskfile.Var, dir string) (string, error)
|
||||||
|
ResetCache()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,11 @@ type CompilerV2 struct {
|
|||||||
muDynamicCache sync.Mutex
|
muDynamicCache sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FastGetVariables is a no-op on v2
|
||||||
|
func (c *CompilerV2) FastGetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) {
|
||||||
|
return c.GetVariables(t, call)
|
||||||
|
}
|
||||||
|
|
||||||
// GetVariables returns fully resolved variables following the priority order:
|
// GetVariables returns fully resolved variables following the priority order:
|
||||||
// 1. Task variables
|
// 1. Task variables
|
||||||
// 2. Call variables
|
// 2. Call variables
|
||||||
@@ -37,8 +42,12 @@ type CompilerV2 struct {
|
|||||||
// 4. Taskvars file variables
|
// 4. Taskvars file variables
|
||||||
// 5. Environment variables
|
// 5. Environment variables
|
||||||
func (c *CompilerV2) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) {
|
func (c *CompilerV2) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) {
|
||||||
vr := varResolver{c: c, vars: compiler.GetEnviron()}
|
vr := varResolver{
|
||||||
|
c: c,
|
||||||
|
vars: compiler.GetEnviron(),
|
||||||
|
}
|
||||||
vr.vars.Set("TASK", taskfile.Var{Static: t.Task})
|
vr.vars.Set("TASK", taskfile.Var{Static: t.Task})
|
||||||
|
|
||||||
for _, vars := range []*taskfile.Vars{c.Taskvars, c.TaskfileVars, call.Vars, t.Vars} {
|
for _, vars := range []*taskfile.Vars{c.Taskvars, c.TaskfileVars, call.Vars, t.Vars} {
|
||||||
for i := 0; i < c.Expansions; i++ {
|
for i := 0; i < c.Expansions; i++ {
|
||||||
vr.merge(vars)
|
vr.merge(vars)
|
||||||
@@ -63,7 +72,7 @@ func (vr *varResolver) merge(vars *taskfile.Vars) {
|
|||||||
Static: tr.Replace(v.Static),
|
Static: tr.Replace(v.Static),
|
||||||
Sh: tr.Replace(v.Sh),
|
Sh: tr.Replace(v.Sh),
|
||||||
}
|
}
|
||||||
static, err := vr.c.HandleDynamicVar(v)
|
static, err := vr.c.HandleDynamicVar(v, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
vr.err = err
|
vr.err = err
|
||||||
return err
|
return err
|
||||||
@@ -74,7 +83,7 @@ func (vr *varResolver) merge(vars *taskfile.Vars) {
|
|||||||
vr.err = tr.Err()
|
vr.err = tr.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CompilerV2) HandleDynamicVar(v taskfile.Var) (string, error) {
|
func (c *CompilerV2) HandleDynamicVar(v taskfile.Var, _ string) (string, error) {
|
||||||
if v.Static != "" || v.Sh == "" {
|
if v.Static != "" || v.Sh == "" {
|
||||||
return v.Static, nil
|
return v.Static, nil
|
||||||
}
|
}
|
||||||
@@ -92,7 +101,6 @@ func (c *CompilerV2) HandleDynamicVar(v taskfile.Var) (string, error) {
|
|||||||
var stdout bytes.Buffer
|
var stdout bytes.Buffer
|
||||||
opts := &execext.RunCommandOptions{
|
opts := &execext.RunCommandOptions{
|
||||||
Command: v.Sh,
|
Command: v.Sh,
|
||||||
Dir: c.Dir,
|
|
||||||
Stdout: &stdout,
|
Stdout: &stdout,
|
||||||
Stderr: c.Logger.Stderr,
|
Stderr: c.Logger.Stderr,
|
||||||
}
|
}
|
||||||
@@ -109,3 +117,11 @@ func (c *CompilerV2) HandleDynamicVar(v taskfile.Var) (string, error) {
|
|||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResetCache clear the dymanic variables cache
|
||||||
|
func (c *CompilerV2) ResetCache() {
|
||||||
|
c.muDynamicCache.Lock()
|
||||||
|
defer c.muDynamicCache.Unlock()
|
||||||
|
|
||||||
|
c.dynamicCache = nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ var _ compiler.Compiler = &CompilerV3{}
|
|||||||
type CompilerV3 struct {
|
type CompilerV3 struct {
|
||||||
Dir string
|
Dir string
|
||||||
|
|
||||||
|
TaskfileEnv *taskfile.Vars
|
||||||
TaskfileVars *taskfile.Vars
|
TaskfileVars *taskfile.Vars
|
||||||
|
|
||||||
Logger *logger.Logger
|
Logger *logger.Logger
|
||||||
@@ -28,40 +30,74 @@ type CompilerV3 struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *CompilerV3) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) {
|
func (c *CompilerV3) GetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) {
|
||||||
|
return c.getVariables(t, call, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CompilerV3) FastGetVariables(t *taskfile.Task, call taskfile.Call) (*taskfile.Vars, error) {
|
||||||
|
return c.getVariables(t, call, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CompilerV3) getVariables(t *taskfile.Task, call taskfile.Call, evaluateShVars bool) (*taskfile.Vars, error) {
|
||||||
result := compiler.GetEnviron()
|
result := compiler.GetEnviron()
|
||||||
result.Set("TASK", taskfile.Var{Static: t.Task})
|
result.Set("TASK", taskfile.Var{Static: t.Task})
|
||||||
|
|
||||||
rangeFunc := func(k string, v taskfile.Var) error {
|
getRangeFunc := func(dir string) func(k string, v taskfile.Var) error {
|
||||||
tr := templater.Templater{Vars: result, RemoveNoValue: true}
|
return func(k string, v taskfile.Var) error {
|
||||||
v = taskfile.Var{
|
tr := templater.Templater{Vars: result, RemoveNoValue: true}
|
||||||
Static: tr.Replace(v.Static),
|
|
||||||
Sh: tr.Replace(v.Sh),
|
|
||||||
}
|
|
||||||
if err := tr.Err(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
static, err := c.HandleDynamicVar(v)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
result.Set(k, taskfile.Var{Static: static})
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if !evaluateShVars {
|
||||||
|
result.Set(k, taskfile.Var{Static: tr.Replace(v.Static)})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
v = taskfile.Var{
|
||||||
|
Static: tr.Replace(v.Static),
|
||||||
|
Sh: tr.Replace(v.Sh),
|
||||||
|
Dir: v.Dir,
|
||||||
|
}
|
||||||
|
if err := tr.Err(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
static, err := c.HandleDynamicVar(v, dir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
result.Set(k, taskfile.Var{Static: static})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rangeFunc := getRangeFunc(c.Dir)
|
||||||
|
|
||||||
|
if err := c.TaskfileEnv.Range(rangeFunc); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if err := c.TaskfileVars.Range(rangeFunc); err != nil {
|
if err := c.TaskfileVars.Range(rangeFunc); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := call.Vars.Range(rangeFunc); err != nil {
|
if err := call.Vars.Range(rangeFunc); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := t.Vars.Range(rangeFunc); err != nil {
|
|
||||||
|
// NOTE(@andreynering): We're manually joining these paths here because
|
||||||
|
// this is the raw task, not the compiled one.
|
||||||
|
tr := templater.Templater{Vars: result, RemoveNoValue: true}
|
||||||
|
dir := tr.Replace(t.Dir)
|
||||||
|
if err := tr.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !filepath.IsAbs(dir) {
|
||||||
|
dir = filepath.Join(c.Dir, dir)
|
||||||
|
}
|
||||||
|
taskRangeFunc := getRangeFunc(dir)
|
||||||
|
|
||||||
|
if err := t.Vars.Range(taskRangeFunc); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CompilerV3) HandleDynamicVar(v taskfile.Var) (string, error) {
|
func (c *CompilerV3) HandleDynamicVar(v taskfile.Var, dir string) (string, error) {
|
||||||
if v.Static != "" || v.Sh == "" {
|
if v.Static != "" || v.Sh == "" {
|
||||||
return v.Static, nil
|
return v.Static, nil
|
||||||
}
|
}
|
||||||
@@ -76,10 +112,15 @@ func (c *CompilerV3) HandleDynamicVar(v taskfile.Var) (string, error) {
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE(@andreynering): If a var have a specific dir, use this instead
|
||||||
|
if v.Dir != "" {
|
||||||
|
dir = v.Dir
|
||||||
|
}
|
||||||
|
|
||||||
var stdout bytes.Buffer
|
var stdout bytes.Buffer
|
||||||
opts := &execext.RunCommandOptions{
|
opts := &execext.RunCommandOptions{
|
||||||
Command: v.Sh,
|
Command: v.Sh,
|
||||||
Dir: c.Dir,
|
Dir: dir,
|
||||||
Stdout: &stdout,
|
Stdout: &stdout,
|
||||||
Stderr: c.Logger.Stderr,
|
Stderr: c.Logger.Stderr,
|
||||||
}
|
}
|
||||||
@@ -96,3 +137,11 @@ func (c *CompilerV3) HandleDynamicVar(v taskfile.Var) (string, error) {
|
|||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResetCache clear the dymanic variables cache
|
||||||
|
func (c *CompilerV3) ResetCache() {
|
||||||
|
c.muDynamicCache.Lock()
|
||||||
|
defer c.muDynamicCache.Unlock()
|
||||||
|
|
||||||
|
c.dynamicCache = nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -46,16 +46,10 @@ func RunCommand(ctx context.Context, opts *RunCommandOptions) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
r, err := interp.New(
|
r, err := interp.New(
|
||||||
|
interp.Params("-e"),
|
||||||
interp.Dir(opts.Dir),
|
interp.Dir(opts.Dir),
|
||||||
interp.Env(expand.ListEnviron(environ...)),
|
interp.Env(expand.ListEnviron(environ...)),
|
||||||
|
interp.OpenHandler(openHandler),
|
||||||
interp.OpenHandler(func(ctx context.Context, path string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) {
|
|
||||||
if path == "/dev/null" {
|
|
||||||
return devNull{}, nil
|
|
||||||
}
|
|
||||||
return interp.DefaultOpenHandler()(ctx, path, flag, perm)
|
|
||||||
}),
|
|
||||||
|
|
||||||
interp.StdIO(opts.Stdin, opts.Stdout, opts.Stderr),
|
interp.StdIO(opts.Stdin, opts.Stdout, opts.Stderr),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -86,3 +80,10 @@ func Expand(s string) (string, error) {
|
|||||||
}
|
}
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func openHandler(ctx context.Context, path string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) {
|
||||||
|
if path == "/dev/null" {
|
||||||
|
return devNull{}, nil
|
||||||
|
}
|
||||||
|
return interp.DefaultOpenHandler()(ctx, path, flag, perm)
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/internal/output"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v3/internal/output"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInterleaved(t *testing.T) {
|
func TestInterleaved(t *testing.T) {
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ import (
|
|||||||
// Checksum validades if a task is up to date by calculating its source
|
// Checksum validades if a task is up to date by calculating its source
|
||||||
// files checksum
|
// files checksum
|
||||||
type Checksum struct {
|
type Checksum struct {
|
||||||
Dir string
|
BaseDir string
|
||||||
|
TaskDir string
|
||||||
Task string
|
Task string
|
||||||
Sources []string
|
Sources []string
|
||||||
Generates []string
|
Generates []string
|
||||||
@@ -32,7 +33,7 @@ func (c *Checksum) IsUpToDate() (bool, error) {
|
|||||||
data, _ := ioutil.ReadFile(checksumFile)
|
data, _ := ioutil.ReadFile(checksumFile)
|
||||||
oldMd5 := strings.TrimSpace(string(data))
|
oldMd5 := strings.TrimSpace(string(data))
|
||||||
|
|
||||||
sources, err := globs(c.Dir, c.Sources)
|
sources, err := globs(c.TaskDir, c.Sources)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@@ -43,7 +44,7 @@ func (c *Checksum) IsUpToDate() (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !c.Dry {
|
if !c.Dry {
|
||||||
_ = os.MkdirAll(filepath.Join(c.Dir, ".task", "checksum"), 0755)
|
_ = os.MkdirAll(filepath.Join(c.BaseDir, ".task", "checksum"), 0755)
|
||||||
if err = ioutil.WriteFile(checksumFile, []byte(newMd5+"\n"), 0644); err != nil {
|
if err = ioutil.WriteFile(checksumFile, []byte(newMd5+"\n"), 0644); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@@ -52,7 +53,7 @@ func (c *Checksum) IsUpToDate() (bool, error) {
|
|||||||
if len(c.Generates) > 0 {
|
if len(c.Generates) > 0 {
|
||||||
// For each specified 'generates' field, check whether the files actually exist
|
// For each specified 'generates' field, check whether the files actually exist
|
||||||
for _, g := range c.Generates {
|
for _, g := range c.Generates {
|
||||||
generates, err := glob(c.Dir, g)
|
generates, err := glob(c.TaskDir, g)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
@@ -107,7 +108,7 @@ func (*Checksum) Kind() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Checksum) checksumFilePath() string {
|
func (c *Checksum) checksumFilePath() string {
|
||||||
return filepath.Join(c.Dir, ".task", "checksum", c.normalizeFilename(c.Task))
|
return filepath.Join(c.BaseDir, ".task", "checksum", c.normalizeFilename(c.Task))
|
||||||
}
|
}
|
||||||
|
|
||||||
var checksumFilenameRegexp = regexp.MustCompile("[^A-z0-9]")
|
var checksumFilenameRegexp = regexp.MustCompile("[^A-z0-9]")
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/internal/execext"
|
|
||||||
|
|
||||||
"github.com/mattn/go-zglob"
|
"github.com/mattn/go-zglob"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v3/internal/execext"
|
||||||
)
|
)
|
||||||
|
|
||||||
func globs(dir string, globs []string) ([]string, error) {
|
func globs(dir string, globs []string) ([]string, error) {
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/internal/logger"
|
"github.com/go-task/task/v3/internal/logger"
|
||||||
"github.com/go-task/task/v3/internal/summary"
|
"github.com/go-task/task/v3/internal/summary"
|
||||||
"github.com/go-task/task/v3/taskfile"
|
"github.com/go-task/task/v3/taskfile"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPrintsDependenciesIfPresent(t *testing.T) {
|
func TestPrintsDependenciesIfPresent(t *testing.T) {
|
||||||
|
|||||||
@@ -76,8 +76,9 @@ func (e *Executor) timestampChecker(t *taskfile.Task) status.Checker {
|
|||||||
|
|
||||||
func (e *Executor) checksumChecker(t *taskfile.Task) status.Checker {
|
func (e *Executor) checksumChecker(t *taskfile.Task) status.Checker {
|
||||||
return &status.Checksum{
|
return &status.Checksum{
|
||||||
Dir: t.Dir,
|
BaseDir: e.Dir,
|
||||||
Task: t.Task,
|
TaskDir: t.Dir,
|
||||||
|
Task: t.Name(),
|
||||||
Sources: t.Sources,
|
Sources: t.Sources,
|
||||||
Generates: t.Generates,
|
Generates: t.Generates,
|
||||||
Dry: e.Dry,
|
Dry: e.Dry,
|
||||||
|
|||||||
24
task.go
24
task.go
@@ -71,7 +71,7 @@ func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error {
|
|||||||
|
|
||||||
if e.Summary {
|
if e.Summary {
|
||||||
for i, c := range calls {
|
for i, c := range calls {
|
||||||
compiledTask, err := e.CompiledTask(c)
|
compiledTask, err := e.FastCompiledTask(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -168,6 +168,7 @@ func (e *Executor) Setup() error {
|
|||||||
} else {
|
} else {
|
||||||
e.Compiler = &compilerv3.CompilerV3{
|
e.Compiler = &compilerv3.CompilerV3{
|
||||||
Dir: e.Dir,
|
Dir: e.Dir,
|
||||||
|
TaskfileEnv: e.Taskfile.Env,
|
||||||
TaskfileVars: e.Taskfile.Vars,
|
TaskfileVars: e.Taskfile.Vars,
|
||||||
Logger: e.Logger,
|
Logger: e.Logger,
|
||||||
}
|
}
|
||||||
@@ -176,7 +177,7 @@ func (e *Executor) Setup() error {
|
|||||||
if v < 2.1 && e.Taskfile.Output != "" {
|
if v < 2.1 && e.Taskfile.Output != "" {
|
||||||
return fmt.Errorf(`task: Taskfile option "output" is only available starting on Taskfile version v2.1`)
|
return fmt.Errorf(`task: Taskfile option "output" is only available starting on Taskfile version v2.1`)
|
||||||
}
|
}
|
||||||
if v < 2.2 && len(e.Taskfile.Includes) > 0 {
|
if v < 2.2 && e.Taskfile.Includes.Len() > 0 {
|
||||||
return fmt.Errorf(`task: Including Taskfiles is only available starting on Taskfile version v2.2`)
|
return fmt.Errorf(`task: Including Taskfiles is only available starting on Taskfile version v2.2`)
|
||||||
}
|
}
|
||||||
if v >= 3.0 && e.Taskfile.Expansions > 2 {
|
if v >= 3.0 && e.Taskfile.Expansions > 2 {
|
||||||
@@ -229,10 +230,14 @@ func (e *Executor) Setup() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if v < 3 {
|
if v < 3 {
|
||||||
for _, taskfile := range e.Taskfile.Includes {
|
err := e.Taskfile.Includes.Range(func(_ string, taskfile taskfile.IncludedTaskfile) error {
|
||||||
if taskfile.AdvancedImport {
|
if taskfile.AdvancedImport {
|
||||||
return errors.New(`task: Import with additional parameters is only available starting on Taskfile version v3`)
|
return errors.New(`task: Import with additional parameters is only available starting on Taskfile version v3`)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,10 +397,19 @@ func getEnviron(t *taskfile.Task) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
environ := os.Environ()
|
environ := os.Environ()
|
||||||
|
|
||||||
for k, v := range t.Env.ToCacheMap() {
|
for k, v := range t.Env.ToCacheMap() {
|
||||||
if s, ok := v.(string); ok {
|
str, isString := v.(string)
|
||||||
environ = append(environ, fmt.Sprintf("%s=%s", k, s))
|
if !isString {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, alreadySet := os.LookupEnv(k); alreadySet {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
environ = append(environ, fmt.Sprintf("%s=%s", k, str))
|
||||||
}
|
}
|
||||||
|
|
||||||
return environ
|
return environ
|
||||||
}
|
}
|
||||||
|
|||||||
41
task_test.go
41
task_test.go
@@ -11,10 +11,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/go-task/task/v3"
|
"github.com/go-task/task/v3"
|
||||||
"github.com/go-task/task/v3/taskfile"
|
"github.com/go-task/task/v3/taskfile"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// fileContentTest provides a basic reusable test-case for running a Taskfile
|
// fileContentTest provides a basic reusable test-case for running a Taskfile
|
||||||
@@ -126,6 +126,7 @@ func TestVarsV3(t *testing.T) {
|
|||||||
"var-order.txt": "ABCDEF\n",
|
"var-order.txt": "ABCDEF\n",
|
||||||
"dependent-sh.txt": "123456\n",
|
"dependent-sh.txt": "123456\n",
|
||||||
"with-call.txt": "Hi, ABC123!\n",
|
"with-call.txt": "Hi, ABC123!\n",
|
||||||
|
"from-dot-env.txt": "From .env file\n",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
tt.Run(t)
|
tt.Run(t)
|
||||||
@@ -303,6 +304,8 @@ func TestPrecondition(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerates(t *testing.T) {
|
func TestGenerates(t *testing.T) {
|
||||||
|
const dir = "testdata/generates"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
srcTask = "sub/src.txt"
|
srcTask = "sub/src.txt"
|
||||||
relTask = "rel.txt"
|
relTask = "rel.txt"
|
||||||
@@ -310,9 +313,6 @@ func TestGenerates(t *testing.T) {
|
|||||||
fileWithSpaces = "my text file.txt"
|
fileWithSpaces = "my text file.txt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This test does not work with a relative dir.
|
|
||||||
dir, err := filepath.Abs("testdata/generates")
|
|
||||||
assert.NoError(t, err)
|
|
||||||
var srcFile = filepath.Join(dir, srcTask)
|
var srcFile = filepath.Join(dir, srcTask)
|
||||||
|
|
||||||
for _, task := range []string{srcTask, relTask, absTask, fileWithSpaces} {
|
for _, task := range []string{srcTask, relTask, absTask, fileWithSpaces} {
|
||||||
@@ -800,6 +800,21 @@ func TestWhenDirAttributeItCreatesMissingAndRunsInThatDir(t *testing.T) {
|
|||||||
_ = os.RemoveAll(toBeCreated)
|
_ = os.RemoveAll(toBeCreated)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDynamicVariablesShouldRunOnTheTaskDir(t *testing.T) {
|
||||||
|
tt := fileContentTest{
|
||||||
|
Dir: "testdata/dir/dynamic_var",
|
||||||
|
Target: "default",
|
||||||
|
TrimSpace: false,
|
||||||
|
Files: map[string]string{
|
||||||
|
"subdirectory/from_root_taskfile.txt": "subdirectory\n",
|
||||||
|
"subdirectory/from_included_taskfile.txt": "subdirectory\n",
|
||||||
|
"subdirectory/from_included_taskfile_task.txt": "subdirectory\n",
|
||||||
|
"subdirectory/from_interpolated_dir.txt": "subdirectory\n",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
tt.Run(t)
|
||||||
|
}
|
||||||
|
|
||||||
func TestDisplaysErrorOnUnsupportedVersion(t *testing.T) {
|
func TestDisplaysErrorOnUnsupportedVersion(t *testing.T) {
|
||||||
e := task.Executor{
|
e := task.Executor{
|
||||||
Dir: "testdata/version/v1",
|
Dir: "testdata/version/v1",
|
||||||
@@ -868,3 +883,19 @@ func TestDotenvShouldAllowMissingEnv(t *testing.T) {
|
|||||||
}
|
}
|
||||||
tt.Run(t)
|
tt.Run(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExitImmediately(t *testing.T) {
|
||||||
|
const dir = "testdata/exit_immediately"
|
||||||
|
|
||||||
|
var buff bytes.Buffer
|
||||||
|
e := task.Executor{
|
||||||
|
Dir: dir,
|
||||||
|
Stdout: &buff,
|
||||||
|
Stderr: &buff,
|
||||||
|
Silent: true,
|
||||||
|
}
|
||||||
|
assert.NoError(t, e.Setup())
|
||||||
|
|
||||||
|
assert.Error(t, e.Run(context.Background(), taskfile.Call{Task: "default"}))
|
||||||
|
assert.Contains(t, buff.String(), `"this_should_fail": executable file not found in $PATH`)
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package taskfile
|
package taskfile
|
||||||
|
|
||||||
import "errors"
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrCantUnmarshalIncludedTaskfile is returned for invalid var YAML.
|
// ErrCantUnmarshalIncludedTaskfile is returned for invalid var YAML.
|
||||||
@@ -15,7 +19,72 @@ type IncludedTaskfile struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IncludedTaskfiles represents information about included tasksfiles
|
// IncludedTaskfiles represents information about included tasksfiles
|
||||||
type IncludedTaskfiles = map[string]IncludedTaskfile
|
type IncludedTaskfiles struct {
|
||||||
|
Keys []string
|
||||||
|
Mapping map[string]IncludedTaskfile
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalYAML implements the yaml.Unmarshaler interface.
|
||||||
|
func (tfs *IncludedTaskfiles) UnmarshalYAML(node *yaml.Node) error {
|
||||||
|
if node.Kind != yaml.MappingNode {
|
||||||
|
return errors.New("task: includes is not a map")
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(@andreynering): on this style of custom unmarsheling,
|
||||||
|
// even number contains the keys, while odd numbers contains
|
||||||
|
// the values.
|
||||||
|
for i := 0; i < len(node.Content); i += 2 {
|
||||||
|
keyNode := node.Content[i]
|
||||||
|
valueNode := node.Content[i+1]
|
||||||
|
|
||||||
|
var v IncludedTaskfile
|
||||||
|
if err := valueNode.Decode(&v); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tfs.Set(keyNode.Value, v)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the length of the map
|
||||||
|
func (tfs *IncludedTaskfiles) Len() int {
|
||||||
|
if tfs == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return len(tfs.Keys)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge merges the given IncludedTaskfiles into the caller one
|
||||||
|
func (tfs *IncludedTaskfiles) Merge(other *IncludedTaskfiles) {
|
||||||
|
other.Range(func(key string, value IncludedTaskfile) error {
|
||||||
|
tfs.Set(key, value)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets a value to a given key
|
||||||
|
func (tfs *IncludedTaskfiles) Set(key string, includedTaskfile IncludedTaskfile) {
|
||||||
|
if tfs.Mapping == nil {
|
||||||
|
tfs.Mapping = make(map[string]IncludedTaskfile, 1)
|
||||||
|
}
|
||||||
|
if !stringSliceContains(tfs.Keys, key) {
|
||||||
|
tfs.Keys = append(tfs.Keys, key)
|
||||||
|
}
|
||||||
|
tfs.Mapping[key] = includedTaskfile
|
||||||
|
}
|
||||||
|
|
||||||
|
// Range allows you to loop into the included taskfiles in its right order
|
||||||
|
func (tfs *IncludedTaskfiles) Range(yield func(key string, includedTaskfile IncludedTaskfile) error) error {
|
||||||
|
if tfs == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for _, k := range tfs.Keys {
|
||||||
|
if err := yield(k, tfs.Mapping[k]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// UnmarshalYAML implements yaml.Unmarshaler interface
|
// UnmarshalYAML implements yaml.Unmarshaler interface
|
||||||
func (it *IncludedTaskfile) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
func (it *IncludedTaskfile) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||||
|
|||||||
@@ -22,11 +22,9 @@ func Merge(t1, t2 *Taskfile, namespaces ...string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if t1.Includes == nil {
|
if t1.Includes == nil {
|
||||||
t1.Includes = make(IncludedTaskfiles)
|
t1.Includes = &IncludedTaskfiles{}
|
||||||
}
|
|
||||||
for k, v := range t2.Includes {
|
|
||||||
t1.Includes[k] = v
|
|
||||||
}
|
}
|
||||||
|
t1.Includes.Merge(t2.Includes)
|
||||||
|
|
||||||
if t1.Vars == nil {
|
if t1.Vars == nil {
|
||||||
t1.Vars = &Vars{}
|
t1.Vars = &Vars{}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ package taskfile_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/taskfile"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v3/taskfile"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPreconditionParse(t *testing.T) {
|
func TestPreconditionParse(t *testing.T) {
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/internal/templater"
|
|
||||||
"github.com/go-task/task/v3/taskfile"
|
|
||||||
|
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v3/internal/templater"
|
||||||
|
"github.com/go-task/task/v3/taskfile"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -58,7 +58,7 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for namespace, includedTask := range t.Includes {
|
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}
|
||||||
includedTask = taskfile.IncludedTaskfile{
|
includedTask = taskfile.IncludedTaskfile{
|
||||||
@@ -67,7 +67,7 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
|||||||
AdvancedImport: includedTask.AdvancedImport,
|
AdvancedImport: includedTask.AdvancedImport,
|
||||||
}
|
}
|
||||||
if err := tr.Err(); err != nil {
|
if err := tr.Err(); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,24 +79,35 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
|||||||
|
|
||||||
info, err := os.Stat(path)
|
info, err := os.Stat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
if info.IsDir() {
|
if info.IsDir() {
|
||||||
path = filepath.Join(path, "Taskfile.yml")
|
path = filepath.Join(path, "Taskfile.yml")
|
||||||
}
|
}
|
||||||
includedTaskfile, err := readTaskfile(path)
|
includedTaskfile, err := readTaskfile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
if len(includedTaskfile.Includes) > 0 {
|
if includedTaskfile.Includes.Len() > 0 {
|
||||||
return nil, ErrIncludedTaskfilesCantHaveIncludes
|
return ErrIncludedTaskfilesCantHaveIncludes
|
||||||
}
|
}
|
||||||
|
|
||||||
if v >= 3.0 && len(includedTaskfile.Dotenv) > 0 {
|
if v >= 3.0 && len(includedTaskfile.Dotenv) > 0 {
|
||||||
return nil, ErrIncludedTaskfilesCantHaveDotenvs
|
return ErrIncludedTaskfilesCantHaveDotenvs
|
||||||
}
|
}
|
||||||
|
|
||||||
if includedTask.AdvancedImport {
|
if includedTask.AdvancedImport {
|
||||||
|
for k, v := range includedTaskfile.Vars.Mapping {
|
||||||
|
o := v
|
||||||
|
o.Dir = filepath.Join(dir, includedTask.Dir)
|
||||||
|
includedTaskfile.Vars.Mapping[k] = o
|
||||||
|
}
|
||||||
|
for k, v := range includedTaskfile.Env.Mapping {
|
||||||
|
o := v
|
||||||
|
o.Dir = filepath.Join(dir, includedTask.Dir)
|
||||||
|
includedTaskfile.Env.Mapping[k] = o
|
||||||
|
}
|
||||||
|
|
||||||
for _, task := range includedTaskfile.Tasks {
|
for _, task := range includedTaskfile.Tasks {
|
||||||
if !filepath.IsAbs(task.Dir) {
|
if !filepath.IsAbs(task.Dir) {
|
||||||
task.Dir = filepath.Join(includedTask.Dir, task.Dir)
|
task.Dir = filepath.Join(includedTask.Dir, task.Dir)
|
||||||
@@ -105,8 +116,12 @@ func Taskfile(dir string, entrypoint string) (*taskfile.Taskfile, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err = taskfile.Merge(t, includedTaskfile, namespace); err != nil {
|
if err = taskfile.Merge(t, includedTaskfile, namespace); err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if v < 3.0 {
|
if v < 3.0 {
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/taskfile"
|
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v3/taskfile"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Taskvars reads a Taskvars for a given directory
|
// Taskvars reads a Taskvars for a given directory
|
||||||
|
|||||||
10
taskfile/slice.go
Normal file
10
taskfile/slice.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package taskfile
|
||||||
|
|
||||||
|
func stringSliceContains(s []string, str string) bool {
|
||||||
|
for _, v := range s {
|
||||||
|
if v == str {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ type Taskfile struct {
|
|||||||
Expansions int
|
Expansions int
|
||||||
Output string
|
Output string
|
||||||
Method string
|
Method string
|
||||||
Includes IncludedTaskfiles
|
Includes *IncludedTaskfiles
|
||||||
Vars *Vars
|
Vars *Vars
|
||||||
Env *Vars
|
Env *Vars
|
||||||
Tasks Tasks
|
Tasks Tasks
|
||||||
@@ -26,7 +26,7 @@ func (tf *Taskfile) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|||||||
Expansions int
|
Expansions int
|
||||||
Output string
|
Output string
|
||||||
Method string
|
Method string
|
||||||
Includes IncludedTaskfiles
|
Includes *IncludedTaskfiles
|
||||||
Vars *Vars
|
Vars *Vars
|
||||||
Env *Vars
|
Env *Vars
|
||||||
Tasks Tasks
|
Tasks Tasks
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ package taskfile_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/go-task/task/v3/taskfile"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
"github.com/go-task/task/v3/taskfile"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCmdParse(t *testing.T) {
|
func TestCmdParse(t *testing.T) {
|
||||||
|
|||||||
@@ -53,21 +53,12 @@ func (vs *Vars) Set(key string, value Var) {
|
|||||||
if vs.Mapping == nil {
|
if vs.Mapping == nil {
|
||||||
vs.Mapping = make(map[string]Var, 1)
|
vs.Mapping = make(map[string]Var, 1)
|
||||||
}
|
}
|
||||||
if !strSliceContains(vs.Keys, key) {
|
if !stringSliceContains(vs.Keys, key) {
|
||||||
vs.Keys = append(vs.Keys, key)
|
vs.Keys = append(vs.Keys, key)
|
||||||
}
|
}
|
||||||
vs.Mapping[key] = value
|
vs.Mapping[key] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
func strSliceContains(s []string, str string) bool {
|
|
||||||
for _, v := range s {
|
|
||||||
if v == str {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Range allows you to loop into the vars in its right order
|
// Range allows you to loop into the vars in its right order
|
||||||
func (vs *Vars) Range(yield func(key string, value Var) error) error {
|
func (vs *Vars) Range(yield func(key string, value Var) error) error {
|
||||||
if vs == nil {
|
if vs == nil {
|
||||||
@@ -107,6 +98,7 @@ type Var struct {
|
|||||||
Static string
|
Static string
|
||||||
Live interface{}
|
Live interface{}
|
||||||
Sh string
|
Sh string
|
||||||
|
Dir string
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalYAML implements yaml.Unmarshaler interface.
|
// UnmarshalYAML implements yaml.Unmarshaler interface.
|
||||||
|
|||||||
1
testdata/dir/dynamic_var/.gitignore
vendored
Normal file
1
testdata/dir/dynamic_var/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.txt
|
||||||
33
testdata/dir/dynamic_var/Taskfile.yml
vendored
Normal file
33
testdata/dir/dynamic_var/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
includes:
|
||||||
|
sub:
|
||||||
|
taskfile: subdirectory
|
||||||
|
dir: subdirectory
|
||||||
|
|
||||||
|
vars:
|
||||||
|
DIRECTORY: subdirectory
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default:
|
||||||
|
- task: from-root-taskfile
|
||||||
|
- task: sub:from-included-taskfile
|
||||||
|
- task: sub:from-included-taskfile-task
|
||||||
|
- task: from-interpolated-dir
|
||||||
|
|
||||||
|
from-root-taskfile:
|
||||||
|
cmds:
|
||||||
|
- echo '{{.TASK_DIR}}' > from_root_taskfile.txt
|
||||||
|
dir: subdirectory
|
||||||
|
vars:
|
||||||
|
TASK_DIR:
|
||||||
|
sh: basename $(pwd)
|
||||||
|
silent: true
|
||||||
|
|
||||||
|
from-interpolated-dir:
|
||||||
|
cmds:
|
||||||
|
- echo '{{.INTERPOLATED_DIR}}' > from_interpolated_dir.txt
|
||||||
|
dir: '{{.DIRECTORY}}'
|
||||||
|
vars:
|
||||||
|
INTERPOLATED_DIR:
|
||||||
|
sh: basename $(pwd)
|
||||||
19
testdata/dir/dynamic_var/subdirectory/Taskfile.yml
vendored
Normal file
19
testdata/dir/dynamic_var/subdirectory/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
vars:
|
||||||
|
TASKFILE_DIR:
|
||||||
|
sh: basename $(pwd)
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
from-included-taskfile:
|
||||||
|
cmds:
|
||||||
|
- echo '{{.TASKFILE_DIR}}' > from_included_taskfile.txt
|
||||||
|
silent: true
|
||||||
|
|
||||||
|
from-included-taskfile-task:
|
||||||
|
cmds:
|
||||||
|
- echo '{{.TASKFILE_TASK_DIR}}' > from_included_taskfile_task.txt
|
||||||
|
silent: true
|
||||||
|
vars:
|
||||||
|
TASKFILE_TASK_DIR:
|
||||||
|
sh: basename $(pwd)
|
||||||
6
testdata/exit_immediately/Taskfile.yml
vendored
Normal file
6
testdata/exit_immediately/Taskfile.yml
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default: |
|
||||||
|
this_should_fail
|
||||||
|
echo "This shoudn't be print"
|
||||||
3
testdata/generates/Taskfile.yml
vendored
3
testdata/generates/Taskfile.yml
vendored
@@ -1,7 +1,8 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
|
|
||||||
vars:
|
vars:
|
||||||
BUILD_DIR: $pwd
|
BUILD_DIR:
|
||||||
|
sh: pwd
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
abs.txt:
|
abs.txt:
|
||||||
|
|||||||
0
testdata/generates/sub/.keep
vendored
Normal file
0
testdata/generates/sub/.keep
vendored
Normal file
1
testdata/vars/v3/.env
vendored
Normal file
1
testdata/vars/v3/.env
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
DOT_ENV_VAR=From .env file
|
||||||
5
testdata/vars/v3/Taskfile.yml
vendored
5
testdata/vars/v3/Taskfile.yml
vendored
@@ -1,5 +1,7 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
|
|
||||||
|
dotenv: [.env]
|
||||||
|
|
||||||
vars:
|
vars:
|
||||||
VAR_A: A
|
VAR_A: A
|
||||||
VAR_B: '{{.VAR_A}}B'
|
VAR_B: '{{.VAR_A}}B'
|
||||||
@@ -15,6 +17,7 @@ tasks:
|
|||||||
- task: var-order
|
- task: var-order
|
||||||
- task: dependent-sh
|
- task: dependent-sh
|
||||||
- task: with-call
|
- task: with-call
|
||||||
|
- task: from-dot-env
|
||||||
|
|
||||||
missing-var: echo '{{.NON_EXISTING_VAR}}' > missing-var.txt
|
missing-var: echo '{{.NON_EXISTING_VAR}}' > missing-var.txt
|
||||||
|
|
||||||
@@ -44,3 +47,5 @@ tasks:
|
|||||||
MESSAGE: Hi, {{.ABC123}}!
|
MESSAGE: Hi, {{.ABC123}}!
|
||||||
cmds:
|
cmds:
|
||||||
- echo "{{.MESSAGE}}" > with-call.txt
|
- echo "{{.MESSAGE}}" > with-call.txt
|
||||||
|
|
||||||
|
from-dot-env: echo '{{.DOT_ENV_VAR}}' > from-dot-env.txt
|
||||||
|
|||||||
35
variables.go
35
variables.go
@@ -13,12 +13,27 @@ import (
|
|||||||
// CompiledTask returns a copy of a task, but replacing variables in almost all
|
// CompiledTask returns a copy of a task, but replacing variables in almost all
|
||||||
// properties using the Go template package.
|
// properties using the Go template package.
|
||||||
func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) {
|
func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) {
|
||||||
|
return e.compiledTask(call, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FastCompiledTask is like CompiledTask, but it skippes dynamic variables.
|
||||||
|
func (e *Executor) FastCompiledTask(call taskfile.Call) (*taskfile.Task, error) {
|
||||||
|
return e.compiledTask(call, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Executor) compiledTask(call taskfile.Call, evaluateShVars bool) (*taskfile.Task, error) {
|
||||||
origTask, ok := e.Taskfile.Tasks[call.Task]
|
origTask, ok := e.Taskfile.Tasks[call.Task]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, &taskNotFoundError{call.Task}
|
return nil, &taskNotFoundError{call.Task}
|
||||||
}
|
}
|
||||||
|
|
||||||
vars, err := e.Compiler.GetVariables(origTask, call)
|
var vars *taskfile.Vars
|
||||||
|
var err error
|
||||||
|
if evaluateShVars {
|
||||||
|
vars, err = e.Compiler.GetVariables(origTask, call)
|
||||||
|
} else {
|
||||||
|
vars, err = e.Compiler.FastGetVariables(origTask, call)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -59,16 +74,18 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) {
|
|||||||
new.Env = &taskfile.Vars{}
|
new.Env = &taskfile.Vars{}
|
||||||
new.Env.Merge(r.ReplaceVars(e.Taskfile.Env))
|
new.Env.Merge(r.ReplaceVars(e.Taskfile.Env))
|
||||||
new.Env.Merge(r.ReplaceVars(origTask.Env))
|
new.Env.Merge(r.ReplaceVars(origTask.Env))
|
||||||
err = new.Env.Range(func(k string, v taskfile.Var) error {
|
if evaluateShVars {
|
||||||
static, err := e.Compiler.HandleDynamicVar(v)
|
err = new.Env.Range(func(k string, v taskfile.Var) error {
|
||||||
|
static, err := e.Compiler.HandleDynamicVar(v, new.Dir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
new.Env.Set(k, taskfile.Var{Static: static})
|
||||||
|
return nil
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
new.Env.Set(k, taskfile.Var{Static: static})
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(origTask.Cmds) > 0 {
|
if len(origTask.Cmds) > 0 {
|
||||||
|
|||||||
52
watch.go
52
watch.go
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
@@ -14,10 +15,7 @@ import (
|
|||||||
"github.com/radovskyb/watcher"
|
"github.com/radovskyb/watcher"
|
||||||
)
|
)
|
||||||
|
|
||||||
var watchIgnoredDirs = []string{
|
const watchInterval = 5 * time.Second
|
||||||
".git",
|
|
||||||
"node_modules",
|
|
||||||
}
|
|
||||||
|
|
||||||
// watchTasks start watching the given tasks
|
// watchTasks start watching the given tasks
|
||||||
func (e *Executor) watchTasks(calls ...taskfile.Call) error {
|
func (e *Executor) watchTasks(calls ...taskfile.Call) error {
|
||||||
@@ -40,9 +38,6 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
|
|||||||
w := watcher.New()
|
w := watcher.New()
|
||||||
defer w.Close()
|
defer w.Close()
|
||||||
w.SetMaxEvents(1)
|
w.SetMaxEvents(1)
|
||||||
if err := w.Ignore(watchIgnoredDirs...); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
closeOnInterrupt(w)
|
closeOnInterrupt(w)
|
||||||
|
|
||||||
@@ -54,6 +49,9 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
|
|||||||
|
|
||||||
cancel()
|
cancel()
|
||||||
ctx, cancel = context.WithCancel(context.Background())
|
ctx, cancel = context.WithCancel(context.Background())
|
||||||
|
|
||||||
|
e.Compiler.ResetCache()
|
||||||
|
|
||||||
for _, c := range calls {
|
for _, c := range calls {
|
||||||
c := c
|
c := c
|
||||||
go func() {
|
go func() {
|
||||||
@@ -65,9 +63,6 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
|
|||||||
case err := <-w.Error:
|
case err := <-w.Error:
|
||||||
switch err {
|
switch err {
|
||||||
case watcher.ErrWatchedFileDeleted:
|
case watcher.ErrWatchedFileDeleted:
|
||||||
go func() {
|
|
||||||
w.TriggerEvent(watcher.Remove, nil)
|
|
||||||
}()
|
|
||||||
default:
|
default:
|
||||||
e.Logger.Errf(logger.Red, "%v", err)
|
e.Logger.Errf(logger.Red, "%v", err)
|
||||||
}
|
}
|
||||||
@@ -79,16 +74,16 @@ func (e *Executor) watchTasks(calls ...taskfile.Call) error {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
// re-register each second because we can have new files
|
// re-register every 5 seconds because we can have new files, but this process is expensive to run
|
||||||
for {
|
for {
|
||||||
if err := e.registerWatchedFiles(w, calls...); err != nil {
|
if err := e.registerWatchedFiles(w, calls...); err != nil {
|
||||||
e.Logger.Errf(logger.Red, "%v", err)
|
e.Logger.Errf(logger.Red, "%v", err)
|
||||||
}
|
}
|
||||||
time.Sleep(time.Second)
|
time.Sleep(watchInterval)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return w.Start(time.Second)
|
return w.Start(watchInterval)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isContextError(err error) bool {
|
func isContextError(err error) bool {
|
||||||
@@ -109,16 +104,7 @@ func closeOnInterrupt(w *watcher.Watcher) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *Executor) registerWatchedFiles(w *watcher.Watcher, calls ...taskfile.Call) error {
|
func (e *Executor) registerWatchedFiles(w *watcher.Watcher, calls ...taskfile.Call) error {
|
||||||
oldWatchedFiles := make(map[string]struct{})
|
watchedFiles := w.WatchedFiles()
|
||||||
for f := range w.WatchedFiles() {
|
|
||||||
oldWatchedFiles[f] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
for f := range oldWatchedFiles {
|
|
||||||
if err := w.Remove(f); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var registerTaskFiles func(taskfile.Call) error
|
var registerTaskFiles func(taskfile.Call) error
|
||||||
registerTaskFiles = func(c taskfile.Call) error {
|
registerTaskFiles = func(c taskfile.Call) error {
|
||||||
@@ -146,12 +132,20 @@ func (e *Executor) registerWatchedFiles(w *watcher.Watcher, calls ...taskfile.Ca
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
if _, ok := oldWatchedFiles[f]; ok {
|
absFile, err := filepath.Abs(f)
|
||||||
continue
|
if err != nil {
|
||||||
}
|
|
||||||
if err := w.Add(f); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if shouldIgnoreFile(absFile) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := watchedFiles[absFile]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := w.Add(absFile); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
e.Logger.VerboseOutf(logger.Green, "task: watching new file: %v", absFile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -164,3 +158,7 @@ func (e *Executor) registerWatchedFiles(w *watcher.Watcher, calls ...taskfile.Ca
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func shouldIgnoreFile(path string) bool {
|
||||||
|
return strings.Contains(path, "/.git") || strings.Contains(path, "/.task") || strings.Contains(path, "/node_modules")
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user