stdlib.go (2153B)
1 // Copyright 2022 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package scan 6 7 import ( 8 "fmt" 9 "strings" 10 11 "golang.org/x/mod/semver" 12 ) 13 14 // Support functions for standard library packages. 15 // These are copied from the internal/stdlib package in the pkgsite repo. 16 17 // semverToGoTag returns the Go standard library repository tag corresponding 18 // to semver, a version string without the initial "v". 19 // Go tags differ from standard semantic versions in a few ways, 20 // such as beginning with "go" instead of "v". 21 func semverToGoTag(v string) string { 22 if strings.HasPrefix(v, "v0.0.0") { 23 return "master" 24 } 25 // Special case: v1.0.0 => go1. 26 if v == "v1.0.0" { 27 return "go1" 28 } 29 if !semver.IsValid(v) { 30 return fmt.Sprintf("<!%s:invalid semver>", v) 31 } 32 goVersion := semver.Canonical(v) 33 prerelease := semver.Prerelease(goVersion) 34 versionWithoutPrerelease := strings.TrimSuffix(goVersion, prerelease) 35 patch := strings.TrimPrefix(versionWithoutPrerelease, semver.MajorMinor(goVersion)+".") 36 if patch == "0" { 37 versionWithoutPrerelease = strings.TrimSuffix(versionWithoutPrerelease, ".0") 38 } 39 goVersion = fmt.Sprintf("go%s", strings.TrimPrefix(versionWithoutPrerelease, "v")) 40 if prerelease != "" { 41 // Go prereleases look like "beta1" instead of "beta.1". 42 // "beta1" is bad for sorting (since beta10 comes before beta9), so 43 // require the dot form. 44 i := finalDigitsIndex(prerelease) 45 if i >= 1 { 46 if prerelease[i-1] != '.' { 47 return fmt.Sprintf("<!%s:final digits in a prerelease must follow a period>", v) 48 } 49 // Remove the dot. 50 prerelease = prerelease[:i-1] + prerelease[i:] 51 } 52 goVersion += strings.TrimPrefix(prerelease, "-") 53 } 54 return goVersion 55 } 56 57 // finalDigitsIndex returns the index of the first digit in the sequence of digits ending s. 58 // If s doesn't end in digits, it returns -1. 59 func finalDigitsIndex(s string) int { 60 // Assume ASCII (since the semver package does anyway). 61 var i int 62 for i = len(s) - 1; i >= 0; i-- { 63 if s[i] < '0' || s[i] > '9' { 64 break 65 } 66 } 67 if i == len(s)-1 { 68 return -1 69 } 70 return i + 1 71 }