mirror of
https://github.com/go-task/task.git
synced 2025-07-13 01:30:33 +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:
24
Gopkg.lock
generated
24
Gopkg.lock
generated
@ -4,14 +4,14 @@
|
|||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/Masterminds/semver"
|
name = "github.com/Masterminds/semver"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "517734cc7d6470c0d07130e40fd40bdeb9bcd3fd"
|
revision = "15d8430ab86497c5c0da827b748823945e1cf1e1"
|
||||||
version = "v1.3.1"
|
version = "v1.4.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/Masterminds/sprig"
|
name = "github.com/Masterminds/sprig"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "175e437013029f9a1c35bdf04bc451b0d20d4331"
|
revision = "82f6f19d47b416d27ae039939b44afaa0575860e"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/aokoli/goutils"
|
name = "github.com/aokoli/goutils"
|
||||||
@ -29,19 +29,19 @@
|
|||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/huandu/xstrings"
|
name = "github.com/huandu/xstrings"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "3959339b333561bf62a38b424fd41517c2c90f40"
|
revision = "d6590c0c31d16526217fa60fbd2067f7afcd78c5"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
|
||||||
name = "github.com/imdario/mergo"
|
name = "github.com/imdario/mergo"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "e3000cb3d28c72b837601cac94debd91032d19fe"
|
revision = "7fe0c75c13abdee74b09fcacef5ea1c6bba6a874"
|
||||||
|
version = "0.2.4"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/mattn/go-zglob"
|
name = "github.com/mattn/go-zglob"
|
||||||
packages = [".","fastwalk"]
|
packages = [".","fastwalk"]
|
||||||
revision = "95345c4e1c0ebc9d16a3284177f09360f4d20fab"
|
revision = "4ecb59231939b2e499b1f2fd8f075565977d2452"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/pmezard/go-difflib"
|
name = "github.com/pmezard/go-difflib"
|
||||||
@ -65,7 +65,7 @@
|
|||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/spf13/pflag"
|
name = "github.com/spf13/pflag"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "7aff26db30c1be810f9de5038ec5ef96ac41fd7c"
|
revision = "a9789e855c7696159b7db0db7f440b449edf2b31"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/stretchr/testify"
|
name = "github.com/stretchr/testify"
|
||||||
@ -77,19 +77,19 @@
|
|||||||
branch = "master"
|
branch = "master"
|
||||||
name = "golang.org/x/crypto"
|
name = "golang.org/x/crypto"
|
||||||
packages = ["pbkdf2","scrypt"]
|
packages = ["pbkdf2","scrypt"]
|
||||||
revision = "81e90905daefcd6fd217b62423c0908922eadb30"
|
revision = "9419663f5a44be8b34ca85f08abc5fe1be11f8a3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "golang.org/x/net"
|
name = "golang.org/x/net"
|
||||||
packages = ["context"]
|
packages = ["context"]
|
||||||
revision = "66aacef3dd8a676686c7ae3716979581e8b03c47"
|
revision = "a04bdaca5b32abe1c069418fb7088ae607de5bd0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "golang.org/x/sync"
|
name = "golang.org/x/sync"
|
||||||
packages = ["errgroup"]
|
packages = ["errgroup"]
|
||||||
revision = "f52d1811a62927559de87708c8913c1650ce4f26"
|
revision = "8e0aa688b654ef28caa72506fa5ec8dba9fc7690"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "v2"
|
branch = "v2"
|
||||||
@ -101,7 +101,7 @@
|
|||||||
branch = "master"
|
branch = "master"
|
||||||
name = "mvdan.cc/sh"
|
name = "mvdan.cc/sh"
|
||||||
packages = ["interp","syntax"]
|
packages = ["interp","syntax"]
|
||||||
revision = "d8d2c36c06455d4bb8e2116cc2b955271046329d"
|
revision = "24a28656b7c1d2532406e69527366ecf9f455a17"
|
||||||
|
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
|
@ -16,6 +16,7 @@ dl-deps:
|
|||||||
update-deps:
|
update-deps:
|
||||||
desc: Updates dependencies
|
desc: Updates dependencies
|
||||||
cmds:
|
cmds:
|
||||||
|
- dep ensure
|
||||||
- dep ensure -update
|
- dep ensure -update
|
||||||
- dep prune
|
- dep prune
|
||||||
|
|
||||||
|
@ -41,9 +41,13 @@ func RunCommand(opts *RunCommandOptions) error {
|
|||||||
Context: opts.Context,
|
Context: opts.Context,
|
||||||
Dir: opts.Dir,
|
Dir: opts.Dir,
|
||||||
Env: opts.Env,
|
Env: opts.Env,
|
||||||
Stdin: opts.Stdin,
|
|
||||||
Stdout: opts.Stdout,
|
Exec: interp.DefaultExec,
|
||||||
Stderr: opts.Stderr,
|
Open: interp.OpenDevImpls(interp.DefaultOpen),
|
||||||
|
|
||||||
|
Stdin: opts.Stdin,
|
||||||
|
Stdout: opts.Stdout,
|
||||||
|
Stderr: opts.Stderr,
|
||||||
}
|
}
|
||||||
if err = r.Reset(); err != nil {
|
if err = r.Reset(); err != nil {
|
||||||
return err
|
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)
|
# 1.3.1 (2017-07-10)
|
||||||
|
|
||||||
## Fixed
|
## 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
|
var temp int64
|
||||||
temp, err := strconv.ParseInt(m[1], 10, 32)
|
temp, err := strconv.ParseInt(m[1], 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error parsing version segment: %s", err)
|
return nil, fmt.Errorf("Error parsing version segment: %s", err)
|
||||||
}
|
}
|
||||||
sv.major = temp
|
sv.major = temp
|
||||||
|
|
||||||
if m[2] != "" {
|
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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error parsing version segment: %s", err)
|
return nil, fmt.Errorf("Error parsing version segment: %s", err)
|
||||||
}
|
}
|
||||||
@ -81,7 +81,7 @@ func NewVersion(v string) (*Version, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if m[3] != "" {
|
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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error parsing version segment: %s", err)
|
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/rsa"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
"crypto/x509/pkix"
|
||||||
"encoding/asn1"
|
"encoding/asn1"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
uuid "github.com/satori/go.uuid"
|
uuid "github.com/satori/go.uuid"
|
||||||
"golang.org/x/crypto/scrypt"
|
"golang.org/x/crypto/scrypt"
|
||||||
@ -146,3 +150,231 @@ func pemBlockForKey(priv interface{}) *pem.Block {
|
|||||||
return nil
|
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
|
duration := time.Since(t) / time.Second * time.Second
|
||||||
return duration.String()
|
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:
|
Conversions:
|
||||||
|
|
||||||
- atoi: Convert a string to an integer. 0 if the integer could not be parsed.
|
- 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.
|
- int: Convert a string or another numeric type to an int.
|
||||||
- float64: Convert a string or another numeric type to a float64.
|
- 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,
|
"dateInZone": dateInZone,
|
||||||
"dateModify": dateModify,
|
"dateModify": dateModify,
|
||||||
"ago": dateAgo,
|
"ago": dateAgo,
|
||||||
|
"toDate": toDate,
|
||||||
|
|
||||||
// Strings
|
// Strings
|
||||||
"abbrev": abbrev,
|
"abbrev": abbrev,
|
||||||
@ -251,8 +252,11 @@ var genericMap = map[string]interface{}{
|
|||||||
"has": func(needle interface{}, haystack []interface{}) bool { return inList(haystack, needle) },
|
"has": func(needle interface{}, haystack []interface{}) bool { return inList(haystack, needle) },
|
||||||
|
|
||||||
// Crypto:
|
// Crypto:
|
||||||
"genPrivateKey": generatePrivateKey,
|
"genPrivateKey": generatePrivateKey,
|
||||||
"derivePassword": derivePassword,
|
"derivePassword": derivePassword,
|
||||||
|
"genCA": generateCertificateAuthority,
|
||||||
|
"genSelfSignedCert": generateSelfSignedCertificate,
|
||||||
|
"genSignedCert": generateSignedCertificate,
|
||||||
|
|
||||||
// UUIDs:
|
// UUIDs:
|
||||||
"uuidv4": uuidv4,
|
"uuidv4": uuidv4,
|
||||||
|
15
vendor/github.com/huandu/xstrings/convert.go
generated
vendored
15
vendor/github.com/huandu/xstrings/convert.go
generated
vendored
@ -44,18 +44,25 @@ func ToCamelCase(str string) string {
|
|||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.WriteRune(unicode.ToUpper(r0))
|
r0 = unicode.ToUpper(r0)
|
||||||
r0, size = utf8.DecodeRuneInString(str)
|
|
||||||
str = str[size:]
|
|
||||||
|
|
||||||
for len(str) > 0 {
|
for len(str) > 0 {
|
||||||
r1 = r0
|
r1 = r0
|
||||||
r0, size = utf8.DecodeRuneInString(str)
|
r0, size = utf8.DecodeRuneInString(str)
|
||||||
str = str[size:]
|
str = str[size:]
|
||||||
|
|
||||||
if r1 == '_' && r0 != '_' {
|
if r1 == '_' && r0 == '_' {
|
||||||
|
buf.WriteRune(r1)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if r1 == '_' {
|
||||||
r0 = unicode.ToUpper(r0)
|
r0 = unicode.ToUpper(r0)
|
||||||
} else {
|
} else {
|
||||||
|
r0 = unicode.ToLower(r0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r1 != '_' {
|
||||||
buf.WriteRune(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()
|
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:
|
case reflect.Struct:
|
||||||
srcMap := src.Interface().(map[string]interface{})
|
srcMap := src.Interface().(map[string]interface{})
|
||||||
for key := range srcMap {
|
for key := range srcMap {
|
||||||
@ -85,6 +92,7 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, over
|
|||||||
srcKind = reflect.Ptr
|
srcKind = reflect.Ptr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !srcElement.IsValid() {
|
if !srcElement.IsValid() {
|
||||||
continue
|
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 {
|
if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else if dstKind == reflect.Interface && dstElement.Kind() == reflect.Interface {
|
||||||
if srcKind == reflect.Map {
|
if err = deepMerge(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
|
||||||
if err = deepMap(dstElement, srcElement, visited, depth+1, overwrite); err != nil {
|
return
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("type mismatch on %s field: found %v, expected %v", fieldName, srcKind, dstKind)
|
|
||||||
}
|
}
|
||||||
|
} 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"
|
"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.
|
// Traverses recursively both values, assigning src's fields values to dst.
|
||||||
// The map argument tracks comparisons that have already been seen, which allows
|
// The map argument tracks comparisons that have already been seen, which allows
|
||||||
// short circuiting on recursive types.
|
// 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() {
|
switch dst.Kind() {
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
for i, n := 0, dst.NumField(); i < n; i++ {
|
if hasExportedField(dst) {
|
||||||
if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, overwrite); err != nil {
|
for i, n := 0, dst.NumField(); i < n; i++ {
|
||||||
return
|
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:
|
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() {
|
for _, key := range src.MapKeys() {
|
||||||
srcElement := src.MapIndex(key)
|
srcElement := src.MapIndex(key)
|
||||||
if !srcElement.IsValid() {
|
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 !isEmptyValue(srcElement) && (overwrite || (!dstElement.IsValid() || isEmptyValue(dst))) {
|
||||||
if dst.IsNil() {
|
if dst.IsNil() {
|
||||||
dst.Set(reflect.MakeMap(dst.Type()))
|
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:
|
case reflect.Ptr:
|
||||||
fallthrough
|
fallthrough
|
||||||
case reflect.Interface:
|
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() {
|
if src.IsNil() {
|
||||||
break
|
break
|
||||||
} else if dst.IsNil() || overwrite {
|
} 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
|
return v.Uint() == 0
|
||||||
case reflect.Float32, reflect.Float64:
|
case reflect.Float32, reflect.Float64:
|
||||||
return v.Float() == 0
|
return v.Float() == 0
|
||||||
case reflect.Interface, reflect.Ptr:
|
case reflect.Interface, reflect.Ptr, reflect.Func:
|
||||||
return v.IsNil()
|
return v.IsNil()
|
||||||
}
|
}
|
||||||
return false
|
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 {
|
func (i *countValue) Set(s string) error {
|
||||||
v, err := strconv.ParseInt(s, 0, 64)
|
// "+1" means that no specific value was passed, so increment
|
||||||
// -1 means that no specific value was passed, so increment
|
if s == "+1" {
|
||||||
if v == -1 {
|
|
||||||
*i = countValue(*i + 1)
|
*i = countValue(*i + 1)
|
||||||
} else {
|
return nil
|
||||||
*i = countValue(v)
|
|
||||||
}
|
}
|
||||||
|
v, err := strconv.ParseInt(s, 0, 0)
|
||||||
|
*i = countValue(v)
|
||||||
return err
|
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.
|
// CountVarP is like CountVar only take a shorthand for the flag name.
|
||||||
func (f *FlagSet) CountVarP(p *int, name, shorthand string, usage string) {
|
func (f *FlagSet) CountVarP(p *int, name, shorthand string, usage string) {
|
||||||
flag := f.VarPF(newCountValue(0, p), name, shorthand, usage)
|
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
|
// 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) {
|
func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) {
|
||||||
f.normalizeNameFunc = n
|
f.normalizeNameFunc = n
|
||||||
f.sortedFormal = f.sortedFormal[:0]
|
f.sortedFormal = f.sortedFormal[:0]
|
||||||
for k, v := range f.orderedFormal {
|
for fname, flag := range f.formal {
|
||||||
delete(f.formal, NormalizedName(v.Name))
|
nname := f.normalizeFlagName(flag.Name)
|
||||||
nname := f.normalizeFlagName(v.Name)
|
if fname == nname {
|
||||||
v.Name = string(nname)
|
continue
|
||||||
f.formal[nname] = v
|
}
|
||||||
f.orderedFormal[k] = v
|
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)
|
return fmt.Errorf("invalid argument %q for %q flag: %v", value, flagName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.actual == nil {
|
if !flag.Changed {
|
||||||
f.actual = make(map[NormalizedName]*Flag)
|
if f.actual == nil {
|
||||||
}
|
f.actual = make(map[NormalizedName]*Flag)
|
||||||
f.actual[normalName] = flag
|
}
|
||||||
f.orderedActual = append(f.orderedActual, flag)
|
f.actual[normalName] = flag
|
||||||
|
f.orderedActual = append(f.orderedActual, flag)
|
||||||
|
|
||||||
flag.Changed = true
|
flag.Changed = true
|
||||||
|
}
|
||||||
|
|
||||||
if flag.Deprecated != "" {
|
if flag.Deprecated != "" {
|
||||||
fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, 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" {
|
if flag.NoOptDefVal != "true" {
|
||||||
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
|
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
|
||||||
}
|
}
|
||||||
|
case "count":
|
||||||
|
if flag.NoOptDefVal != "+1" {
|
||||||
|
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
line += fmt.Sprintf("[=%s]", flag.NoOptDefVal)
|
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)
|
err = fn(flag, value)
|
||||||
|
if err != nil {
|
||||||
|
f.failf(err.Error())
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -966,6 +981,9 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = fn(flag, value)
|
err = fn(flag, value)
|
||||||
|
if err != nil {
|
||||||
|
f.failf(err.Error())
|
||||||
|
}
|
||||||
return
|
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)
|
// dk, err := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32)
|
||||||
//
|
//
|
||||||
// The recommended parameters for interactive logins as of 2009 are N=16384,
|
// The recommended parameters for interactive logins as of 2017 are N=32768, r=8
|
||||||
// r=8, p=1. They should be increased as memory latency and CPU parallelism
|
// and p=1. The parameters N, r, and p should be increased as memory latency and
|
||||||
// increases. Remember to get a good random salt.
|
// 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) {
|
func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) {
|
||||||
if N <= 1 || N&(N-1) != 0 {
|
if N <= 1 || N&(N-1) != 0 {
|
||||||
return nil, errors.New("scrypt: N must be > 1 and a power of 2")
|
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 ./...
|
- go test -short -race ./...
|
||||||
- shfmt -version
|
- shfmt -version
|
||||||
- goveralls
|
- 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],
|
A shell parser, formatter and interpreter. Supports [POSIX Shell],
|
||||||
[Bash] and [mksh]. Requires Go 1.8 or later.
|
[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
|
### shfmt
|
||||||
|
|
||||||
go get -u mvdan.cc/sh/cmd/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 {
|
} else {
|
||||||
val--
|
val--
|
||||||
}
|
}
|
||||||
r.setVar(name, strconv.Itoa(val))
|
r.setVar(name, nil, strconv.Itoa(val))
|
||||||
if x.Post {
|
if x.Post {
|
||||||
return old
|
return old
|
||||||
}
|
}
|
||||||
@ -108,7 +108,7 @@ func (r *Runner) assgnArit(b *syntax.BinaryArithm) int {
|
|||||||
case syntax.ShrAssgn:
|
case syntax.ShrAssgn:
|
||||||
val >>= uint(arg)
|
val >>= uint(arg)
|
||||||
}
|
}
|
||||||
r.setVar(name, strconv.Itoa(val))
|
r.setVar(name, nil, strconv.Itoa(val))
|
||||||
return 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",
|
"echo", "printf", "break", "continue", "pwd", "cd",
|
||||||
"wait", "builtin", "trap", "type", "source", ".", "command",
|
"wait", "builtin", "trap", "type", "source", ".", "command",
|
||||||
"pushd", "popd", "umask", "alias", "unalias", "fg", "bg",
|
"pushd", "popd", "umask", "alias", "unalias", "fg", "bg",
|
||||||
"getopts", "eval", "test", "[":
|
"getopts", "eval", "test", "[", "exec":
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -161,6 +161,9 @@ func (r *Runner) builtinCode(pos syntax.Pos, name string, args []string) int {
|
|||||||
if err != nil || !info.IsDir() {
|
if err != nil || !info.IsDir() {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
if !hasPermissionToDir(info) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
r.Dir = dir
|
r.Dir = dir
|
||||||
case "wait":
|
case "wait":
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
@ -213,7 +216,7 @@ func (r *Runner) builtinCode(pos syntax.Pos, name string, args []string) int {
|
|||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
r.runErr(pos, "source: need filename")
|
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 {
|
if err != nil {
|
||||||
r.errf("eval: %v\n", err)
|
r.errf("eval: %v\n", err)
|
||||||
return 1
|
return 1
|
||||||
@ -247,6 +250,18 @@ func (r *Runner) builtinCode(pos syntax.Pos, name string, args []string) int {
|
|||||||
p.next()
|
p.next()
|
||||||
expr := p.classicTest("[", false)
|
expr := p.classicTest("[", false)
|
||||||
return oneIf(r.bashTest(expr) == "")
|
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",
|
case "trap", "command", "pushd", "popd",
|
||||||
"umask", "alias", "unalias", "fg", "bg", "getopts":
|
"umask", "alias", "unalias", "fg", "bg", "getopts":
|
||||||
r.runErr(pos, "unhandled builtin: %s", name)
|
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 {
|
func (r *Runner) relPath(path string) string {
|
||||||
if filepath.IsAbs(path) {
|
if !filepath.IsAbs(path) {
|
||||||
return 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"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"os/user"
|
"os/user"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"mvdan.cc/sh/syntax"
|
"mvdan.cc/sh/syntax"
|
||||||
@ -48,6 +46,9 @@ type Runner struct {
|
|||||||
// of vars.
|
// of vars.
|
||||||
Params []string
|
Params []string
|
||||||
|
|
||||||
|
Exec ModuleExec
|
||||||
|
Open ModuleOpen
|
||||||
|
|
||||||
filename string // only if Node was a File
|
filename string // only if Node was a File
|
||||||
|
|
||||||
// Separate maps, note that bash allows a name to be both a var
|
// Separate maps, note that bash allows a name to be both a var
|
||||||
@ -78,6 +79,76 @@ type Runner struct {
|
|||||||
stopOnCmdErr bool // set -e
|
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
|
// varValue can hold a string, an indexed array ([]string) or an
|
||||||
// associative array (map[string]string)
|
// associative array (map[string]string)
|
||||||
// TODO: implement associative arrays
|
// 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)
|
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 {
|
if r.err == nil {
|
||||||
r.err = RunError{
|
r.err = err
|
||||||
Filename: r.filename,
|
|
||||||
Pos: pos,
|
|
||||||
Text: fmt.Sprintf(format, a...),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
func (r *Runner) lastExit() {
|
||||||
if r.err == nil {
|
if r.err == nil {
|
||||||
r.err = ExitCode(r.exit)
|
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 {
|
if r.vars == nil {
|
||||||
r.vars = make(map[string]varValue, 4)
|
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) {
|
func (r *Runner) lookupVar(name string) (varValue, bool) {
|
||||||
switch name {
|
switch name {
|
||||||
case "PWD":
|
case "PWD":
|
||||||
return r.Dir, true
|
return r.Dir, true
|
||||||
case "HOME":
|
|
||||||
u, _ := user.Current()
|
|
||||||
return u.HomeDir, true
|
|
||||||
}
|
}
|
||||||
if val, e := r.cmdVars[name]; e {
|
if val, e := r.cmdVars[name]; e {
|
||||||
return val, true
|
return val, true
|
||||||
@ -221,42 +312,6 @@ opts:
|
|||||||
return args, nil
|
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.
|
// Run starts the interpreter and returns any error.
|
||||||
func (r *Runner) Run(node syntax.Node) error {
|
func (r *Runner) Run(node syntax.Node) error {
|
||||||
r.filename = ""
|
r.filename = ""
|
||||||
@ -278,6 +333,11 @@ func (r *Runner) Run(node syntax.Node) error {
|
|||||||
return r.err
|
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{}) {
|
func (r *Runner) outf(format string, a ...interface{}) {
|
||||||
fmt.Fprintf(r.Stdout, format, a...)
|
fmt.Fprintf(r.Stdout, format, a...)
|
||||||
}
|
}
|
||||||
@ -375,7 +435,7 @@ func escapedGlob(parts []fieldPart) (escaped string, glob bool) {
|
|||||||
return buf.String(), glob
|
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))
|
fields := make([]string, 0, len(words))
|
||||||
baseDir, _ := escapedGlob([]fieldPart{{val: r.Dir}})
|
baseDir, _ := escapedGlob([]fieldPart{{val: r.Dir}})
|
||||||
for _, word := range words {
|
for _, word := range words {
|
||||||
@ -465,9 +525,22 @@ func (r *Runner) assignValue(as *syntax.Assign) varValue {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
if as.Array != nil {
|
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 {
|
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 {
|
if !as.Append || prev == nil {
|
||||||
return strs
|
return strs
|
||||||
@ -524,10 +597,11 @@ func (r *Runner) cmd(cm syntax.Command) {
|
|||||||
r2 := *r
|
r2 := *r
|
||||||
r2.stmts(x.StmtList)
|
r2.stmts(x.StmtList)
|
||||||
r.exit = r2.exit
|
r.exit = r2.exit
|
||||||
|
r.setErr(r2.err)
|
||||||
case *syntax.CallExpr:
|
case *syntax.CallExpr:
|
||||||
if len(x.Args) == 0 {
|
if len(x.Args) == 0 {
|
||||||
for _, as := range x.Assigns {
|
for _, as := range x.Assigns {
|
||||||
r.setVar(as.Name.Value, r.assignValue(as))
|
r.setVar(as.Name.Value, as.Index, r.assignValue(as))
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -538,7 +612,7 @@ func (r *Runner) cmd(cm syntax.Command) {
|
|||||||
for _, as := range x.Assigns {
|
for _, as := range x.Assigns {
|
||||||
r.cmdVars[as.Name.Value] = r.assignValue(as)
|
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.call(x.Args[0].Pos(), fields[0], fields[1:])
|
||||||
r.cmdVars = oldVars
|
r.cmdVars = oldVars
|
||||||
case *syntax.BinaryCmd:
|
case *syntax.BinaryCmd:
|
||||||
@ -564,12 +638,17 @@ func (r *Runner) cmd(cm syntax.Command) {
|
|||||||
r2.Stderr = r.Stderr
|
r2.Stderr = r.Stderr
|
||||||
}
|
}
|
||||||
r.Stdin = pr
|
r.Stdin = pr
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
r2.stmt(x.X)
|
r2.stmt(x.X)
|
||||||
pw.Close()
|
pw.Close()
|
||||||
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
r.stmt(x.Y)
|
r.stmt(x.Y)
|
||||||
pr.Close()
|
pr.Close()
|
||||||
|
wg.Wait()
|
||||||
|
r.setErr(r2.err)
|
||||||
}
|
}
|
||||||
case *syntax.IfClause:
|
case *syntax.IfClause:
|
||||||
r.stmts(x.Cond)
|
r.stmts(x.Cond)
|
||||||
@ -592,8 +671,8 @@ func (r *Runner) cmd(cm syntax.Command) {
|
|||||||
switch y := x.Loop.(type) {
|
switch y := x.Loop.(type) {
|
||||||
case *syntax.WordIter:
|
case *syntax.WordIter:
|
||||||
name := y.Name.Value
|
name := y.Name.Value
|
||||||
for _, field := range r.fields(y.Items) {
|
for _, field := range r.Fields(y.Items) {
|
||||||
r.setVar(name, field)
|
r.setVar(name, nil, field)
|
||||||
if r.loopStmtsBroken(x.Do) {
|
if r.loopStmtsBroken(x.Do) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -645,18 +724,16 @@ func (r *Runner) cmd(cm syntax.Command) {
|
|||||||
r.runErr(cm.Pos(), "unhandled declare opts")
|
r.runErr(cm.Pos(), "unhandled declare opts")
|
||||||
}
|
}
|
||||||
for _, as := range x.Assigns {
|
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:
|
case *syntax.TimeClause:
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
if x.Stmt != nil {
|
if x.Stmt != nil {
|
||||||
r.stmt(x.Stmt)
|
r.stmt(x.Stmt)
|
||||||
}
|
}
|
||||||
elapsed := time.Since(start)
|
real := time.Since(start)
|
||||||
r.outf("\n")
|
r.outf("\n")
|
||||||
min := int(elapsed.Minutes())
|
r.outf("real\t%s\n", elapsedString(real))
|
||||||
sec := math.Remainder(elapsed.Seconds(), 60.0)
|
|
||||||
r.outf("real\t%dm%.3fs\n", min, sec)
|
|
||||||
// TODO: can we do these?
|
// TODO: can we do these?
|
||||||
r.outf("user\t0m0.000s\n")
|
r.outf("user\t0m0.000s\n")
|
||||||
r.outf("sys\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) {
|
func (r *Runner) stmts(sl syntax.StmtList) {
|
||||||
for _, stmt := range sl.Stmts {
|
for _, stmt := range sl.Stmts {
|
||||||
r.stmt(stmt)
|
r.stmt(stmt)
|
||||||
@ -716,17 +799,9 @@ func (r *Runner) redir(rd *syntax.Redirect) (io.Closer, error) {
|
|||||||
case syntax.RdrOut, syntax.RdrAll:
|
case syntax.RdrOut, syntax.RdrAll:
|
||||||
mode = os.O_RDWR | os.O_CREATE | os.O_TRUNC
|
mode = os.O_RDWR | os.O_CREATE | os.O_TRUNC
|
||||||
}
|
}
|
||||||
var f io.ReadWriteCloser
|
f, err := r.open(r.relPath(arg), mode, 0644, true)
|
||||||
switch arg {
|
if err != nil {
|
||||||
case "/dev/null":
|
return nil, err
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
switch rd.Op {
|
switch rd.Op {
|
||||||
case syntax.RdrIn:
|
case syntax.RdrIn:
|
||||||
@ -844,6 +919,7 @@ func (r *Runner) wordFields(wps []syntax.WordPart, quoted bool) [][]fieldPart {
|
|||||||
} else {
|
} else {
|
||||||
splitAdd(val)
|
splitAdd(val)
|
||||||
}
|
}
|
||||||
|
r.setErr(r2.err)
|
||||||
case *syntax.ArithmExp:
|
case *syntax.ArithmExp:
|
||||||
curField = append(curField, fieldPart{
|
curField = append(curField, fieldPart{
|
||||||
val: strconv.Itoa(r.arithm(x.X)),
|
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)
|
r.exit = r.builtinCode(pos, name, args)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cmd := exec.CommandContext(r.Context, name, args...)
|
r.exec(name, args)
|
||||||
cmd.Env = r.Env
|
}
|
||||||
for name, val := range r.cmdVars {
|
|
||||||
cmd.Env = append(cmd.Env, name+"="+varStr(val))
|
func (r *Runner) exec(name string, args []string) {
|
||||||
}
|
err := r.Exec(r.ctx(), name, args)
|
||||||
cmd.Dir = r.Dir
|
|
||||||
cmd.Stdin = r.Stdin
|
|
||||||
cmd.Stdout = r.Stdout
|
|
||||||
cmd.Stderr = r.Stderr
|
|
||||||
err := cmd.Run()
|
|
||||||
switch x := err.(type) {
|
switch x := err.(type) {
|
||||||
case *exec.ExitError:
|
case nil:
|
||||||
// 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:
|
|
||||||
r.exit = 0
|
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
|
fallthrough
|
||||||
case syntax.SubstColAssgn:
|
case syntax.SubstColAssgn:
|
||||||
if str == "" {
|
if str == "" {
|
||||||
r.setVar(name, arg)
|
r.setVar(name, nil, arg)
|
||||||
str = arg
|
str = arg
|
||||||
}
|
}
|
||||||
case syntax.RemSmallPrefix:
|
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.TsUsrOwn:
|
||||||
//case syntax.TsModif:
|
//case syntax.TsModif:
|
||||||
case syntax.TsRead:
|
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 {
|
if err == nil {
|
||||||
f.Close()
|
f.Close()
|
||||||
}
|
}
|
||||||
return err == nil
|
return err == nil
|
||||||
case syntax.TsWrite:
|
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 {
|
if err == nil {
|
||||||
f.Close()
|
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 {
|
if p.r == utf8.RuneSelf {
|
||||||
s = string(p.litBs)
|
s = string(p.litBs)
|
||||||
} else if len(p.litBs) > 0 {
|
} 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
|
p.litBs = nil
|
||||||
return
|
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) {
|
func (p *Parser) advanceLitOther(r rune) {
|
||||||
tok := _LitWord
|
tok := _LitWord
|
||||||
loop:
|
loop:
|
||||||
@ -754,40 +774,18 @@ loop:
|
|||||||
if p.quote&allArithmExpr != 0 {
|
if p.quote&allArithmExpr != 0 {
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
if p.quote == paramName && p.peekByte('(') {
|
case ':', '=', '%', '^', ',', '?':
|
||||||
tok = _Lit
|
if p.quote&allArithmExpr != 0 || p.quote == paramExpName {
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
case '?':
|
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 '#', '[':
|
|
||||||
if p.quote&allParamReg != 0 {
|
if p.quote&allParamReg != 0 {
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
if r == '[' && p.lang != LangPOSIX && p.quote&allArithmExpr != 0 {
|
if r == '[' && p.lang != LangPOSIX && p.quote&allArithmExpr != 0 {
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
case '+':
|
case '+', '-':
|
||||||
if p.quote == paramName && p.peekByte('(') {
|
|
||||||
tok = _Lit
|
|
||||||
break loop
|
|
||||||
}
|
|
||||||
fallthrough
|
|
||||||
case '-':
|
|
||||||
switch p.quote {
|
switch p.quote {
|
||||||
case paramExpExp, paramExpRepl, sglQuotes:
|
case paramExpExp, paramExpRepl, sglQuotes:
|
||||||
default:
|
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
|
// expression. In the latter, it will be a word with a single DblQuoted
|
||||||
// part.
|
// 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
|
// 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. In that context, if the name wasn't a literal, it will be in
|
||||||
// Value instead of Name.
|
// 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
|
arithmExprBrack
|
||||||
testRegexp
|
testRegexp
|
||||||
switchCase
|
switchCase
|
||||||
paramName
|
|
||||||
paramExpName
|
paramExpName
|
||||||
paramExpInd
|
paramExpInd
|
||||||
paramExpOff
|
paramExpOff
|
||||||
@ -247,9 +246,9 @@ const (
|
|||||||
switchCase | arrayElems
|
switchCase | arrayElems
|
||||||
allArithmExpr = arithmExpr | arithmExprLet | arithmExprCmd |
|
allArithmExpr = arithmExpr | arithmExprLet | arithmExprCmd |
|
||||||
arithmExprBrack | allParamArith
|
arithmExprBrack | allParamArith
|
||||||
allRbrack = arithmExprBrack | paramExpInd | paramName
|
allRbrack = arithmExprBrack | paramExpInd
|
||||||
allParamArith = paramExpInd | paramExpOff | paramExpLen
|
allParamArith = paramExpInd | paramExpOff | paramExpLen
|
||||||
allParamReg = paramName | paramExpName | allParamArith
|
allParamReg = paramExpName | allParamArith
|
||||||
allParamExp = allParamReg | paramExpRepl | paramExpExp
|
allParamExp = allParamReg | paramExpRepl | paramExpExp
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -676,13 +675,23 @@ func (p *Parser) wordPart() WordPart {
|
|||||||
return cs
|
return cs
|
||||||
case dollar:
|
case dollar:
|
||||||
r := p.r
|
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, "$")
|
l := p.lit(p.pos, "$")
|
||||||
p.next()
|
p.next()
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
p.ensureNoNested()
|
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:
|
case cmdIn, cmdOut:
|
||||||
p.ensureNoNested()
|
p.ensureNoNested()
|
||||||
ps := &ProcSubst{Op: ProcOperator(p.tok), OpPos: p.pos}
|
ps := &ProcSubst{Op: ProcOperator(p.tok), OpPos: p.pos}
|
||||||
@ -1012,21 +1021,13 @@ func (p *Parser) arithmExprBase(compact bool) ArithmExpr {
|
|||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) shortParamExp() *ParamExp {
|
func singleRuneParam(r rune) bool {
|
||||||
pe := &ParamExp{Dollar: p.pos, Short: true}
|
switch r {
|
||||||
p.pos = posAddCol(p.pos, 1)
|
case '@', '*', '#', '$', '?', '!', '-',
|
||||||
switch p.r {
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
|
||||||
case '@', '*', '#', '$', '?', '!', '0', '-':
|
return true
|
||||||
p.tok, p.val = _LitWord, string(p.r)
|
|
||||||
p.rune()
|
|
||||||
default:
|
|
||||||
old := p.quote
|
|
||||||
p.quote = paramName
|
|
||||||
p.advanceLitOther(p.r)
|
|
||||||
p.quote = old
|
|
||||||
}
|
}
|
||||||
pe.Param = p.getLit()
|
return false
|
||||||
return pe
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) paramExp() *ParamExp {
|
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.
|
// ValidName returns whether val is a valid name as per the POSIX spec.
|
||||||
func ValidName(val string) bool {
|
func ValidName(val string) bool {
|
||||||
for i, c := range val {
|
for i, r := range val {
|
||||||
switch {
|
switch {
|
||||||
case 'a' <= c && c <= 'z':
|
case 'a' <= r && r <= 'z':
|
||||||
case 'A' <= c && c <= 'Z':
|
case 'A' <= r && r <= 'Z':
|
||||||
case c == '_':
|
case r == '_':
|
||||||
case i > 0 && '0' <= c && c <= '9':
|
case i > 0 && '0' <= r && r <= '9':
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -1275,6 +1276,9 @@ func (p *Parser) getAssign(needEqual bool) *Assign {
|
|||||||
if p.lang == LangPOSIX {
|
if p.lang == LangPOSIX {
|
||||||
p.curErr("arrays are a bash feature")
|
p.curErr("arrays are a bash feature")
|
||||||
}
|
}
|
||||||
|
if as.Index != nil {
|
||||||
|
p.curErr("arrays cannot be nested")
|
||||||
|
}
|
||||||
as.Array = &ArrayExpr{Lparen: p.pos}
|
as.Array = &ArrayExpr{Lparen: p.pos}
|
||||||
newQuote := p.quote
|
newQuote := p.quote
|
||||||
if p.lang == LangBash {
|
if p.lang == LangBash {
|
||||||
@ -1308,6 +1312,9 @@ func (p *Parser) getAssign(needEqual bool) *Assign {
|
|||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
if ae.Value = p.getWord(); ae.Value == nil {
|
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")
|
p.curErr("array element values must be words")
|
||||||
break
|
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 {
|
for _, s := range sl.Stmts {
|
||||||
Walk(s, f)
|
Walk(s, f)
|
||||||
}
|
}
|
||||||
|
for _, c := range sl.Last {
|
||||||
|
Walk(&c, f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func walkWords(words []*Word, f func(Node) bool) {
|
func walkWords(words []*Word, f func(Node) bool) {
|
||||||
@ -29,7 +32,15 @@ func Walk(node Node, f func(Node) bool) {
|
|||||||
switch x := node.(type) {
|
switch x := node.(type) {
|
||||||
case *File:
|
case *File:
|
||||||
walkStmts(x.StmtList, f)
|
walkStmts(x.StmtList, f)
|
||||||
|
case *Comment:
|
||||||
case *Stmt:
|
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 {
|
if x.Cmd != nil {
|
||||||
Walk(x.Cmd, f)
|
Walk(x.Cmd, f)
|
||||||
}
|
}
|
||||||
@ -146,7 +157,17 @@ func Walk(node Node, f func(Node) bool) {
|
|||||||
for _, ci := range x.Items {
|
for _, ci := range x.Items {
|
||||||
Walk(ci, f)
|
Walk(ci, f)
|
||||||
}
|
}
|
||||||
|
for _, c := range x.Last {
|
||||||
|
Walk(&c, f)
|
||||||
|
}
|
||||||
case *CaseItem:
|
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)
|
walkWords(x.Patterns, f)
|
||||||
walkStmts(x.StmtList, f)
|
walkStmts(x.StmtList, f)
|
||||||
case *TestClause:
|
case *TestClause:
|
||||||
@ -160,7 +181,17 @@ func Walk(node Node, f func(Node) bool) {
|
|||||||
for _, el := range x.Elems {
|
for _, el := range x.Elems {
|
||||||
Walk(el, f)
|
Walk(el, f)
|
||||||
}
|
}
|
||||||
|
for _, c := range x.Last {
|
||||||
|
Walk(&c, f)
|
||||||
|
}
|
||||||
case *ArrayElem:
|
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 {
|
if x.Index != nil {
|
||||||
Walk(x.Index, f)
|
Walk(x.Index, f)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user