From c068b05232be27a9023614ec2123ed440cf6f631 Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Mon, 23 Dec 2019 22:25:19 -0300 Subject: [PATCH 01/12] Delete taskfile.org -> taskfile.dev redirect code This has been migrated to Netlify --- cmd/redirector/redirector.go | 421 ----------------------------------- 1 file changed, 421 deletions(-) delete mode 100644 cmd/redirector/redirector.go diff --git a/cmd/redirector/redirector.go b/cmd/redirector/redirector.go deleted file mode 100644 index 2aa6023a..00000000 --- a/cmd/redirector/redirector.go +++ /dev/null @@ -1,421 +0,0 @@ -// This small web app is used to redirect from the old taskfile.org domain -// to the new taskfile.dev without breaking CIs that uses cURL to download -// "/install.sh" without the -L flag (which follow redirects). - -package main - -import ( - "net/http" -) - -func main() { - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - if r.URL.Path == "/install.sh" { - println("Dumping install.sh") - - w.Write(installShContent) - return - } - - println("Redirecting to https://taskfile.dev" + r.URL.Path) - - w.Header().Set("Location", "https://taskfile.dev"+r.URL.Path) - w.WriteHeader(301) - }) - - println("Listening :8080") - - panic(http.ListenAndServe(":8080", nil)) -} - -var installShContent = []byte(`#!/bin/sh -set -e -# Code generated by godownloader on 2018-04-07T17:47:38Z. DO NOT EDIT. -# - -usage() { - this=$1 - cat </dev/null -} -echoerr() { - echo "$@" 1>&2 -} -log_prefix() { - echo "$0" -} -_logp=6 -log_set_priority() { - _logp="$1" -} -log_priority() { - if test -z "$1"; then - echo "$_logp" - return - fi - [ "$1" -le "$_logp" ] -} -log_tag() { - case $1 in - 0) echo "emerg" ;; - 1) echo "alert" ;; - 2) echo "crit" ;; - 3) echo "err" ;; - 4) echo "warning" ;; - 5) echo "notice" ;; - 6) echo "info" ;; - 7) echo "debug" ;; - *) echo "$1" ;; - esac -} -log_debug() { - log_priority 7 || return 0 - echoerr "$(log_prefix)" "$(log_tag 7)" "$@" -} -log_info() { - log_priority 6 || return 0 - echoerr "$(log_prefix)" "$(log_tag 6)" "$@" -} -log_err() { - log_priority 3 || return 0 - echoerr "$(log_prefix)" "$(log_tag 3)" "$@" -} -log_crit() { - log_priority 2 || return 0 - echoerr "$(log_prefix)" "$(log_tag 2)" "$@" -} -uname_os() { - os=$(uname -s | tr '[:upper:]' '[:lower:]') - case "$os" in - msys_nt) os="windows" ;; - esac - echo "$os" -} -uname_arch() { - arch=$(uname -m) - case $arch in - x86_64) arch="amd64" ;; - x86) arch="386" ;; - i686) arch="386" ;; - i386) arch="386" ;; - aarch64) arch="arm64" ;; - armv5*) arch="arm5" ;; - armv6*) arch="arm6" ;; - armv7*) arch="arm7" ;; - esac - echo ${arch} -} -uname_os_check() { - os=$(uname_os) - case "$os" in - darwin) return 0 ;; - dragonfly) return 0 ;; - freebsd) return 0 ;; - linux) return 0 ;; - android) return 0 ;; - nacl) return 0 ;; - netbsd) return 0 ;; - openbsd) return 0 ;; - plan9) return 0 ;; - solaris) return 0 ;; - windows) return 0 ;; - esac - log_crit "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib" - return 1 -} -uname_arch_check() { - arch=$(uname_arch) - case "$arch" in - 386) return 0 ;; - amd64) return 0 ;; - arm64) return 0 ;; - armv5) return 0 ;; - armv6) return 0 ;; - armv7) return 0 ;; - ppc64) return 0 ;; - ppc64le) return 0 ;; - mips) return 0 ;; - mipsle) return 0 ;; - mips64) return 0 ;; - mips64le) return 0 ;; - s390x) return 0 ;; - amd64p32) return 0 ;; - esac - log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value. Please file bug report at https://github.com/client9/shlib" - return 1 -} -untar() { - tarball=$1 - case "${tarball}" in - *.tar.gz | *.tgz) tar -xzf "${tarball}" ;; - *.tar) tar -xf "${tarball}" ;; - *.zip) unzip "${tarball}" ;; - *) - log_err "untar unknown archive format for ${tarball}" - return 1 - ;; - esac -} -mktmpdir() { - test -z "$TMPDIR" && TMPDIR="$(mktemp -d)" - mkdir -p "${TMPDIR}" - echo "${TMPDIR}" -} -http_download_curl() { - local_file=$1 - source_url=$2 - header=$3 - if [ -z "$header" ]; then - code=$(curl -w '%{http_code}' -sL -o "$local_file" "$source_url") - else - code=$(curl -w '%{http_code}' -sL -H "$header" -o "$local_file" "$source_url") - fi - if [ "$code" != "200" ]; then - log_debug "http_download_curl received HTTP status $code" - return 1 - fi - return 0 -} -http_download_wget() { - local_file=$1 - source_url=$2 - header=$3 - if [ -z "$header" ]; then - wget -q -O "$local_file" "$source_url" - else - wget -q --header "$header" -O "$local_file" "$source_url" - fi -} -http_download() { - log_debug "http_download $2" - if is_command curl; then - http_download_curl "$@" - return - elif is_command wget; then - http_download_wget "$@" - return - fi - log_crit "http_download unable to find wget or curl" - return 1 -} -http_copy() { - tmp=$(mktemp) - http_download "${tmp}" "$1" "$2" || return 1 - body=$(cat "$tmp") - rm -f "${tmp}" - echo "$body" -} -github_release() { - owner_repo=$1 - version=$2 - test -z "$version" && version="latest" - giturl="https://github.com/${owner_repo}/releases/${version}" - json=$(http_copy "$giturl" "Accept:application/json") - test -z "$json" && return 1 - version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//') - test -z "$version" && return 1 - echo "$version" -} -hash_sha256() { - TARGET=${1:-/dev/stdin} - if is_command gsha256sum; then - hash=$(gsha256sum "$TARGET") || return 1 - echo "$hash" | cut -d ' ' -f 1 - elif is_command sha256sum; then - hash=$(sha256sum "$TARGET") || return 1 - echo "$hash" | cut -d ' ' -f 1 - elif is_command shasum; then - hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1 - echo "$hash" | cut -d ' ' -f 1 - elif is_command openssl; then - hash=$(openssl -dst openssl dgst -sha256 "$TARGET") || return 1 - echo "$hash" | cut -d ' ' -f a - else - log_crit "hash_sha256 unable to find command to compute sha-256 hash" - return 1 - fi -} -hash_sha256_verify() { - TARGET=$1 - checksums=$2 - if [ -z "$checksums" ]; then - log_err "hash_sha256_verify checksum file not specified in arg2" - return 1 - fi - BASENAME=${TARGET##*/} - want=$(grep "${BASENAME}" "${checksums}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1) - if [ -z "$want" ]; then - log_err "hash_sha256_verify unable to find checksum for '${TARGET}' in '${checksums}'" - return 1 - fi - got=$(hash_sha256 "$TARGET") - if [ "$want" != "$got" ]; then - log_err "hash_sha256_verify checksum for '$TARGET' did not verify ${want} vs $got" - return 1 - fi -} -cat /dev/null < Date: Sat, 11 Jan 2020 21:29:04 -0300 Subject: [PATCH 02/12] GitHub Actions: Add action to run GoReleaser on new tags --- .github/workflows/release.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..b3bda401 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,26 @@ +name: goreleaser + +on: + push: + tags: + - '*' + +jobs: + goreleaser: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v1 + + - name: Set up Go + uses: actions/setup-go@v1 + with: + go-version: 1.13.x + + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v1 + with: + version: latest + args: release --rm-dist + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From de98a53b43f1337b27288207eb3e393724838128 Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Sat, 11 Jan 2020 21:46:57 -0300 Subject: [PATCH 03/12] Upgrade mvdan.cc/sh to v3.0.1 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ada15578..2940a815 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/stretchr/testify v1.4.0 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e gopkg.in/yaml.v2 v2.2.2 - mvdan.cc/sh/v3 v3.0.0-beta1 + mvdan.cc/sh/v3 v3.0.1 ) go 1.13 diff --git a/go.sum b/go.sum index eb567a1d..3928c284 100644 --- a/go.sum +++ b/go.sum @@ -55,5 +55,5 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= mvdan.cc/editorconfig v0.1.1-0.20191109213504-890940e3f00e/go.mod h1:Ge4atmRUYqueGppvJ7JNrtqpqokoJEFxYbP0Z+WeKS8= -mvdan.cc/sh/v3 v3.0.0-beta1 h1:UqiwBEXEPzelaGxuvixaOtzc7WzKtrElePJ8HqvW7K8= -mvdan.cc/sh/v3 v3.0.0-beta1/go.mod h1:rBIndNJFYPp8xSppiZcGIk6B5d1g3OEARxEaXjPxwVI= +mvdan.cc/sh/v3 v3.0.1 h1:f6huEnEEwLTsHYSNiyhkheojUe8P5KnDdEjiBTFUbP0= +mvdan.cc/sh/v3 v3.0.1/go.mod h1:rBIndNJFYPp8xSppiZcGIk6B5d1g3OEARxEaXjPxwVI= From 68ecb7fbdd42014d6c7a44d264eb8104b9f37412 Mon Sep 17 00:00:00 2001 From: Paul Varache Date: Mon, 20 Jan 2020 11:26:15 +0000 Subject: [PATCH 04/12] Add PowerShell completion script --- completion/ps/task.ps1 | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 completion/ps/task.ps1 diff --git a/completion/ps/task.ps1 b/completion/ps/task.ps1 new file mode 100644 index 00000000..948d333e --- /dev/null +++ b/completion/ps/task.ps1 @@ -0,0 +1,10 @@ +$scriptBlock = { + param($commandName, $wordToComplete, $cursorPosition) + $curReg = "task{.exe}? (.*?)$" + $startsWith = $wordToComplete | Select-String $curReg -AllMatches | ForEach-Object { $_.Matches.Groups[1].Value } + $reg = "\* ($startsWith.+?):" + $listOutput = $(task -l) + $listOutput | Select-String $reg -AllMatches | ForEach-Object { $_.Matches.Groups[1].Value + " " } +} + +Register-ArgumentCompleter -Native -CommandName task -ScriptBlock $scriptBlock From 22394def7843a130e582c0dd723f216ae37272cd Mon Sep 17 00:00:00 2001 From: Egor Kovetskiy Date: Sat, 25 Jan 2020 15:44:55 +0300 Subject: [PATCH 05/12] Add note about Arch Linux package --- docs/installation.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/installation.md b/docs/installation.md index 4675df3c..9f39e4f5 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -40,6 +40,19 @@ scoop install task This installation method is community owned. After a new release of Task, it may take some time until it's available on Scoop. +## Arch Linux + +If you're on Arch Linux you can install Task from +[AUR](https://aur.archlinux.org/packages/taskfile-git) using your favorite +package manager such as `yay`, `pacaur` or `yaourt`: + +```cmd +yay -S taskfile-git +``` + +This installation method is community owned, but since it's `-git` version of +the package, it's always latest available version based on the git repository. + ## Go Task now uses [Go Modules](https://github.com/golang/go/wiki/Modules), which From 7453e688fdc264f0361dcbe35885a57418d4ccdf Mon Sep 17 00:00:00 2001 From: Paul Varache Date: Mon, 20 Jan 2020 13:38:18 +0000 Subject: [PATCH 06/12] Compile tasks before printing help or summary (Closes #276) --- help.go | 4 ++++ internal/summary/summary.go | 4 ++-- task.go | 9 ++++++++- variables.go | 1 + 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/help.go b/help.go index 79417609..b586c1c5 100644 --- a/help.go +++ b/help.go @@ -29,6 +29,10 @@ func (e *Executor) tasksWithDesc() (tasks []*taskfile.Task) { tasks = make([]*taskfile.Task, 0, len(e.Taskfile.Tasks)) for _, task := range e.Taskfile.Tasks { if task.Desc != "" { + compiledTask, err := e.CompiledTask(taskfile.Call{Task: task.Task}) + if err == nil { + task = compiledTask + } tasks = append(tasks, task) } } diff --git a/internal/summary/summary.go b/internal/summary/summary.go index 655ec76c..1671e69d 100644 --- a/internal/summary/summary.go +++ b/internal/summary/summary.go @@ -9,12 +9,12 @@ import ( func PrintTasks(l *logger.Logger, t *taskfile.Taskfile, c []taskfile.Call) { for i, call := range c { - printSpaceBetweenSummaries(l, i) + PrintSpaceBetweenSummaries(l, i) PrintTask(l, t.Tasks[call.Task]) } } -func printSpaceBetweenSummaries(l *logger.Logger, i int) { +func PrintSpaceBetweenSummaries(l *logger.Logger, i int) { spaceRequired := i > 0 if !spaceRequired { return diff --git a/task.go b/task.go index 067d7229..4d303684 100644 --- a/task.go +++ b/task.go @@ -70,7 +70,14 @@ func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error { } if e.Summary { - summary.PrintTasks(e.Logger, e.Taskfile, calls) + for i, c := range calls { + compiledTask, err := e.CompiledTask(c) + if err != nil { + return nil + } + summary.PrintSpaceBetweenSummaries(e.Logger, i) + summary.PrintTask(e.Logger, compiledTask) + } return nil } diff --git a/variables.go b/variables.go index 9c227372..d3e591f0 100644 --- a/variables.go +++ b/variables.go @@ -25,6 +25,7 @@ func (e *Executor) CompiledTask(call taskfile.Call) (*taskfile.Task, error) { new := taskfile.Task{ Task: origTask.Task, Desc: r.Replace(origTask.Desc), + Summary: r.Replace(origTask.Summary), Sources: r.ReplaceSlice(origTask.Sources), Generates: r.ReplaceSlice(origTask.Generates), Status: r.ReplaceSlice(origTask.Status), From 94ac60fa0978843c7099b6d71dd8b1d973999c8b Mon Sep 17 00:00:00 2001 From: Egor Kovetskiy Date: Mon, 10 Feb 2020 11:45:27 +0300 Subject: [PATCH 07/12] docs/installation.md: fix typo for Git Co-Authored-By: Andrey Nering --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index 9f39e4f5..876d0060 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -51,7 +51,7 @@ yay -S taskfile-git ``` This installation method is community owned, but since it's `-git` version of -the package, it's always latest available version based on the git repository. +the package, it's always latest available version based on the Git repository. ## Go From 069257151e67860ad260462620650c52d5431b95 Mon Sep 17 00:00:00 2001 From: thejray <11284494+thejray@users.noreply.github.com> Date: Wed, 19 Feb 2020 07:22:37 -0500 Subject: [PATCH 08/12] Remove trailing colon from task listing --- completion/bash/task.bash | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/completion/bash/task.bash b/completion/bash/task.bash index 1e212979..4ad88373 100644 --- a/completion/bash/task.bash +++ b/completion/bash/task.bash @@ -6,7 +6,7 @@ _task_completion() # Remove colon from word breaks COMP_WORDBREAKS=${COMP_WORDBREAKS//:} - scripts=$(task -l | sed '1d' | sed 's/^\* //' | awk '{ print $1 }'); + scripts=$(task -l | sed '1d' | awk '{ print $2 }' | sed 's/:$//'); curr_arg="${COMP_WORDS[COMP_CWORD]:-"."}" From eef84bda26a2cbbf33bad616d9da3bb2685ec28c Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Sun, 1 Mar 2020 15:35:23 -0300 Subject: [PATCH 09/12] Upgrade mvdan.cc/sh to v3.0.2 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 2940a815..c08a264b 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/stretchr/testify v1.4.0 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e gopkg.in/yaml.v2 v2.2.2 - mvdan.cc/sh/v3 v3.0.1 + mvdan.cc/sh/v3 v3.0.2 ) go 1.13 diff --git a/go.sum b/go.sum index 3928c284..9ba871fb 100644 --- a/go.sum +++ b/go.sum @@ -55,5 +55,5 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= mvdan.cc/editorconfig v0.1.1-0.20191109213504-890940e3f00e/go.mod h1:Ge4atmRUYqueGppvJ7JNrtqpqokoJEFxYbP0Z+WeKS8= -mvdan.cc/sh/v3 v3.0.1 h1:f6huEnEEwLTsHYSNiyhkheojUe8P5KnDdEjiBTFUbP0= -mvdan.cc/sh/v3 v3.0.1/go.mod h1:rBIndNJFYPp8xSppiZcGIk6B5d1g3OEARxEaXjPxwVI= +mvdan.cc/sh/v3 v3.0.2 h1:NU+UpTZHRdIZ9igRo8zi/7+5/NpetYlhlyDhz1/AdMM= +mvdan.cc/sh/v3 v3.0.2/go.mod h1:rBIndNJFYPp8xSppiZcGIk6B5d1g3OEARxEaXjPxwVI= From ca07a663e18f980b609668c7eb61732ae3df70eb Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Sun, 1 Mar 2020 15:45:51 -0300 Subject: [PATCH 10/12] Remove Travis CI --- .travis.yml | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index bf669e5a..00000000 --- a/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: go - -go: - - 1.12.x - - 1.13.x - -env: - - GO111MODULE=on - -addons: - apt: - packages: - - rpm - -script: - - go install -v ./cmd/task - - task ci From 628c4a7b5f68e2798050678f6c0e3f974de269be Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Sun, 1 Mar 2020 15:46:56 -0300 Subject: [PATCH 11/12] Upgrade Go version on CI --- .github/workflows/release.yml | 4 ++-- .github/workflows/test.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b3bda401..95f611ea 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v1 with: - go-version: 1.13.x + go-version: 1.14.x - name: Run GoReleaser uses: goreleaser/goreleaser-action@v1 @@ -23,4 +23,4 @@ jobs: version: latest args: release --rm-dist env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c8ec8c2c..d797964e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,7 +5,7 @@ jobs: name: Test strategy: matrix: - go-version: [1.12.x, 1.13.x] + go-version: [1.13.x, 1.14.x] platform: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{matrix.platform}} steps: From d52d74c64cbbcbcfa44dbe3e0c76db30183f20b6 Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Sun, 22 Mar 2020 21:42:45 -0300 Subject: [PATCH 12/12] go mod vendor --- vendor/modules.txt | 2 +- vendor/mvdan.cc/sh/v3/expand/braces.go | 12 ++--- vendor/mvdan.cc/sh/v3/expand/expand.go | 17 ++++--- vendor/mvdan.cc/sh/v3/interp/interp.go | 5 ++- vendor/mvdan.cc/sh/v3/pattern/pattern.go | 21 +++++++-- vendor/mvdan.cc/sh/v3/shell/source.go | 57 ------------------------ vendor/mvdan.cc/sh/v3/syntax/braces.go | 1 - vendor/mvdan.cc/sh/v3/syntax/lexer.go | 2 + vendor/mvdan.cc/sh/v3/syntax/nodes.go | 9 ++-- vendor/mvdan.cc/sh/v3/syntax/parser.go | 16 ++++--- vendor/mvdan.cc/sh/v3/syntax/printer.go | 11 +++-- 11 files changed, 63 insertions(+), 90 deletions(-) delete mode 100644 vendor/mvdan.cc/sh/v3/shell/source.go diff --git a/vendor/modules.txt b/vendor/modules.txt index 128c3fc0..faebaa02 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -37,7 +37,7 @@ golang.org/x/xerrors golang.org/x/xerrors/internal # gopkg.in/yaml.v2 v2.2.2 gopkg.in/yaml.v2 -# mvdan.cc/sh/v3 v3.0.0-beta1 +# mvdan.cc/sh/v3 v3.0.2 mvdan.cc/sh/v3/expand mvdan.cc/sh/v3/interp mvdan.cc/sh/v3/pattern diff --git a/vendor/mvdan.cc/sh/v3/expand/braces.go b/vendor/mvdan.cc/sh/v3/expand/braces.go index 482f8116..9914fe44 100644 --- a/vendor/mvdan.cc/sh/v3/expand/braces.go +++ b/vendor/mvdan.cc/sh/v3/expand/braces.go @@ -24,13 +24,13 @@ func Braces(word *syntax.Word) []*syntax.Word { continue } if br.Sequence { - var from, to int - if br.Chars { + chars := false + from, err1 := strconv.Atoi(br.Elems[0].Lit()) + to, err2 := strconv.Atoi(br.Elems[1].Lit()) + if err1 != nil || err2 != nil { + chars = true from = int(br.Elems[0].Lit()[0]) to = int(br.Elems[1].Lit()[0]) - } else { - from, _ = strconv.Atoi(br.Elems[0].Lit()) - to, _ = strconv.Atoi(br.Elems[1].Lit()) } upward := from <= to incr := 1 @@ -54,7 +54,7 @@ func Braces(word *syntax.Word) []*syntax.Word { next := *word next.Parts = next.Parts[i+1:] lit := &syntax.Lit{} - if br.Chars { + if chars { lit.Value = string(n) } else { lit.Value = strconv.Itoa(n) diff --git a/vendor/mvdan.cc/sh/v3/expand/expand.go b/vendor/mvdan.cc/sh/v3/expand/expand.go index 0186a8fc..847cd46d 100644 --- a/vendor/mvdan.cc/sh/v3/expand/expand.go +++ b/vendor/mvdan.cc/sh/v3/expand/expand.go @@ -159,6 +159,8 @@ func Document(cfg *Config, word *syntax.Word) (string, error) { return cfg.fieldJoin(field), nil } +const patMode = pattern.Filenames | pattern.Braces + // Pattern expands a single shell word as a pattern, using syntax.QuotePattern // on any non-quoted parts of the input word. The result can be used on // syntax.TranslatePattern directly. @@ -174,7 +176,7 @@ func Pattern(cfg *Config, word *syntax.Word) (string, error) { buf := cfg.strBuilder() for _, part := range field { if part.quote > quoteNone { - buf.WriteString(pattern.QuoteMeta(part.val)) + buf.WriteString(pattern.QuoteMeta(part.val, patMode)) } else { buf.WriteString(part.val) } @@ -345,11 +347,11 @@ func (cfg *Config) escapedGlobField(parts []fieldPart) (escaped string, glob boo buf := cfg.strBuilder() for _, part := range parts { if part.quote > quoteNone { - buf.WriteString(pattern.QuoteMeta(part.val)) + buf.WriteString(pattern.QuoteMeta(part.val, patMode)) continue } buf.WriteString(part.val) - if pattern.HasMeta(part.val) { + if pattern.HasMeta(part.val, patMode) { glob = true } } @@ -367,9 +369,10 @@ func Fields(cfg *Config, words ...*syntax.Word) ([]string, error) { fields := make([]string, 0, len(words)) dir := cfg.envGet("PWD") for _, word := range words { - afterBraces := []*syntax.Word{word} - if syntax.SplitBraces(word) { - afterBraces = Braces(word) + word := *word // make a copy, since SplitBraces replaces the Parts slice + afterBraces := []*syntax.Word{&word} + if syntax.SplitBraces(&word) { + afterBraces = Braces(&word) } for _, word2 := range afterBraces { wfields, err := cfg.wordFields(word2.Parts) @@ -540,7 +543,6 @@ func (cfg *Config) wordFields(wps []syntax.WordPart) ([][]fieldPart, error) { } curField = append(curField, fp) case *syntax.DblQuoted: - allowEmpty = true if len(x.Parts) == 1 { pe, _ := x.Parts[0].(*syntax.ParamExp) if elems := cfg.quotedElems(pe); elems != nil { @@ -556,6 +558,7 @@ func (cfg *Config) wordFields(wps []syntax.WordPart) ([][]fieldPart, error) { continue } } + allowEmpty = true wfield, err := cfg.wordField(x.Parts, quoteDouble) if err != nil { return nil, err diff --git a/vendor/mvdan.cc/sh/v3/interp/interp.go b/vendor/mvdan.cc/sh/v3/interp/interp.go index 257ed04f..c3e8e347 100644 --- a/vendor/mvdan.cc/sh/v3/interp/interp.go +++ b/vendor/mvdan.cc/sh/v3/interp/interp.go @@ -745,7 +745,6 @@ func (r *Runner) sub() *Runner { Env: r.Env, Dir: r.Dir, Params: r.Params, - Funcs: r.Funcs, execHandler: r.execHandler, openHandler: r.openHandler, stdin: r.stdin, @@ -766,6 +765,10 @@ func (r *Runner) sub() *Runner { for k, v := range r.cmdVars { r2.cmdVars[k] = v } + r2.Funcs = make(map[string]*syntax.Stmt, len(r.Funcs)) + for k, v := range r.Funcs { + r2.Funcs[k] = v + } r2.dirStack = append(r2.dirBootstrap[:0], r.dirStack...) r2.fillExpandConfig(r.ectx) r2.didReset = true diff --git a/vendor/mvdan.cc/sh/v3/pattern/pattern.go b/vendor/mvdan.cc/sh/v3/pattern/pattern.go index 185f2d80..a36e30c4 100644 --- a/vendor/mvdan.cc/sh/v3/pattern/pattern.go +++ b/vendor/mvdan.cc/sh/v3/pattern/pattern.go @@ -16,8 +16,8 @@ import ( "strings" ) -// TODO: support Mode in the other APIs too - +// Mode can be used to supply a number of options to the package's functions. +// Not all functions change their behavior with all of the options below. type Mode uint const ( @@ -254,13 +254,17 @@ func charClass(s string) (string, error) { // This can be useful to avoid extra work, like TranslatePattern. Note that this // function cannot be used to avoid QuotePattern, as backslashes are quoted by // that function but ignored here. -func HasMeta(pat string) bool { +func HasMeta(pat string, mode Mode) bool { for i := 0; i < len(pat); i++ { switch pat[i] { case '\\': i++ case '*', '?', '[': return true + case '{': + if mode&Braces != 0 { + return true + } } } return false @@ -270,11 +274,16 @@ func HasMeta(pat string) bool { // given text. The returned string is a pattern that matches the literal text. // // For example, QuoteMeta(`foo*bar?`) returns `foo\*bar\?`. -func QuoteMeta(pat string) string { +func QuoteMeta(pat string, mode Mode) string { any := false loop: for _, r := range pat { switch r { + case '{': + if mode&Braces == 0 { + continue + } + fallthrough case '*', '?', '[', '\\': any = true break loop @@ -288,6 +297,10 @@ loop: switch r { case '*', '?', '[', '\\': buf.WriteByte('\\') + case '{': + if mode&Braces != 0 { + buf.WriteByte('\\') + } } buf.WriteRune(r) } diff --git a/vendor/mvdan.cc/sh/v3/shell/source.go b/vendor/mvdan.cc/sh/v3/shell/source.go deleted file mode 100644 index 13261ffd..00000000 --- a/vendor/mvdan.cc/sh/v3/shell/source.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2018, Daniel Martí -// See LICENSE for licensing information - -package shell - -import ( - "context" - "fmt" - "os" - - "mvdan.cc/sh/v3/expand" - "mvdan.cc/sh/v3/interp" - "mvdan.cc/sh/v3/syntax" -) - -// SourceFile sources a shell file from disk and returns the variables -// declared in it. It is a convenience function that uses a default shell -// parser, parses a file from disk, and calls SourceNode. -// -// This function should be used with caution, as it can interpret arbitrary -// code. Untrusted shell programs shoudn't be sourced outside of a sandbox -// environment. -func SourceFile(ctx context.Context, path string) (map[string]expand.Variable, error) { - f, err := os.Open(path) - if err != nil { - return nil, fmt.Errorf("could not open: %v", err) - } - defer f.Close() - file, err := syntax.NewParser().Parse(f, path) - if err != nil { - return nil, fmt.Errorf("could not parse: %v", err) - } - return SourceNode(ctx, file) -} - -// SourceNode sources a shell program from a node and returns the -// variables declared in it. It accepts the same set of node types that -// interp/Runner.Run does. -// -// This function should be used with caution, as it can interpret arbitrary -// code. Untrusted shell programs shoudn't be sourced outside of a sandbox -// environment. -func SourceNode(ctx context.Context, node syntax.Node) (map[string]expand.Variable, error) { - r, _ := interp.New() - if err := r.Run(ctx, node); err != nil { - return nil, fmt.Errorf("could not run: %v", err) - } - // delete the internal shell vars that the user is not - // interested in - delete(r.Vars, "PWD") - delete(r.Vars, "UID") - delete(r.Vars, "HOME") - delete(r.Vars, "PATH") - delete(r.Vars, "IFS") - delete(r.Vars, "OPTIND") - return r.Vars, nil -} diff --git a/vendor/mvdan.cc/sh/v3/syntax/braces.go b/vendor/mvdan.cc/sh/v3/syntax/braces.go index 0baa43a0..dca854fd 100644 --- a/vendor/mvdan.cc/sh/v3/syntax/braces.go +++ b/vendor/mvdan.cc/sh/v3/syntax/braces.go @@ -129,7 +129,6 @@ func SplitBraces(word *Word) bool { broken = true } if !broken { - br.Chars = chars[0] acc.Parts = append(acc.Parts, br) break } diff --git a/vendor/mvdan.cc/sh/v3/syntax/lexer.go b/vendor/mvdan.cc/sh/v3/syntax/lexer.go index ac144cc2..b3daba6d 100644 --- a/vendor/mvdan.cc/sh/v3/syntax/lexer.go +++ b/vendor/mvdan.cc/sh/v3/syntax/lexer.go @@ -256,6 +256,7 @@ skipSpace: for r != '\n' && r != utf8.RuneSelf { if r == escNewl { p.litBs = append(p.litBs, '\\', '\n') + break } r = p.rune() } @@ -316,6 +317,7 @@ skipSpace: } else { p.tok = rightParen p.quote = noState + p.rune() // we are tokenizing manually } default: // including '(', '|' p.advanceLitRe(r) diff --git a/vendor/mvdan.cc/sh/v3/syntax/nodes.go b/vendor/mvdan.cc/sh/v3/syntax/nodes.go index e3d08b24..b8fa71bf 100644 --- a/vendor/mvdan.cc/sh/v3/syntax/nodes.go +++ b/vendor/mvdan.cc/sh/v3/syntax/nodes.go @@ -409,9 +409,9 @@ type Word struct { func (w *Word) Pos() Pos { return w.Parts[0].Pos() } func (w *Word) End() Pos { return w.Parts[len(w.Parts)-1].End() } -// Lit returns the word as a literal value, if the word consists of *syntax.Lit -// nodes only. An empty string is returned otherwise. Words with multiple -// literals, which can appear in some edge cases, are handled properly. +// Lit returns the word as a literal value, if the word consists of *Lit nodes +// only. An empty string is returned otherwise. Words with multiple literals, +// which can appear in some edge cases, are handled properly. // // For example, the word "foo" will return "foo", but the word "foo${bar}" will // return "". @@ -859,12 +859,11 @@ type LetClause struct { func (l *LetClause) Pos() Pos { return l.Let } func (l *LetClause) End() Pos { return l.Exprs[len(l.Exprs)-1].End() } -// BraceExp represents a Bash brace expression, such as "{x,y}" or "{1..10}". +// BraceExp represents a Bash brace expression, such as "{a,f}" or "{1..10}". // // This node will only appear as a result of SplitBraces. type BraceExp struct { Sequence bool // {x..y[..incr]} instead of {x,y[,...]} - Chars bool // sequence is of chars, not numbers (TODO: remove) Elems []*Word } diff --git a/vendor/mvdan.cc/sh/v3/syntax/parser.go b/vendor/mvdan.cc/sh/v3/syntax/parser.go index bce05999..e445b0ad 100644 --- a/vendor/mvdan.cc/sh/v3/syntax/parser.go +++ b/vendor/mvdan.cc/sh/v3/syntax/parser.go @@ -14,7 +14,7 @@ import ( // ParserOption is a function which can be passed to NewParser // to alter its behaviour. To apply option to existing Parser -// call it directly, for example syntax.KeepComments(true)(parser). +// call it directly, for example KeepComments(true)(parser). type ParserOption func(*Parser) // KeepComments makes the parser parse comments and attach them to @@ -524,9 +524,13 @@ func (p *Parser) unquotedWordPart(buf *bytes.Buffer, wp WordPart, quotes bool) ( } func (p *Parser) doHeredocs() { + hdocs := p.heredocs[p.buriedHdocs:] + if len(hdocs) == 0 { + // Nothing do do; don't even issue a read. + return + } p.rune() // consume '\n', since we know p.tok == _Newl old := p.quote - hdocs := p.heredocs[p.buriedHdocs:] p.heredocs = p.heredocs[:p.buriedHdocs] for i, r := range hdocs { if p.err != nil { @@ -840,7 +844,7 @@ func (p *Parser) invalidStmtStart() { } func (p *Parser) getWord() *Word { - if parts := p.wordParts(); len(parts) > 0 { + if parts := p.wordParts(); len(parts) > 0 && p.err == nil { return p.word(parts) } return nil @@ -1546,13 +1550,15 @@ func (p *Parser) hasValidIdent() bool { } if end := p.eqlOffs; end > 0 { if p.val[end-1] == '+' && p.lang != LangPOSIX { - end-- + end-- // a+=x } if ValidName(p.val[:end]) { return true } + } else if !ValidName(p.val) { + return false // *[i]=x } - return p.r == '[' + return p.r == '[' // a[i]=x } func (p *Parser) getAssign(needEqual bool) *Assign { diff --git a/vendor/mvdan.cc/sh/v3/syntax/printer.go b/vendor/mvdan.cc/sh/v3/syntax/printer.go index 2bb80e47..8ab1bdcd 100644 --- a/vendor/mvdan.cc/sh/v3/syntax/printer.go +++ b/vendor/mvdan.cc/sh/v3/syntax/printer.go @@ -15,7 +15,7 @@ import ( // PrinterOption is a function which can be passed to NewPrinter // to alter its behaviour. To apply option to existing Printer -// call it directly, for example syntax.KeepPadding(true)(printer). +// call it directly, for example KeepPadding(true)(printer). type PrinterOption func(*Printer) // Indent sets the number of spaces used for indentation. If set to 0, @@ -414,13 +414,13 @@ func (p *Printer) flushHeredocs() { bufWriter: &extra, line: r.Hdoc.Pos().Line(), } - p.tabsPrinter.word(r.Hdoc) + p.tabsPrinter.wordParts(r.Hdoc.Parts, true) p.indent() } else { p.indent() } } else if r.Hdoc != nil { - p.word(r.Hdoc) + p.wordParts(r.Hdoc.Parts, true) } p.unquotedWord(r.Word) if r.Hdoc != nil { @@ -478,6 +478,11 @@ func (p *Printer) semiRsrv(s string, pos Pos) { func (p *Printer) flushComments() { for i, c := range p.pendingComments { + if i == 0 { + // Flush any pending heredocs first. Otherwise, the + // comments would become part of a heredoc body. + p.flushHeredocs() + } p.firstLine = false // We can't call any of the newline methods, as they call this // function and we'd recurse forever.