Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: sources brace expansion #2075

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ require (
github.com/go-task/slim-sprig/v3 v3.0.0
github.com/go-task/template v0.1.0
github.com/joho/godotenv v1.5.1
github.com/mattn/go-zglob v0.0.6
github.com/mitchellh/hashstructure/v2 v2.0.2
github.com/otiai10/copy v1.14.1
github.com/radovskyb/watcher v1.0.7
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,6 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-zglob v0.0.6 h1:mP8RnmCgho4oaUYDIDn6GNxYk+qJGUs8fJLn+twYj2A=
github.com/mattn/go-zglob v0.0.6/go.mod h1:MxxjyoXXnMxfIpxTK2GAkw1w8glPsQILx3N5wrKakiY=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
Expand Down
65 changes: 53 additions & 12 deletions internal/execext/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ import (

"mvdan.cc/sh/v3/expand"
"mvdan.cc/sh/v3/interp"
"mvdan.cc/sh/v3/shell"
"mvdan.cc/sh/v3/syntax"

"github.com/go-task/task/v3/errors"
)

// RunCommandOptions is the options for the RunCommand func
// ErrNilOptions is returned when a nil options is given
var ErrNilOptions = errors.New("execext: nil options given")

// RunCommandOptions is the options for the [RunCommand] func.
type RunCommandOptions struct {
Command string
Dir string
Expand All @@ -29,9 +31,6 @@ type RunCommandOptions struct {
Stderr io.Writer
}

// ErrNilOptions is returned when a nil options is given
var ErrNilOptions = errors.New("execext: nil options given")

// RunCommand runs a shell command
func RunCommand(ctx context.Context, opts *RunCommandOptions) error {
if opts == nil {
Expand Down Expand Up @@ -91,22 +90,64 @@ func RunCommand(ctx context.Context, opts *RunCommandOptions) error {
return r.Run(ctx, p)
}

// Expand is a helper to mvdan.cc/shell.Fields that returns the first field
// if available.
func Expand(s string) (string, error) {
func escape(s string) string {
s = filepath.ToSlash(s)
s = strings.ReplaceAll(s, " ", `\ `)
s = strings.ReplaceAll(s, "&", `\&`)
s = strings.ReplaceAll(s, "(", `\(`)
s = strings.ReplaceAll(s, ")", `\)`)
fields, err := shell.Fields(s, nil)
return s
}

// ExpandLiteral is a wrapper around [expand.Literal]. It will escape the input
// string, expand any shell symbols (such as '~') and resolve any environment
// variables.
func ExpandLiteral(s string) (string, error) {
if s == "" {
return "", nil
}
s = escape(s)
p := syntax.NewParser()
var words []*syntax.Word
err := p.Words(strings.NewReader(s), func(w *syntax.Word) bool {
words = append(words, w)
return true
})
if err != nil {
return "", err
}
if len(fields) > 0 {
return fields[0], nil
if len(words) == 0 {
return "", nil
}
cfg := &expand.Config{
Env: expand.FuncEnviron(os.Getenv),
ReadDir2: os.ReadDir,
GlobStar: true,
}
return expand.Literal(cfg, words[0])
}

// ExpandFields is a wrapper around [expand.Fields]. It will escape the input
// string, expand any shell symbols (such as '~') and resolve any environment
// variables. It also expands brace expressions ({a.b}) and globs (*/**) and
// returns the results as a list of strings.
func ExpandFields(s string) ([]string, error) {
s = escape(s)
p := syntax.NewParser()
var words []*syntax.Word
err := p.Words(strings.NewReader(s), func(w *syntax.Word) bool {
words = append(words, w)
return true
})
if err != nil {
return nil, err
}
cfg := &expand.Config{
Env: expand.FuncEnviron(os.Getenv),
ReadDir2: os.ReadDir,
GlobStar: true,
}
return "", nil
return expand.Fields(cfg, words...)
}

func execHandler(next interp.ExecHandlerFunc) interp.ExecHandlerFunc {
Expand Down
9 changes: 1 addition & 8 deletions internal/fingerprint/glob.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import (
"os"
"sort"

"github.com/mattn/go-zglob"

"github.com/go-task/task/v3/internal/execext"
"github.com/go-task/task/v3/internal/filepathext"
"github.com/go-task/task/v3/taskfile/ast"
Expand Down Expand Up @@ -36,12 +34,7 @@ func Glob(dir string, g string) ([]string, error) {
files := make([]string, 0)
g = filepathext.SmartJoin(dir, g)

g, err := execext.Expand(g)
if err != nil {
return nil, err
}

fs, err := zglob.GlobFollowSymlinks(g)
fs, err := execext.ExpandFields(g)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ func (e *Executor) setupTempDir() error {
Fingerprint: filepathext.SmartJoin(e.Dir, ".task"),
}
} else if filepath.IsAbs(tempDir) || strings.HasPrefix(tempDir, "~") {
tempDir, err := execext.Expand(tempDir)
tempDir, err := execext.ExpandLiteral(tempDir)
if err != nil {
return err
}
Expand All @@ -141,7 +141,7 @@ func (e *Executor) setupTempDir() error {
remoteDir := env.GetTaskEnv("REMOTE_DIR")
if remoteDir != "" {
if filepath.IsAbs(remoteDir) || strings.HasPrefix(remoteDir, "~") {
remoteTempDir, err := execext.Expand(remoteDir)
remoteTempDir, err := execext.ExpandLiteral(remoteDir)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions taskfile/node_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (node *FileNode) ResolveEntrypoint(entrypoint string) (string, error) {
return entrypoint, nil
}

path, err := execext.Expand(entrypoint)
path, err := execext.ExpandLiteral(entrypoint)
if err != nil {
return "", err
}
Expand All @@ -100,7 +100,7 @@ func (node *FileNode) ResolveEntrypoint(entrypoint string) (string, error) {
}

func (node *FileNode) ResolveDir(dir string) (string, error) {
path, err := execext.Expand(dir)
path, err := execext.ExpandLiteral(dir)
if err != nil {
return "", err
}
Expand Down
2 changes: 1 addition & 1 deletion taskfile/node_git.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (node *GitNode) ResolveEntrypoint(entrypoint string) (string, error) {
}

func (node *GitNode) ResolveDir(dir string) (string, error) {
path, err := execext.Expand(dir)
path, err := execext.ExpandLiteral(dir)
if err != nil {
return "", err
}
Expand Down
2 changes: 1 addition & 1 deletion taskfile/node_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (node *HTTPNode) ResolveEntrypoint(entrypoint string) (string, error) {
}

func (node *HTTPNode) ResolveDir(dir string) (string, error) {
path, err := execext.Expand(dir)
path, err := execext.ExpandLiteral(dir)
if err != nil {
return "", err
}
Expand Down
4 changes: 2 additions & 2 deletions taskfile/node_stdin.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (node *StdinNode) ResolveEntrypoint(entrypoint string) (string, error) {
return entrypoint, nil
}

path, err := execext.Expand(entrypoint)
path, err := execext.ExpandLiteral(entrypoint)
if err != nil {
return "", err
}
Expand All @@ -61,7 +61,7 @@ func (node *StdinNode) ResolveEntrypoint(entrypoint string) (string, error) {
}

func (node *StdinNode) ResolveDir(dir string) (string, error) {
path, err := execext.Expand(dir)
path, err := execext.ExpandLiteral(dir)
if err != nil {
return "", err
}
Expand Down
2 changes: 1 addition & 1 deletion variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func (e *Executor) compiledTask(call *Call, evaluateShVars bool) (*ast.Task, err
Watch: origTask.Watch,
Namespace: origTask.Namespace,
}
new.Dir, err = execext.Expand(new.Dir)
new.Dir, err = execext.ExpandLiteral(new.Dir)
if err != nil {
return nil, err
}
Expand Down
Loading