envsubst vendor fix
This commit is contained in:
parent
a03e962c2a
commit
2bb64949d1
4 changed files with 738 additions and 0 deletions
86
vendor/github.com/drone/envsubst/parse/node.go
generated
vendored
Normal file
86
vendor/github.com/drone/envsubst/parse/node.go
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
package parse
|
||||
|
||||
// Node is an element in the parse tree.
|
||||
type Node interface {
|
||||
node()
|
||||
}
|
||||
|
||||
// empty string node
|
||||
var empty = new(TextNode)
|
||||
|
||||
// a template is represented by a tree consisting of one
|
||||
// or more of the following nodes.
|
||||
type (
|
||||
// TextNode represents a string of text.
|
||||
TextNode struct {
|
||||
Value string
|
||||
}
|
||||
|
||||
// FuncNode represents a string function.
|
||||
FuncNode struct {
|
||||
Param string
|
||||
Name string
|
||||
Args []Node
|
||||
}
|
||||
|
||||
// ListNode represents a list of nodes.
|
||||
ListNode struct {
|
||||
Nodes []Node
|
||||
}
|
||||
|
||||
// ParamNode struct{
|
||||
// Name string
|
||||
// }
|
||||
//
|
||||
// CaseNode struct {
|
||||
// Name string
|
||||
// First bool
|
||||
// }
|
||||
//
|
||||
// LowerNode struct {
|
||||
// Name string
|
||||
// First bool
|
||||
// }
|
||||
//
|
||||
// SubstrNode struct {
|
||||
// Name string
|
||||
// Pos Node
|
||||
// Len Node
|
||||
// }
|
||||
//
|
||||
// ReplaceNode struct {
|
||||
// Name string
|
||||
// Substring Node
|
||||
// Replacement Node
|
||||
// }
|
||||
//
|
||||
// TrimNode struct{
|
||||
//
|
||||
// }
|
||||
//
|
||||
// DefaultNode struct {
|
||||
// Name string
|
||||
// Default Node
|
||||
// }
|
||||
)
|
||||
|
||||
// newTextNode returns a new TextNode.
|
||||
func newTextNode(text string) *TextNode {
|
||||
return &TextNode{Value: text}
|
||||
}
|
||||
|
||||
// newListNode returns a new ListNode.
|
||||
func newListNode(nodes ...Node) *ListNode {
|
||||
return &ListNode{Nodes: nodes}
|
||||
}
|
||||
|
||||
// newFuncNode returns a new FuncNode.
|
||||
func newFuncNode(name string) *FuncNode {
|
||||
return &FuncNode{Param: name}
|
||||
}
|
||||
|
||||
// node() defines the node in a parse tree
|
||||
|
||||
func (*TextNode) node() {}
|
||||
func (*ListNode) node() {}
|
||||
func (*FuncNode) node() {}
|
371
vendor/github.com/drone/envsubst/parse/parse.go
generated
vendored
Normal file
371
vendor/github.com/drone/envsubst/parse/parse.go
generated
vendored
Normal file
|
@ -0,0 +1,371 @@
|
|||
package parse
|
||||
|
||||
import "errors"
|
||||
|
||||
// ErrBadSubstitution represents a substitution parsing error.
|
||||
var ErrBadSubstitution = errors.New("bad substitution")
|
||||
|
||||
// Tree is the representation of a single parsed SQL statement.
|
||||
type Tree struct {
|
||||
Root Node
|
||||
|
||||
// Parsing only; cleared after parse.
|
||||
scanner *scanner
|
||||
}
|
||||
|
||||
// Parse parses the string and returns a Tree.
|
||||
func Parse(buf string) (*Tree, error) {
|
||||
t := new(Tree)
|
||||
t.scanner = new(scanner)
|
||||
return t.Parse(buf)
|
||||
}
|
||||
|
||||
// Parse parses the string buffer to construct an ast
|
||||
// representation for expansion.
|
||||
func (t *Tree) Parse(buf string) (tree *Tree, err error) {
|
||||
t.scanner.init(buf)
|
||||
t.Root, err = t.parseAny()
|
||||
return t, err
|
||||
}
|
||||
|
||||
func (t *Tree) parseAny() (Node, error) {
|
||||
t.scanner.accept = acceptRune
|
||||
t.scanner.mode = scanIdent | scanLbrack
|
||||
|
||||
switch t.scanner.scan() {
|
||||
case tokenIdent:
|
||||
left := newTextNode(
|
||||
t.scanner.string(),
|
||||
)
|
||||
right, err := t.parseAny()
|
||||
switch {
|
||||
case err != nil:
|
||||
return nil, err
|
||||
case right == empty:
|
||||
return left, nil
|
||||
}
|
||||
return newListNode(left, right), nil
|
||||
case tokenEOF:
|
||||
return empty, nil
|
||||
case tokenLbrack:
|
||||
left, err := t.parseFunc()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
right, err := t.parseAny()
|
||||
switch {
|
||||
case err != nil:
|
||||
return nil, err
|
||||
case right == empty:
|
||||
return left, nil
|
||||
}
|
||||
return newListNode(left, right), nil
|
||||
}
|
||||
|
||||
return nil, ErrBadSubstitution
|
||||
}
|
||||
|
||||
func (t *Tree) parseFunc() (Node, error) {
|
||||
switch t.scanner.peek() {
|
||||
case '#':
|
||||
return t.parseLenFunc()
|
||||
}
|
||||
|
||||
var name string
|
||||
t.scanner.accept = acceptIdent
|
||||
t.scanner.mode = scanIdent
|
||||
|
||||
switch t.scanner.scan() {
|
||||
case tokenIdent:
|
||||
name = t.scanner.string()
|
||||
default:
|
||||
return nil, ErrBadSubstitution
|
||||
}
|
||||
|
||||
switch t.scanner.peek() {
|
||||
case ':':
|
||||
return t.parseDefaultOrSubstr(name)
|
||||
case '=':
|
||||
return t.parseDefaultFunc(name)
|
||||
case ',', '^':
|
||||
return t.parseCasingFunc(name)
|
||||
case '/':
|
||||
return t.parseReplaceFunc(name)
|
||||
case '#':
|
||||
return t.parseRemoveFunc(name, acceptHashFunc)
|
||||
case '%':
|
||||
return t.parseRemoveFunc(name, acceptPercentFunc)
|
||||
}
|
||||
|
||||
t.scanner.accept = acceptIdent
|
||||
t.scanner.mode = scanRbrack
|
||||
switch t.scanner.scan() {
|
||||
case tokenRbrack:
|
||||
return newFuncNode(name), nil
|
||||
default:
|
||||
return nil, ErrBadSubstitution
|
||||
}
|
||||
}
|
||||
|
||||
// parse a substitution function parameter.
|
||||
func (t *Tree) parseParam(accept acceptFunc, mode byte) (Node, error) {
|
||||
t.scanner.accept = accept
|
||||
t.scanner.mode = mode | scanLbrack
|
||||
switch t.scanner.scan() {
|
||||
case tokenLbrack:
|
||||
return t.parseFunc()
|
||||
case tokenIdent:
|
||||
return newTextNode(
|
||||
t.scanner.string(),
|
||||
), nil
|
||||
default:
|
||||
return nil, ErrBadSubstitution
|
||||
}
|
||||
}
|
||||
|
||||
// parse either a default or substring substitution function.
|
||||
func (t *Tree) parseDefaultOrSubstr(name string) (Node, error) {
|
||||
t.scanner.read()
|
||||
r := t.scanner.peek()
|
||||
t.scanner.unread()
|
||||
switch r {
|
||||
case '=', '-', '?', '+':
|
||||
return t.parseDefaultFunc(name)
|
||||
default:
|
||||
return t.parseSubstrFunc(name)
|
||||
}
|
||||
}
|
||||
|
||||
// parses the ${param:offset} string function
|
||||
// parses the ${param:offset:length} string function
|
||||
func (t *Tree) parseSubstrFunc(name string) (Node, error) {
|
||||
node := new(FuncNode)
|
||||
node.Param = name
|
||||
|
||||
t.scanner.accept = acceptOneColon
|
||||
t.scanner.mode = scanIdent
|
||||
switch t.scanner.scan() {
|
||||
case tokenIdent:
|
||||
node.Name = t.scanner.string()
|
||||
default:
|
||||
return nil, ErrBadSubstitution
|
||||
}
|
||||
|
||||
// scan arg[1]
|
||||
{
|
||||
param, err := t.parseParam(rejectColonClose, scanIdent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// param.Value = t.scanner.string()
|
||||
node.Args = append(node.Args, param)
|
||||
}
|
||||
|
||||
// expect delimiter or close
|
||||
t.scanner.accept = acceptColon
|
||||
t.scanner.mode = scanIdent | scanRbrack
|
||||
switch t.scanner.scan() {
|
||||
case tokenRbrack:
|
||||
return node, nil
|
||||
case tokenIdent:
|
||||
// no-op
|
||||
default:
|
||||
return nil, ErrBadSubstitution
|
||||
}
|
||||
// err := t.consumeDelimiter(acceptColon, scanIdent|scanRbrack)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
|
||||
// scan arg[2]
|
||||
{
|
||||
param, err := t.parseParam(acceptNotClosing, scanIdent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
node.Args = append(node.Args, param)
|
||||
}
|
||||
|
||||
return node, t.consumeRbrack()
|
||||
}
|
||||
|
||||
// parses the ${param%word} string function
|
||||
// parses the ${param%%word} string function
|
||||
// parses the ${param#word} string function
|
||||
// parses the ${param##word} string function
|
||||
func (t *Tree) parseRemoveFunc(name string, accept acceptFunc) (Node, error) {
|
||||
node := new(FuncNode)
|
||||
node.Param = name
|
||||
|
||||
t.scanner.accept = accept
|
||||
t.scanner.mode = scanIdent
|
||||
switch t.scanner.scan() {
|
||||
case tokenIdent:
|
||||
node.Name = t.scanner.string()
|
||||
default:
|
||||
return nil, ErrBadSubstitution
|
||||
}
|
||||
|
||||
// scan arg[1]
|
||||
{
|
||||
param, err := t.parseParam(acceptNotClosing, scanIdent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// param.Value = t.scanner.string()
|
||||
node.Args = append(node.Args, param)
|
||||
}
|
||||
|
||||
return node, t.consumeRbrack()
|
||||
}
|
||||
|
||||
// parses the ${param/pattern/string} string function
|
||||
// parses the ${param//pattern/string} string function
|
||||
// parses the ${param/#pattern/string} string function
|
||||
// parses the ${param/%pattern/string} string function
|
||||
func (t *Tree) parseReplaceFunc(name string) (Node, error) {
|
||||
node := new(FuncNode)
|
||||
node.Param = name
|
||||
|
||||
t.scanner.accept = acceptReplaceFunc
|
||||
t.scanner.mode = scanIdent
|
||||
switch t.scanner.scan() {
|
||||
case tokenIdent:
|
||||
node.Name = t.scanner.string()
|
||||
default:
|
||||
return nil, ErrBadSubstitution
|
||||
}
|
||||
|
||||
// scan arg[1]
|
||||
{
|
||||
param, err := t.parseParam(acceptNotSlash, scanIdent|scanEscape)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
node.Args = append(node.Args, param)
|
||||
}
|
||||
|
||||
// expect delimiter
|
||||
t.scanner.accept = acceptSlash
|
||||
t.scanner.mode = scanIdent
|
||||
switch t.scanner.scan() {
|
||||
case tokenIdent:
|
||||
// no-op
|
||||
default:
|
||||
return nil, ErrBadSubstitution
|
||||
}
|
||||
|
||||
{
|
||||
param, err := t.parseParam(acceptNotClosing, scanIdent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
node.Args = append(node.Args, param)
|
||||
}
|
||||
|
||||
return node, t.consumeRbrack()
|
||||
}
|
||||
|
||||
// parses the ${parameter=word} string function
|
||||
// parses the ${parameter:=word} string function
|
||||
// parses the ${parameter:-word} string function
|
||||
// parses the ${parameter:?word} string function
|
||||
// parses the ${parameter:+word} string function
|
||||
func (t *Tree) parseDefaultFunc(name string) (Node, error) {
|
||||
node := new(FuncNode)
|
||||
node.Param = name
|
||||
|
||||
t.scanner.accept = acceptDefaultFunc
|
||||
if t.scanner.peek() == '=' {
|
||||
t.scanner.accept = acceptOneEqual
|
||||
}
|
||||
t.scanner.mode = scanIdent
|
||||
switch t.scanner.scan() {
|
||||
case tokenIdent:
|
||||
node.Name = t.scanner.string()
|
||||
default:
|
||||
return nil, ErrBadSubstitution
|
||||
}
|
||||
|
||||
// scan arg[1]
|
||||
{
|
||||
param, err := t.parseParam(acceptNotClosing, scanIdent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// param.Value = t.scanner.string()
|
||||
node.Args = append(node.Args, param)
|
||||
}
|
||||
|
||||
return node, t.consumeRbrack()
|
||||
}
|
||||
|
||||
// parses the ${param,} string function
|
||||
// parses the ${param,,} string function
|
||||
// parses the ${param^} string function
|
||||
// parses the ${param^^} string function
|
||||
func (t *Tree) parseCasingFunc(name string) (Node, error) {
|
||||
node := new(FuncNode)
|
||||
node.Param = name
|
||||
|
||||
t.scanner.accept = acceptCasingFunc
|
||||
t.scanner.mode = scanIdent
|
||||
switch t.scanner.scan() {
|
||||
case tokenIdent:
|
||||
node.Name = t.scanner.string()
|
||||
default:
|
||||
return nil, ErrBadSubstitution
|
||||
}
|
||||
|
||||
return node, t.consumeRbrack()
|
||||
}
|
||||
|
||||
// parses the ${#param} string function
|
||||
func (t *Tree) parseLenFunc() (Node, error) {
|
||||
node := new(FuncNode)
|
||||
|
||||
t.scanner.accept = acceptOneHash
|
||||
t.scanner.mode = scanIdent
|
||||
switch t.scanner.scan() {
|
||||
case tokenIdent:
|
||||
node.Name = t.scanner.string()
|
||||
default:
|
||||
return nil, ErrBadSubstitution
|
||||
}
|
||||
|
||||
t.scanner.accept = acceptIdent
|
||||
t.scanner.mode = scanIdent
|
||||
switch t.scanner.scan() {
|
||||
case tokenIdent:
|
||||
node.Param = t.scanner.string()
|
||||
default:
|
||||
return nil, ErrBadSubstitution
|
||||
}
|
||||
|
||||
return node, t.consumeRbrack()
|
||||
}
|
||||
|
||||
// consumeRbrack consumes a right closing bracket. If a closing
|
||||
// bracket token is not consumed an ErrBadSubstitution is returned.
|
||||
func (t *Tree) consumeRbrack() error {
|
||||
t.scanner.mode = scanRbrack
|
||||
if t.scanner.scan() != tokenRbrack {
|
||||
return ErrBadSubstitution
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// consumeDelimiter consumes a function argument delimiter. If a
|
||||
// delimiter is not consumed an ErrBadSubstitution is returned.
|
||||
// func (t *Tree) consumeDelimiter(accept acceptFunc, mode uint) error {
|
||||
// t.scanner.accept = accept
|
||||
// t.scanner.mode = mode
|
||||
// if t.scanner.scan() != tokenRbrack {
|
||||
// return ErrBadSubstitution
|
||||
// }
|
||||
// return nil
|
||||
// }
|
275
vendor/github.com/drone/envsubst/parse/scan.go
generated
vendored
Normal file
275
vendor/github.com/drone/envsubst/parse/scan.go
generated
vendored
Normal file
|
@ -0,0 +1,275 @@
|
|||
package parse
|
||||
|
||||
import (
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// eof rune sent when end of file is reached
|
||||
var eof = rune(0)
|
||||
|
||||
// token is a lexical token.
|
||||
type token uint
|
||||
|
||||
// list of lexical tokens.
|
||||
const (
|
||||
// special tokens
|
||||
tokenIllegal token = iota
|
||||
tokenEOF
|
||||
|
||||
// identifiers and literals
|
||||
tokenIdent
|
||||
|
||||
// operators and delimiters
|
||||
tokenLbrack
|
||||
tokenRbrack
|
||||
tokenQuote
|
||||
)
|
||||
|
||||
// predefined mode bits to control recognition of tokens.
|
||||
const (
|
||||
scanIdent byte = 1 << iota
|
||||
scanLbrack
|
||||
scanRbrack
|
||||
scanEscape
|
||||
)
|
||||
|
||||
// returns true if rune is accepted.
|
||||
type acceptFunc func(r rune, i int) bool
|
||||
|
||||
// scanner implements a lexical scanner that reads unicode
|
||||
// characters and tokens from a string buffer.
|
||||
type scanner struct {
|
||||
buf string
|
||||
pos int
|
||||
start int
|
||||
width int
|
||||
mode byte
|
||||
|
||||
accept acceptFunc
|
||||
}
|
||||
|
||||
// init initializes a scanner with a new buffer.
|
||||
func (s *scanner) init(buf string) {
|
||||
s.buf = buf
|
||||
s.pos = 0
|
||||
s.start = 0
|
||||
s.width = 0
|
||||
s.accept = nil
|
||||
}
|
||||
|
||||
// read returns the next unicode character. It returns eof at
|
||||
// the end of the string buffer.
|
||||
func (s *scanner) read() rune {
|
||||
if s.pos >= len(s.buf) {
|
||||
s.width = 0
|
||||
return eof
|
||||
}
|
||||
r, w := utf8.DecodeRuneInString(s.buf[s.pos:])
|
||||
s.width = w
|
||||
s.pos += s.width
|
||||
return r
|
||||
}
|
||||
|
||||
func (s *scanner) unread() {
|
||||
s.pos -= s.width
|
||||
}
|
||||
|
||||
// skip skips over the curring unicode character in the buffer
|
||||
// by slicing and removing from the buffer.
|
||||
func (s *scanner) skip() {
|
||||
l := s.buf[:s.pos-1]
|
||||
r := s.buf[s.pos:]
|
||||
s.buf = l + r
|
||||
}
|
||||
|
||||
// peek returns the next unicode character in the buffer without
|
||||
// advancing the scanner. It returns eof if the scanner's position
|
||||
// is at the last character of the source.
|
||||
func (s *scanner) peek() rune {
|
||||
r := s.read()
|
||||
s.unread()
|
||||
return r
|
||||
}
|
||||
|
||||
// string returns the string corresponding to the most recently
|
||||
// scanned token. Valid after calling scan().
|
||||
func (s *scanner) string() string {
|
||||
return s.buf[s.start:s.pos]
|
||||
}
|
||||
|
||||
// scan reads the next token or Unicode character from source and
|
||||
// returns it. It returns EOF at the end of the source.
|
||||
func (s *scanner) scan() token {
|
||||
s.start = s.pos
|
||||
r := s.read()
|
||||
switch {
|
||||
case r == eof:
|
||||
return tokenEOF
|
||||
case s.scanLbrack(r):
|
||||
return tokenLbrack
|
||||
case s.scanRbrack(r):
|
||||
return tokenRbrack
|
||||
case s.scanIdent(r):
|
||||
return tokenIdent
|
||||
}
|
||||
return tokenIllegal
|
||||
}
|
||||
|
||||
// scanIdent reads the next token or Unicode character from source
|
||||
// and returns true if the Ident character is accepted.
|
||||
func (s *scanner) scanIdent(r rune) bool {
|
||||
if s.mode&scanIdent == 0 {
|
||||
return false
|
||||
}
|
||||
if s.scanEscaped(r) {
|
||||
s.skip()
|
||||
} else if !s.accept(r, s.pos-s.start) {
|
||||
return false
|
||||
}
|
||||
loop:
|
||||
for {
|
||||
r := s.read()
|
||||
switch {
|
||||
case r == eof:
|
||||
s.unread()
|
||||
break loop
|
||||
case s.scanLbrack(r):
|
||||
s.unread()
|
||||
s.unread()
|
||||
break loop
|
||||
}
|
||||
if s.scanEscaped(r) {
|
||||
s.skip()
|
||||
continue
|
||||
}
|
||||
if !s.accept(r, s.pos-s.start) {
|
||||
s.unread()
|
||||
break loop
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// scanLbrack reads the next token or Unicode character from source
|
||||
// and returns true if the open bracket is encountered.
|
||||
func (s *scanner) scanLbrack(r rune) bool {
|
||||
if s.mode&scanLbrack == 0 {
|
||||
return false
|
||||
}
|
||||
if r == '$' {
|
||||
if s.read() == '{' {
|
||||
return true
|
||||
}
|
||||
s.unread()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// scanRbrack reads the next token or Unicode character from source
|
||||
// and returns true if the closing bracket is encountered.
|
||||
func (s *scanner) scanRbrack(r rune) bool {
|
||||
if s.mode&scanRbrack == 0 {
|
||||
return false
|
||||
}
|
||||
return r == '}'
|
||||
}
|
||||
|
||||
// scanEscaped reads the next token or Unicode character from source
|
||||
// and returns true if it being escaped and should be sipped.
|
||||
func (s *scanner) scanEscaped(r rune) bool {
|
||||
if s.mode&scanEscape == 0 {
|
||||
return false
|
||||
}
|
||||
if r != '\\' {
|
||||
return false
|
||||
}
|
||||
switch s.peek() {
|
||||
case '/', '\\':
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// scanner functions accept or reject runes.
|
||||
//
|
||||
|
||||
func acceptRune(r rune, i int) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func acceptIdent(r rune, i int) bool {
|
||||
return unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_'
|
||||
}
|
||||
|
||||
func acceptColon(r rune, i int) bool {
|
||||
return r == ':'
|
||||
}
|
||||
|
||||
func acceptOneHash(r rune, i int) bool {
|
||||
return r == '#' && i == 1
|
||||
}
|
||||
|
||||
func acceptNone(r rune, i int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func acceptNotClosing(r rune, i int) bool {
|
||||
return r != '}'
|
||||
}
|
||||
|
||||
func acceptHashFunc(r rune, i int) bool {
|
||||
return r == '#' && i < 3
|
||||
}
|
||||
|
||||
func acceptPercentFunc(r rune, i int) bool {
|
||||
return r == '%' && i < 3
|
||||
}
|
||||
|
||||
func acceptDefaultFunc(r rune, i int) bool {
|
||||
switch {
|
||||
case i == 1 && r == ':':
|
||||
return true
|
||||
case i == 2 && (r == '=' || r == '-' || r == '?' || r == '+'):
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func acceptReplaceFunc(r rune, i int) bool {
|
||||
switch {
|
||||
case i == 1 && r == '/':
|
||||
return true
|
||||
case i == 2 && (r == '/' || r == '#' || r == '%'):
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func acceptOneEqual(r rune, i int) bool {
|
||||
return i == 1 && r == '='
|
||||
}
|
||||
|
||||
func acceptOneColon(r rune, i int) bool {
|
||||
return i == 1 && r == ':'
|
||||
}
|
||||
|
||||
func rejectColonClose(r rune, i int) bool {
|
||||
return r != ':' && r != '}'
|
||||
}
|
||||
|
||||
func acceptSlash(r rune, i int) bool {
|
||||
return r == '/'
|
||||
}
|
||||
|
||||
func acceptNotSlash(r rune, i int) bool {
|
||||
return r != '/'
|
||||
}
|
||||
|
||||
func acceptCasingFunc(r rune, i int) bool {
|
||||
return (r == ',' || r == '^') && i < 3
|
||||
}
|
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
|
@ -59,6 +59,12 @@
|
|||
"revision": "3e65ae5fd2d944d56fdf52cb3f887247498d50e9",
|
||||
"revisionTime": "2017-01-18T15:01:55Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "LPKfsjm4AYVgCLVcAWnQdSpt5SA=",
|
||||
"path": "github.com/drone/envsubst/parse",
|
||||
"revision": "3e65ae5fd2d944d56fdf52cb3f887247498d50e9",
|
||||
"revisionTime": "2017-01-18T15:01:55Z"
|
||||
},
|
||||
{
|
||||
"path": "github.com/eknkc/amber",
|
||||
"revision": "144da19a9994994c069f0693294a66dd310e14a4",
|
||||
|
|
Loading…
Reference in a new issue