Remove github.com/satori/go.uuid.
This commit is contained in:
parent
e1d097ea20
commit
2e19e45aa4
25 changed files with 1027 additions and 365 deletions
27
Gopkg.lock
generated
27
Gopkg.lock
generated
|
@ -61,6 +61,14 @@
|
||||||
pruneopts = "NUT"
|
pruneopts = "NUT"
|
||||||
revision = "2fd0705ce648e602e6c9c57329a174270a4f6688"
|
revision = "2fd0705ce648e602e6c9c57329a174270a4f6688"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
digest = "1:25870183293a3fb61cc9afd060a61d63a486f091db72af01a8ea3449f5ca530d"
|
||||||
|
name = "github.com/Masterminds/goutils"
|
||||||
|
packages = ["."]
|
||||||
|
pruneopts = "NUT"
|
||||||
|
revision = "41ac8693c5c10a92ea1ff5ac3a7f95646f6123b0"
|
||||||
|
version = "v1.1.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:0ce2a409217f52078c6b8642993deb1025940cded6d5054047c1d5c7379f753c"
|
digest = "1:0ce2a409217f52078c6b8642993deb1025940cded6d5054047c1d5c7379f753c"
|
||||||
name = "github.com/Masterminds/semver"
|
name = "github.com/Masterminds/semver"
|
||||||
|
@ -70,11 +78,12 @@
|
||||||
version = "v1.2.2"
|
version = "v1.2.2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:a49472e7d73071005f436b7da85567220f24bb26fbfccbec45d2cd1359d4c67d"
|
digest = "1:876a1121171c083c4e3a4789683d02a40c0f644c8190da521d15b59799f556d6"
|
||||||
name = "github.com/Masterminds/sprig"
|
name = "github.com/Masterminds/sprig"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "NUT"
|
pruneopts = "NUT"
|
||||||
revision = "e039e20e500c2c025d9145be375e27cf42a94174"
|
revision = "9f8fceff796fb9f4e992cd2bece016be0121ab74"
|
||||||
|
version = "2.19.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:915c86626dfd65f8105c48b2972d29f34fd77ff16b31157147cb8ebbddeebbe3"
|
digest = "1:915c86626dfd65f8105c48b2972d29f34fd77ff16b31157147cb8ebbddeebbe3"
|
||||||
|
@ -175,14 +184,6 @@
|
||||||
revision = "cad214d7d71fba7883fcf3b7e550ba782c15b400"
|
revision = "cad214d7d71fba7883fcf3b7e550ba782c15b400"
|
||||||
version = "1.27.7"
|
version = "1.27.7"
|
||||||
|
|
||||||
[[projects]]
|
|
||||||
digest = "1:975108e8d4f5dab096fc991326e96a5716ee8d02e5e7386bb4796171afc4ab9a"
|
|
||||||
name = "github.com/aokoli/goutils"
|
|
||||||
packages = ["."]
|
|
||||||
pruneopts = "NUT"
|
|
||||||
revision = "3391d3790d23d03408670993e957e8f408993c34"
|
|
||||||
version = "v1.0.1"
|
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:b39cf81d5f440b9c0757a25058432d33af867e5201109bf53621356d9dab4b73"
|
digest = "1:b39cf81d5f440b9c0757a25058432d33af867e5201109bf53621356d9dab4b73"
|
||||||
name = "github.com/apache/thrift"
|
name = "github.com/apache/thrift"
|
||||||
|
@ -913,11 +914,12 @@
|
||||||
revision = "0fb14efe8c47ae851c0034ed7a448854d3d34cf3"
|
revision = "0fb14efe8c47ae851c0034ed7a448854d3d34cf3"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
digest = "1:45e66b20393507035c6a7d15bef5ffe8faf5b083621c1284d9824cc052776de5"
|
digest = "1:dc54242755f5b6721dd880843de6e45fe234838ea9149ec8249951880fd5802f"
|
||||||
name = "github.com/huandu/xstrings"
|
name = "github.com/huandu/xstrings"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
pruneopts = "NUT"
|
pruneopts = "NUT"
|
||||||
revision = "3959339b333561bf62a38b424fd41517c2c90f40"
|
revision = "f02667b379e2fb5916c3cda2cf31e0eb885d79f8"
|
||||||
|
version = "v1.2.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
@ -2239,7 +2241,6 @@
|
||||||
"github.com/prometheus/client_model/go",
|
"github.com/prometheus/client_model/go",
|
||||||
"github.com/rancher/go-rancher-metadata/metadata",
|
"github.com/rancher/go-rancher-metadata/metadata",
|
||||||
"github.com/ryanuber/go-glob",
|
"github.com/ryanuber/go-glob",
|
||||||
"github.com/satori/go.uuid",
|
|
||||||
"github.com/sirupsen/logrus",
|
"github.com/sirupsen/logrus",
|
||||||
"github.com/stretchr/testify/assert",
|
"github.com/stretchr/testify/assert",
|
||||||
"github.com/stretchr/testify/mock",
|
"github.com/stretchr/testify/mock",
|
||||||
|
|
|
@ -159,8 +159,8 @@ required = [
|
||||||
name = "github.com/ryanuber/go-glob"
|
name = "github.com/ryanuber/go-glob"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
name = "github.com/satori/go.uuid"
|
name = "github.com/Masterminds/sprig"
|
||||||
version = "1.1.0"
|
version = "2.19.0"
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
|
|
|
@ -94,7 +94,7 @@ func main() {
|
||||||
// traefik Command init
|
// traefik Command init
|
||||||
traefikCmd := &flaeg.Command{
|
traefikCmd := &flaeg.Command{
|
||||||
Name: "traefik",
|
Name: "traefik",
|
||||||
Description: `traefik is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease.
|
Description: `Traefik is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease.
|
||||||
Complete documentation is available at https://traefik.io`,
|
Complete documentation is available at https://traefik.io`,
|
||||||
Config: traefikConfiguration,
|
Config: traefikConfiguration,
|
||||||
DefaultPointersConfig: traefikPointersConfiguration,
|
DefaultPointersConfig: traefikPointersConfiguration,
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
package uuid
|
|
||||||
|
|
||||||
import guuid "github.com/satori/go.uuid"
|
|
||||||
|
|
||||||
var uuid string
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
uuid = guuid.NewV4().String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the instance UUID
|
|
||||||
func Get() string {
|
|
||||||
return uuid
|
|
||||||
}
|
|
251
vendor/github.com/Masterminds/goutils/cryptorandomstringutils.go
generated
vendored
Normal file
251
vendor/github.com/Masterminds/goutils/cryptorandomstringutils.go
generated
vendored
Normal file
|
@ -0,0 +1,251 @@
|
||||||
|
/*
|
||||||
|
Copyright 2014 Alexander Okoli
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package goutils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
"regexp"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
CryptoRandomNonAlphaNumeric creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of all characters (ASCII/Unicode values between 0 to 2,147,483,647 (math.MaxInt32)).
|
||||||
|
|
||||||
|
Parameter:
|
||||||
|
count - the length of random string to create
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, CryptoRandom(...)
|
||||||
|
*/
|
||||||
|
func CryptoRandomNonAlphaNumeric(count int) (string, error) {
|
||||||
|
return CryptoRandomAlphaNumericCustom(count, false, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
CryptoRandomAscii creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of characters whose ASCII value is between 32 and 126 (inclusive).
|
||||||
|
|
||||||
|
Parameter:
|
||||||
|
count - the length of random string to create
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, CryptoRandom(...)
|
||||||
|
*/
|
||||||
|
func CryptoRandomAscii(count int) (string, error) {
|
||||||
|
return CryptoRandom(count, 32, 127, false, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
CryptoRandomNumeric creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of numeric characters.
|
||||||
|
|
||||||
|
Parameter:
|
||||||
|
count - the length of random string to create
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, CryptoRandom(...)
|
||||||
|
*/
|
||||||
|
func CryptoRandomNumeric(count int) (string, error) {
|
||||||
|
return CryptoRandom(count, 0, 0, false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
CryptoRandomAlphabetic creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of alpha-numeric characters as indicated by the arguments.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
count - the length of random string to create
|
||||||
|
letters - if true, generated string may include alphabetic characters
|
||||||
|
numbers - if true, generated string may include numeric characters
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, CryptoRandom(...)
|
||||||
|
*/
|
||||||
|
func CryptoRandomAlphabetic(count int) (string, error) {
|
||||||
|
return CryptoRandom(count, 0, 0, true, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
CryptoRandomAlphaNumeric creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of alpha-numeric characters.
|
||||||
|
|
||||||
|
Parameter:
|
||||||
|
count - the length of random string to create
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, CryptoRandom(...)
|
||||||
|
*/
|
||||||
|
func CryptoRandomAlphaNumeric(count int) (string, error) {
|
||||||
|
if count == 0 {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
RandomString, err := CryptoRandom(count, 0, 0, true, true)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("Error: %s", err)
|
||||||
|
}
|
||||||
|
match, err := regexp.MatchString("([0-9]+)", RandomString)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !match {
|
||||||
|
//Get the position between 0 and the length of the string-1 to insert a random number
|
||||||
|
position := getCryptoRandomInt(count)
|
||||||
|
//Insert a random number between [0-9] in the position
|
||||||
|
RandomString = RandomString[:position] + string('0' + getCryptoRandomInt(10)) + RandomString[position + 1:]
|
||||||
|
return RandomString, err
|
||||||
|
}
|
||||||
|
return RandomString, err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
CryptoRandomAlphaNumericCustom creates a random string whose length is the number of characters specified.
|
||||||
|
Characters will be chosen from the set of alpha-numeric characters as indicated by the arguments.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
count - the length of random string to create
|
||||||
|
letters - if true, generated string may include alphabetic characters
|
||||||
|
numbers - if true, generated string may include numeric characters
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from an invalid parameter within underlying function, CryptoRandom(...)
|
||||||
|
*/
|
||||||
|
func CryptoRandomAlphaNumericCustom(count int, letters bool, numbers bool) (string, error) {
|
||||||
|
return CryptoRandom(count, 0, 0, letters, numbers)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
CryptoRandom creates a random string based on a variety of options, using using golang's crypto/rand source of randomness.
|
||||||
|
If the parameters start and end are both 0, start and end are set to ' ' and 'z', the ASCII printable characters, will be used,
|
||||||
|
unless letters and numbers are both false, in which case, start and end are set to 0 and math.MaxInt32, respectively.
|
||||||
|
If chars is not nil, characters stored in chars that are between start and end are chosen.
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
count - the length of random string to create
|
||||||
|
start - the position in set of chars (ASCII/Unicode int) to start at
|
||||||
|
end - the position in set of chars (ASCII/Unicode int) to end before
|
||||||
|
letters - if true, generated string may include alphabetic characters
|
||||||
|
numbers - if true, generated string may include numeric characters
|
||||||
|
chars - the set of chars to choose randoms from. If nil, then it will use the set of all chars.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
string - the random string
|
||||||
|
error - an error stemming from invalid parameters: if count < 0; or the provided chars array is empty; or end <= start; or end > len(chars)
|
||||||
|
*/
|
||||||
|
func CryptoRandom(count int, start int, end int, letters bool, numbers bool, chars ...rune) (string, error) {
|
||||||
|
if count == 0 {
|
||||||
|
return "", nil
|
||||||
|
} else if count < 0 {
|
||||||
|
err := fmt.Errorf("randomstringutils illegal argument: Requested random string length %v is less than 0.", count) // equiv to err := errors.New("...")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if chars != nil && len(chars) == 0 {
|
||||||
|
err := fmt.Errorf("randomstringutils illegal argument: The chars array must not be empty")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if start == 0 && end == 0 {
|
||||||
|
if chars != nil {
|
||||||
|
end = len(chars)
|
||||||
|
} else {
|
||||||
|
if !letters && !numbers {
|
||||||
|
end = math.MaxInt32
|
||||||
|
} else {
|
||||||
|
end = 'z' + 1
|
||||||
|
start = ' '
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if end <= start {
|
||||||
|
err := fmt.Errorf("randomstringutils illegal argument: Parameter end (%v) must be greater than start (%v)", end, start)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if chars != nil && end > len(chars) {
|
||||||
|
err := fmt.Errorf("randomstringutils illegal argument: Parameter end (%v) cannot be greater than len(chars) (%v)", end, len(chars))
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := make([]rune, count)
|
||||||
|
gap := end - start
|
||||||
|
|
||||||
|
// high-surrogates range, (\uD800-\uDBFF) = 55296 - 56319
|
||||||
|
// low-surrogates range, (\uDC00-\uDFFF) = 56320 - 57343
|
||||||
|
|
||||||
|
for count != 0 {
|
||||||
|
count--
|
||||||
|
var ch rune
|
||||||
|
if chars == nil {
|
||||||
|
ch = rune(getCryptoRandomInt(gap) + int64(start))
|
||||||
|
} else {
|
||||||
|
ch = chars[getCryptoRandomInt(gap) + int64(start)]
|
||||||
|
}
|
||||||
|
|
||||||
|
if letters && unicode.IsLetter(ch) || numbers && unicode.IsDigit(ch) || !letters && !numbers {
|
||||||
|
if ch >= 56320 && ch <= 57343 { // low surrogate range
|
||||||
|
if count == 0 {
|
||||||
|
count++
|
||||||
|
} else {
|
||||||
|
// Insert low surrogate
|
||||||
|
buffer[count] = ch
|
||||||
|
count--
|
||||||
|
// Insert high surrogate
|
||||||
|
buffer[count] = rune(55296 + getCryptoRandomInt(128))
|
||||||
|
}
|
||||||
|
} else if ch >= 55296 && ch <= 56191 { // High surrogates range (Partial)
|
||||||
|
if count == 0 {
|
||||||
|
count++
|
||||||
|
} else {
|
||||||
|
// Insert low surrogate
|
||||||
|
buffer[count] = rune(56320 + getCryptoRandomInt(128))
|
||||||
|
count--
|
||||||
|
// Insert high surrogate
|
||||||
|
buffer[count] = ch
|
||||||
|
}
|
||||||
|
} else if ch >= 56192 && ch <= 56319 {
|
||||||
|
// private high surrogate, skip it
|
||||||
|
count++
|
||||||
|
} else {
|
||||||
|
// not one of the surrogates*
|
||||||
|
buffer[count] = ch
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string(buffer), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCryptoRandomInt(count int) int64 {
|
||||||
|
nBig, err := rand.Int(rand.Reader, big.NewInt(int64(count)))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return nBig.Int64()
|
||||||
|
}
|
|
@ -129,14 +129,15 @@ func WrapCustom(str string, wrapLength int, newLineStr string, wrapLongWords boo
|
||||||
} else {
|
} else {
|
||||||
// long words aren't wrapped, just extended beyond limit
|
// long words aren't wrapped, just extended beyond limit
|
||||||
end := wrapLength + offset
|
end := wrapLength + offset
|
||||||
spaceToWrapAt = strings.IndexRune(str[end:len(str)], ' ') + end
|
index := strings.IndexRune(str[end:len(str)], ' ')
|
||||||
if spaceToWrapAt >= 0 {
|
if index == -1 {
|
||||||
|
wrappedLine.WriteString(str[offset:len(str)])
|
||||||
|
offset = inputLineLength
|
||||||
|
} else {
|
||||||
|
spaceToWrapAt = index + end
|
||||||
wrappedLine.WriteString(str[offset:spaceToWrapAt])
|
wrappedLine.WriteString(str[offset:spaceToWrapAt])
|
||||||
wrappedLine.WriteString(newLineStr)
|
wrappedLine.WriteString(newLineStr)
|
||||||
offset = spaceToWrapAt + 1
|
offset = spaceToWrapAt + 1
|
||||||
} else {
|
|
||||||
wrappedLine.WriteString(str[offset:len(str)])
|
|
||||||
offset = inputLineLength
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
297
vendor/github.com/Masterminds/sprig/crypto.go
generated
vendored
297
vendor/github.com/Masterminds/sprig/crypto.go
generated
vendored
|
@ -8,16 +8,23 @@ import (
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
|
"crypto/sha1"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
"crypto/x509/pkix"
|
||||||
"encoding/asn1"
|
"encoding/asn1"
|
||||||
|
"encoding/base64"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash/adler32"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
uuid "github.com/satori/go.uuid"
|
"github.com/google/uuid"
|
||||||
"golang.org/x/crypto/scrypt"
|
"golang.org/x/crypto/scrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -26,9 +33,19 @@ func sha256sum(input string) string {
|
||||||
return hex.EncodeToString(hash[:])
|
return hex.EncodeToString(hash[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sha1sum(input string) string {
|
||||||
|
hash := sha1.Sum([]byte(input))
|
||||||
|
return hex.EncodeToString(hash[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func adler32sum(input string) string {
|
||||||
|
hash := adler32.Checksum([]byte(input))
|
||||||
|
return fmt.Sprintf("%d", hash)
|
||||||
|
}
|
||||||
|
|
||||||
// uuidv4 provides a safe and secure UUID v4 implementation
|
// uuidv4 provides a safe and secure UUID v4 implementation
|
||||||
func uuidv4() string {
|
func uuidv4() string {
|
||||||
return fmt.Sprintf("%s", uuid.NewV4())
|
return fmt.Sprintf("%s", uuid.New())
|
||||||
}
|
}
|
||||||
|
|
||||||
var master_password_seed = "com.lyndir.masterpassword"
|
var master_password_seed = "com.lyndir.masterpassword"
|
||||||
|
@ -146,3 +163,279 @@ func pemBlockForKey(priv interface{}) *pem.Block {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type certificate struct {
|
||||||
|
Cert string
|
||||||
|
Key string
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildCustomCertificate(b64cert string, b64key string) (certificate, error) {
|
||||||
|
crt := certificate{}
|
||||||
|
|
||||||
|
cert, err := base64.StdEncoding.DecodeString(b64cert)
|
||||||
|
if err != nil {
|
||||||
|
return crt, errors.New("unable to decode base64 certificate")
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := base64.StdEncoding.DecodeString(b64key)
|
||||||
|
if err != nil {
|
||||||
|
return crt, errors.New("unable to decode base64 private key")
|
||||||
|
}
|
||||||
|
|
||||||
|
decodedCert, _ := pem.Decode(cert)
|
||||||
|
if decodedCert == nil {
|
||||||
|
return crt, errors.New("unable to decode certificate")
|
||||||
|
}
|
||||||
|
_, err = x509.ParseCertificate(decodedCert.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return crt, fmt.Errorf(
|
||||||
|
"error parsing certificate: decodedCert.Bytes: %s",
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
decodedKey, _ := pem.Decode(key)
|
||||||
|
if decodedKey == nil {
|
||||||
|
return crt, errors.New("unable to decode key")
|
||||||
|
}
|
||||||
|
_, err = x509.ParsePKCS1PrivateKey(decodedKey.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return crt, fmt.Errorf(
|
||||||
|
"error parsing prive key: decodedKey.Bytes: %s",
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
crt.Cert = string(cert)
|
||||||
|
crt.Key = string(key)
|
||||||
|
|
||||||
|
return crt, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
serialNumberUpperBound := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||||
|
serialNumber, err := rand.Int(rand.Reader, serialNumberUpperBound)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &x509.Certificate{
|
||||||
|
SerialNumber: serialNumber,
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
23
vendor/github.com/Masterminds/sprig/date.go
generated
vendored
23
vendor/github.com/Masterminds/sprig/date.go
generated
vendored
|
@ -51,3 +51,26 @@ func dateModify(fmt string, date time.Time) time.Time {
|
||||||
}
|
}
|
||||||
return date.Add(d)
|
return date.Add(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dateAgo(date interface{}) string {
|
||||||
|
var t time.Time
|
||||||
|
|
||||||
|
switch date := date.(type) {
|
||||||
|
default:
|
||||||
|
t = time.Now()
|
||||||
|
case time.Time:
|
||||||
|
t = date
|
||||||
|
case int64:
|
||||||
|
t = time.Unix(date, 0)
|
||||||
|
case int:
|
||||||
|
t = time.Unix(int64(date), 0)
|
||||||
|
}
|
||||||
|
// Drop resolution to seconds
|
||||||
|
duration := time.Since(t).Round(time.Second)
|
||||||
|
return duration.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func toDate(fmt, str string) time.Time {
|
||||||
|
t, _ := time.ParseInLocation(fmt, str, time.Local)
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
10
vendor/github.com/Masterminds/sprig/defaults.go
generated
vendored
10
vendor/github.com/Masterminds/sprig/defaults.go
generated
vendored
|
@ -49,7 +49,6 @@ func empty(given interface{}) bool {
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// coalesce returns the first non-empty value.
|
// coalesce returns the first non-empty value.
|
||||||
|
@ -73,3 +72,12 @@ func toPrettyJson(v interface{}) string {
|
||||||
output, _ := json.MarshalIndent(v, "", " ")
|
output, _ := json.MarshalIndent(v, "", " ")
|
||||||
return string(output)
|
return string(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ternary returns the first value if the last value is true, otherwise returns the second value.
|
||||||
|
func ternary(vt interface{}, vf interface{}, v bool) interface{} {
|
||||||
|
if v {
|
||||||
|
return vt
|
||||||
|
}
|
||||||
|
|
||||||
|
return vf
|
||||||
|
}
|
||||||
|
|
37
vendor/github.com/Masterminds/sprig/dict.go
generated
vendored
37
vendor/github.com/Masterminds/sprig/dict.go
generated
vendored
|
@ -27,10 +27,12 @@ func pluck(key string, d ...map[string]interface{}) []interface{} {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
func keys(dict map[string]interface{}) []string {
|
func keys(dicts ...map[string]interface{}) []string {
|
||||||
k := []string{}
|
k := []string{}
|
||||||
for key := range dict {
|
for _, dict := range dicts {
|
||||||
k = append(k, key)
|
for key := range dict {
|
||||||
|
k = append(k, key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return k
|
return k
|
||||||
}
|
}
|
||||||
|
@ -75,10 +77,31 @@ func dict(v ...interface{}) map[string]interface{} {
|
||||||
return dict
|
return dict
|
||||||
}
|
}
|
||||||
|
|
||||||
func merge(dst map[string]interface{}, src map[string]interface{}) interface{} {
|
func merge(dst map[string]interface{}, srcs ...map[string]interface{}) interface{} {
|
||||||
if err := mergo.Merge(&dst, src); err != nil {
|
for _, src := range srcs {
|
||||||
// Swallow errors inside of a template.
|
if err := mergo.Merge(&dst, src); err != nil {
|
||||||
return ""
|
// Swallow errors inside of a template.
|
||||||
|
return ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mergeOverwrite(dst map[string]interface{}, srcs ...map[string]interface{}) interface{} {
|
||||||
|
for _, src := range srcs {
|
||||||
|
if err := mergo.MergeWithOverwrite(&dst, src); err != nil {
|
||||||
|
// Swallow errors inside of a template.
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
func values(dict map[string]interface{}) []interface{} {
|
||||||
|
values := []interface{}{}
|
||||||
|
for _, value := range dict {
|
||||||
|
values = append(values, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
208
vendor/github.com/Masterminds/sprig/doc.go
generated
vendored
208
vendor/github.com/Masterminds/sprig/doc.go
generated
vendored
|
@ -14,212 +14,6 @@ Note that you should add the function map before you parse any template files.
|
||||||
appear in the standard library. This is to make it easier to pipe
|
appear in the standard library. This is to make it easier to pipe
|
||||||
arguments into functions.
|
arguments into functions.
|
||||||
|
|
||||||
Date Functions
|
See http://masterminds.github.io/sprig/ for more detailed documentation on each of the available functions.
|
||||||
|
|
||||||
- date FORMAT TIME: Format a date, where a date is an integer type or a time.Time type, and
|
|
||||||
format is a time.Format formatting string.
|
|
||||||
- dateModify: Given a date, modify it with a duration: `date_modify "-1.5h" now`. If the duration doesn't
|
|
||||||
parse, it returns the time unaltered. See `time.ParseDuration` for info on duration strings.
|
|
||||||
- now: Current time.Time, for feeding into date-related functions.
|
|
||||||
- htmlDate TIME: Format a date for use in the value field of an HTML "date" form element.
|
|
||||||
- dateInZone FORMAT TIME TZ: Like date, but takes three arguments: format, timestamp,
|
|
||||||
timezone.
|
|
||||||
- htmlDateInZone TIME TZ: Like htmlDate, but takes two arguments: timestamp,
|
|
||||||
timezone.
|
|
||||||
|
|
||||||
String Functions
|
|
||||||
|
|
||||||
- abbrev: Truncate a string with ellipses. `abbrev 5 "hello world"` yields "he..."
|
|
||||||
- abbrevboth: Abbreviate from both sides, yielding "...lo wo..."
|
|
||||||
- trunc: Truncate a string (no suffix). `trunc 5 "Hello World"` yields "hello".
|
|
||||||
- trim: strings.TrimSpace
|
|
||||||
- trimAll: strings.Trim, but with the argument order reversed `trimAll "$" "$5.00"` or `"$5.00 | trimAll "$"`
|
|
||||||
- trimSuffix: strings.TrimSuffix, but with the argument order reversed: `trimSuffix "-" "ends-with-"`
|
|
||||||
- trimPrefix: strings.TrimPrefix, but with the argument order reversed `trimPrefix "$" "$5"`
|
|
||||||
- upper: strings.ToUpper
|
|
||||||
- lower: strings.ToLower
|
|
||||||
- nospace: Remove all space characters from a string. `nospace "h e l l o"` becomes "hello"
|
|
||||||
- title: strings.Title
|
|
||||||
- untitle: Remove title casing
|
|
||||||
- repeat: strings.Repeat, but with the arguments switched: `repeat count str`. (This simplifies common pipelines)
|
|
||||||
- substr: Given string, start, and length, return a substr.
|
|
||||||
- initials: Given a multi-word string, return the initials. `initials "Matt Butcher"` returns "MB"
|
|
||||||
- randAlphaNum: Given a length, generate a random alphanumeric sequence
|
|
||||||
- randAlpha: Given a length, generate an alphabetic string
|
|
||||||
- randAscii: Given a length, generate a random ASCII string (symbols included)
|
|
||||||
- randNumeric: Given a length, generate a string of digits.
|
|
||||||
- wrap: Force a line wrap at the given width. `wrap 80 "imagine a longer string"`
|
|
||||||
- wrapWith: Wrap a line at the given length, but using 'sep' instead of a newline. `wrapWith 50, "<br>", $html`
|
|
||||||
- contains: strings.Contains, but with the arguments switched: `contains substr str`. (This simplifies common pipelines)
|
|
||||||
- hasPrefix: strings.hasPrefix, but with the arguments switched
|
|
||||||
- hasSuffix: strings.hasSuffix, but with the arguments switched
|
|
||||||
- quote: Wrap string(s) in double quotation marks, escape the contents by adding '\' before '"'.
|
|
||||||
- squote: Wrap string(s) in double quotation marks, does not escape content.
|
|
||||||
- cat: Concatenate strings, separating them by spaces. `cat $a $b $c`.
|
|
||||||
- indent: Indent a string using space characters. `indent 4 "foo\nbar"` produces " foo\n bar"
|
|
||||||
- replace: Replace an old with a new in a string: `$name | replace " " "-"`
|
|
||||||
- plural: Choose singular or plural based on length: `len $fish | plural "one anchovy" "many anchovies"`
|
|
||||||
- sha256sum: Generate a hex encoded sha256 hash of the input
|
|
||||||
- toString: Convert something to a string
|
|
||||||
|
|
||||||
String Slice Functions:
|
|
||||||
|
|
||||||
- join: strings.Join, but as `join SEP SLICE`
|
|
||||||
- split: strings.Split, but as `split SEP STRING`. The results are returned
|
|
||||||
as a map with the indexes set to _N, where N is an integer starting from 0.
|
|
||||||
Use it like this: `{{$v := "foo/bar/baz" | split "/"}}{{$v._0}}` (Prints `foo`)
|
|
||||||
- splitList: strings.Split, but as `split SEP STRING`. The results are returned
|
|
||||||
as an array.
|
|
||||||
- toStrings: convert a list to a list of strings. 'list 1 2 3 | toStrings' produces '["1" "2" "3"]'
|
|
||||||
- sortAlpha: sort a list lexicographically.
|
|
||||||
|
|
||||||
Integer Slice Functions:
|
|
||||||
|
|
||||||
- until: Given an integer, returns a slice of counting integers from 0 to one
|
|
||||||
less than the given integer: `range $i, $e := until 5`
|
|
||||||
- untilStep: Given start, stop, and step, return an integer slice starting at
|
|
||||||
'start', stopping at `stop`, and incrementing by 'step. This is the same
|
|
||||||
as Python's long-form of 'range'.
|
|
||||||
|
|
||||||
Conversions:
|
|
||||||
|
|
||||||
- atoi: Convert a string to an integer. 0 if the integer could not be parsed.
|
|
||||||
- in64: Convert a string or another numeric type to an int64.
|
|
||||||
- int: Convert a string or another numeric type to an int.
|
|
||||||
- float64: Convert a string or another numeric type to a float64.
|
|
||||||
|
|
||||||
Defaults:
|
|
||||||
|
|
||||||
- default: Give a default value. Used like this: trim " "| default "empty".
|
|
||||||
Since trim produces an empty string, the default value is returned. For
|
|
||||||
things with a length (strings, slices, maps), len(0) will trigger the default.
|
|
||||||
For numbers, the value 0 will trigger the default. For booleans, false will
|
|
||||||
trigger the default. For structs, the default is never returned (there is
|
|
||||||
no clear empty condition). For everything else, nil value triggers a default.
|
|
||||||
- empty: Return true if the given value is the zero value for its type.
|
|
||||||
Caveats: structs are always non-empty. This should match the behavior of
|
|
||||||
{{if pipeline}}, but can be used inside of a pipeline.
|
|
||||||
- coalesce: Given a list of items, return the first non-empty one.
|
|
||||||
This follows the same rules as 'empty'. '{{ coalesce .someVal 0 "hello" }}`
|
|
||||||
will return `.someVal` if set, or else return "hello". The 0 is skipped
|
|
||||||
because it is an empty value.
|
|
||||||
- compact: Return a copy of a list with all of the empty values removed.
|
|
||||||
'list 0 1 2 "" | compact' will return '[1 2]'
|
|
||||||
|
|
||||||
OS:
|
|
||||||
- env: Resolve an environment variable
|
|
||||||
- expandenv: Expand a string through the environment
|
|
||||||
|
|
||||||
File Paths:
|
|
||||||
- base: Return the last element of a path. https://golang.org/pkg/path#Base
|
|
||||||
- dir: Remove the last element of a path. https://golang.org/pkg/path#Dir
|
|
||||||
- clean: Clean a path to the shortest equivalent name. (e.g. remove "foo/.."
|
|
||||||
from "foo/../bar.html") https://golang.org/pkg/path#Clean
|
|
||||||
- ext: https://golang.org/pkg/path#Ext
|
|
||||||
- isAbs: https://golang.org/pkg/path#IsAbs
|
|
||||||
|
|
||||||
Encoding:
|
|
||||||
- b64enc: Base 64 encode a string.
|
|
||||||
- b64dec: Base 64 decode a string.
|
|
||||||
|
|
||||||
Reflection:
|
|
||||||
|
|
||||||
- typeOf: Takes an interface and returns a string representation of the type.
|
|
||||||
For pointers, this will return a type prefixed with an asterisk(`*`). So
|
|
||||||
a pointer to type `Foo` will be `*Foo`.
|
|
||||||
- typeIs: Compares an interface with a string name, and returns true if they match.
|
|
||||||
Note that a pointer will not match a reference. For example `*Foo` will not
|
|
||||||
match `Foo`.
|
|
||||||
- typeIsLike: Compares an interface with a string name and returns true if
|
|
||||||
the interface is that `name` or that `*name`. In other words, if the given
|
|
||||||
value matches the given type or is a pointer to the given type, this returns
|
|
||||||
true.
|
|
||||||
- kindOf: Takes an interface and returns a string representation of its kind.
|
|
||||||
- kindIs: Returns true if the given string matches the kind of the given interface.
|
|
||||||
|
|
||||||
Note: None of these can test whether or not something implements a given
|
|
||||||
interface, since doing so would require compiling the interface in ahead of
|
|
||||||
time.
|
|
||||||
|
|
||||||
Data Structures:
|
|
||||||
|
|
||||||
- tuple: Takes an arbitrary list of items and returns a slice of items. Its
|
|
||||||
tuple-ish properties are mainly gained through the template idiom, and not
|
|
||||||
through an API provided here. WARNING: The implementation of tuple will
|
|
||||||
change in the future.
|
|
||||||
- list: An arbitrary ordered list of items. (This is prefered over tuple.)
|
|
||||||
- dict: Takes a list of name/values and returns a map[string]interface{}.
|
|
||||||
The first parameter is converted to a string and stored as a key, the
|
|
||||||
second parameter is treated as the value. And so on, with odds as keys and
|
|
||||||
evens as values. If the function call ends with an odd, the last key will
|
|
||||||
be assigned the empty string. Non-string keys are converted to strings as
|
|
||||||
follows: []byte are converted, fmt.Stringers will have String() called.
|
|
||||||
errors will have Error() called. All others will be passed through
|
|
||||||
fmt.Sprtinf("%v").
|
|
||||||
|
|
||||||
Lists Functions:
|
|
||||||
|
|
||||||
These are used to manipulate lists: '{{ list 1 2 3 | reverse | first }}'
|
|
||||||
|
|
||||||
- first: Get the first item in a 'list'. 'list 1 2 3 | first' prints '1'
|
|
||||||
- last: Get the last item in a 'list': 'list 1 2 3 | last ' prints '3'
|
|
||||||
- rest: Get all but the first item in a list: 'list 1 2 3 | rest' returns '[2 3]'
|
|
||||||
- initial: Get all but the last item in a list: 'list 1 2 3 | initial' returns '[1 2]'
|
|
||||||
- append: Add an item to the end of a list: 'append $list 4' adds '4' to the end of '$list'
|
|
||||||
- prepend: Add an item to the beginning of a list: 'prepend $list 4' puts 4 at the beginning of the list.
|
|
||||||
- reverse: Reverse the items in a list.
|
|
||||||
- uniq: Remove duplicates from a list.
|
|
||||||
- without: Return a list with the given values removed: 'without (list 1 2 3) 1' would return '[2 3]'
|
|
||||||
- has: Return 'true' if the item is found in the list: 'has "foo" $list' will return 'true' if the list contains "foo"
|
|
||||||
|
|
||||||
Dict Functions:
|
|
||||||
|
|
||||||
These are used to manipulate dicts.
|
|
||||||
|
|
||||||
- set: Takes a dict, a key, and a value, and sets that key/value pair in
|
|
||||||
the dict. `set $dict $key $value`. For convenience, it returns the dict,
|
|
||||||
even though the dict was modified in place.
|
|
||||||
- unset: Takes a dict and a key, and deletes that key/value pair from the
|
|
||||||
dict. `unset $dict $key`. This returns the dict for convenience.
|
|
||||||
- hasKey: Takes a dict and a key, and returns boolean true if the key is in
|
|
||||||
the dict.
|
|
||||||
- pluck: Given a key and one or more maps, get all of the values for that key.
|
|
||||||
- keys: Get an array of all of the keys in a dict.
|
|
||||||
- pick: Select just the given keys out of the dict, and return a new dict.
|
|
||||||
- omit: Return a dict without the given keys.
|
|
||||||
|
|
||||||
Math Functions:
|
|
||||||
|
|
||||||
Integer functions will convert integers of any width to `int64`. If a
|
|
||||||
string is passed in, functions will attempt to convert with
|
|
||||||
`strconv.ParseInt(s, 1064)`. If this fails, the value will be treated as 0.
|
|
||||||
|
|
||||||
- add1: Increment an integer by 1
|
|
||||||
- add: Sum an arbitrary number of integers
|
|
||||||
- sub: Subtract the second integer from the first
|
|
||||||
- div: Divide the first integer by the second
|
|
||||||
- mod: Module of first integer divided by second
|
|
||||||
- mul: Multiply integers
|
|
||||||
- max: Return the biggest of a series of one or more integers
|
|
||||||
- min: Return the smallest of a series of one or more integers
|
|
||||||
- biggest: DEPRECATED. Return the biggest of a series of one or more integers
|
|
||||||
|
|
||||||
Crypto Functions:
|
|
||||||
|
|
||||||
- genPrivateKey: Generate a private key for the given cryptosystem. If no
|
|
||||||
argument is supplied, by default it will generate a private key using
|
|
||||||
the RSA algorithm. Accepted values are `rsa`, `dsa`, and `ecdsa`.
|
|
||||||
- derivePassword: Derive a password from the given parameters according to the ["Master Password" algorithm](http://masterpasswordapp.com/algorithm.html)
|
|
||||||
Given parameters (in order) are:
|
|
||||||
`counter` (starting with 1), `password_type` (maximum, long, medium, short, basic, or pin), `password`,
|
|
||||||
`user`, and `site`
|
|
||||||
|
|
||||||
SemVer Functions:
|
|
||||||
|
|
||||||
These functions provide version parsing and comparisons for SemVer 2 version
|
|
||||||
strings.
|
|
||||||
|
|
||||||
- semver: Parse a semantic version and return a Version object.
|
|
||||||
- semverCompare: Compare a SemVer range to a particular version.
|
|
||||||
*/
|
*/
|
||||||
package sprig
|
package sprig
|
||||||
|
|
34
vendor/github.com/Masterminds/sprig/functions.go
generated
vendored
34
vendor/github.com/Masterminds/sprig/functions.go
generated
vendored
|
@ -10,7 +10,7 @@ import (
|
||||||
ttemplate "text/template"
|
ttemplate "text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
util "github.com/aokoli/goutils"
|
util "github.com/Masterminds/goutils"
|
||||||
"github.com/huandu/xstrings"
|
"github.com/huandu/xstrings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -98,6 +98,8 @@ var genericMap = map[string]interface{}{
|
||||||
"htmlDateInZone": htmlDateInZone,
|
"htmlDateInZone": htmlDateInZone,
|
||||||
"dateInZone": dateInZone,
|
"dateInZone": dateInZone,
|
||||||
"dateModify": dateModify,
|
"dateModify": dateModify,
|
||||||
|
"ago": dateAgo,
|
||||||
|
"toDate": toDate,
|
||||||
|
|
||||||
// Strings
|
// Strings
|
||||||
"abbrev": abbrev,
|
"abbrev": abbrev,
|
||||||
|
@ -127,6 +129,7 @@ var genericMap = map[string]interface{}{
|
||||||
"shuffle": xstrings.Shuffle,
|
"shuffle": xstrings.Shuffle,
|
||||||
"snakecase": xstrings.ToSnakeCase,
|
"snakecase": xstrings.ToSnakeCase,
|
||||||
"camelcase": xstrings.ToCamelCase,
|
"camelcase": xstrings.ToCamelCase,
|
||||||
|
"kebabcase": xstrings.ToKebabCase,
|
||||||
"wrap": func(l int, s string) string { return util.Wrap(s, l) },
|
"wrap": func(l int, s string) string { return util.Wrap(s, l) },
|
||||||
"wrapWith": func(l int, sep, str string) string { return util.WrapCustom(str, l, sep, true) },
|
"wrapWith": func(l int, sep, str string) string { return util.WrapCustom(str, l, sep, true) },
|
||||||
// Switch order so that "foobar" | contains "foo"
|
// Switch order so that "foobar" | contains "foo"
|
||||||
|
@ -137,9 +140,12 @@ var genericMap = map[string]interface{}{
|
||||||
"squote": squote,
|
"squote": squote,
|
||||||
"cat": cat,
|
"cat": cat,
|
||||||
"indent": indent,
|
"indent": indent,
|
||||||
|
"nindent": nindent,
|
||||||
"replace": replace,
|
"replace": replace,
|
||||||
"plural": plural,
|
"plural": plural,
|
||||||
|
"sha1sum": sha1sum,
|
||||||
"sha256sum": sha256sum,
|
"sha256sum": sha256sum,
|
||||||
|
"adler32sum": adler32sum,
|
||||||
"toString": strval,
|
"toString": strval,
|
||||||
|
|
||||||
// Wrap Atoi to stop errors.
|
// Wrap Atoi to stop errors.
|
||||||
|
@ -156,6 +162,8 @@ var genericMap = map[string]interface{}{
|
||||||
// split "/" foo/bar returns map[int]string{0: foo, 1: bar}
|
// split "/" foo/bar returns map[int]string{0: foo, 1: bar}
|
||||||
"split": split,
|
"split": split,
|
||||||
"splitList": func(sep, orig string) []string { return strings.Split(orig, sep) },
|
"splitList": func(sep, orig string) []string { return strings.Split(orig, sep) },
|
||||||
|
// splitn "/" foo/bar/fuu returns map[int]string{0: foo, 1: bar/fuu}
|
||||||
|
"splitn": splitn,
|
||||||
"toStrings": strslice,
|
"toStrings": strslice,
|
||||||
|
|
||||||
"until": until,
|
"until": until,
|
||||||
|
@ -199,6 +207,7 @@ var genericMap = map[string]interface{}{
|
||||||
"compact": compact,
|
"compact": compact,
|
||||||
"toJson": toJson,
|
"toJson": toJson,
|
||||||
"toPrettyJson": toPrettyJson,
|
"toPrettyJson": toPrettyJson,
|
||||||
|
"ternary": ternary,
|
||||||
|
|
||||||
// Reflection
|
// Reflection
|
||||||
"typeOf": typeOf,
|
"typeOf": typeOf,
|
||||||
|
@ -236,6 +245,8 @@ var genericMap = map[string]interface{}{
|
||||||
"pick": pick,
|
"pick": pick,
|
||||||
"omit": omit,
|
"omit": omit,
|
||||||
"merge": merge,
|
"merge": merge,
|
||||||
|
"mergeOverwrite": mergeOverwrite,
|
||||||
|
"values": values,
|
||||||
|
|
||||||
"append": push, "push": push,
|
"append": push, "push": push,
|
||||||
"prepend": prepend,
|
"prepend": prepend,
|
||||||
|
@ -246,11 +257,16 @@ var genericMap = map[string]interface{}{
|
||||||
"reverse": reverse,
|
"reverse": reverse,
|
||||||
"uniq": uniq,
|
"uniq": uniq,
|
||||||
"without": without,
|
"without": without,
|
||||||
"has": func(needle interface{}, haystack []interface{}) bool { return inList(haystack, needle) },
|
"has": has,
|
||||||
|
"slice": slice,
|
||||||
|
|
||||||
// Crypto:
|
// Crypto:
|
||||||
"genPrivateKey": generatePrivateKey,
|
"genPrivateKey": generatePrivateKey,
|
||||||
"derivePassword": derivePassword,
|
"derivePassword": derivePassword,
|
||||||
|
"buildCustomCert": buildCustomCertificate,
|
||||||
|
"genCA": generateCertificateAuthority,
|
||||||
|
"genSelfSignedCert": generateSelfSignedCertificate,
|
||||||
|
"genSignedCert": generateSignedCertificate,
|
||||||
|
|
||||||
// UUIDs:
|
// UUIDs:
|
||||||
"uuidv4": uuidv4,
|
"uuidv4": uuidv4,
|
||||||
|
@ -263,10 +279,10 @@ var genericMap = map[string]interface{}{
|
||||||
"fail": func(msg string) (string, error) { return "", errors.New(msg) },
|
"fail": func(msg string) (string, error) { return "", errors.New(msg) },
|
||||||
|
|
||||||
// Regex
|
// Regex
|
||||||
"regexMatch": regexMatch,
|
"regexMatch": regexMatch,
|
||||||
"regexFindAll": regexFindAll,
|
"regexFindAll": regexFindAll,
|
||||||
"regexFind": regexFind,
|
"regexFind": regexFind,
|
||||||
"regexReplaceAll": regexReplaceAll,
|
"regexReplaceAll": regexReplaceAll,
|
||||||
"regexReplaceAllLiteral": regexReplaceAllLiteral,
|
"regexReplaceAllLiteral": regexReplaceAllLiteral,
|
||||||
"regexSplit": regexSplit,
|
"regexSplit": regexSplit,
|
||||||
}
|
}
|
||||||
|
|
283
vendor/github.com/Masterminds/sprig/list.go
generated
vendored
283
vendor/github.com/Masterminds/sprig/list.go
generated
vendored
|
@ -1,50 +1,135 @@
|
||||||
package sprig
|
package sprig
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Reflection is used in these functions so that slices and arrays of strings,
|
||||||
|
// ints, and other types not implementing []interface{} can be worked with.
|
||||||
|
// For example, this is useful if you need to work on the output of regexs.
|
||||||
|
|
||||||
func list(v ...interface{}) []interface{} {
|
func list(v ...interface{}) []interface{} {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func push(list []interface{}, v interface{}) []interface{} {
|
func push(list interface{}, v interface{}) []interface{} {
|
||||||
return append(list, v)
|
tp := reflect.TypeOf(list).Kind()
|
||||||
}
|
switch tp {
|
||||||
|
case reflect.Slice, reflect.Array:
|
||||||
|
l2 := reflect.ValueOf(list)
|
||||||
|
|
||||||
func prepend(list []interface{}, v interface{}) []interface{} {
|
l := l2.Len()
|
||||||
return append([]interface{}{v}, list...)
|
nl := make([]interface{}, l)
|
||||||
}
|
for i := 0; i < l; i++ {
|
||||||
|
nl[i] = l2.Index(i).Interface()
|
||||||
|
}
|
||||||
|
|
||||||
func last(list []interface{}) interface{} {
|
return append(nl, v)
|
||||||
l := len(list)
|
|
||||||
if l == 0 {
|
default:
|
||||||
return nil
|
panic(fmt.Sprintf("Cannot push on type %s", tp))
|
||||||
}
|
}
|
||||||
return list[l-1]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func first(list []interface{}) interface{} {
|
func prepend(list interface{}, v interface{}) []interface{} {
|
||||||
if len(list) == 0 {
|
//return append([]interface{}{v}, list...)
|
||||||
return nil
|
|
||||||
|
tp := reflect.TypeOf(list).Kind()
|
||||||
|
switch tp {
|
||||||
|
case reflect.Slice, reflect.Array:
|
||||||
|
l2 := reflect.ValueOf(list)
|
||||||
|
|
||||||
|
l := l2.Len()
|
||||||
|
nl := make([]interface{}, l)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
nl[i] = l2.Index(i).Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
return append([]interface{}{v}, nl...)
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Cannot prepend on type %s", tp))
|
||||||
}
|
}
|
||||||
return list[0]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func rest(list []interface{}) []interface{} {
|
func last(list interface{}) interface{} {
|
||||||
if len(list) == 0 {
|
tp := reflect.TypeOf(list).Kind()
|
||||||
return list
|
switch tp {
|
||||||
|
case reflect.Slice, reflect.Array:
|
||||||
|
l2 := reflect.ValueOf(list)
|
||||||
|
|
||||||
|
l := l2.Len()
|
||||||
|
if l == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return l2.Index(l - 1).Interface()
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Cannot find last on type %s", tp))
|
||||||
}
|
}
|
||||||
return list[1:]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func initial(list []interface{}) []interface{} {
|
func first(list interface{}) interface{} {
|
||||||
l := len(list)
|
tp := reflect.TypeOf(list).Kind()
|
||||||
if l == 0 {
|
switch tp {
|
||||||
return list
|
case reflect.Slice, reflect.Array:
|
||||||
|
l2 := reflect.ValueOf(list)
|
||||||
|
|
||||||
|
l := l2.Len()
|
||||||
|
if l == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return l2.Index(0).Interface()
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Cannot find first on type %s", tp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func rest(list interface{}) []interface{} {
|
||||||
|
tp := reflect.TypeOf(list).Kind()
|
||||||
|
switch tp {
|
||||||
|
case reflect.Slice, reflect.Array:
|
||||||
|
l2 := reflect.ValueOf(list)
|
||||||
|
|
||||||
|
l := l2.Len()
|
||||||
|
if l == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
nl := make([]interface{}, l-1)
|
||||||
|
for i := 1; i < l; i++ {
|
||||||
|
nl[i-1] = l2.Index(i).Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nl
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Cannot find rest on type %s", tp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func initial(list interface{}) []interface{} {
|
||||||
|
tp := reflect.TypeOf(list).Kind()
|
||||||
|
switch tp {
|
||||||
|
case reflect.Slice, reflect.Array:
|
||||||
|
l2 := reflect.ValueOf(list)
|
||||||
|
|
||||||
|
l := l2.Len()
|
||||||
|
if l == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
nl := make([]interface{}, l-1)
|
||||||
|
for i := 0; i < l-1; i++ {
|
||||||
|
nl[i] = l2.Index(i).Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nl
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Cannot find initial on type %s", tp))
|
||||||
}
|
}
|
||||||
return list[:l-1]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func sortAlpha(list interface{}) []string {
|
func sortAlpha(list interface{}) []string {
|
||||||
|
@ -59,34 +144,67 @@ func sortAlpha(list interface{}) []string {
|
||||||
return []string{strval(list)}
|
return []string{strval(list)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func reverse(v []interface{}) []interface{} {
|
func reverse(v interface{}) []interface{} {
|
||||||
// We do not sort in place because the incomming array should not be altered.
|
tp := reflect.TypeOf(v).Kind()
|
||||||
l := len(v)
|
switch tp {
|
||||||
c := make([]interface{}, l)
|
case reflect.Slice, reflect.Array:
|
||||||
for i := 0; i < l; i++ {
|
l2 := reflect.ValueOf(v)
|
||||||
c[l-i-1] = v[i]
|
|
||||||
|
l := l2.Len()
|
||||||
|
// We do not sort in place because the incoming array should not be altered.
|
||||||
|
nl := make([]interface{}, l)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
nl[l-i-1] = l2.Index(i).Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nl
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Cannot find reverse on type %s", tp))
|
||||||
}
|
}
|
||||||
return c
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func compact(list []interface{}) []interface{} {
|
func compact(list interface{}) []interface{} {
|
||||||
res := []interface{}{}
|
tp := reflect.TypeOf(list).Kind()
|
||||||
for _, item := range list {
|
switch tp {
|
||||||
if !empty(item) {
|
case reflect.Slice, reflect.Array:
|
||||||
res = append(res, item)
|
l2 := reflect.ValueOf(list)
|
||||||
|
|
||||||
|
l := l2.Len()
|
||||||
|
nl := []interface{}{}
|
||||||
|
var item interface{}
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
item = l2.Index(i).Interface()
|
||||||
|
if !empty(item) {
|
||||||
|
nl = append(nl, item)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nl
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Cannot compact on type %s", tp))
|
||||||
}
|
}
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func uniq(list []interface{}) []interface{} {
|
func uniq(list interface{}) []interface{} {
|
||||||
dest := []interface{}{}
|
tp := reflect.TypeOf(list).Kind()
|
||||||
for _, item := range list {
|
switch tp {
|
||||||
if !inList(dest, item) {
|
case reflect.Slice, reflect.Array:
|
||||||
dest = append(dest, item)
|
l2 := reflect.ValueOf(list)
|
||||||
|
|
||||||
|
l := l2.Len()
|
||||||
|
dest := []interface{}{}
|
||||||
|
var item interface{}
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
item = l2.Index(i).Interface()
|
||||||
|
if !inList(dest, item) {
|
||||||
|
dest = append(dest, item)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return dest
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Cannot find uniq on type %s", tp))
|
||||||
}
|
}
|
||||||
return dest
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func inList(haystack []interface{}, needle interface{}) bool {
|
func inList(haystack []interface{}, needle interface{}) bool {
|
||||||
|
@ -98,12 +216,79 @@ func inList(haystack []interface{}, needle interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func without(list []interface{}, omit ...interface{}) []interface{} {
|
func without(list interface{}, omit ...interface{}) []interface{} {
|
||||||
res := []interface{}{}
|
tp := reflect.TypeOf(list).Kind()
|
||||||
for _, i := range list {
|
switch tp {
|
||||||
if !inList(omit, i) {
|
case reflect.Slice, reflect.Array:
|
||||||
res = append(res, i)
|
l2 := reflect.ValueOf(list)
|
||||||
|
|
||||||
|
l := l2.Len()
|
||||||
|
res := []interface{}{}
|
||||||
|
var item interface{}
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
item = l2.Index(i).Interface()
|
||||||
|
if !inList(omit, item) {
|
||||||
|
res = append(res, item)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Cannot find without on type %s", tp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func has(needle interface{}, haystack interface{}) bool {
|
||||||
|
if haystack == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
tp := reflect.TypeOf(haystack).Kind()
|
||||||
|
switch tp {
|
||||||
|
case reflect.Slice, reflect.Array:
|
||||||
|
l2 := reflect.ValueOf(haystack)
|
||||||
|
var item interface{}
|
||||||
|
l := l2.Len()
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
item = l2.Index(i).Interface()
|
||||||
|
if reflect.DeepEqual(needle, item) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("Cannot find has on type %s", tp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// $list := [1, 2, 3, 4, 5]
|
||||||
|
// slice $list -> list[0:5] = list[:]
|
||||||
|
// slice $list 0 3 -> list[0:3] = list[:3]
|
||||||
|
// slice $list 3 5 -> list[3:5]
|
||||||
|
// slice $list 3 -> list[3:5] = list[3:]
|
||||||
|
func slice(list interface{}, indices ...interface{}) interface{} {
|
||||||
|
tp := reflect.TypeOf(list).Kind()
|
||||||
|
switch tp {
|
||||||
|
case reflect.Slice, reflect.Array:
|
||||||
|
l2 := reflect.ValueOf(list)
|
||||||
|
|
||||||
|
l := l2.Len()
|
||||||
|
if l == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var start, end int
|
||||||
|
if len(indices) > 0 {
|
||||||
|
start = toInt(indices[0])
|
||||||
|
}
|
||||||
|
if len(indices) < 2 {
|
||||||
|
end = l
|
||||||
|
} else {
|
||||||
|
end = toInt(indices[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
return l2.Slice(start, end).Interface()
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("list should be type of slice or array but %s", tp))
|
||||||
}
|
}
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
|
|
86
vendor/github.com/Masterminds/sprig/strings.go
generated
vendored
86
vendor/github.com/Masterminds/sprig/strings.go
generated
vendored
|
@ -8,7 +8,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
util "github.com/aokoli/goutils"
|
util "github.com/Masterminds/goutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func base64encode(v string) string {
|
func base64encode(v string) string {
|
||||||
|
@ -57,22 +57,22 @@ func initials(s string) string {
|
||||||
|
|
||||||
func randAlphaNumeric(count int) string {
|
func randAlphaNumeric(count int) string {
|
||||||
// It is not possible, it appears, to actually generate an error here.
|
// It is not possible, it appears, to actually generate an error here.
|
||||||
r, _ := util.RandomAlphaNumeric(count)
|
r, _ := util.CryptoRandomAlphaNumeric(count)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func randAlpha(count int) string {
|
func randAlpha(count int) string {
|
||||||
r, _ := util.RandomAlphabetic(count)
|
r, _ := util.CryptoRandomAlphabetic(count)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func randAscii(count int) string {
|
func randAscii(count int) string {
|
||||||
r, _ := util.RandomAscii(count)
|
r, _ := util.CryptoRandomAscii(count)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func randNumeric(count int) string {
|
func randNumeric(count int) string {
|
||||||
r, _ := util.RandomNumeric(count)
|
r, _ := util.CryptoRandomNumeric(count)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,22 +81,27 @@ func untitle(str string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func quote(str ...interface{}) string {
|
func quote(str ...interface{}) string {
|
||||||
out := make([]string, len(str))
|
out := make([]string, 0, len(str))
|
||||||
for i, s := range str {
|
for _, s := range str {
|
||||||
out[i] = fmt.Sprintf("%q", strval(s))
|
if s != nil {
|
||||||
|
out = append(out, fmt.Sprintf("%q", strval(s)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return strings.Join(out, " ")
|
return strings.Join(out, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
func squote(str ...interface{}) string {
|
func squote(str ...interface{}) string {
|
||||||
out := make([]string, len(str))
|
out := make([]string, 0, len(str))
|
||||||
for i, s := range str {
|
for _, s := range str {
|
||||||
out[i] = fmt.Sprintf("'%v'", s)
|
if s != nil {
|
||||||
|
out = append(out, fmt.Sprintf("'%v'", s))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return strings.Join(out, " ")
|
return strings.Join(out, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
func cat(v ...interface{}) string {
|
func cat(v ...interface{}) string {
|
||||||
|
v = removeNilElements(v)
|
||||||
r := strings.TrimSpace(strings.Repeat("%v ", len(v)))
|
r := strings.TrimSpace(strings.Repeat("%v ", len(v)))
|
||||||
return fmt.Sprintf(r, v...)
|
return fmt.Sprintf(r, v...)
|
||||||
}
|
}
|
||||||
|
@ -106,6 +111,10 @@ func indent(spaces int, v string) string {
|
||||||
return pad + strings.Replace(v, "\n", "\n"+pad, -1)
|
return pad + strings.Replace(v, "\n", "\n"+pad, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func nindent(spaces int, v string) string {
|
||||||
|
return "\n" + indent(spaces, v)
|
||||||
|
}
|
||||||
|
|
||||||
func replace(old, new, src string) string {
|
func replace(old, new, src string) string {
|
||||||
return strings.Replace(src, old, new, -1)
|
return strings.Replace(src, old, new, -1)
|
||||||
}
|
}
|
||||||
|
@ -122,10 +131,11 @@ func strslice(v interface{}) []string {
|
||||||
case []string:
|
case []string:
|
||||||
return v
|
return v
|
||||||
case []interface{}:
|
case []interface{}:
|
||||||
l := len(v)
|
b := make([]string, 0, len(v))
|
||||||
b := make([]string, l)
|
for _, s := range v {
|
||||||
for i := 0; i < l; i++ {
|
if s != nil {
|
||||||
b[i] = strval(v[i])
|
b = append(b, strval(s))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
default:
|
default:
|
||||||
|
@ -133,17 +143,34 @@ func strslice(v interface{}) []string {
|
||||||
switch val.Kind() {
|
switch val.Kind() {
|
||||||
case reflect.Array, reflect.Slice:
|
case reflect.Array, reflect.Slice:
|
||||||
l := val.Len()
|
l := val.Len()
|
||||||
b := make([]string, l)
|
b := make([]string, 0, l)
|
||||||
for i := 0; i < l; i++ {
|
for i := 0; i < l; i++ {
|
||||||
b[i] = strval(val.Index(i).Interface())
|
value := val.Index(i).Interface()
|
||||||
|
if value != nil {
|
||||||
|
b = append(b, strval(value))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
default:
|
default:
|
||||||
return []string{strval(v)}
|
if v == nil {
|
||||||
|
return []string{}
|
||||||
|
} else {
|
||||||
|
return []string{strval(v)}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func removeNilElements(v []interface{}) []interface{} {
|
||||||
|
newSlice := make([]interface{}, 0, len(v))
|
||||||
|
for _, i := range v {
|
||||||
|
if i != nil {
|
||||||
|
newSlice = append(newSlice, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newSlice
|
||||||
|
}
|
||||||
|
|
||||||
func strval(v interface{}) string {
|
func strval(v interface{}) string {
|
||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
case string:
|
case string:
|
||||||
|
@ -179,19 +206,28 @@ func split(sep, orig string) map[string]string {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func splitn(sep string, n int, orig string) map[string]string {
|
||||||
|
parts := strings.SplitN(orig, sep, n)
|
||||||
|
res := make(map[string]string, len(parts))
|
||||||
|
for i, v := range parts {
|
||||||
|
res["_"+strconv.Itoa(i)] = v
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
// substring creates a substring of the given string.
|
// substring creates a substring of the given string.
|
||||||
//
|
//
|
||||||
// If start is < 0, this calls string[:length].
|
// If start is < 0, this calls string[:end].
|
||||||
//
|
//
|
||||||
// If start is >= 0 and length < 0, this calls string[start:]
|
// If start is >= 0 and end < 0 or end bigger than s length, this calls string[start:]
|
||||||
//
|
//
|
||||||
// Otherwise, this calls string[start, length].
|
// Otherwise, this calls string[start, end].
|
||||||
func substring(start, length int, s string) string {
|
func substring(start, end int, s string) string {
|
||||||
if start < 0 {
|
if start < 0 {
|
||||||
return s[:length]
|
return s[:end]
|
||||||
}
|
}
|
||||||
if length < 0 {
|
if end < 0 || end > len(s) {
|
||||||
return s[start:]
|
return s[start:]
|
||||||
}
|
}
|
||||||
return s[start:length]
|
return s[start:end]
|
||||||
}
|
}
|
||||||
|
|
6
vendor/github.com/huandu/xstrings/common.go
generated
vendored
6
vendor/github.com/huandu/xstrings/common.go
generated
vendored
|
@ -7,7 +7,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
)
|
)
|
||||||
|
|
||||||
const _BUFFER_INIT_GROW_SIZE_MAX = 2048
|
const bufferMaxInitGrowSize = 2048
|
||||||
|
|
||||||
// Lazy initialize a buffer.
|
// Lazy initialize a buffer.
|
||||||
func allocBuffer(orig, cur string) *bytes.Buffer {
|
func allocBuffer(orig, cur string) *bytes.Buffer {
|
||||||
|
@ -15,8 +15,8 @@ func allocBuffer(orig, cur string) *bytes.Buffer {
|
||||||
maxSize := len(orig) * 4
|
maxSize := len(orig) * 4
|
||||||
|
|
||||||
// Avoid to reserve too much memory at once.
|
// Avoid to reserve too much memory at once.
|
||||||
if maxSize > _BUFFER_INIT_GROW_SIZE_MAX {
|
if maxSize > bufferMaxInitGrowSize {
|
||||||
maxSize = _BUFFER_INIT_GROW_SIZE_MAX
|
maxSize = bufferMaxInitGrowSize
|
||||||
}
|
}
|
||||||
|
|
||||||
output.Grow(maxSize)
|
output.Grow(maxSize)
|
||||||
|
|
77
vendor/github.com/huandu/xstrings/convert.go
generated
vendored
77
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +72,7 @@ func ToCamelCase(str string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToSnakeCase can convert all upper case characters in a string to
|
// ToSnakeCase can convert all upper case characters in a string to
|
||||||
// underscore format.
|
// snake case format.
|
||||||
//
|
//
|
||||||
// Some samples.
|
// Some samples.
|
||||||
// "FirstName" => "first_name"
|
// "FirstName" => "first_name"
|
||||||
|
@ -74,7 +81,31 @@ func ToCamelCase(str string) string {
|
||||||
// "GO_PATH" => "go_path"
|
// "GO_PATH" => "go_path"
|
||||||
// "GO PATH" => "go_path" // space is converted to underscore.
|
// "GO PATH" => "go_path" // space is converted to underscore.
|
||||||
// "GO-PATH" => "go_path" // hyphen is converted to underscore.
|
// "GO-PATH" => "go_path" // hyphen is converted to underscore.
|
||||||
|
// "HTTP2XX" => "http_2xx" // insert an underscore before a number and after an alphabet.
|
||||||
|
// "http2xx" => "http_2xx"
|
||||||
|
// "HTTP20xOK" => "http_20x_ok"
|
||||||
func ToSnakeCase(str string) string {
|
func ToSnakeCase(str string) string {
|
||||||
|
return camelCaseToLowerCase(str, '_')
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToKebabCase can convert all upper case characters in a string to
|
||||||
|
// kebab case format.
|
||||||
|
//
|
||||||
|
// Some samples.
|
||||||
|
// "FirstName" => "first-name"
|
||||||
|
// "HTTPServer" => "http-server"
|
||||||
|
// "NoHTTPS" => "no-https"
|
||||||
|
// "GO_PATH" => "go-path"
|
||||||
|
// "GO PATH" => "go-path" // space is converted to '-'.
|
||||||
|
// "GO-PATH" => "go-path" // hyphen is converted to '-'.
|
||||||
|
// "HTTP2XX" => "http-2xx" // insert a '-' before a number and after an alphabet.
|
||||||
|
// "http2xx" => "http-2xx"
|
||||||
|
// "HTTP20xOK" => "http-20x-ok"
|
||||||
|
func ToKebabCase(str string) string {
|
||||||
|
return camelCaseToLowerCase(str, '-')
|
||||||
|
}
|
||||||
|
|
||||||
|
func camelCaseToLowerCase(str string, connector rune) string {
|
||||||
if len(str) == 0 {
|
if len(str) == 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -83,7 +114,7 @@ func ToSnakeCase(str string) string {
|
||||||
var prev, r0, r1 rune
|
var prev, r0, r1 rune
|
||||||
var size int
|
var size int
|
||||||
|
|
||||||
r0 = '_'
|
r0 = connector
|
||||||
|
|
||||||
for len(str) > 0 {
|
for len(str) > 0 {
|
||||||
prev = r0
|
prev = r0
|
||||||
|
@ -92,11 +123,11 @@ func ToSnakeCase(str string) string {
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case r0 == utf8.RuneError:
|
case r0 == utf8.RuneError:
|
||||||
buf.WriteByte(byte(str[0]))
|
buf.WriteRune(r0)
|
||||||
|
|
||||||
case unicode.IsUpper(r0):
|
case unicode.IsUpper(r0):
|
||||||
if prev != '_' {
|
if prev != connector && !unicode.IsNumber(prev) {
|
||||||
buf.WriteRune('_')
|
buf.WriteRune(connector)
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.WriteRune(unicode.ToLower(r0))
|
buf.WriteRune(unicode.ToLower(r0))
|
||||||
|
@ -113,7 +144,7 @@ func ToSnakeCase(str string) string {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// find next non-upper-case character and insert `_` properly.
|
// find next non-upper-case character and insert connector properly.
|
||||||
// it's designed to convert `HTTPServer` to `http_server`.
|
// it's designed to convert `HTTPServer` to `http_server`.
|
||||||
// if there are more than 2 adjacent upper case characters in a word,
|
// if there are more than 2 adjacent upper case characters in a word,
|
||||||
// treat them as an abbreviation plus a normal word.
|
// treat them as an abbreviation plus a normal word.
|
||||||
|
@ -124,17 +155,23 @@ func ToSnakeCase(str string) string {
|
||||||
|
|
||||||
if r0 == utf8.RuneError {
|
if r0 == utf8.RuneError {
|
||||||
buf.WriteRune(unicode.ToLower(r1))
|
buf.WriteRune(unicode.ToLower(r1))
|
||||||
buf.WriteByte(byte(str[0]))
|
buf.WriteRune(r0)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if !unicode.IsUpper(r0) {
|
if !unicode.IsUpper(r0) {
|
||||||
if r0 == '_' || r0 == ' ' || r0 == '-' {
|
if r0 == '_' || r0 == ' ' || r0 == '-' {
|
||||||
r0 = '_'
|
r0 = connector
|
||||||
|
|
||||||
buf.WriteRune(unicode.ToLower(r1))
|
buf.WriteRune(unicode.ToLower(r1))
|
||||||
|
} else if unicode.IsNumber(r0) {
|
||||||
|
// treat a number as an upper case rune
|
||||||
|
// so that both `http2xx` and `HTTP2XX` can be converted to `http_2xx`.
|
||||||
|
buf.WriteRune(unicode.ToLower(r1))
|
||||||
|
buf.WriteRune(connector)
|
||||||
|
buf.WriteRune(r0)
|
||||||
} else {
|
} else {
|
||||||
buf.WriteRune('_')
|
buf.WriteRune(connector)
|
||||||
buf.WriteRune(unicode.ToLower(r1))
|
buf.WriteRune(unicode.ToLower(r1))
|
||||||
buf.WriteRune(r0)
|
buf.WriteRune(r0)
|
||||||
}
|
}
|
||||||
|
@ -145,14 +182,20 @@ func ToSnakeCase(str string) string {
|
||||||
buf.WriteRune(unicode.ToLower(r1))
|
buf.WriteRune(unicode.ToLower(r1))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(str) == 0 || r0 == '_' {
|
if len(str) == 0 || r0 == connector {
|
||||||
buf.WriteRune(unicode.ToLower(r0))
|
buf.WriteRune(unicode.ToLower(r0))
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case unicode.IsNumber(r0):
|
||||||
|
if prev != connector && !unicode.IsNumber(prev) {
|
||||||
|
buf.WriteRune(connector)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteRune(r0)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if r0 == ' ' || r0 == '-' {
|
if r0 == ' ' || r0 == '-' || r0 == '_' {
|
||||||
r0 = '_'
|
r0 = connector
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.WriteRune(r0)
|
buf.WriteRune(r0)
|
||||||
|
|
4
vendor/github.com/huandu/xstrings/count.go
generated
vendored
4
vendor/github.com/huandu/xstrings/count.go
generated
vendored
|
@ -8,12 +8,12 @@ import (
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Get str's utf8 rune length.
|
// Len returns str's utf8 rune length.
|
||||||
func Len(str string) int {
|
func Len(str string) int {
|
||||||
return utf8.RuneCountInString(str)
|
return utf8.RuneCountInString(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count number of words in a string.
|
// WordCount returns number of words in a string.
|
||||||
//
|
//
|
||||||
// Word is defined as a locale dependent string containing alphabetic characters,
|
// Word is defined as a locale dependent string containing alphabetic characters,
|
||||||
// which may also contain but not start with `'` and `-` characters.
|
// which may also contain but not start with `'` and `-` characters.
|
||||||
|
|
4
vendor/github.com/huandu/xstrings/doc.go
generated
vendored
4
vendor/github.com/huandu/xstrings/doc.go
generated
vendored
|
@ -1,8 +1,8 @@
|
||||||
// Copyright 2015 Huan Du. All rights reserved.
|
// Copyright 2015 Huan Du. All rights reserved.
|
||||||
// Licensed under the MIT license that can be found in the LICENSE file.
|
// Licensed under the MIT license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Package `xstrings` is to provide string algorithms which are useful but not included in `strings` package.
|
// Package xstrings is to provide string algorithms which are useful but not included in `strings` package.
|
||||||
// See project home page for details. https://github.com/huandu/xstrings
|
// See project home page for details. https://github.com/huandu/xstrings
|
||||||
//
|
//
|
||||||
// Package `xstrings` assumes all strings are encoded in utf8.
|
// Package xstrings assumes all strings are encoded in utf8.
|
||||||
package xstrings
|
package xstrings
|
||||||
|
|
4
vendor/github.com/huandu/xstrings/manipulate.go
generated
vendored
4
vendor/github.com/huandu/xstrings/manipulate.go
generated
vendored
|
@ -128,7 +128,7 @@ func Insert(dst, src string, index int) string {
|
||||||
return Slice(dst, 0, index) + src + Slice(dst, index, -1)
|
return Slice(dst, 0, index) + src + Slice(dst, index, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scrubs invalid utf8 bytes with repl string.
|
// Scrub scrubs invalid utf8 bytes with repl string.
|
||||||
// Adjacent invalid bytes are replaced only once.
|
// Adjacent invalid bytes are replaced only once.
|
||||||
func Scrub(str, repl string) string {
|
func Scrub(str, repl string) string {
|
||||||
var buf *bytes.Buffer
|
var buf *bytes.Buffer
|
||||||
|
@ -171,7 +171,7 @@ func Scrub(str, repl string) string {
|
||||||
return origin
|
return origin
|
||||||
}
|
}
|
||||||
|
|
||||||
// Splits a string into words. Returns a slice of words.
|
// WordSplit splits a string into words. Returns a slice of words.
|
||||||
// If there is no word in a string, return nil.
|
// If there is no word in a string, return nil.
|
||||||
//
|
//
|
||||||
// Word is defined as a locale dependent string containing alphabetic characters,
|
// Word is defined as a locale dependent string containing alphabetic characters,
|
||||||
|
|
6
vendor/github.com/huandu/xstrings/translate.go
generated
vendored
6
vendor/github.com/huandu/xstrings/translate.go
generated
vendored
|
@ -492,8 +492,9 @@ func Count(str, pattern string) int {
|
||||||
// If pattern is not empty, only runes matching the pattern will be squeezed.
|
// If pattern is not empty, only runes matching the pattern will be squeezed.
|
||||||
//
|
//
|
||||||
// Samples:
|
// Samples:
|
||||||
// Squeeze("hello", "") => "helo"
|
// Squeeze("hello", "") => "helo"
|
||||||
// Squeeze("hello", "m-z") => "hello"
|
// Squeeze("hello", "m-z") => "hello"
|
||||||
|
// Squeeze("hello world", " ") => "hello world"
|
||||||
func Squeeze(str, pattern string) string {
|
func Squeeze(str, pattern string) string {
|
||||||
var last, r rune
|
var last, r rune
|
||||||
var size int
|
var size int
|
||||||
|
@ -532,6 +533,7 @@ func Squeeze(str, pattern string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
last = r
|
last = r
|
||||||
|
skipSqueeze = false
|
||||||
}
|
}
|
||||||
|
|
||||||
str = str[size:]
|
str = str[size:]
|
||||||
|
|
Loading…
Reference in a new issue