mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-28 01:09:56 +00:00
TUN-6937: Bump golang.org/x/* packages to new release tags
This commit is contained in:
78
vendor/golang.org/x/mod/internal/lazyregexp/lazyre.go
generated
vendored
Normal file
78
vendor/golang.org/x/mod/internal/lazyregexp/lazyre.go
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package lazyregexp is a thin wrapper over regexp, allowing the use of global
|
||||
// regexp variables without forcing them to be compiled at init.
|
||||
package lazyregexp
|
||||
|
||||
import (
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Regexp is a wrapper around regexp.Regexp, where the underlying regexp will be
|
||||
// compiled the first time it is needed.
|
||||
type Regexp struct {
|
||||
str string
|
||||
once sync.Once
|
||||
rx *regexp.Regexp
|
||||
}
|
||||
|
||||
func (r *Regexp) re() *regexp.Regexp {
|
||||
r.once.Do(r.build)
|
||||
return r.rx
|
||||
}
|
||||
|
||||
func (r *Regexp) build() {
|
||||
r.rx = regexp.MustCompile(r.str)
|
||||
r.str = ""
|
||||
}
|
||||
|
||||
func (r *Regexp) FindSubmatch(s []byte) [][]byte {
|
||||
return r.re().FindSubmatch(s)
|
||||
}
|
||||
|
||||
func (r *Regexp) FindStringSubmatch(s string) []string {
|
||||
return r.re().FindStringSubmatch(s)
|
||||
}
|
||||
|
||||
func (r *Regexp) FindStringSubmatchIndex(s string) []int {
|
||||
return r.re().FindStringSubmatchIndex(s)
|
||||
}
|
||||
|
||||
func (r *Regexp) ReplaceAllString(src, repl string) string {
|
||||
return r.re().ReplaceAllString(src, repl)
|
||||
}
|
||||
|
||||
func (r *Regexp) FindString(s string) string {
|
||||
return r.re().FindString(s)
|
||||
}
|
||||
|
||||
func (r *Regexp) FindAllString(s string, n int) []string {
|
||||
return r.re().FindAllString(s, n)
|
||||
}
|
||||
|
||||
func (r *Regexp) MatchString(s string) bool {
|
||||
return r.re().MatchString(s)
|
||||
}
|
||||
|
||||
func (r *Regexp) SubexpNames() []string {
|
||||
return r.re().SubexpNames()
|
||||
}
|
||||
|
||||
var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test")
|
||||
|
||||
// New creates a new lazy regexp, delaying the compiling work until it is first
|
||||
// needed. If the code is being run as part of tests, the regexp compiling will
|
||||
// happen immediately.
|
||||
func New(str string) *Regexp {
|
||||
lr := &Regexp{str: str}
|
||||
if inTest {
|
||||
// In tests, always compile the regexps early.
|
||||
lr.re()
|
||||
}
|
||||
return lr
|
||||
}
|
69
vendor/golang.org/x/mod/module/module.go
generated
vendored
69
vendor/golang.org/x/mod/module/module.go
generated
vendored
@@ -15,7 +15,7 @@
|
||||
// but additional checking functions, most notably Check, verify that
|
||||
// a particular path, version pair is valid.
|
||||
//
|
||||
// Escaped Paths
|
||||
// # Escaped Paths
|
||||
//
|
||||
// Module paths appear as substrings of file system paths
|
||||
// (in the download cache) and of web server URLs in the proxy protocol.
|
||||
@@ -55,7 +55,7 @@
|
||||
// Import paths have never allowed exclamation marks, so there is no
|
||||
// need to define how to escape a literal !.
|
||||
//
|
||||
// Unicode Restrictions
|
||||
// # Unicode Restrictions
|
||||
//
|
||||
// Today, paths are disallowed from using Unicode.
|
||||
//
|
||||
@@ -102,9 +102,9 @@ import (
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
"errors"
|
||||
|
||||
"golang.org/x/mod/semver"
|
||||
errors "golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
// A Version (for clients, a module.Version) is defined by a module path and version pair.
|
||||
@@ -192,6 +192,21 @@ func (e *InvalidVersionError) Error() string {
|
||||
|
||||
func (e *InvalidVersionError) Unwrap() error { return e.Err }
|
||||
|
||||
// An InvalidPathError indicates a module, import, or file path doesn't
|
||||
// satisfy all naming constraints. See CheckPath, CheckImportPath,
|
||||
// and CheckFilePath for specific restrictions.
|
||||
type InvalidPathError struct {
|
||||
Kind string // "module", "import", or "file"
|
||||
Path string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *InvalidPathError) Error() string {
|
||||
return fmt.Sprintf("malformed %s path %q: %v", e.Kind, e.Path, e.Err)
|
||||
}
|
||||
|
||||
func (e *InvalidPathError) Unwrap() error { return e.Err }
|
||||
|
||||
// Check checks that a given module path, version pair is valid.
|
||||
// In addition to the path being a valid module path
|
||||
// and the version being a valid semantic version,
|
||||
@@ -271,12 +286,7 @@ func fileNameOK(r rune) bool {
|
||||
if '0' <= r && r <= '9' || 'A' <= r && r <= 'Z' || 'a' <= r && r <= 'z' {
|
||||
return true
|
||||
}
|
||||
for i := 0; i < len(allowed); i++ {
|
||||
if rune(allowed[i]) == r {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return strings.ContainsRune(allowed, r)
|
||||
}
|
||||
// It may be OK to add more ASCII punctuation here, but only carefully.
|
||||
// For example Windows disallows < > \, and macOS disallows :, so we must not allow those.
|
||||
@@ -296,30 +306,36 @@ func fileNameOK(r rune) bool {
|
||||
// this second requirement is replaced by a requirement that the path
|
||||
// follow the gopkg.in server's conventions.
|
||||
// Third, no path element may begin with a dot.
|
||||
func CheckPath(path string) error {
|
||||
func CheckPath(path string) (err error) {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
err = &InvalidPathError{Kind: "module", Path: path, Err: err}
|
||||
}
|
||||
}()
|
||||
|
||||
if err := checkPath(path, modulePath); err != nil {
|
||||
return fmt.Errorf("malformed module path %q: %v", path, err)
|
||||
return err
|
||||
}
|
||||
i := strings.Index(path, "/")
|
||||
if i < 0 {
|
||||
i = len(path)
|
||||
}
|
||||
if i == 0 {
|
||||
return fmt.Errorf("malformed module path %q: leading slash", path)
|
||||
return fmt.Errorf("leading slash")
|
||||
}
|
||||
if !strings.Contains(path[:i], ".") {
|
||||
return fmt.Errorf("malformed module path %q: missing dot in first path element", path)
|
||||
return fmt.Errorf("missing dot in first path element")
|
||||
}
|
||||
if path[0] == '-' {
|
||||
return fmt.Errorf("malformed module path %q: leading dash in first path element", path)
|
||||
return fmt.Errorf("leading dash in first path element")
|
||||
}
|
||||
for _, r := range path[:i] {
|
||||
if !firstPathOK(r) {
|
||||
return fmt.Errorf("malformed module path %q: invalid char %q in first path element", path, r)
|
||||
return fmt.Errorf("invalid char %q in first path element", r)
|
||||
}
|
||||
}
|
||||
if _, _, ok := SplitPathVersion(path); !ok {
|
||||
return fmt.Errorf("malformed module path %q: invalid version", path)
|
||||
return fmt.Errorf("invalid version")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -343,7 +359,7 @@ func CheckPath(path string) error {
|
||||
// subtleties of Unicode.
|
||||
func CheckImportPath(path string) error {
|
||||
if err := checkPath(path, importPath); err != nil {
|
||||
return fmt.Errorf("malformed import path %q: %v", path, err)
|
||||
return &InvalidPathError{Kind: "import", Path: path, Err: err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -358,12 +374,13 @@ const (
|
||||
filePath
|
||||
)
|
||||
|
||||
// checkPath checks that a general path is valid.
|
||||
// It returns an error describing why but not mentioning path.
|
||||
// Because these checks apply to both module paths and import paths,
|
||||
// the caller is expected to add the "malformed ___ path %q: " prefix.
|
||||
// fileName indicates whether the final element of the path is a file name
|
||||
// (as opposed to a directory name).
|
||||
// checkPath checks that a general path is valid. kind indicates what
|
||||
// specific constraints should be applied.
|
||||
//
|
||||
// checkPath returns an error describing why the path is not valid.
|
||||
// Because these checks apply to module, import, and file paths,
|
||||
// and because other checks may be applied, the caller is expected to wrap
|
||||
// this error with InvalidPathError.
|
||||
func checkPath(path string, kind pathKind) error {
|
||||
if !utf8.ValidString(path) {
|
||||
return fmt.Errorf("invalid UTF-8")
|
||||
@@ -371,7 +388,7 @@ func checkPath(path string, kind pathKind) error {
|
||||
if path == "" {
|
||||
return fmt.Errorf("empty string")
|
||||
}
|
||||
if path[0] == '-' {
|
||||
if path[0] == '-' && kind != filePath {
|
||||
return fmt.Errorf("leading dash")
|
||||
}
|
||||
if strings.Contains(path, "//") {
|
||||
@@ -477,7 +494,7 @@ func checkElem(elem string, kind pathKind) error {
|
||||
// subtleties of Unicode.
|
||||
func CheckFilePath(path string) error {
|
||||
if err := checkPath(path, filePath); err != nil {
|
||||
return fmt.Errorf("malformed file path %q: %v", path, err)
|
||||
return &InvalidPathError{Kind: "file", Path: path, Err: err}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -781,6 +798,7 @@ func unescapeString(escaped string) (string, bool) {
|
||||
// GOPRIVATE environment variable, as described by 'go help module-private'.
|
||||
//
|
||||
// It ignores any empty or malformed patterns in the list.
|
||||
// Trailing slashes on patterns are ignored.
|
||||
func MatchPrefixPatterns(globs, target string) bool {
|
||||
for globs != "" {
|
||||
// Extract next non-empty glob in comma-separated list.
|
||||
@@ -790,6 +808,7 @@ func MatchPrefixPatterns(globs, target string) bool {
|
||||
} else {
|
||||
glob, globs = globs, ""
|
||||
}
|
||||
glob = strings.TrimSuffix(glob, "/")
|
||||
if glob == "" {
|
||||
continue
|
||||
}
|
||||
|
250
vendor/golang.org/x/mod/module/pseudo.go
generated
vendored
Normal file
250
vendor/golang.org/x/mod/module/pseudo.go
generated
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Pseudo-versions
|
||||
//
|
||||
// Code authors are expected to tag the revisions they want users to use,
|
||||
// including prereleases. However, not all authors tag versions at all,
|
||||
// and not all commits a user might want to try will have tags.
|
||||
// A pseudo-version is a version with a special form that allows us to
|
||||
// address an untagged commit and order that version with respect to
|
||||
// other versions we might encounter.
|
||||
//
|
||||
// A pseudo-version takes one of the general forms:
|
||||
//
|
||||
// (1) vX.0.0-yyyymmddhhmmss-abcdef123456
|
||||
// (2) vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456
|
||||
// (3) vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456+incompatible
|
||||
// (4) vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456
|
||||
// (5) vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456+incompatible
|
||||
//
|
||||
// If there is no recently tagged version with the right major version vX,
|
||||
// then form (1) is used, creating a space of pseudo-versions at the bottom
|
||||
// of the vX version range, less than any tagged version, including the unlikely v0.0.0.
|
||||
//
|
||||
// If the most recent tagged version before the target commit is vX.Y.Z or vX.Y.Z+incompatible,
|
||||
// then the pseudo-version uses form (2) or (3), making it a prerelease for the next
|
||||
// possible semantic version after vX.Y.Z. The leading 0 segment in the prerelease string
|
||||
// ensures that the pseudo-version compares less than possible future explicit prereleases
|
||||
// like vX.Y.(Z+1)-rc1 or vX.Y.(Z+1)-1.
|
||||
//
|
||||
// If the most recent tagged version before the target commit is vX.Y.Z-pre or vX.Y.Z-pre+incompatible,
|
||||
// then the pseudo-version uses form (4) or (5), making it a slightly later prerelease.
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/mod/internal/lazyregexp"
|
||||
"golang.org/x/mod/semver"
|
||||
)
|
||||
|
||||
var pseudoVersionRE = lazyregexp.New(`^v[0-9]+\.(0\.0-|\d+\.\d+-([^+]*\.)?0\.)\d{14}-[A-Za-z0-9]+(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$`)
|
||||
|
||||
const PseudoVersionTimestampFormat = "20060102150405"
|
||||
|
||||
// PseudoVersion returns a pseudo-version for the given major version ("v1")
|
||||
// preexisting older tagged version ("" or "v1.2.3" or "v1.2.3-pre"), revision time,
|
||||
// and revision identifier (usually a 12-byte commit hash prefix).
|
||||
func PseudoVersion(major, older string, t time.Time, rev string) string {
|
||||
if major == "" {
|
||||
major = "v0"
|
||||
}
|
||||
segment := fmt.Sprintf("%s-%s", t.UTC().Format(PseudoVersionTimestampFormat), rev)
|
||||
build := semver.Build(older)
|
||||
older = semver.Canonical(older)
|
||||
if older == "" {
|
||||
return major + ".0.0-" + segment // form (1)
|
||||
}
|
||||
if semver.Prerelease(older) != "" {
|
||||
return older + ".0." + segment + build // form (4), (5)
|
||||
}
|
||||
|
||||
// Form (2), (3).
|
||||
// Extract patch from vMAJOR.MINOR.PATCH
|
||||
i := strings.LastIndex(older, ".") + 1
|
||||
v, patch := older[:i], older[i:]
|
||||
|
||||
// Reassemble.
|
||||
return v + incDecimal(patch) + "-0." + segment + build
|
||||
}
|
||||
|
||||
// ZeroPseudoVersion returns a pseudo-version with a zero timestamp and
|
||||
// revision, which may be used as a placeholder.
|
||||
func ZeroPseudoVersion(major string) string {
|
||||
return PseudoVersion(major, "", time.Time{}, "000000000000")
|
||||
}
|
||||
|
||||
// incDecimal returns the decimal string incremented by 1.
|
||||
func incDecimal(decimal string) string {
|
||||
// Scan right to left turning 9s to 0s until you find a digit to increment.
|
||||
digits := []byte(decimal)
|
||||
i := len(digits) - 1
|
||||
for ; i >= 0 && digits[i] == '9'; i-- {
|
||||
digits[i] = '0'
|
||||
}
|
||||
if i >= 0 {
|
||||
digits[i]++
|
||||
} else {
|
||||
// digits is all zeros
|
||||
digits[0] = '1'
|
||||
digits = append(digits, '0')
|
||||
}
|
||||
return string(digits)
|
||||
}
|
||||
|
||||
// decDecimal returns the decimal string decremented by 1, or the empty string
|
||||
// if the decimal is all zeroes.
|
||||
func decDecimal(decimal string) string {
|
||||
// Scan right to left turning 0s to 9s until you find a digit to decrement.
|
||||
digits := []byte(decimal)
|
||||
i := len(digits) - 1
|
||||
for ; i >= 0 && digits[i] == '0'; i-- {
|
||||
digits[i] = '9'
|
||||
}
|
||||
if i < 0 {
|
||||
// decimal is all zeros
|
||||
return ""
|
||||
}
|
||||
if i == 0 && digits[i] == '1' && len(digits) > 1 {
|
||||
digits = digits[1:]
|
||||
} else {
|
||||
digits[i]--
|
||||
}
|
||||
return string(digits)
|
||||
}
|
||||
|
||||
// IsPseudoVersion reports whether v is a pseudo-version.
|
||||
func IsPseudoVersion(v string) bool {
|
||||
return strings.Count(v, "-") >= 2 && semver.IsValid(v) && pseudoVersionRE.MatchString(v)
|
||||
}
|
||||
|
||||
// IsZeroPseudoVersion returns whether v is a pseudo-version with a zero base,
|
||||
// timestamp, and revision, as returned by ZeroPseudoVersion.
|
||||
func IsZeroPseudoVersion(v string) bool {
|
||||
return v == ZeroPseudoVersion(semver.Major(v))
|
||||
}
|
||||
|
||||
// PseudoVersionTime returns the time stamp of the pseudo-version v.
|
||||
// It returns an error if v is not a pseudo-version or if the time stamp
|
||||
// embedded in the pseudo-version is not a valid time.
|
||||
func PseudoVersionTime(v string) (time.Time, error) {
|
||||
_, timestamp, _, _, err := parsePseudoVersion(v)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
t, err := time.Parse("20060102150405", timestamp)
|
||||
if err != nil {
|
||||
return time.Time{}, &InvalidVersionError{
|
||||
Version: v,
|
||||
Pseudo: true,
|
||||
Err: fmt.Errorf("malformed time %q", timestamp),
|
||||
}
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
// PseudoVersionRev returns the revision identifier of the pseudo-version v.
|
||||
// It returns an error if v is not a pseudo-version.
|
||||
func PseudoVersionRev(v string) (rev string, err error) {
|
||||
_, _, rev, _, err = parsePseudoVersion(v)
|
||||
return
|
||||
}
|
||||
|
||||
// PseudoVersionBase returns the canonical parent version, if any, upon which
|
||||
// the pseudo-version v is based.
|
||||
//
|
||||
// If v has no parent version (that is, if it is "vX.0.0-[…]"),
|
||||
// PseudoVersionBase returns the empty string and a nil error.
|
||||
func PseudoVersionBase(v string) (string, error) {
|
||||
base, _, _, build, err := parsePseudoVersion(v)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
switch pre := semver.Prerelease(base); pre {
|
||||
case "":
|
||||
// vX.0.0-yyyymmddhhmmss-abcdef123456 → ""
|
||||
if build != "" {
|
||||
// Pseudo-versions of the form vX.0.0-yyyymmddhhmmss-abcdef123456+incompatible
|
||||
// are nonsensical: the "vX.0.0-" prefix implies that there is no parent tag,
|
||||
// but the "+incompatible" suffix implies that the major version of
|
||||
// the parent tag is not compatible with the module's import path.
|
||||
//
|
||||
// There are a few such entries in the index generated by proxy.golang.org,
|
||||
// but we believe those entries were generated by the proxy itself.
|
||||
return "", &InvalidVersionError{
|
||||
Version: v,
|
||||
Pseudo: true,
|
||||
Err: fmt.Errorf("lacks base version, but has build metadata %q", build),
|
||||
}
|
||||
}
|
||||
return "", nil
|
||||
|
||||
case "-0":
|
||||
// vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456 → vX.Y.Z
|
||||
// vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456+incompatible → vX.Y.Z+incompatible
|
||||
base = strings.TrimSuffix(base, pre)
|
||||
i := strings.LastIndexByte(base, '.')
|
||||
if i < 0 {
|
||||
panic("base from parsePseudoVersion missing patch number: " + base)
|
||||
}
|
||||
patch := decDecimal(base[i+1:])
|
||||
if patch == "" {
|
||||
// vX.0.0-0 is invalid, but has been observed in the wild in the index
|
||||
// generated by requests to proxy.golang.org.
|
||||
//
|
||||
// NOTE(bcmills): I cannot find a historical bug that accounts for
|
||||
// pseudo-versions of this form, nor have I seen such versions in any
|
||||
// actual go.mod files. If we find actual examples of this form and a
|
||||
// reasonable theory of how they came into existence, it seems fine to
|
||||
// treat them as equivalent to vX.0.0 (especially since the invalid
|
||||
// pseudo-versions have lower precedence than the real ones). For now, we
|
||||
// reject them.
|
||||
return "", &InvalidVersionError{
|
||||
Version: v,
|
||||
Pseudo: true,
|
||||
Err: fmt.Errorf("version before %s would have negative patch number", base),
|
||||
}
|
||||
}
|
||||
return base[:i+1] + patch + build, nil
|
||||
|
||||
default:
|
||||
// vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456 → vX.Y.Z-pre
|
||||
// vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456+incompatible → vX.Y.Z-pre+incompatible
|
||||
if !strings.HasSuffix(base, ".0") {
|
||||
panic(`base from parsePseudoVersion missing ".0" before date: ` + base)
|
||||
}
|
||||
return strings.TrimSuffix(base, ".0") + build, nil
|
||||
}
|
||||
}
|
||||
|
||||
var errPseudoSyntax = errors.New("syntax error")
|
||||
|
||||
func parsePseudoVersion(v string) (base, timestamp, rev, build string, err error) {
|
||||
if !IsPseudoVersion(v) {
|
||||
return "", "", "", "", &InvalidVersionError{
|
||||
Version: v,
|
||||
Pseudo: true,
|
||||
Err: errPseudoSyntax,
|
||||
}
|
||||
}
|
||||
build = semver.Build(v)
|
||||
v = strings.TrimSuffix(v, build)
|
||||
j := strings.LastIndex(v, "-")
|
||||
v, rev = v[:j], v[j+1:]
|
||||
i := strings.LastIndex(v, "-")
|
||||
if j := strings.LastIndex(v, "."); j > i {
|
||||
base = v[:j] // "vX.Y.Z-pre.0" or "vX.Y.(Z+1)-0"
|
||||
timestamp = v[j+1:]
|
||||
} else {
|
||||
base = v[:i] // "vX.0.0"
|
||||
timestamp = v[i+1:]
|
||||
}
|
||||
return base, timestamp, rev, build, nil
|
||||
}
|
30
vendor/golang.org/x/mod/semver/semver.go
generated
vendored
30
vendor/golang.org/x/mod/semver/semver.go
generated
vendored
@@ -22,6 +22,8 @@
|
||||
// as shorthands for vMAJOR.0.0 and vMAJOR.MINOR.0.
|
||||
package semver
|
||||
|
||||
import "sort"
|
||||
|
||||
// parsed returns the parsed form of a semantic version string.
|
||||
type parsed struct {
|
||||
major string
|
||||
@@ -30,7 +32,6 @@ type parsed struct {
|
||||
short string
|
||||
prerelease string
|
||||
build string
|
||||
err string
|
||||
}
|
||||
|
||||
// IsValid reports whether v is a valid semantic version string.
|
||||
@@ -150,14 +151,30 @@ func Max(v, w string) string {
|
||||
return w
|
||||
}
|
||||
|
||||
// ByVersion implements sort.Interface for sorting semantic version strings.
|
||||
type ByVersion []string
|
||||
|
||||
func (vs ByVersion) Len() int { return len(vs) }
|
||||
func (vs ByVersion) Swap(i, j int) { vs[i], vs[j] = vs[j], vs[i] }
|
||||
func (vs ByVersion) Less(i, j int) bool {
|
||||
cmp := Compare(vs[i], vs[j])
|
||||
if cmp != 0 {
|
||||
return cmp < 0
|
||||
}
|
||||
return vs[i] < vs[j]
|
||||
}
|
||||
|
||||
// Sort sorts a list of semantic version strings using ByVersion.
|
||||
func Sort(list []string) {
|
||||
sort.Sort(ByVersion(list))
|
||||
}
|
||||
|
||||
func parse(v string) (p parsed, ok bool) {
|
||||
if v == "" || v[0] != 'v' {
|
||||
p.err = "missing v prefix"
|
||||
return
|
||||
}
|
||||
p.major, v, ok = parseInt(v[1:])
|
||||
if !ok {
|
||||
p.err = "bad major version"
|
||||
return
|
||||
}
|
||||
if v == "" {
|
||||
@@ -167,13 +184,11 @@ func parse(v string) (p parsed, ok bool) {
|
||||
return
|
||||
}
|
||||
if v[0] != '.' {
|
||||
p.err = "bad minor prefix"
|
||||
ok = false
|
||||
return
|
||||
}
|
||||
p.minor, v, ok = parseInt(v[1:])
|
||||
if !ok {
|
||||
p.err = "bad minor version"
|
||||
return
|
||||
}
|
||||
if v == "" {
|
||||
@@ -182,31 +197,26 @@ func parse(v string) (p parsed, ok bool) {
|
||||
return
|
||||
}
|
||||
if v[0] != '.' {
|
||||
p.err = "bad patch prefix"
|
||||
ok = false
|
||||
return
|
||||
}
|
||||
p.patch, v, ok = parseInt(v[1:])
|
||||
if !ok {
|
||||
p.err = "bad patch version"
|
||||
return
|
||||
}
|
||||
if len(v) > 0 && v[0] == '-' {
|
||||
p.prerelease, v, ok = parsePrerelease(v)
|
||||
if !ok {
|
||||
p.err = "bad prerelease"
|
||||
return
|
||||
}
|
||||
}
|
||||
if len(v) > 0 && v[0] == '+' {
|
||||
p.build, v, ok = parseBuild(v)
|
||||
if !ok {
|
||||
p.err = "bad build"
|
||||
return
|
||||
}
|
||||
}
|
||||
if v != "" {
|
||||
p.err = "junk on end"
|
||||
ok = false
|
||||
return
|
||||
}
|
||||
|
Reference in New Issue
Block a user