1
0
mirror of https://github.com/go-task/task.git synced 2025-04-23 12:18:57 +02:00

go mod vendor

This commit is contained in:
Andrey Nering 2020-03-22 21:42:45 -03:00
parent d36f73de01
commit d52d74c64c
11 changed files with 63 additions and 90 deletions

2
vendor/modules.txt vendored
View File

@ -37,7 +37,7 @@ golang.org/x/xerrors
golang.org/x/xerrors/internal golang.org/x/xerrors/internal
# gopkg.in/yaml.v2 v2.2.2 # gopkg.in/yaml.v2 v2.2.2
gopkg.in/yaml.v2 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/expand
mvdan.cc/sh/v3/interp mvdan.cc/sh/v3/interp
mvdan.cc/sh/v3/pattern mvdan.cc/sh/v3/pattern

View File

@ -24,13 +24,13 @@ func Braces(word *syntax.Word) []*syntax.Word {
continue continue
} }
if br.Sequence { if br.Sequence {
var from, to int chars := false
if br.Chars { 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]) from = int(br.Elems[0].Lit()[0])
to = int(br.Elems[1].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 upward := from <= to
incr := 1 incr := 1
@ -54,7 +54,7 @@ func Braces(word *syntax.Word) []*syntax.Word {
next := *word next := *word
next.Parts = next.Parts[i+1:] next.Parts = next.Parts[i+1:]
lit := &syntax.Lit{} lit := &syntax.Lit{}
if br.Chars { if chars {
lit.Value = string(n) lit.Value = string(n)
} else { } else {
lit.Value = strconv.Itoa(n) lit.Value = strconv.Itoa(n)

View File

@ -159,6 +159,8 @@ func Document(cfg *Config, word *syntax.Word) (string, error) {
return cfg.fieldJoin(field), nil return cfg.fieldJoin(field), nil
} }
const patMode = pattern.Filenames | pattern.Braces
// Pattern expands a single shell word as a pattern, using syntax.QuotePattern // 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 // on any non-quoted parts of the input word. The result can be used on
// syntax.TranslatePattern directly. // syntax.TranslatePattern directly.
@ -174,7 +176,7 @@ func Pattern(cfg *Config, word *syntax.Word) (string, error) {
buf := cfg.strBuilder() buf := cfg.strBuilder()
for _, part := range field { for _, part := range field {
if part.quote > quoteNone { if part.quote > quoteNone {
buf.WriteString(pattern.QuoteMeta(part.val)) buf.WriteString(pattern.QuoteMeta(part.val, patMode))
} else { } else {
buf.WriteString(part.val) buf.WriteString(part.val)
} }
@ -345,11 +347,11 @@ func (cfg *Config) escapedGlobField(parts []fieldPart) (escaped string, glob boo
buf := cfg.strBuilder() buf := cfg.strBuilder()
for _, part := range parts { for _, part := range parts {
if part.quote > quoteNone { if part.quote > quoteNone {
buf.WriteString(pattern.QuoteMeta(part.val)) buf.WriteString(pattern.QuoteMeta(part.val, patMode))
continue continue
} }
buf.WriteString(part.val) buf.WriteString(part.val)
if pattern.HasMeta(part.val) { if pattern.HasMeta(part.val, patMode) {
glob = true glob = true
} }
} }
@ -367,9 +369,10 @@ func Fields(cfg *Config, words ...*syntax.Word) ([]string, error) {
fields := make([]string, 0, len(words)) fields := make([]string, 0, len(words))
dir := cfg.envGet("PWD") dir := cfg.envGet("PWD")
for _, word := range words { for _, word := range words {
afterBraces := []*syntax.Word{word} word := *word // make a copy, since SplitBraces replaces the Parts slice
if syntax.SplitBraces(word) { afterBraces := []*syntax.Word{&word}
afterBraces = Braces(word) if syntax.SplitBraces(&word) {
afterBraces = Braces(&word)
} }
for _, word2 := range afterBraces { for _, word2 := range afterBraces {
wfields, err := cfg.wordFields(word2.Parts) wfields, err := cfg.wordFields(word2.Parts)
@ -540,7 +543,6 @@ func (cfg *Config) wordFields(wps []syntax.WordPart) ([][]fieldPart, error) {
} }
curField = append(curField, fp) curField = append(curField, fp)
case *syntax.DblQuoted: case *syntax.DblQuoted:
allowEmpty = true
if len(x.Parts) == 1 { if len(x.Parts) == 1 {
pe, _ := x.Parts[0].(*syntax.ParamExp) pe, _ := x.Parts[0].(*syntax.ParamExp)
if elems := cfg.quotedElems(pe); elems != nil { if elems := cfg.quotedElems(pe); elems != nil {
@ -556,6 +558,7 @@ func (cfg *Config) wordFields(wps []syntax.WordPart) ([][]fieldPart, error) {
continue continue
} }
} }
allowEmpty = true
wfield, err := cfg.wordField(x.Parts, quoteDouble) wfield, err := cfg.wordField(x.Parts, quoteDouble)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -745,7 +745,6 @@ func (r *Runner) sub() *Runner {
Env: r.Env, Env: r.Env,
Dir: r.Dir, Dir: r.Dir,
Params: r.Params, Params: r.Params,
Funcs: r.Funcs,
execHandler: r.execHandler, execHandler: r.execHandler,
openHandler: r.openHandler, openHandler: r.openHandler,
stdin: r.stdin, stdin: r.stdin,
@ -766,6 +765,10 @@ func (r *Runner) sub() *Runner {
for k, v := range r.cmdVars { for k, v := range r.cmdVars {
r2.cmdVars[k] = v 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.dirStack = append(r2.dirBootstrap[:0], r.dirStack...)
r2.fillExpandConfig(r.ectx) r2.fillExpandConfig(r.ectx)
r2.didReset = true r2.didReset = true

View File

@ -16,8 +16,8 @@ import (
"strings" "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 type Mode uint
const ( const (
@ -254,13 +254,17 @@ func charClass(s string) (string, error) {
// This can be useful to avoid extra work, like TranslatePattern. Note that this // 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 // function cannot be used to avoid QuotePattern, as backslashes are quoted by
// that function but ignored here. // that function but ignored here.
func HasMeta(pat string) bool { func HasMeta(pat string, mode Mode) bool {
for i := 0; i < len(pat); i++ { for i := 0; i < len(pat); i++ {
switch pat[i] { switch pat[i] {
case '\\': case '\\':
i++ i++
case '*', '?', '[': case '*', '?', '[':
return true return true
case '{':
if mode&Braces != 0 {
return true
}
} }
} }
return false return false
@ -270,11 +274,16 @@ func HasMeta(pat string) bool {
// given text. The returned string is a pattern that matches the literal text. // given text. The returned string is a pattern that matches the literal text.
// //
// For example, QuoteMeta(`foo*bar?`) returns `foo\*bar\?`. // For example, QuoteMeta(`foo*bar?`) returns `foo\*bar\?`.
func QuoteMeta(pat string) string { func QuoteMeta(pat string, mode Mode) string {
any := false any := false
loop: loop:
for _, r := range pat { for _, r := range pat {
switch r { switch r {
case '{':
if mode&Braces == 0 {
continue
}
fallthrough
case '*', '?', '[', '\\': case '*', '?', '[', '\\':
any = true any = true
break loop break loop
@ -288,6 +297,10 @@ loop:
switch r { switch r {
case '*', '?', '[', '\\': case '*', '?', '[', '\\':
buf.WriteByte('\\') buf.WriteByte('\\')
case '{':
if mode&Braces != 0 {
buf.WriteByte('\\')
}
} }
buf.WriteRune(r) buf.WriteRune(r)
} }

View File

@ -1,57 +0,0 @@
// Copyright (c) 2018, Daniel Martí <mvdan@mvdan.cc>
// 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
}

View File

@ -129,7 +129,6 @@ func SplitBraces(word *Word) bool {
broken = true broken = true
} }
if !broken { if !broken {
br.Chars = chars[0]
acc.Parts = append(acc.Parts, br) acc.Parts = append(acc.Parts, br)
break break
} }

View File

@ -256,6 +256,7 @@ skipSpace:
for r != '\n' && r != utf8.RuneSelf { for r != '\n' && r != utf8.RuneSelf {
if r == escNewl { if r == escNewl {
p.litBs = append(p.litBs, '\\', '\n') p.litBs = append(p.litBs, '\\', '\n')
break
} }
r = p.rune() r = p.rune()
} }
@ -316,6 +317,7 @@ skipSpace:
} else { } else {
p.tok = rightParen p.tok = rightParen
p.quote = noState p.quote = noState
p.rune() // we are tokenizing manually
} }
default: // including '(', '|' default: // including '(', '|'
p.advanceLitRe(r) p.advanceLitRe(r)

View File

@ -409,9 +409,9 @@ type Word struct {
func (w *Word) Pos() Pos { return w.Parts[0].Pos() } func (w *Word) Pos() Pos { return w.Parts[0].Pos() }
func (w *Word) End() Pos { return w.Parts[len(w.Parts)-1].End() } 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 // Lit returns the word as a literal value, if the word consists of *Lit nodes
// nodes only. An empty string is returned otherwise. Words with multiple // only. An empty string is returned otherwise. Words with multiple literals,
// literals, which can appear in some edge cases, are handled properly. // which can appear in some edge cases, are handled properly.
// //
// For example, the word "foo" will return "foo", but the word "foo${bar}" will // For example, the word "foo" will return "foo", but the word "foo${bar}" will
// return "". // return "".
@ -859,12 +859,11 @@ type LetClause struct {
func (l *LetClause) Pos() Pos { return l.Let } func (l *LetClause) Pos() Pos { return l.Let }
func (l *LetClause) End() Pos { return l.Exprs[len(l.Exprs)-1].End() } 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. // This node will only appear as a result of SplitBraces.
type BraceExp struct { type BraceExp struct {
Sequence bool // {x..y[..incr]} instead of {x,y[,...]} Sequence bool // {x..y[..incr]} instead of {x,y[,...]}
Chars bool // sequence is of chars, not numbers (TODO: remove)
Elems []*Word Elems []*Word
} }

View File

@ -14,7 +14,7 @@ import (
// ParserOption is a function which can be passed to NewParser // ParserOption is a function which can be passed to NewParser
// to alter its behaviour. To apply option to existing Parser // 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) type ParserOption func(*Parser)
// KeepComments makes the parser parse comments and attach them to // 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() { 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 p.rune() // consume '\n', since we know p.tok == _Newl
old := p.quote old := p.quote
hdocs := p.heredocs[p.buriedHdocs:]
p.heredocs = p.heredocs[:p.buriedHdocs] p.heredocs = p.heredocs[:p.buriedHdocs]
for i, r := range hdocs { for i, r := range hdocs {
if p.err != nil { if p.err != nil {
@ -840,7 +844,7 @@ func (p *Parser) invalidStmtStart() {
} }
func (p *Parser) getWord() *Word { 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 p.word(parts)
} }
return nil return nil
@ -1546,13 +1550,15 @@ func (p *Parser) hasValidIdent() bool {
} }
if end := p.eqlOffs; end > 0 { if end := p.eqlOffs; end > 0 {
if p.val[end-1] == '+' && p.lang != LangPOSIX { if p.val[end-1] == '+' && p.lang != LangPOSIX {
end-- end-- // a+=x
} }
if ValidName(p.val[:end]) { if ValidName(p.val[:end]) {
return true 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 { func (p *Parser) getAssign(needEqual bool) *Assign {

View File

@ -15,7 +15,7 @@ import (
// PrinterOption is a function which can be passed to NewPrinter // PrinterOption is a function which can be passed to NewPrinter
// to alter its behaviour. To apply option to existing Printer // 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) type PrinterOption func(*Printer)
// Indent sets the number of spaces used for indentation. If set to 0, // Indent sets the number of spaces used for indentation. If set to 0,
@ -414,13 +414,13 @@ func (p *Printer) flushHeredocs() {
bufWriter: &extra, bufWriter: &extra,
line: r.Hdoc.Pos().Line(), line: r.Hdoc.Pos().Line(),
} }
p.tabsPrinter.word(r.Hdoc) p.tabsPrinter.wordParts(r.Hdoc.Parts, true)
p.indent() p.indent()
} else { } else {
p.indent() p.indent()
} }
} else if r.Hdoc != nil { } else if r.Hdoc != nil {
p.word(r.Hdoc) p.wordParts(r.Hdoc.Parts, true)
} }
p.unquotedWord(r.Word) p.unquotedWord(r.Word)
if r.Hdoc != nil { if r.Hdoc != nil {
@ -478,6 +478,11 @@ func (p *Printer) semiRsrv(s string, pos Pos) {
func (p *Printer) flushComments() { func (p *Printer) flushComments() {
for i, c := range p.pendingComments { 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 p.firstLine = false
// We can't call any of the newline methods, as they call this // We can't call any of the newline methods, as they call this
// function and we'd recurse forever. // function and we'd recurse forever.