update vendor

This commit is contained in:
deepzz0
2017-07-11 23:50:01 +08:00
parent e1ec5cd08a
commit c18d9c0bef
107 changed files with 8347 additions and 126 deletions

264
vendor/github.com/qiniu/x/cmdline.v7/cmdline.go generated vendored Normal file
View File

@@ -0,0 +1,264 @@
package cmdline
import (
"errors"
"strings"
. "qiniupkg.com/x/ctype.v7"
)
/* ---------------------------------------------------------------------------
Shell 基础规则:
* 多行字符串:用 '...' 或 "..."。其中 " 会自动转义 $(var),而 ' 不会。
* 普通字符串:用 [ \t] 分隔。转义符以 \ 开头。
* 外部命令:`...`。
七牛规则:
* 外部命令: `...` 或 |...| 。
* 多行字符串:用 '...' 或 ```\n...``` 或 ===\n...=== 不转义。用 "...",支持以 \ 开头的转义,也支持外部命令。
* 普通字符串:用 [ \t] 分隔。转义符以 \ 开头,同时也支持外部命令。
* 关于 $(var) 支持:每个命令自己执行 $(var) 的展开。不统一执行的原因是,在不同上下文需要不同的转义方式。
样例:
post http://rs.qiniu.com/delete/`base64 Bucket:Key`
auth `qbox AccessKey SecretKey`
ret 200
post http://rs.qiniu.com/batch
auth qboxtest
form op=/delete/`base64 Bucket:Key`&op=/delete/`base64 Bucket2:Key2`
ret 200
post http://rs.qiniu.com/batch
auth qboxtest
form op=/delete/`base64 Bucket:Key`&op=/delete/`base64 Bucket:NotExistKey`
ret 298
json '[
{"code": 200}, {"code": 612}
]'
equal $(code1) 200
// -------------------------------------------------------------------------*/
var (
EOF = errors.New("end of file")
ErrUnsupportedFeatureSubCmd = errors.New("unsupported feature: sub command")
ErrUnsupportedFeatureMultiCmds = errors.New("unsupported feature: multi commands")
ErrInvalidEscapeChar = errors.New("invalid escape char")
ErrIncompleteStringExpectQuot = errors.New("incomplete string, expect \"")
ErrIncompleteStringExpectSquot = errors.New("incomplete string, expect '")
ErrIncompleteStringExpectBacktick = errors.New("incomplete string, expect ` or |")
)
var (
errEOL = errors.New("end of line")
)
// ---------------------------------------------------------------------------
func Skip(str string, typeMask uint32) string {
for i := 0; i < len(str); i++ {
if !Is(typeMask, rune(str[i])) {
return str[i:]
}
}
return ""
}
func Find(str string, typeMask uint32) (n int) {
for n = 0; n < len(str); n++ {
if Is(typeMask, rune(str[n])) {
break
}
}
return
}
// ---------------------------------------------------------------------------
// EOL = \r\n? | \n
//
func requireEOL(code string) (hasEOL bool, codeNext string) {
if strings.HasPrefix(code, "\r") {
if strings.HasPrefix(code[1:], "\n") {
return true, code[2:]
}
} else if !strings.HasPrefix(code, "\n") {
return false, code
}
return true, code[1:]
}
// ---------------------------------------------------------------------------
type Parser struct {
ExecSub func(code string) (string, error)
Escape func(c byte) string
comment bool
}
func NewParser() *Parser {
return &Parser{
ExecSub: defaultExecSub,
Escape: defaultEscape,
}
}
func defaultExecSub(code string) (string, error) {
return "", ErrUnsupportedFeatureSubCmd
}
// ---------------------------------------------------------------------------
const (
endOfLine = EOL | SEMICOLON // [\r\n;]
blanks = SPACE_BAR | TAB
blankAndEOLs = SPACE_BAR | TAB | endOfLine
)
const (
endMask_QuotString = RDIV | BACKTICK | OR | QUOT // [\\`|"]
endMask_NonquotString = RDIV | BACKTICK | OR | blankAndEOLs // [\\`| \t\r\n;]
)
func (p *Parser) parseString(
code string, endMask uint32) (item string, ok bool, codeNext string, err error) {
codeNext = code
for {
n := Find(codeNext, endMask)
if n > 0 {
item += codeNext[:n]
ok = true
}
if len(codeNext) == n {
codeNext = ""
if endMask == endMask_QuotString {
err = ErrIncompleteStringExpectQuot
} else {
err = EOF
}
return
}
switch codeNext[n] {
case '\\':
if len(codeNext) == n+1 {
err = ErrInvalidEscapeChar
return
}
item += p.Escape(codeNext[n+1])
codeNext = codeNext[n+2:]
case '`', '|':
c := codeNext[n]
codeNext = codeNext[n+1:]
len := strings.IndexByte(codeNext, c)
if len < 0 {
err = ErrIncompleteStringExpectBacktick
return
}
if !p.comment {
valSub, errSub := p.ExecSub(codeNext[:len])
if errSub != nil {
err = errors.New("Exec `" + codeNext[:len] + "` failed: " + errSub.Error())
return
}
item += valSub
}
codeNext = codeNext[len+1:]
case '"':
ok = true
codeNext = codeNext[n+1:]
return
default:
if Is(endOfLine, rune(codeNext[n])) {
err = errEOL
}
codeNext = codeNext[n+1:]
return
}
ok = true
}
return
}
func (p *Parser) parseItem(
code string, skipMask uint32) (item string, ok bool, codeNext string, err error) {
codeNext = Skip(code, skipMask)
if len(codeNext) == 0 {
err = EOF
return
}
switch codeNext[0] {
case '"':
return p.parseString(codeNext[1:], endMask_QuotString)
case '\'':
codeNext = codeNext[1:]
len := strings.IndexByte(codeNext, '\'')
if len < 0 {
err = ErrIncompleteStringExpectSquot
return
}
return codeNext[:len], true, codeNext[len+1:], nil
default:
if strings.HasPrefix(codeNext, "```") || strings.HasPrefix(codeNext, "===") {
endMark := codeNext[:3]
_, codeNext = requireEOL(codeNext[3:])
len := strings.Index(codeNext, endMark)
if len < 0 {
err = errors.New("incomplete string, expect " + endMark)
return
}
return codeNext[:len], true, codeNext[len+3:], nil
}
return p.parseString(codeNext, endMask_NonquotString)
}
}
func (p *Parser) ParseCmd(cmdline string) (cmd []string, err error) {
cmd, _, err = p.ParseCode(cmdline)
if err == EOF && len(cmd) > 0 {
return cmd, nil
}
if err == nil {
err = ErrUnsupportedFeatureMultiCmds
}
return
}
func (p *Parser) ParseCode(code string) (cmd []string, codeNext string, err error) {
item, ok, codeNext, err := p.parseItem(code, blankAndEOLs)
if !ok {
return
}
p.comment = strings.HasPrefix(item, "#")
cmd = append(cmd, item)
for err == nil {
item, ok, codeNext, err = p.parseItem(codeNext, blanks)
if ok {
cmd = append(cmd, item)
}
}
if err == errEOL {
err = nil
}
if p.comment {
cmd = nil
}
return
}
// ---------------------------------------------------------------------------

173
vendor/github.com/qiniu/x/cmdline.v7/cmdline_test.go generated vendored Normal file
View File

@@ -0,0 +1,173 @@
package cmdline
import (
"reflect"
"testing"
)
// ---------------------------------------------------------------------------
func equalErr(err error, errExp interface{}) bool {
if err == nil || errExp == nil {
return err == nil && errExp == nil
}
return err.Error() == errExp.(string)
}
// ---------------------------------------------------------------------------
func TestComment(t *testing.T) {
execSub := false
ctx := Parser{
ExecSub: func(code string) (string, error) {
execSub = true
return "[" + code + "]", nil
},
Escape: func(c byte) string {
return string(c)
},
}
cmd, codeNext, err := ctx.ParseCode("#abc `calc $(a)+$(b)`")
if err != EOF || codeNext != "" {
t.Fatal("ParseCode: eof is expected")
}
if execSub {
t.Fatal("don't execSub")
}
if len(cmd) != 0 {
t.Fatal("len(cmd) != 0")
}
}
// ---------------------------------------------------------------------------
type caseParse struct {
code string
cmd []string
codeNext string
err interface{}
}
func TestParse(t *testing.T) {
cases := []caseParse{
{
code: ";b",
cmd: []string{"b"},
codeNext: "",
err: "end of file",
},
{
code: ";b;abc",
cmd: []string{"b"},
codeNext: "abc",
err: nil,
},
{
code: "a`b`\\c",
cmd: []string{"a[b]c"},
codeNext: "",
err: "end of file",
},
{
code: "a`b`c 'c\\n`123`' \"c\\n\"",
cmd: []string{"a[b]c", "c\\n`123`", "cn"},
codeNext: "",
err: "end of file",
},
{
code: "auth qboxtest 'mac AccessKey SecretKey'",
cmd: []string{"auth", "qboxtest", "mac AccessKey SecretKey"},
codeNext: "",
err: "end of file",
},
{
code: "post http://rs.qiniu.com/delete/`base64 Bucket:Key`",
cmd: []string{"post", "http://rs.qiniu.com/delete/[base64 Bucket:Key]"},
codeNext: "",
err: "end of file",
},
{
code: "post http://rs.qiniu.com/delete `base64 Bucket:Key`",
cmd: []string{"post", "http://rs.qiniu.com/delete", "[base64 Bucket:Key]"},
codeNext: "",
err: "end of file",
},
{
code: "post http://rs.qiniu.com/delete/|base64 Bucket:Key|",
cmd: []string{"post", "http://rs.qiniu.com/delete/[base64 Bucket:Key]"},
codeNext: "",
err: "end of file",
},
{
code: `json '[
{"code": 200}, {"code": 612}
]'`,
cmd: []string{"json", `[
{"code": 200}, {"code": 612}
]`},
codeNext: "",
err: "end of file",
},
{
code: "auth qboxtest ```\nmac AccessKey SecretKey```",
cmd: []string{"auth", "qboxtest", "mac AccessKey SecretKey"},
codeNext: "",
err: "end of file",
},
{
code: "auth qboxtest ===\nmac AccessKey SecretKey```",
cmd: []string{"auth", "qboxtest"},
codeNext: "mac AccessKey SecretKey```",
err: "incomplete string, expect ===",
},
{
code: "auth qboxtest ===\rmac AccessKey SecretKey===",
cmd: []string{"auth", "qboxtest", "mac AccessKey SecretKey"},
codeNext: "",
err: "end of file",
},
{
code: "auth qboxtest ===\n\rmac AccessKey SecretKey===",
cmd: []string{"auth", "qboxtest", "\rmac AccessKey SecretKey"},
codeNext: "",
err: "end of file",
},
{
code: "auth qboxtest ===\r\n\nmac AccessKey SecretKey===",
cmd: []string{"auth", "qboxtest", "\nmac AccessKey SecretKey"},
codeNext: "",
err: "end of file",
},
{
code: "auth qboxtest ===mac AccessKey SecretKey===",
cmd: []string{"auth", "qboxtest", "mac AccessKey SecretKey"},
codeNext: "",
err: "end of file",
},
}
ctx := Parser{
ExecSub: func(code string) (string, error) {
return "[" + code + "]", nil
},
Escape: func(c byte) string {
return string(c)
},
}
for _, c := range cases {
cmd, codeNext, err := ctx.ParseCode(c.code)
if !equalErr(err, c.err) {
t.Fatal("Parse failed:", c, err)
}
if !reflect.DeepEqual(cmd, c.cmd) || codeNext != c.codeNext {
t.Fatal("Parse failed:", c, cmd, codeNext)
}
}
}
// ---------------------------------------------------------------------------

98
vendor/github.com/qiniu/x/cmdline.v7/escape.go generated vendored Normal file
View File

@@ -0,0 +1,98 @@
package cmdline
// ---------------------------------------------------------------------------
const (
escTableBaseChar = '0'
escTableLen = ('z' - escTableBaseChar + 1)
)
var escTable = []byte{
0, // 0 [48]
49, // 1 [49]
50, // 2 [50]
51, // 3 [51]
52, // 4 [52]
53, // 5 [53]
54, // 6 [54]
55, // 7 [55]
56, // 8 [56]
57, // 9 [57]
58, // : [58]
59, // ; [59]
60, // < [60]
61, // = [61]
62, // > [62]
63, // ? [63]
64, // @ [64]
65, // A [65]
66, // B [66]
67, // C [67]
68, // D [68]
69, // E [69]
70, // F [70]
71, // G [71]
72, // H [72]
73, // I [73]
74, // J [74]
75, // K [75]
76, // L [76]
77, // M [77]
78, // N [78]
79, // O [79]
80, // P [80]
81, // Q [81]
82, // R [82]
83, // S [83]
84, // T [84]
85, // U [85]
86, // V [86]
87, // W [87]
88, // X [88]
89, // Y [89]
90, // Z [90]
91, // [ [91]
92, // \ [92]
93, // ] [93]
94, // ^ [94]
95, // _ [95]
96, // ` [96]
97, // a [97]
98, // b [98]
99, // c [99]
100, // d [100]
101, // e [101]
102, // f [102]
103, // g [103]
104, // h [104]
105, // i [105]
106, // j [106]
107, // k [107]
108, // l [108]
109, // m [109]
'\n', // n [110]
111, // o [111]
112, // p [112]
113, // q [113]
'\r', // r [114]
115, // s [115]
'\t', // t [116]
117, // u [117]
118, // v [118]
119, // w [119]
120, // x [120]
121, // y [121]
122, // z [122]
123, // { [123]
}
func defaultEscape(c byte) string {
if c - escTableBaseChar < escTableLen {
c = escTable[c - escTableBaseChar]
}
return string(c)
}
// ---------------------------------------------------------------------------

41
vendor/github.com/qiniu/x/cmdline.v7/escape_test.go generated vendored Normal file
View File

@@ -0,0 +1,41 @@
package cmdline
import (
"testing"
)
// ---------------------------------------------------------------------------
func TestEscape(t *testing.T) {
for i := 0; i < escTableBaseChar; i++ {
checkEscapeChar(t, i, i)
}
table := make([]int, escTableLen)
for i := 0; i < escTableLen; i++ {
table[i] = escTableBaseChar + i
}
table['0'-escTableBaseChar] = 0
table['r'-escTableBaseChar] = '\r'
table['t'-escTableBaseChar] = '\t'
table['n'-escTableBaseChar] = '\n'
for i := 0; i < escTableLen; i++ {
checkEscapeChar(t, escTableBaseChar+i, table[i])
}
for i := int(escTableBaseChar + escTableLen); i < 256; i++ {
checkEscapeChar(t, i, i)
}
}
func checkEscapeChar(t *testing.T, i, exp int) {
ret := defaultEscape(byte(i))
if ret != string(exp) {
t.Fatal("escapeChar failed:", i)
}
}
// ---------------------------------------------------------------------------