mirror of
https://github.com/go-task/task.git
synced 2025-03-17 21:08:01 +02:00
update dependencies
also make sure the module that enables /dev/null path of the sh interpreter is enabled
This commit is contained in:
parent
2fc32414f5
commit
0513a21e25
24
Gopkg.lock
generated
24
Gopkg.lock
generated
@ -4,14 +4,14 @@
|
||||
[[projects]]
|
||||
name = "github.com/Masterminds/semver"
|
||||
packages = ["."]
|
||||
revision = "517734cc7d6470c0d07130e40fd40bdeb9bcd3fd"
|
||||
version = "v1.3.1"
|
||||
revision = "15d8430ab86497c5c0da827b748823945e1cf1e1"
|
||||
version = "v1.4.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/Masterminds/sprig"
|
||||
packages = ["."]
|
||||
revision = "175e437013029f9a1c35bdf04bc451b0d20d4331"
|
||||
revision = "82f6f19d47b416d27ae039939b44afaa0575860e"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/aokoli/goutils"
|
||||
@ -29,19 +29,19 @@
|
||||
branch = "master"
|
||||
name = "github.com/huandu/xstrings"
|
||||
packages = ["."]
|
||||
revision = "3959339b333561bf62a38b424fd41517c2c90f40"
|
||||
revision = "d6590c0c31d16526217fa60fbd2067f7afcd78c5"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/imdario/mergo"
|
||||
packages = ["."]
|
||||
revision = "e3000cb3d28c72b837601cac94debd91032d19fe"
|
||||
revision = "7fe0c75c13abdee74b09fcacef5ea1c6bba6a874"
|
||||
version = "0.2.4"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/mattn/go-zglob"
|
||||
packages = [".","fastwalk"]
|
||||
revision = "95345c4e1c0ebc9d16a3284177f09360f4d20fab"
|
||||
revision = "4ecb59231939b2e499b1f2fd8f075565977d2452"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pmezard/go-difflib"
|
||||
@ -65,7 +65,7 @@
|
||||
branch = "master"
|
||||
name = "github.com/spf13/pflag"
|
||||
packages = ["."]
|
||||
revision = "7aff26db30c1be810f9de5038ec5ef96ac41fd7c"
|
||||
revision = "a9789e855c7696159b7db0db7f440b449edf2b31"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/stretchr/testify"
|
||||
@ -77,19 +77,19 @@
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = ["pbkdf2","scrypt"]
|
||||
revision = "81e90905daefcd6fd217b62423c0908922eadb30"
|
||||
revision = "9419663f5a44be8b34ca85f08abc5fe1be11f8a3"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = ["context"]
|
||||
revision = "66aacef3dd8a676686c7ae3716979581e8b03c47"
|
||||
revision = "a04bdaca5b32abe1c069418fb7088ae607de5bd0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sync"
|
||||
packages = ["errgroup"]
|
||||
revision = "f52d1811a62927559de87708c8913c1650ce4f26"
|
||||
revision = "8e0aa688b654ef28caa72506fa5ec8dba9fc7690"
|
||||
|
||||
[[projects]]
|
||||
branch = "v2"
|
||||
@ -101,7 +101,7 @@
|
||||
branch = "master"
|
||||
name = "mvdan.cc/sh"
|
||||
packages = ["interp","syntax"]
|
||||
revision = "d8d2c36c06455d4bb8e2116cc2b955271046329d"
|
||||
revision = "24a28656b7c1d2532406e69527366ecf9f455a17"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
|
@ -16,6 +16,7 @@ dl-deps:
|
||||
update-deps:
|
||||
desc: Updates dependencies
|
||||
cmds:
|
||||
- dep ensure
|
||||
- dep ensure -update
|
||||
- dep prune
|
||||
|
||||
|
@ -41,9 +41,13 @@ func RunCommand(opts *RunCommandOptions) error {
|
||||
Context: opts.Context,
|
||||
Dir: opts.Dir,
|
||||
Env: opts.Env,
|
||||
Stdin: opts.Stdin,
|
||||
Stdout: opts.Stdout,
|
||||
Stderr: opts.Stderr,
|
||||
|
||||
Exec: interp.DefaultExec,
|
||||
Open: interp.OpenDevImpls(interp.DefaultOpen),
|
||||
|
||||
Stdin: opts.Stdin,
|
||||
Stdout: opts.Stdout,
|
||||
Stderr: opts.Stderr,
|
||||
}
|
||||
if err = r.Reset(); err != nil {
|
||||
return err
|
||||
|
5
vendor/github.com/Masterminds/semver/CHANGELOG.md
generated
vendored
5
vendor/github.com/Masterminds/semver/CHANGELOG.md
generated
vendored
@ -1,3 +1,8 @@
|
||||
# 1.4.0 (2017-10-04)
|
||||
|
||||
## Changed
|
||||
- #61: Update NewVersion to parse ints with a 64bit int size (thanks @zknill)
|
||||
|
||||
# 1.3.1 (2017-07-10)
|
||||
|
||||
## Fixed
|
||||
|
6
vendor/github.com/Masterminds/semver/version.go
generated
vendored
6
vendor/github.com/Masterminds/semver/version.go
generated
vendored
@ -64,14 +64,14 @@ func NewVersion(v string) (*Version, error) {
|
||||
}
|
||||
|
||||
var temp int64
|
||||
temp, err := strconv.ParseInt(m[1], 10, 32)
|
||||
temp, err := strconv.ParseInt(m[1], 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error parsing version segment: %s", err)
|
||||
}
|
||||
sv.major = temp
|
||||
|
||||
if m[2] != "" {
|
||||
temp, err = strconv.ParseInt(strings.TrimPrefix(m[2], "."), 10, 32)
|
||||
temp, err = strconv.ParseInt(strings.TrimPrefix(m[2], "."), 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error parsing version segment: %s", err)
|
||||
}
|
||||
@ -81,7 +81,7 @@ func NewVersion(v string) (*Version, error) {
|
||||
}
|
||||
|
||||
if m[3] != "" {
|
||||
temp, err = strconv.ParseInt(strings.TrimPrefix(m[3], "."), 10, 32)
|
||||
temp, err = strconv.ParseInt(strings.TrimPrefix(m[3], "."), 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Error parsing version segment: %s", err)
|
||||
}
|
||||
|
232
vendor/github.com/Masterminds/sprig/crypto.go
generated
vendored
232
vendor/github.com/Masterminds/sprig/crypto.go
generated
vendored
@ -10,12 +10,16 @@ import (
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"golang.org/x/crypto/scrypt"
|
||||
@ -146,3 +150,231 @@ func pemBlockForKey(priv interface{}) *pem.Block {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type certificate struct {
|
||||
Cert string
|
||||
Key string
|
||||
}
|
||||
|
||||
func generateCertificateAuthority(
|
||||
cn string,
|
||||
daysValid int,
|
||||
) (certificate, error) {
|
||||
ca := certificate{}
|
||||
|
||||
template, err := getBaseCertTemplate(cn, nil, nil, daysValid)
|
||||
if err != nil {
|
||||
return ca, err
|
||||
}
|
||||
// Override KeyUsage and IsCA
|
||||
template.KeyUsage = x509.KeyUsageKeyEncipherment |
|
||||
x509.KeyUsageDigitalSignature |
|
||||
x509.KeyUsageCertSign
|
||||
template.IsCA = true
|
||||
|
||||
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
return ca, fmt.Errorf("error generating rsa key: %s", err)
|
||||
}
|
||||
|
||||
ca.Cert, ca.Key, err = getCertAndKey(template, priv, template, priv)
|
||||
if err != nil {
|
||||
return ca, err
|
||||
}
|
||||
|
||||
return ca, nil
|
||||
}
|
||||
|
||||
func generateSelfSignedCertificate(
|
||||
cn string,
|
||||
ips []interface{},
|
||||
alternateDNS []interface{},
|
||||
daysValid int,
|
||||
) (certificate, error) {
|
||||
cert := certificate{}
|
||||
|
||||
template, err := getBaseCertTemplate(cn, ips, alternateDNS, daysValid)
|
||||
if err != nil {
|
||||
return cert, err
|
||||
}
|
||||
|
||||
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
return cert, fmt.Errorf("error generating rsa key: %s", err)
|
||||
}
|
||||
|
||||
cert.Cert, cert.Key, err = getCertAndKey(template, priv, template, priv)
|
||||
if err != nil {
|
||||
return cert, err
|
||||
}
|
||||
|
||||
return cert, nil
|
||||
}
|
||||
|
||||
func generateSignedCertificate(
|
||||
cn string,
|
||||
ips []interface{},
|
||||
alternateDNS []interface{},
|
||||
daysValid int,
|
||||
ca certificate,
|
||||
) (certificate, error) {
|
||||
cert := certificate{}
|
||||
|
||||
decodedSignerCert, _ := pem.Decode([]byte(ca.Cert))
|
||||
if decodedSignerCert == nil {
|
||||
return cert, errors.New("unable to decode certificate")
|
||||
}
|
||||
signerCert, err := x509.ParseCertificate(decodedSignerCert.Bytes)
|
||||
if err != nil {
|
||||
return cert, fmt.Errorf(
|
||||
"error parsing certificate: decodedSignerCert.Bytes: %s",
|
||||
err,
|
||||
)
|
||||
}
|
||||
decodedSignerKey, _ := pem.Decode([]byte(ca.Key))
|
||||
if decodedSignerKey == nil {
|
||||
return cert, errors.New("unable to decode key")
|
||||
}
|
||||
signerKey, err := x509.ParsePKCS1PrivateKey(decodedSignerKey.Bytes)
|
||||
if err != nil {
|
||||
return cert, fmt.Errorf(
|
||||
"error parsing prive key: decodedSignerKey.Bytes: %s",
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
||||
template, err := getBaseCertTemplate(cn, ips, alternateDNS, daysValid)
|
||||
if err != nil {
|
||||
return cert, err
|
||||
}
|
||||
|
||||
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
return cert, fmt.Errorf("error generating rsa key: %s", err)
|
||||
}
|
||||
|
||||
cert.Cert, cert.Key, err = getCertAndKey(
|
||||
template,
|
||||
priv,
|
||||
signerCert,
|
||||
signerKey,
|
||||
)
|
||||
if err != nil {
|
||||
return cert, err
|
||||
}
|
||||
|
||||
return cert, nil
|
||||
}
|
||||
|
||||
func getCertAndKey(
|
||||
template *x509.Certificate,
|
||||
signeeKey *rsa.PrivateKey,
|
||||
parent *x509.Certificate,
|
||||
signingKey *rsa.PrivateKey,
|
||||
) (string, string, error) {
|
||||
derBytes, err := x509.CreateCertificate(
|
||||
rand.Reader,
|
||||
template,
|
||||
parent,
|
||||
&signeeKey.PublicKey,
|
||||
signingKey,
|
||||
)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("error creating certificate: %s", err)
|
||||
}
|
||||
|
||||
certBuffer := bytes.Buffer{}
|
||||
if err := pem.Encode(
|
||||
&certBuffer,
|
||||
&pem.Block{Type: "CERTIFICATE", Bytes: derBytes},
|
||||
); err != nil {
|
||||
return "", "", fmt.Errorf("error pem-encoding certificate: %s", err)
|
||||
}
|
||||
|
||||
keyBuffer := bytes.Buffer{}
|
||||
if err := pem.Encode(
|
||||
&keyBuffer,
|
||||
&pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(signeeKey),
|
||||
},
|
||||
); err != nil {
|
||||
return "", "", fmt.Errorf("error pem-encoding key: %s", err)
|
||||
}
|
||||
|
||||
return string(certBuffer.Bytes()), string(keyBuffer.Bytes()), nil
|
||||
}
|
||||
|
||||
func getBaseCertTemplate(
|
||||
cn string,
|
||||
ips []interface{},
|
||||
alternateDNS []interface{},
|
||||
daysValid int,
|
||||
) (*x509.Certificate, error) {
|
||||
ipAddresses, err := getNetIPs(ips)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dnsNames, err := getAlternateDNSStrs(alternateDNS)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &x509.Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
Subject: pkix.Name{
|
||||
CommonName: cn,
|
||||
},
|
||||
IPAddresses: ipAddresses,
|
||||
DNSNames: dnsNames,
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().Add(time.Hour * 24 * time.Duration(daysValid)),
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{
|
||||
x509.ExtKeyUsageServerAuth,
|
||||
x509.ExtKeyUsageClientAuth,
|
||||
},
|
||||
BasicConstraintsValid: true,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getNetIPs(ips []interface{}) ([]net.IP, error) {
|
||||
if ips == nil {
|
||||
return []net.IP{}, nil
|
||||
}
|
||||
var ipStr string
|
||||
var ok bool
|
||||
var netIP net.IP
|
||||
netIPs := make([]net.IP, len(ips))
|
||||
for i, ip := range ips {
|
||||
ipStr, ok = ip.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("error parsing ip: %v is not a string", ip)
|
||||
}
|
||||
netIP = net.ParseIP(ipStr)
|
||||
if netIP == nil {
|
||||
return nil, fmt.Errorf("error parsing ip: %s", ipStr)
|
||||
}
|
||||
netIPs[i] = netIP
|
||||
}
|
||||
return netIPs, nil
|
||||
}
|
||||
|
||||
func getAlternateDNSStrs(alternateDNS []interface{}) ([]string, error) {
|
||||
if alternateDNS == nil {
|
||||
return []string{}, nil
|
||||
}
|
||||
var dnsStr string
|
||||
var ok bool
|
||||
alternateDNSStrs := make([]string, len(alternateDNS))
|
||||
for i, dns := range alternateDNS {
|
||||
dnsStr, ok = dns.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(
|
||||
"error processing alternate dns name: %v is not a string",
|
||||
dns,
|
||||
)
|
||||
}
|
||||
alternateDNSStrs[i] = dnsStr
|
||||
}
|
||||
return alternateDNSStrs, nil
|
||||
}
|
||||
|
5
vendor/github.com/Masterminds/sprig/date.go
generated
vendored
5
vendor/github.com/Masterminds/sprig/date.go
generated
vendored
@ -69,3 +69,8 @@ func dateAgo(date interface{}) string {
|
||||
duration := time.Since(t) / time.Second * time.Second
|
||||
return duration.String()
|
||||
}
|
||||
|
||||
func toDate(fmt, str string) time.Time {
|
||||
t, _ := time.ParseInLocation(fmt, str, time.Local)
|
||||
return t
|
||||
}
|
||||
|
2
vendor/github.com/Masterminds/sprig/doc.go
generated
vendored
2
vendor/github.com/Masterminds/sprig/doc.go
generated
vendored
@ -89,7 +89,7 @@ Integer Slice Functions:
|
||||
Conversions:
|
||||
|
||||
- atoi: Convert a string to an integer. 0 if the integer could not be parsed.
|
||||
- in64: Convert a string or another numeric type to an int64.
|
||||
- int64: Convert a string or another numeric type to an int64.
|
||||
- int: Convert a string or another numeric type to an int.
|
||||
- float64: Convert a string or another numeric type to a float64.
|
||||
|
||||
|
8
vendor/github.com/Masterminds/sprig/functions.go
generated
vendored
8
vendor/github.com/Masterminds/sprig/functions.go
generated
vendored
@ -99,6 +99,7 @@ var genericMap = map[string]interface{}{
|
||||
"dateInZone": dateInZone,
|
||||
"dateModify": dateModify,
|
||||
"ago": dateAgo,
|
||||
"toDate": toDate,
|
||||
|
||||
// Strings
|
||||
"abbrev": abbrev,
|
||||
@ -251,8 +252,11 @@ var genericMap = map[string]interface{}{
|
||||
"has": func(needle interface{}, haystack []interface{}) bool { return inList(haystack, needle) },
|
||||
|
||||
// Crypto:
|
||||
"genPrivateKey": generatePrivateKey,
|
||||
"derivePassword": derivePassword,
|
||||
"genPrivateKey": generatePrivateKey,
|
||||
"derivePassword": derivePassword,
|
||||
"genCA": generateCertificateAuthority,
|
||||
"genSelfSignedCert": generateSelfSignedCertificate,
|
||||
"genSignedCert": generateSignedCertificate,
|
||||
|
||||
// UUIDs:
|
||||
"uuidv4": uuidv4,
|
||||
|
17
vendor/github.com/huandu/xstrings/convert.go
generated
vendored
17
vendor/github.com/huandu/xstrings/convert.go
generated
vendored
@ -43,19 +43,26 @@ func ToCamelCase(str string) string {
|
||||
if len(str) == 0 {
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
buf.WriteRune(unicode.ToUpper(r0))
|
||||
r0, size = utf8.DecodeRuneInString(str)
|
||||
str = str[size:]
|
||||
|
||||
r0 = unicode.ToUpper(r0)
|
||||
|
||||
for len(str) > 0 {
|
||||
r1 = r0
|
||||
r0, size = utf8.DecodeRuneInString(str)
|
||||
str = str[size:]
|
||||
|
||||
if r1 == '_' && r0 != '_' {
|
||||
if r1 == '_' && r0 == '_' {
|
||||
buf.WriteRune(r1)
|
||||
continue
|
||||
}
|
||||
|
||||
if r1 == '_' {
|
||||
r0 = unicode.ToUpper(r0)
|
||||
} else {
|
||||
r0 = unicode.ToLower(r0)
|
||||
}
|
||||
|
||||
if r1 != '_' {
|
||||
buf.WriteRune(r1)
|
||||
}
|
||||
}
|
||||
|
24
vendor/github.com/imdario/mergo/map.go
generated
vendored
24
vendor/github.com/imdario/mergo/map.go
generated
vendored
@ -61,6 +61,13 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
|
||||
dstMap[fieldName] = src.Field(i).Interface()
|
||||
}
|
||||
}
|
||||
case reflect.Ptr:
|
||||
if dst.IsNil() {
|
||||
v := reflect.New(dst.Type().Elem())
|
||||
dst.Set(v)
|
||||
}
|
||||
dst = dst.Elem()
|
||||
fallthrough
|
||||
case reflect.Struct:
|
||||
srcMap := src.Interface().(map[string]interface{})
|
||||
for key := range srcMap {
|
||||
@ -85,6 +92,7 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
|
||||
srcKind = reflect.Ptr
|
||||
}
|
||||
}
|
||||
|
||||
if !srcElement.IsValid() {
|
||||
continue
|
||||
}
|
||||
@ -92,14 +100,16 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
|
||||
if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if srcKind == reflect.Map {
|
||||
if err = deepMap(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("type mismatch on %s field: found %v, expected %v", fieldName, srcKind, dstKind)
|
||||
} else if dstKind == reflect.Interface && dstElement.Kind() == reflect.Interface {
|
||||
if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
|
||||
return
|
||||
}
|
||||
} else if srcKind == reflect.Map {
|
||||
if err = deepMap(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("type mismatch on %s field: found %v, expected %v", fieldName, srcKind, dstKind)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
50
vendor/github.com/imdario/mergo/merge.go
generated
vendored
50
vendor/github.com/imdario/mergo/merge.go
generated
vendored
@ -12,6 +12,18 @@ import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func hasExportedField(dst reflect.Value) (exported bool) {
|
||||
for i, n := 0, dst.NumField(); i < n; i++ {
|
||||
field := dst.Type().Field(i)
|
||||
if field.Anonymous {
|
||||
exported = exported || hasExportedField(dst.Field(i))
|
||||
} else {
|
||||
exported = exported || len(field.PkgPath) == 0
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Traverses recursively both values, assigning src's fields values to dst.
|
||||
// The map argument tracks comparisons that have already been seen, which allows
|
||||
// short circuiting on recursive types.
|
||||
@ -34,12 +46,22 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
|
||||
}
|
||||
switch dst.Kind() {
|
||||
case reflect.Struct:
|
||||
for i, n := 0, dst.NumField(); i < n; i++ {
|
||||
if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, overwrite); err != nil {
|
||||
return
|
||||
if hasExportedField(dst) {
|
||||
for i, n := 0, dst.NumField(); i < n; i++ {
|
||||
if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, overwrite); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) {
|
||||
dst.Set(src)
|
||||
}
|
||||
}
|
||||
case reflect.Map:
|
||||
if len(src.MapKeys()) == 0 && !src.IsNil() && len(dst.MapKeys()) == 0 {
|
||||
dst.Set(reflect.MakeMap(dst.Type()))
|
||||
return
|
||||
}
|
||||
for _, key := range src.MapKeys() {
|
||||
srcElement := src.MapIndex(key)
|
||||
if !srcElement.IsValid() {
|
||||
@ -67,6 +89,10 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
|
||||
}
|
||||
}
|
||||
}
|
||||
if dstElement.IsValid() && reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map {
|
||||
continue
|
||||
}
|
||||
|
||||
if !isEmptyValue(srcElement) && (overwrite || (!dstElement.IsValid() || isEmptyValue(dst))) {
|
||||
if dst.IsNil() {
|
||||
dst.Set(reflect.MakeMap(dst.Type()))
|
||||
@ -77,6 +103,24 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, ov
|
||||
case reflect.Ptr:
|
||||
fallthrough
|
||||
case reflect.Interface:
|
||||
if src.Kind() != reflect.Interface {
|
||||
if dst.IsNil() || overwrite {
|
||||
if dst.CanSet() && (overwrite || isEmptyValue(dst)) {
|
||||
dst.Set(src)
|
||||
}
|
||||
} else if src.Kind() == reflect.Ptr {
|
||||
if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, overwrite); err != nil {
|
||||
return
|
||||
}
|
||||
} else if dst.Elem().Type() == src.Type() {
|
||||
if err = deepMerge(dst.Elem(), src, visited, depth+1, overwrite); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
return ErrDifferentArgumentsTypes
|
||||
}
|
||||
break
|
||||
}
|
||||
if src.IsNil() {
|
||||
break
|
||||
} else if dst.IsNil() || overwrite {
|
||||
|
2
vendor/github.com/imdario/mergo/mergo.go
generated
vendored
2
vendor/github.com/imdario/mergo/mergo.go
generated
vendored
@ -45,7 +45,7 @@ func isEmptyValue(v reflect.Value) bool {
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
case reflect.Interface, reflect.Ptr, reflect.Func:
|
||||
return v.IsNil()
|
||||
}
|
||||
return false
|
||||
|
21
vendor/github.com/mattn/go-zglob/LICENSE
generated
vendored
Normal file
21
vendor/github.com/mattn/go-zglob/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Yasuhiro Matsumoto
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
12
vendor/github.com/spf13/pflag/count.go
generated
vendored
12
vendor/github.com/spf13/pflag/count.go
generated
vendored
@ -11,13 +11,13 @@ func newCountValue(val int, p *int) *countValue {
|
||||
}
|
||||
|
||||
func (i *countValue) Set(s string) error {
|
||||
v, err := strconv.ParseInt(s, 0, 64)
|
||||
// -1 means that no specific value was passed, so increment
|
||||
if v == -1 {
|
||||
// "+1" means that no specific value was passed, so increment
|
||||
if s == "+1" {
|
||||
*i = countValue(*i + 1)
|
||||
} else {
|
||||
*i = countValue(v)
|
||||
return nil
|
||||
}
|
||||
v, err := strconv.ParseInt(s, 0, 0)
|
||||
*i = countValue(v)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ func (f *FlagSet) CountVar(p *int, name string, usage string) {
|
||||
// CountVarP is like CountVar only take a shorthand for the flag name.
|
||||
func (f *FlagSet) CountVarP(p *int, name, shorthand string, usage string) {
|
||||
flag := f.VarPF(newCountValue(0, p), name, shorthand, usage)
|
||||
flag.NoOptDefVal = "-1"
|
||||
flag.NoOptDefVal = "+1"
|
||||
}
|
||||
|
||||
// CountVar like CountVar only the flag is placed on the CommandLine instead of a given flag set
|
||||
|
42
vendor/github.com/spf13/pflag/flag.go
generated
vendored
42
vendor/github.com/spf13/pflag/flag.go
generated
vendored
@ -202,12 +202,18 @@ func sortFlags(flags map[NormalizedName]*Flag) []*Flag {
|
||||
func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) {
|
||||
f.normalizeNameFunc = n
|
||||
f.sortedFormal = f.sortedFormal[:0]
|
||||
for k, v := range f.orderedFormal {
|
||||
delete(f.formal, NormalizedName(v.Name))
|
||||
nname := f.normalizeFlagName(v.Name)
|
||||
v.Name = string(nname)
|
||||
f.formal[nname] = v
|
||||
f.orderedFormal[k] = v
|
||||
for fname, flag := range f.formal {
|
||||
nname := f.normalizeFlagName(flag.Name)
|
||||
if fname == nname {
|
||||
continue
|
||||
}
|
||||
flag.Name = string(nname)
|
||||
delete(f.formal, fname)
|
||||
f.formal[nname] = flag
|
||||
if _, set := f.actual[fname]; set {
|
||||
delete(f.actual, fname)
|
||||
f.actual[nname] = flag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -440,13 +446,15 @@ func (f *FlagSet) Set(name, value string) error {
|
||||
return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err)
|
||||
}
|
||||
|
||||
if f.actual == nil {
|
||||
f.actual = make(map[NormalizedName]*Flag)
|
||||
}
|
||||
f.actual[normalName] = flag
|
||||
f.orderedActual = append(f.orderedActual, flag)
|
||||
if !flag.Changed {
|
||||
if f.actual == nil {
|
||||
f.actual = make(map[NormalizedName]*Flag)
|
||||
}
|
||||
f.actual[normalName] = flag
|
||||
f.orderedActual = append(f.orderedActual, flag)
|
||||
|
||||
flag.Changed = true
|
||||
flag.Changed = true
|
||||
}
|
||||
|
||||
if flag.Deprecated != "" {
|
||||
fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
|
||||
@ -664,6 +672,10 @@ func (f *FlagSet) FlagUsagesWrapped(cols int) string {
|
||||
if flag.NoOptDefVal != "true" {
|
||||
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
|
||||
}
|
||||
case "count":
|
||||
if flag.NoOptDefVal != "+1" {
|
||||
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
|
||||
}
|
||||
default:
|
||||
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
|
||||
}
|
||||
@ -916,6 +928,9 @@ func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []strin
|
||||
}
|
||||
|
||||
err = fn(flag, value)
|
||||
if err != nil {
|
||||
f.failf(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -966,6 +981,9 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
|
||||
}
|
||||
|
||||
err = fn(flag, value)
|
||||
if err != nil {
|
||||
f.failf(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
7
vendor/golang.org/x/crypto/scrypt/scrypt.go
generated
vendored
7
vendor/golang.org/x/crypto/scrypt/scrypt.go
generated
vendored
@ -220,9 +220,10 @@ func smix(b []byte, r, N int, v, xy []uint32) {
|
||||
//
|
||||
// dk, err := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32)
|
||||
//
|
||||
// The recommended parameters for interactive logins as of 2009 are N=16384,
|
||||
// r=8, p=1. They should be increased as memory latency and CPU parallelism
|
||||
// increases. Remember to get a good random salt.
|
||||
// The recommended parameters for interactive logins as of 2017 are N=32768, r=8
|
||||
// and p=1. The parameters N, r, and p should be increased as memory latency and
|
||||
// CPU parallelism increases; consider setting N to the highest power of 2 you
|
||||
// can derive within 100 milliseconds. Remember to get a good random salt.
|
||||
func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) {
|
||||
if N <= 1 || N&(N-1) != 0 {
|
||||
return nil, errors.New("scrypt: N must be > 1 and a power of 2")
|
||||
|
3
vendor/golang.org/x/net/README
generated
vendored
3
vendor/golang.org/x/net/README
generated
vendored
@ -1,3 +0,0 @@
|
||||
This repository holds supplementary Go networking libraries.
|
||||
|
||||
To submit changes to this repository, see http://golang.org/doc/contribute.html.
|
16
vendor/golang.org/x/net/README.md
generated
vendored
Normal file
16
vendor/golang.org/x/net/README.md
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
# Go Networking
|
||||
|
||||
This repository holds supplementary Go networking libraries.
|
||||
|
||||
## Download/Install
|
||||
|
||||
The easiest way to install is to run `go get -u golang.org/x/net`. You can
|
||||
also manually git clone the repository to `$GOPATH/src/golang.org/x/net`.
|
||||
|
||||
## Report Issues / Send Patches
|
||||
|
||||
This repository uses Gerrit for code changes. To learn how to submit
|
||||
changes to this repository, see https://golang.org/doc/contribute.html.
|
||||
The main issue tracker for the net repository is located at
|
||||
https://github.com/golang/go/issues. Prefix your issue with "x/net:" in the
|
||||
subject line, so it is easy to find.
|
2
vendor/golang.org/x/sync/README
generated
vendored
2
vendor/golang.org/x/sync/README
generated
vendored
@ -1,2 +0,0 @@
|
||||
This repository provides Go concurrency primitives in addition to the
|
||||
ones provided by the language and "sync" and "sync/atomic" packages.
|
18
vendor/golang.org/x/sync/README.md
generated
vendored
Normal file
18
vendor/golang.org/x/sync/README.md
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
# Go Sync
|
||||
|
||||
This repository provides Go concurrency primitives in addition to the
|
||||
ones provided by the language and "sync" and "sync/atomic" packages.
|
||||
|
||||
## Download/Install
|
||||
|
||||
The easiest way to install is to run `go get -u golang.org/x/sync`. You can
|
||||
also manually git clone the repository to `$GOPATH/src/golang.org/x/sync`.
|
||||
|
||||
## Report Issues / Send Patches
|
||||
|
||||
This repository uses Gerrit for code changes. To learn how to submit changes to
|
||||
this repository, see https://golang.org/doc/contribute.html.
|
||||
|
||||
The main issue tracker for the sync repository is located at
|
||||
https://github.com/golang/go/issues. Prefix your issue with "x/sync:" in the
|
||||
subject line, so it is easy to find.
|
3
vendor/mvdan.cc/sh/.travis.yml
vendored
3
vendor/mvdan.cc/sh/.travis.yml
vendored
@ -14,3 +14,6 @@ script:
|
||||
- go test -short -race ./...
|
||||
- shfmt -version
|
||||
- goveralls
|
||||
# at least make sure the builds work
|
||||
- GOOS=windows go install ./interp
|
||||
- GOOS=darwin go install ./interp
|
||||
|
4
vendor/mvdan.cc/sh/README.md
vendored
4
vendor/mvdan.cc/sh/README.md
vendored
@ -7,10 +7,6 @@
|
||||
A shell parser, formatter and interpreter. Supports [POSIX Shell],
|
||||
[Bash] and [mksh]. Requires Go 1.8 or later.
|
||||
|
||||
**Please note that the import paths have been moved from
|
||||
`github.com/mvdan/sh/...` to `mvdan.cc/sh/...` for 2.0.** This will help
|
||||
future-proof the project by making it depend less on GitHub.
|
||||
|
||||
### shfmt
|
||||
|
||||
go get -u mvdan.cc/sh/cmd/shfmt
|
||||
|
4
vendor/mvdan.cc/sh/interp/arith.go
vendored
4
vendor/mvdan.cc/sh/interp/arith.go
vendored
@ -36,7 +36,7 @@ func (r *Runner) arithm(expr syntax.ArithmExpr) int {
|
||||
} else {
|
||||
val--
|
||||
}
|
||||
r.setVar(name, strconv.Itoa(val))
|
||||
r.setVar(name, nil, strconv.Itoa(val))
|
||||
if x.Post {
|
||||
return old
|
||||
}
|
||||
@ -108,7 +108,7 @@ func (r *Runner) assgnArit(b *syntax.BinaryArithm) int {
|
||||
case syntax.ShrAssgn:
|
||||
val >>= uint(arg)
|
||||
}
|
||||
r.setVar(name, strconv.Itoa(val))
|
||||
r.setVar(name, nil, strconv.Itoa(val))
|
||||
return val
|
||||
}
|
||||
|
||||
|
25
vendor/mvdan.cc/sh/interp/builtin.go
vendored
25
vendor/mvdan.cc/sh/interp/builtin.go
vendored
@ -19,7 +19,7 @@ func isBuiltin(name string) bool {
|
||||
"echo", "printf", "break", "continue", "pwd", "cd",
|
||||
"wait", "builtin", "trap", "type", "source", ".", "command",
|
||||
"pushd", "popd", "umask", "alias", "unalias", "fg", "bg",
|
||||
"getopts", "eval", "test", "[":
|
||||
"getopts", "eval", "test", "[", "exec":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@ -161,6 +161,9 @@ func (r *Runner) builtinCode(pos syntax.Pos, name string, args []string) int {
|
||||
if err != nil || !info.IsDir() {
|
||||
return 1
|
||||
}
|
||||
if !hasPermissionToDir(info) {
|
||||
return 1
|
||||
}
|
||||
r.Dir = dir
|
||||
case "wait":
|
||||
if len(args) > 0 {
|
||||
@ -213,7 +216,7 @@ func (r *Runner) builtinCode(pos syntax.Pos, name string, args []string) int {
|
||||
if len(args) < 1 {
|
||||
r.runErr(pos, "source: need filename")
|
||||
}
|
||||
f, err := os.Open(r.relPath(args[0]))
|
||||
f, err := r.open(r.relPath(args[0]), os.O_RDONLY, 0, false)
|
||||
if err != nil {
|
||||
r.errf("eval: %v\n", err)
|
||||
return 1
|
||||
@ -247,6 +250,18 @@ func (r *Runner) builtinCode(pos syntax.Pos, name string, args []string) int {
|
||||
p.next()
|
||||
expr := p.classicTest("[", false)
|
||||
return oneIf(r.bashTest(expr) == "")
|
||||
case "exec":
|
||||
// TODO: Consider syscall.Exec, i.e. actually replacing
|
||||
// the process. It's in theory what a shell should do,
|
||||
// but in practice it would kill the entire Go process
|
||||
// and it's not available on Windows.
|
||||
if len(args) == 0 {
|
||||
// TODO: different behavior, apparently
|
||||
return 0
|
||||
}
|
||||
r.exec(args[0], args[1:])
|
||||
r.lastExit()
|
||||
return r.exit
|
||||
case "trap", "command", "pushd", "popd",
|
||||
"umask", "alias", "unalias", "fg", "bg", "getopts":
|
||||
r.runErr(pos, "unhandled builtin: %s", name)
|
||||
@ -255,8 +270,8 @@ func (r *Runner) builtinCode(pos syntax.Pos, name string, args []string) int {
|
||||
}
|
||||
|
||||
func (r *Runner) relPath(path string) string {
|
||||
if filepath.IsAbs(path) {
|
||||
return path
|
||||
if !filepath.IsAbs(path) {
|
||||
path = filepath.Join(r.Dir, path)
|
||||
}
|
||||
return filepath.Join(r.Dir, path)
|
||||
return filepath.Clean(path)
|
||||
}
|
||||
|
21
vendor/mvdan.cc/sh/interp/dev.go
vendored
21
vendor/mvdan.cc/sh/interp/dev.go
vendored
@ -1,21 +0,0 @@
|
||||
package interp
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
var _ io.ReadWriteCloser = devNull{}
|
||||
|
||||
type devNull struct{}
|
||||
|
||||
func (devNull) Read(_ []byte) (int, error) {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
func (devNull) Write(p []byte) (int, error) {
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func (devNull) Close() error {
|
||||
return nil
|
||||
}
|
268
vendor/mvdan.cc/sh/interp/interp.go
vendored
268
vendor/mvdan.cc/sh/interp/interp.go
vendored
@ -10,14 +10,12 @@ import (
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"mvdan.cc/sh/syntax"
|
||||
@ -48,6 +46,9 @@ type Runner struct {
|
||||
// of vars.
|
||||
Params []string
|
||||
|
||||
Exec ModuleExec
|
||||
Open ModuleOpen
|
||||
|
||||
filename string // only if Node was a File
|
||||
|
||||
// Separate maps, note that bash allows a name to be both a var
|
||||
@ -78,6 +79,76 @@ type Runner struct {
|
||||
stopOnCmdErr bool // set -e
|
||||
}
|
||||
|
||||
// Reset will set the unexported fields back to zero, fill any exported
|
||||
// fields with their default values if not set, and prepare the runner
|
||||
// to interpret a program.
|
||||
//
|
||||
// This function should be called once before running any node. It can
|
||||
// be skipped before any following runs to keep internal state, such as
|
||||
// declared variables.
|
||||
func (r *Runner) Reset() error {
|
||||
// reset the internal state
|
||||
*r = Runner{
|
||||
Env: r.Env,
|
||||
Dir: r.Dir,
|
||||
Params: r.Params,
|
||||
Context: r.Context,
|
||||
Stdin: r.Stdin,
|
||||
Stdout: r.Stdout,
|
||||
Stderr: r.Stderr,
|
||||
Exec: r.Exec,
|
||||
Open: r.Open,
|
||||
}
|
||||
if r.Context == nil {
|
||||
r.Context = context.Background()
|
||||
}
|
||||
if r.Env == nil {
|
||||
r.Env = os.Environ()
|
||||
}
|
||||
r.envMap = make(map[string]string, len(r.Env))
|
||||
for _, kv := range r.Env {
|
||||
i := strings.IndexByte(kv, '=')
|
||||
if i < 0 {
|
||||
return fmt.Errorf("env not in the form key=value: %q", kv)
|
||||
}
|
||||
name, val := kv[:i], kv[i+1:]
|
||||
r.envMap[name] = val
|
||||
}
|
||||
if _, ok := r.envMap["HOME"]; !ok {
|
||||
u, _ := user.Current()
|
||||
r.envMap["HOME"] = u.HomeDir
|
||||
}
|
||||
if r.Dir == "" {
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get current dir: %v", err)
|
||||
}
|
||||
r.Dir = dir
|
||||
}
|
||||
if r.Exec == nil {
|
||||
r.Exec = DefaultExec
|
||||
}
|
||||
if r.Open == nil {
|
||||
r.Open = DefaultOpen
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Runner) ctx() Ctxt {
|
||||
c := Ctxt{
|
||||
Context: r.Context,
|
||||
Env: r.Env,
|
||||
Dir: r.Dir,
|
||||
Stdin: r.Stdin,
|
||||
Stdout: r.Stdout,
|
||||
Stderr: r.Stderr,
|
||||
}
|
||||
for name, val := range r.cmdVars {
|
||||
c.Env = append(c.Env, name+"="+varStr(val))
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// varValue can hold a string, an indexed array ([]string) or an
|
||||
// associative array (map[string]string)
|
||||
// TODO: implement associative arrays
|
||||
@ -136,36 +207,56 @@ func (e RunError) Error() string {
|
||||
return fmt.Sprintf("%s:%s: %s", e.Filename, e.Pos.String(), e.Text)
|
||||
}
|
||||
|
||||
func (r *Runner) runErr(pos syntax.Pos, format string, a ...interface{}) {
|
||||
func (r *Runner) setErr(err error) {
|
||||
if r.err == nil {
|
||||
r.err = RunError{
|
||||
Filename: r.filename,
|
||||
Pos: pos,
|
||||
Text: fmt.Sprintf(format, a...),
|
||||
}
|
||||
r.err = err
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runner) runErr(pos syntax.Pos, format string, a ...interface{}) {
|
||||
r.setErr(RunError{
|
||||
Filename: r.filename,
|
||||
Pos: pos,
|
||||
Text: fmt.Sprintf(format, a...),
|
||||
})
|
||||
}
|
||||
|
||||
func (r *Runner) lastExit() {
|
||||
if r.err == nil {
|
||||
r.err = ExitCode(r.exit)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runner) setVar(name string, val varValue) {
|
||||
func (r *Runner) setVar(name string, index syntax.ArithmExpr, val varValue) {
|
||||
if r.vars == nil {
|
||||
r.vars = make(map[string]varValue, 4)
|
||||
}
|
||||
r.vars[name] = val
|
||||
if index == nil {
|
||||
r.vars[name] = val
|
||||
return
|
||||
}
|
||||
// from the syntax package, we know that val must be a string if
|
||||
// index is non-nil; nested arrays are forbidden.
|
||||
valStr := val.(string)
|
||||
var list []string
|
||||
switch x := r.vars[name].(type) {
|
||||
case string:
|
||||
list = []string{x}
|
||||
case []string:
|
||||
list = x
|
||||
}
|
||||
k := r.arithm(index)
|
||||
for len(list) < k+1 {
|
||||
list = append(list, "")
|
||||
}
|
||||
list[k] = valStr
|
||||
r.vars[name] = list
|
||||
}
|
||||
|
||||
func (r *Runner) lookupVar(name string) (varValue, bool) {
|
||||
switch name {
|
||||
case "PWD":
|
||||
return r.Dir, true
|
||||
case "HOME":
|
||||
u, _ := user.Current()
|
||||
return u.HomeDir, true
|
||||
}
|
||||
if val, e := r.cmdVars[name]; e {
|
||||
return val, true
|
||||
@ -221,42 +312,6 @@ opts:
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (r *Runner) Reset() error {
|
||||
// reset the internal state
|
||||
*r = Runner{
|
||||
Env: r.Env,
|
||||
Dir: r.Dir,
|
||||
Params: r.Params,
|
||||
Context: r.Context,
|
||||
Stdin: r.Stdin,
|
||||
Stdout: r.Stdout,
|
||||
Stderr: r.Stderr,
|
||||
}
|
||||
if r.Context == nil {
|
||||
r.Context = context.Background()
|
||||
}
|
||||
if r.Env == nil {
|
||||
r.Env = os.Environ()
|
||||
}
|
||||
r.envMap = make(map[string]string, len(r.Env))
|
||||
for _, kv := range r.Env {
|
||||
i := strings.IndexByte(kv, '=')
|
||||
if i < 0 {
|
||||
return fmt.Errorf("env not in the form key=value: %q", kv)
|
||||
}
|
||||
name, val := kv[:i], kv[i+1:]
|
||||
r.envMap[name] = val
|
||||
}
|
||||
if r.Dir == "" {
|
||||
dir, err := os.Getwd()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not get current dir: %v", err)
|
||||
}
|
||||
r.Dir = dir
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run starts the interpreter and returns any error.
|
||||
func (r *Runner) Run(node syntax.Node) error {
|
||||
r.filename = ""
|
||||
@ -278,6 +333,11 @@ func (r *Runner) Run(node syntax.Node) error {
|
||||
return r.err
|
||||
}
|
||||
|
||||
func (r *Runner) Stmt(stmt *syntax.Stmt) error {
|
||||
r.stmt(stmt)
|
||||
return r.err
|
||||
}
|
||||
|
||||
func (r *Runner) outf(format string, a ...interface{}) {
|
||||
fmt.Fprintf(r.Stdout, format, a...)
|
||||
}
|
||||
@ -375,7 +435,7 @@ func escapedGlob(parts []fieldPart) (escaped string, glob bool) {
|
||||
return buf.String(), glob
|
||||
}
|
||||
|
||||
func (r *Runner) fields(words []*syntax.Word) []string {
|
||||
func (r *Runner) Fields(words []*syntax.Word) []string {
|
||||
fields := make([]string, 0, len(words))
|
||||
baseDir, _ := escapedGlob([]fieldPart{{val: r.Dir}})
|
||||
for _, word := range words {
|
||||
@ -465,9 +525,22 @@ func (r *Runner) assignValue(as *syntax.Assign) varValue {
|
||||
return s
|
||||
}
|
||||
if as.Array != nil {
|
||||
strs := make([]string, len(as.Array.Elems))
|
||||
maxIndex := len(as.Array.Elems) - 1
|
||||
indexes := make([]int, len(as.Array.Elems))
|
||||
for i, elem := range as.Array.Elems {
|
||||
strs[i] = r.loneWord(elem.Value)
|
||||
if elem.Index == nil {
|
||||
indexes[i] = i
|
||||
continue
|
||||
}
|
||||
k := r.arithm(elem.Index)
|
||||
indexes[i] = k
|
||||
if k > maxIndex {
|
||||
maxIndex = k
|
||||
}
|
||||
}
|
||||
strs := make([]string, maxIndex+1)
|
||||
for i, elem := range as.Array.Elems {
|
||||
strs[indexes[i]] = r.loneWord(elem.Value)
|
||||
}
|
||||
if !as.Append || prev == nil {
|
||||
return strs
|
||||
@ -524,10 +597,11 @@ func (r *Runner) cmd(cm syntax.Command) {
|
||||
r2 := *r
|
||||
r2.stmts(x.StmtList)
|
||||
r.exit = r2.exit
|
||||
r.setErr(r2.err)
|
||||
case *syntax.CallExpr:
|
||||
if len(x.Args) == 0 {
|
||||
for _, as := range x.Assigns {
|
||||
r.setVar(as.Name.Value, r.assignValue(as))
|
||||
r.setVar(as.Name.Value, as.Index, r.assignValue(as))
|
||||
}
|
||||
break
|
||||
}
|
||||
@ -538,7 +612,7 @@ func (r *Runner) cmd(cm syntax.Command) {
|
||||
for _, as := range x.Assigns {
|
||||
r.cmdVars[as.Name.Value] = r.assignValue(as)
|
||||
}
|
||||
fields := r.fields(x.Args)
|
||||
fields := r.Fields(x.Args)
|
||||
r.call(x.Args[0].Pos(), fields[0], fields[1:])
|
||||
r.cmdVars = oldVars
|
||||
case *syntax.BinaryCmd:
|
||||
@ -564,12 +638,17 @@ func (r *Runner) cmd(cm syntax.Command) {
|
||||
r2.Stderr = r.Stderr
|
||||
}
|
||||
r.Stdin = pr
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
r2.stmt(x.X)
|
||||
pw.Close()
|
||||
wg.Done()
|
||||
}()
|
||||
r.stmt(x.Y)
|
||||
pr.Close()
|
||||
wg.Wait()
|
||||
r.setErr(r2.err)
|
||||
}
|
||||
case *syntax.IfClause:
|
||||
r.stmts(x.Cond)
|
||||
@ -592,8 +671,8 @@ func (r *Runner) cmd(cm syntax.Command) {
|
||||
switch y := x.Loop.(type) {
|
||||
case *syntax.WordIter:
|
||||
name := y.Name.Value
|
||||
for _, field := range r.fields(y.Items) {
|
||||
r.setVar(name, field)
|
||||
for _, field := range r.Fields(y.Items) {
|
||||
r.setVar(name, nil, field)
|
||||
if r.loopStmtsBroken(x.Do) {
|
||||
break
|
||||
}
|
||||
@ -645,18 +724,16 @@ func (r *Runner) cmd(cm syntax.Command) {
|
||||
r.runErr(cm.Pos(), "unhandled declare opts")
|
||||
}
|
||||
for _, as := range x.Assigns {
|
||||
r.setVar(as.Name.Value, r.assignValue(as))
|
||||
r.setVar(as.Name.Value, as.Index, r.assignValue(as))
|
||||
}
|
||||
case *syntax.TimeClause:
|
||||
start := time.Now()
|
||||
if x.Stmt != nil {
|
||||
r.stmt(x.Stmt)
|
||||
}
|
||||
elapsed := time.Since(start)
|
||||
real := time.Since(start)
|
||||
r.outf("\n")
|
||||
min := int(elapsed.Minutes())
|
||||
sec := math.Remainder(elapsed.Seconds(), 60.0)
|
||||
r.outf("real\t%dm%.3fs\n", min, sec)
|
||||
r.outf("real\t%s\n", elapsedString(real))
|
||||
// TODO: can we do these?
|
||||
r.outf("user\t0m0.000s\n")
|
||||
r.outf("sys\t0m0.000s\n")
|
||||
@ -668,6 +745,12 @@ func (r *Runner) cmd(cm syntax.Command) {
|
||||
}
|
||||
}
|
||||
|
||||
func elapsedString(d time.Duration) string {
|
||||
min := int(d.Minutes())
|
||||
sec := math.Remainder(d.Seconds(), 60.0)
|
||||
return fmt.Sprintf("%dm%.3fs", min, sec)
|
||||
}
|
||||
|
||||
func (r *Runner) stmts(sl syntax.StmtList) {
|
||||
for _, stmt := range sl.Stmts {
|
||||
r.stmt(stmt)
|
||||
@ -716,17 +799,9 @@ func (r *Runner) redir(rd *syntax.Redirect) (io.Closer, error) {
|
||||
case syntax.RdrOut, syntax.RdrAll:
|
||||
mode = os.O_RDWR | os.O_CREATE | os.O_TRUNC
|
||||
}
|
||||
var f io.ReadWriteCloser
|
||||
switch arg {
|
||||
case "/dev/null":
|
||||
f = devNull{}
|
||||
default:
|
||||
var err error
|
||||
f, err = os.OpenFile(r.relPath(arg), mode, 0644)
|
||||
if err != nil {
|
||||
// TODO: print to stderr?
|
||||
return nil, err
|
||||
}
|
||||
f, err := r.open(r.relPath(arg), mode, 0644, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch rd.Op {
|
||||
case syntax.RdrIn:
|
||||
@ -844,6 +919,7 @@ func (r *Runner) wordFields(wps []syntax.WordPart, quoted bool) [][]fieldPart {
|
||||
} else {
|
||||
splitAdd(val)
|
||||
}
|
||||
r.setErr(r2.err)
|
||||
case *syntax.ArithmExp:
|
||||
curField = append(curField, fieldPart{
|
||||
val: strconv.Itoa(r.arithm(x.X)),
|
||||
@ -872,31 +948,31 @@ func (r *Runner) call(pos syntax.Pos, name string, args []string) {
|
||||
r.exit = r.builtinCode(pos, name, args)
|
||||
return
|
||||
}
|
||||
cmd := exec.CommandContext(r.Context, name, args...)
|
||||
cmd.Env = r.Env
|
||||
for name, val := range r.cmdVars {
|
||||
cmd.Env = append(cmd.Env, name+"="+varStr(val))
|
||||
}
|
||||
cmd.Dir = r.Dir
|
||||
cmd.Stdin = r.Stdin
|
||||
cmd.Stdout = r.Stdout
|
||||
cmd.Stderr = r.Stderr
|
||||
err := cmd.Run()
|
||||
r.exec(name, args)
|
||||
}
|
||||
|
||||
func (r *Runner) exec(name string, args []string) {
|
||||
err := r.Exec(r.ctx(), name, args)
|
||||
switch x := err.(type) {
|
||||
case *exec.ExitError:
|
||||
// started, but errored - default to 1 if OS
|
||||
// doesn't have exit statuses
|
||||
r.exit = 1
|
||||
if status, ok := x.Sys().(syscall.WaitStatus); ok {
|
||||
r.exit = status.ExitStatus()
|
||||
}
|
||||
case *exec.Error:
|
||||
// did not start
|
||||
// TODO: can this be anything other than
|
||||
// "command not found"?
|
||||
r.exit = 127
|
||||
// TODO: print something?
|
||||
default:
|
||||
case nil:
|
||||
r.exit = 0
|
||||
case ExitCode:
|
||||
r.exit = int(x)
|
||||
default:
|
||||
r.setErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runner) open(path string, flags int, mode os.FileMode, print bool) (io.ReadWriteCloser, error) {
|
||||
f, err := r.Open(r.ctx(), path, flags, mode)
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
case *os.PathError:
|
||||
if print {
|
||||
r.errf("%v\n", err)
|
||||
}
|
||||
default:
|
||||
r.setErr(err)
|
||||
}
|
||||
return f, err
|
||||
}
|
||||
|
100
vendor/mvdan.cc/sh/interp/module.go
vendored
Normal file
100
vendor/mvdan.cc/sh/interp/module.go
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
// Copyright (c) 2017, Daniel Martí <mvdan@mvdan.cc>
|
||||
// See LICENSE for licensing information
|
||||
|
||||
package interp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Ctxt is the type passed to all the module functions. It contains some
|
||||
// of the current state of the Runner, as well as some fields necessary
|
||||
// to implement some of the modules.
|
||||
type Ctxt struct {
|
||||
Context context.Context
|
||||
Env []string
|
||||
Dir string
|
||||
Stdin io.Reader
|
||||
Stdout io.Writer
|
||||
Stderr io.Writer
|
||||
}
|
||||
|
||||
// ModuleExec is the module responsible for executing a program. It is
|
||||
// executed for all CallExpr nodes where the name is neither a declared
|
||||
// function nor a builtin.
|
||||
//
|
||||
// Use a return error of type ExitCode to set the exit code. A nil error
|
||||
// has the same effect as ExitCode(0). If the error is of any other
|
||||
// type, the interpreter will come to a stop.
|
||||
//
|
||||
// TODO: replace name with path, to avoid the common "path :=
|
||||
// exec.LookPath(name)"?
|
||||
type ModuleExec func(ctx Ctxt, name string, args []string) error
|
||||
|
||||
func DefaultExec(ctx Ctxt, name string, args []string) error {
|
||||
cmd := exec.CommandContext(ctx.Context, name, args...)
|
||||
cmd.Env = ctx.Env
|
||||
cmd.Dir = ctx.Dir
|
||||
cmd.Stdin = ctx.Stdin
|
||||
cmd.Stdout = ctx.Stdout
|
||||
cmd.Stderr = ctx.Stderr
|
||||
err := cmd.Run()
|
||||
switch x := err.(type) {
|
||||
case *exec.ExitError:
|
||||
// started, but errored - default to 1 if OS
|
||||
// doesn't have exit statuses
|
||||
if status, ok := x.Sys().(syscall.WaitStatus); ok {
|
||||
return ExitCode(status.ExitStatus())
|
||||
}
|
||||
return ExitCode(1)
|
||||
case *exec.Error:
|
||||
// did not start
|
||||
// TODO: can this be anything other than
|
||||
// "command not found"?
|
||||
return ExitCode(127)
|
||||
// TODO: print something?
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ModuleOpen is the module responsible for opening a file. It is
|
||||
// executed for all files that are opened directly by the shell, such as
|
||||
// in redirects. Files opened by executed programs are not included.
|
||||
//
|
||||
// The path parameter is absolute and has been cleaned.
|
||||
//
|
||||
// Use a return error of type *os.PathError to have the error printed to
|
||||
// stderr and the exit code set to 1. If the error is of any other type,
|
||||
// the interpreter will come to a stop.
|
||||
//
|
||||
// TODO: What about stat calls? They are used heavily in the builtin
|
||||
// test expressions, and also when doing a cd. Should they have a
|
||||
// separate module?
|
||||
type ModuleOpen func(ctx Ctxt, path string, flag int, perm os.FileMode) (io.ReadWriteCloser, error)
|
||||
|
||||
func DefaultOpen(ctx Ctxt, path string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) {
|
||||
return os.OpenFile(path, flag, perm)
|
||||
}
|
||||
|
||||
func OpenDevImpls(next ModuleOpen) ModuleOpen {
|
||||
return func(ctx Ctxt, path string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) {
|
||||
switch path {
|
||||
case "/dev/null":
|
||||
return devNull{}, nil
|
||||
}
|
||||
return next(ctx, path, flag, perm)
|
||||
}
|
||||
}
|
||||
|
||||
var _ io.ReadWriteCloser = devNull{}
|
||||
|
||||
type devNull struct{}
|
||||
|
||||
func (devNull) Read(p []byte) (int, error) { return 0, io.EOF }
|
||||
func (devNull) Write(p []byte) (int, error) { return len(p), nil }
|
||||
func (devNull) Close() error { return nil }
|
2
vendor/mvdan.cc/sh/interp/param.go
vendored
2
vendor/mvdan.cc/sh/interp/param.go
vendored
@ -136,7 +136,7 @@ func (r *Runner) paramExp(pe *syntax.ParamExp) string {
|
||||
fallthrough
|
||||
case syntax.SubstColAssgn:
|
||||
if str == "" {
|
||||
r.setVar(name, arg)
|
||||
r.setVar(name, nil, arg)
|
||||
str = arg
|
||||
}
|
||||
case syntax.RemSmallPrefix:
|
||||
|
49
vendor/mvdan.cc/sh/interp/perm_unix.go
vendored
Normal file
49
vendor/mvdan.cc/sh/interp/perm_unix.go
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2017, Andrey Nering <andrey.nering@gmail.com>
|
||||
// See LICENSE for licensing information
|
||||
|
||||
// +build !windows
|
||||
|
||||
package interp
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/user"
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// hasPermissionToDir returns if the OS current user has execute permission
|
||||
// to the given directory
|
||||
func hasPermissionToDir(info os.FileInfo) bool {
|
||||
user, err := user.Current()
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
uid, _ := strconv.Atoi(user.Uid)
|
||||
// super-user
|
||||
if uid == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
st, _ := info.Sys().(*syscall.Stat_t)
|
||||
if st == nil {
|
||||
return true
|
||||
}
|
||||
perm := info.Mode().Perm()
|
||||
// user (u)
|
||||
if perm&0100 != 0 && st.Uid == uint32(uid) {
|
||||
return true
|
||||
}
|
||||
|
||||
gid, _ := strconv.Atoi(user.Gid)
|
||||
// other users in group (g)
|
||||
if perm&0010 != 0 && st.Uid != uint32(uid) && st.Gid == uint32(gid) {
|
||||
return true
|
||||
}
|
||||
// remaining users (o)
|
||||
if perm&0001 != 0 && st.Uid != uint32(uid) && st.Gid != uint32(gid) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
11
vendor/mvdan.cc/sh/interp/perm_windows.go
vendored
Normal file
11
vendor/mvdan.cc/sh/interp/perm_windows.go
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright (c) 2017, Andrey Nering <andrey.nering@gmail.com>
|
||||
// See LICENSE for licensing information
|
||||
|
||||
package interp
|
||||
|
||||
import "os"
|
||||
|
||||
// hasPermissionToDir is a no-op on Windows.
|
||||
func hasPermissionToDir(info os.FileInfo) bool {
|
||||
return true
|
||||
}
|
4
vendor/mvdan.cc/sh/interp/test.go
vendored
4
vendor/mvdan.cc/sh/interp/test.go
vendored
@ -132,13 +132,13 @@ func (r *Runner) unTest(op syntax.UnTestOperator, x string) bool {
|
||||
//case syntax.TsUsrOwn:
|
||||
//case syntax.TsModif:
|
||||
case syntax.TsRead:
|
||||
f, err := os.OpenFile(r.relPath(x), os.O_RDONLY, 0)
|
||||
f, err := r.open(r.relPath(x), os.O_RDONLY, 0, false)
|
||||
if err == nil {
|
||||
f.Close()
|
||||
}
|
||||
return err == nil
|
||||
case syntax.TsWrite:
|
||||
f, err := os.OpenFile(r.relPath(x), os.O_WRONLY, 0)
|
||||
f, err := r.open(r.relPath(x), os.O_WRONLY, 0, false)
|
||||
if err == nil {
|
||||
f.Close()
|
||||
}
|
||||
|
52
vendor/mvdan.cc/sh/syntax/lexer.go
vendored
52
vendor/mvdan.cc/sh/syntax/lexer.go
vendored
@ -706,12 +706,32 @@ func (p *Parser) endLit() (s string) {
|
||||
if p.r == utf8.RuneSelf {
|
||||
s = string(p.litBs)
|
||||
} else if len(p.litBs) > 0 {
|
||||
s = string(p.litBs[:len(p.litBs)-1])
|
||||
s = string(p.litBs[:len(p.litBs)-int(p.w)])
|
||||
}
|
||||
p.litBs = nil
|
||||
return
|
||||
}
|
||||
|
||||
func (p *Parser) advanceNameCont(r rune) {
|
||||
// we know that r is a letter or underscore
|
||||
loop:
|
||||
for p.newLit(r); r != utf8.RuneSelf; r = p.rune() {
|
||||
switch {
|
||||
case r == '\\':
|
||||
if r = p.rune(); r == '\n' {
|
||||
p.discardLit(2)
|
||||
}
|
||||
case 'a' <= r && r <= 'z':
|
||||
case 'A' <= r && r <= 'Z':
|
||||
case r == '_':
|
||||
case '0' <= r && r <= '9':
|
||||
default:
|
||||
break loop
|
||||
}
|
||||
}
|
||||
p.tok, p.val = _LitWord, p.endLit()
|
||||
}
|
||||
|
||||
func (p *Parser) advanceLitOther(r rune) {
|
||||
tok := _LitWord
|
||||
loop:
|
||||
@ -754,40 +774,18 @@ loop:
|
||||
if p.quote&allArithmExpr != 0 {
|
||||
break loop
|
||||
}
|
||||
if p.quote == paramName && p.peekByte('(') {
|
||||
tok = _Lit
|
||||
case ':', '=', '%', '^', ',', '?':
|
||||
if p.quote&allArithmExpr != 0 || p.quote == paramExpName {
|
||||
break loop
|
||||
}
|
||||
case '?':
|
||||
if p.quote == paramName && p.peekByte('(') {
|
||||
tok = _Lit
|
||||
break loop
|
||||
}
|
||||
fallthrough
|
||||
case ':', '=', '%', '^', ',':
|
||||
if p.quote&allArithmExpr != 0 || p.quote&allParamReg != 0 {
|
||||
break loop
|
||||
}
|
||||
case '@':
|
||||
if p.quote == paramName && p.peekByte('(') {
|
||||
tok = _Lit
|
||||
break loop
|
||||
}
|
||||
fallthrough
|
||||
case '#', '[':
|
||||
case '#', '[', '@':
|
||||
if p.quote&allParamReg != 0 {
|
||||
break loop
|
||||
}
|
||||
if r == '[' && p.lang != LangPOSIX && p.quote&allArithmExpr != 0 {
|
||||
break loop
|
||||
}
|
||||
case '+':
|
||||
if p.quote == paramName && p.peekByte('(') {
|
||||
tok = _Lit
|
||||
break loop
|
||||
}
|
||||
fallthrough
|
||||
case '-':
|
||||
case '+', '-':
|
||||
switch p.quote {
|
||||
case paramExpExp, paramExpRepl, sglQuotes:
|
||||
default:
|
||||
|
3
vendor/mvdan.cc/sh/syntax/nodes.go
vendored
3
vendor/mvdan.cc/sh/syntax/nodes.go
vendored
@ -183,6 +183,9 @@ func (*CoprocClause) commandNode() {}
|
||||
// expression. In the latter, it will be a word with a single DblQuoted
|
||||
// part.
|
||||
//
|
||||
// If Index is non-nil, the value will be a word and not an array as
|
||||
// nested arrays are not allowed.
|
||||
//
|
||||
// If Naked is true, it's part of a DeclClause and doesn't contain a
|
||||
// value. In that context, if the name wasn't a literal, it will be in
|
||||
// Value instead of Name.
|
||||
|
55
vendor/mvdan.cc/sh/syntax/parser.go
vendored
55
vendor/mvdan.cc/sh/syntax/parser.go
vendored
@ -232,7 +232,6 @@ const (
|
||||
arithmExprBrack
|
||||
testRegexp
|
||||
switchCase
|
||||
paramName
|
||||
paramExpName
|
||||
paramExpInd
|
||||
paramExpOff
|
||||
@ -247,9 +246,9 @@ const (
|
||||
switchCase | arrayElems
|
||||
allArithmExpr = arithmExpr | arithmExprLet | arithmExprCmd |
|
||||
arithmExprBrack | allParamArith
|
||||
allRbrack = arithmExprBrack | paramExpInd | paramName
|
||||
allRbrack = arithmExprBrack | paramExpInd
|
||||
allParamArith = paramExpInd | paramExpOff | paramExpLen
|
||||
allParamReg = paramName | paramExpName | allParamArith
|
||||
allParamReg = paramExpName | allParamArith
|
||||
allParamExp = allParamReg | paramExpRepl | paramExpExp
|
||||
)
|
||||
|
||||
@ -676,13 +675,23 @@ func (p *Parser) wordPart() WordPart {
|
||||
return cs
|
||||
case dollar:
|
||||
r := p.r
|
||||
if r == utf8.RuneSelf || wordBreak(r) || r == '"' || r == '\'' || r == '`' || r == '[' {
|
||||
switch {
|
||||
case singleRuneParam(r):
|
||||
p.tok, p.val = _LitWord, string(r)
|
||||
p.rune()
|
||||
case 'a' <= r && r <= 'z', 'A' <= r && r <= 'Z',
|
||||
'0' <= r && r <= '9', r == '_', r == '\\':
|
||||
p.advanceNameCont(r)
|
||||
default:
|
||||
l := p.lit(p.pos, "$")
|
||||
p.next()
|
||||
return l
|
||||
}
|
||||
p.ensureNoNested()
|
||||
return p.shortParamExp()
|
||||
pe := &ParamExp{Dollar: p.pos, Short: true}
|
||||
p.pos = posAddCol(p.pos, 1)
|
||||
pe.Param = p.getLit()
|
||||
return pe
|
||||
case cmdIn, cmdOut:
|
||||
p.ensureNoNested()
|
||||
ps := &ProcSubst{Op: ProcOperator(p.tok), OpPos: p.pos}
|
||||
@ -1012,21 +1021,13 @@ func (p *Parser) arithmExprBase(compact bool) ArithmExpr {
|
||||
return x
|
||||
}
|
||||
|
||||
func (p *Parser) shortParamExp() *ParamExp {
|
||||
pe := &ParamExp{Dollar: p.pos, Short: true}
|
||||
p.pos = posAddCol(p.pos, 1)
|
||||
switch p.r {
|
||||
case '@', '*', '#', '$', '?', '!', '0', '-':
|
||||
p.tok, p.val = _LitWord, string(p.r)
|
||||
p.rune()
|
||||
default:
|
||||
old := p.quote
|
||||
p.quote = paramName
|
||||
p.advanceLitOther(p.r)
|
||||
p.quote = old
|
||||
func singleRuneParam(r rune) bool {
|
||||
switch r {
|
||||
case '@', '*', '#', '$', '?', '!', '-',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||
return true
|
||||
}
|
||||
pe.Param = p.getLit()
|
||||
return pe
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Parser) paramExp() *ParamExp {
|
||||
@ -1186,12 +1187,12 @@ func stopToken(tok token) bool {
|
||||
|
||||
// ValidName returns whether val is a valid name as per the POSIX spec.
|
||||
func ValidName(val string) bool {
|
||||
for i, c := range val {
|
||||
for i, r := range val {
|
||||
switch {
|
||||
case 'a' <= c && c <= 'z':
|
||||
case 'A' <= c && c <= 'Z':
|
||||
case c == '_':
|
||||
case i > 0 && '0' <= c && c <= '9':
|
||||
case 'a' <= r && r <= 'z':
|
||||
case 'A' <= r && r <= 'Z':
|
||||
case r == '_':
|
||||
case i > 0 && '0' <= r && r <= '9':
|
||||
default:
|
||||
return false
|
||||
}
|
||||
@ -1275,6 +1276,9 @@ func (p *Parser) getAssign(needEqual bool) *Assign {
|
||||
if p.lang == LangPOSIX {
|
||||
p.curErr("arrays are a bash feature")
|
||||
}
|
||||
if as.Index != nil {
|
||||
p.curErr("arrays cannot be nested")
|
||||
}
|
||||
as.Array = &ArrayExpr{Lparen: p.pos}
|
||||
newQuote := p.quote
|
||||
if p.lang == LangBash {
|
||||
@ -1308,6 +1312,9 @@ func (p *Parser) getAssign(needEqual bool) *Assign {
|
||||
p.next()
|
||||
}
|
||||
if ae.Value = p.getWord(); ae.Value == nil {
|
||||
if p.tok == leftParen {
|
||||
p.curErr("arrays cannot be nested")
|
||||
}
|
||||
p.curErr("array element values must be words")
|
||||
break
|
||||
}
|
||||
|
31
vendor/mvdan.cc/sh/syntax/walk.go
vendored
31
vendor/mvdan.cc/sh/syntax/walk.go
vendored
@ -9,6 +9,9 @@ func walkStmts(sl StmtList, f func(Node) bool) {
|
||||
for _, s := range sl.Stmts {
|
||||
Walk(s, f)
|
||||
}
|
||||
for _, c := range sl.Last {
|
||||
Walk(&c, f)
|
||||
}
|
||||
}
|
||||
|
||||
func walkWords(words []*Word, f func(Node) bool) {
|
||||
@ -29,7 +32,15 @@ func Walk(node Node, f func(Node) bool) {
|
||||
switch x := node.(type) {
|
||||
case *File:
|
||||
walkStmts(x.StmtList, f)
|
||||
case *Comment:
|
||||
case *Stmt:
|
||||
for _, c := range x.Comments {
|
||||
if c.Pos().After(x.Pos()) {
|
||||
defer Walk(&c, f)
|
||||
break
|
||||
}
|
||||
Walk(&c, f)
|
||||
}
|
||||
if x.Cmd != nil {
|
||||
Walk(x.Cmd, f)
|
||||
}
|
||||
@ -146,7 +157,17 @@ func Walk(node Node, f func(Node) bool) {
|
||||
for _, ci := range x.Items {
|
||||
Walk(ci, f)
|
||||
}
|
||||
for _, c := range x.Last {
|
||||
Walk(&c, f)
|
||||
}
|
||||
case *CaseItem:
|
||||
for _, c := range x.Comments {
|
||||
if c.Pos().After(x.Pos()) {
|
||||
defer Walk(&c, f)
|
||||
break
|
||||
}
|
||||
Walk(&c, f)
|
||||
}
|
||||
walkWords(x.Patterns, f)
|
||||
walkStmts(x.StmtList, f)
|
||||
case *TestClause:
|
||||
@ -160,7 +181,17 @@ func Walk(node Node, f func(Node) bool) {
|
||||
for _, el := range x.Elems {
|
||||
Walk(el, f)
|
||||
}
|
||||
for _, c := range x.Last {
|
||||
Walk(&c, f)
|
||||
}
|
||||
case *ArrayElem:
|
||||
for _, c := range x.Comments {
|
||||
if c.Pos().After(x.Pos()) {
|
||||
defer Walk(&c, f)
|
||||
break
|
||||
}
|
||||
Walk(&c, f)
|
||||
}
|
||||
if x.Index != nil {
|
||||
Walk(x.Index, f)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user