}
return x
}
+
+// ModIsPrefix reports whether v is a valid version syntax prefix for the module with the given path.
+// The caller is assumed to have checked that ModIsValid(path, vers) is true.
+func ModIsPrefix(path, vers string) bool {
+ if IsToolchain(path) {
+ return IsLang(vers)
+ }
+ // Semver
+ dots := 0
+ for i := 0; i < len(vers); i++ {
+ switch vers[i] {
+ case '-', '+':
+ return false
+ case '.':
+ dots++
+ if dots >= 2 {
+ return false
+ }
+ }
+ }
+ return true
+}
// Check that the arguments satisfy syntactic constraints.
var version string
+ var firstPath string
for _, arg := range args {
if i := strings.Index(arg, "@"); i >= 0 {
- version = arg[i+1:]
+ firstPath, version = arg[:i], arg[i+1:]
if version == "" {
return nil, fmt.Errorf("%s: version must not be empty", arg)
}
// later arguments, and other modules would. Let's not try to be too
// magical though.
allowed := modload.CheckAllowed
- if modload.IsRevisionQuery(version) {
+ if modload.IsRevisionQuery(firstPath, version) {
// Don't check for retractions if a specific revision is requested.
allowed = nil
}
if err != nil {
return "", err
}
- if !semver.IsValid(m.Version) {
+ if !gover.ModIsValid(m.Path, m.Version) {
return "", fmt.Errorf("non-semver module version %q", m.Version)
}
if module.CanonicalVersion(m.Version) != m.Version {
if err != nil {
return "", err
}
- if !semver.IsValid(m.Version) {
+ if !gover.ModIsValid(m.Path, m.Version) {
return "", fmt.Errorf("non-semver module version %q", m.Version)
}
if module.CanonicalVersion(m.Version) != m.Version {
// InfoFile is like Lookup(ctx, path).Stat(version) but also returns the name of the file
// containing the cached information.
func InfoFile(ctx context.Context, path, version string) (*RevInfo, string, error) {
- if !semver.IsValid(version) {
+ if !gover.ModIsValid(path, version) {
return nil, "", fmt.Errorf("invalid version %q", version)
}
func GoMod(ctx context.Context, path, rev string) ([]byte, error) {
// Convert commit hash to pseudo-version
// to increase cache hit rate.
- if !semver.IsValid(rev) {
+ if !gover.ModIsValid(path, rev) {
if _, info, err := readDiskStat(ctx, path, rev); err == nil {
rev = info.Version
} else {
// GoModFile is like GoMod but returns the name of the file containing
// the cached information.
func GoModFile(ctx context.Context, path, version string) (string, error) {
- if !semver.IsValid(version) {
+ if !gover.ModIsValid(path, version) {
return "", fmt.Errorf("invalid version %q", version)
}
if _, err := GoMod(ctx, path, version); err != nil {
// GoModSum returns the go.sum entry for the module version's go.mod file.
// (That is, it returns the entry listed in go.sum as "path version/go.mod".)
func GoModSum(ctx context.Context, path, version string) (string, error) {
- if !semver.IsValid(version) {
+ if !gover.ModIsValid(path, version) {
return "", fmt.Errorf("invalid version %q", version)
}
data, err := GoMod(ctx, path, version)
}
allowed := CheckAllowed
- if IsRevisionQuery(vers) || mode&ListRetracted != 0 {
+ if IsRevisionQuery(path, vers) || mode&ListRetracted != 0 {
// Allow excluded and retracted versions if the user asked for a
// specific revision or used 'go list -retracted'.
allowed = nil
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
- "golang.org/x/mod/semver"
)
const (
return "", nil, module.VersionError(m, fmt.Errorf("reading %s: %v", base.ShortPath(name), err))
}
} else {
- if !semver.IsValid(m.Version) {
+ if !gover.ModIsValid(m.Path, m.Version) {
// Disallow the broader queries supported by fetch.Lookup.
base.Fatalf("go: internal error: %s@%s: unexpected invalid semantic version", m.Path, m.Version)
}
return summary.require, nil
}
-// Max returns the maximum of v1 and v2 according to semver.Compare.
+// Max returns the maximum of v1 and v2 according to gover.ModCompare.
//
// As a special case, the version "" is considered higher than all other
// versions. The main module (also known as the target) has no version and must
// a particular version or revision in a repository like "v1.0.0", "master",
// or "0123abcd". IsRevisionQuery returns false if vers is a query that
// chooses from among available versions like "latest" or ">v1.0.0".
-func IsRevisionQuery(vers string) bool {
+func IsRevisionQuery(path, vers string) bool {
if vers == "latest" ||
vers == "upgrade" ||
vers == "patch" ||
strings.HasPrefix(vers, "<") ||
strings.HasPrefix(vers, ">") ||
- (semver.IsValid(vers) && isSemverPrefix(vers)) {
+ (gover.ModIsValid(path, vers) && gover.ModIsPrefix(path, vers)) {
return false
}
return true
}
-// isSemverPrefix reports whether v is a semantic version prefix: v1 or v1.2 (not v1.2.3).
-// The caller is assumed to have checked that semver.IsValid(v) is true.
-func isSemverPrefix(v string) bool {
- dots := 0
- for i := 0; i < len(v); i++ {
- switch v[i] {
- case '-', '+':
- return false
- case '.':
- dots++
- if dots >= 2 {
- return false
- }
- }
- }
- return true
-}
-
type queryMatcher struct {
path string
prefix string
case strings.HasPrefix(query, "<="):
v := query[len("<="):]
- if !semver.IsValid(v) {
+ if !gover.ModIsValid(path, v) {
return badVersion(v)
}
- if isSemverPrefix(v) {
+ if gover.ModIsPrefix(path, v) {
// Refuse to say whether <=v1.2 allows v1.2.3 (remember, @v1.2 might mean v1.2.3).
return nil, fmt.Errorf("ambiguous semantic version %q in range %q", v, query)
}
case strings.HasPrefix(query, "<"):
v := query[len("<"):]
- if !semver.IsValid(v) {
+ if !gover.ModIsValid(path, v) {
return badVersion(v)
}
qm.filter = func(mv string) bool { return gover.ModCompare(qm.path, mv, v) < 0 }
case strings.HasPrefix(query, ">="):
v := query[len(">="):]
- if !semver.IsValid(v) {
+ if !gover.ModIsValid(path, v) {
return badVersion(v)
}
qm.filter = func(mv string) bool { return gover.ModCompare(qm.path, mv, v) >= 0 }
case strings.HasPrefix(query, ">"):
v := query[len(">"):]
- if !semver.IsValid(v) {
+ if !gover.ModIsValid(path, v) {
return badVersion(v)
}
- if isSemverPrefix(v) {
+ if gover.ModIsPrefix(path, v) {
// Refuse to say whether >v1.2 allows v1.2.3 (remember, @v1.2 might mean v1.2.3).
return nil, fmt.Errorf("ambiguous semantic version %q in range %q", v, query)
}
qm.preferIncompatible = true
}
- case semver.IsValid(query):
- if isSemverPrefix(query) {
+ case gover.ModIsValid(path, query):
+ if gover.ModIsPrefix(path, query) {
qm.prefix = query + "."
// Do not allow the query "v1.2" to match versions lower than "v1.2.0",
// such as prereleases for that version. (https://golang.org/issue/31972)