mirror of https://go.googlesource.com/go
128 lines
3.4 KiB
Go
128 lines
3.4 KiB
Go
// Copyright 2023 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 gover
|
|
|
|
import (
|
|
"sort"
|
|
"strings"
|
|
|
|
"golang.org/x/mod/module"
|
|
"golang.org/x/mod/semver"
|
|
)
|
|
|
|
// IsToolchain reports whether the module path corresponds to the
|
|
// virtual, non-downloadable module tracking go or toolchain directives in the go.mod file.
|
|
//
|
|
// Note that IsToolchain only matches "go" and "toolchain", not the
|
|
// real, downloadable module "golang.org/toolchain" containing toolchain files.
|
|
//
|
|
// IsToolchain("go") = true
|
|
// IsToolchain("toolchain") = true
|
|
// IsToolchain("golang.org/x/tools") = false
|
|
// IsToolchain("golang.org/toolchain") = false
|
|
func IsToolchain(path string) bool {
|
|
return path == "go" || path == "toolchain"
|
|
}
|
|
|
|
// ModCompare returns the result of comparing the versions x and y
|
|
// for the module with the given path.
|
|
// The path is necessary because the "go" and "toolchain" modules
|
|
// use a different version syntax and semantics (gover, this package)
|
|
// than most modules (semver).
|
|
func ModCompare(path string, x, y string) int {
|
|
if path == "go" {
|
|
return Compare(x, y)
|
|
}
|
|
if path == "toolchain" {
|
|
return Compare(maybeToolchainVersion(x), maybeToolchainVersion(y))
|
|
}
|
|
return semver.Compare(x, y)
|
|
}
|
|
|
|
// ModSort is like module.Sort but understands the "go" and "toolchain"
|
|
// modules and their version ordering.
|
|
func ModSort(list []module.Version) {
|
|
sort.Slice(list, func(i, j int) bool {
|
|
mi := list[i]
|
|
mj := list[j]
|
|
if mi.Path != mj.Path {
|
|
return mi.Path < mj.Path
|
|
}
|
|
// To help go.sum formatting, allow version/file.
|
|
// Compare semver prefix by semver rules,
|
|
// file by string order.
|
|
vi := mi.Version
|
|
vj := mj.Version
|
|
var fi, fj string
|
|
if k := strings.Index(vi, "/"); k >= 0 {
|
|
vi, fi = vi[:k], vi[k:]
|
|
}
|
|
if k := strings.Index(vj, "/"); k >= 0 {
|
|
vj, fj = vj[:k], vj[k:]
|
|
}
|
|
if vi != vj {
|
|
return ModCompare(mi.Path, vi, vj) < 0
|
|
}
|
|
return fi < fj
|
|
})
|
|
}
|
|
|
|
// ModIsValid reports whether vers is a valid version syntax for the module with the given path.
|
|
func ModIsValid(path, vers string) bool {
|
|
if IsToolchain(path) {
|
|
if path == "toolchain" {
|
|
return IsValid(FromToolchain(vers))
|
|
}
|
|
return IsValid(vers)
|
|
}
|
|
return semver.IsValid(vers)
|
|
}
|
|
|
|
// 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) {
|
|
if path == "toolchain" {
|
|
return IsLang(FromToolchain(vers))
|
|
}
|
|
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
|
|
}
|
|
|
|
// ModIsPrerelease reports whether v is a prerelease version for the module with the given path.
|
|
// The caller is assumed to have checked that ModIsValid(path, vers) is true.
|
|
func ModIsPrerelease(path, vers string) bool {
|
|
if IsToolchain(path) {
|
|
return IsPrerelease(vers)
|
|
}
|
|
return semver.Prerelease(vers) != ""
|
|
}
|
|
|
|
// ModMajorMinor returns the "major.minor" truncation of the version v,
|
|
// for use as a prefix in "@patch" queries.
|
|
func ModMajorMinor(path, vers string) string {
|
|
if IsToolchain(path) {
|
|
if path == "toolchain" {
|
|
return "go" + Lang(FromToolchain(vers))
|
|
}
|
|
return Lang(vers)
|
|
}
|
|
return semver.MajorMinor(vers)
|
|
}
|