Skip to content

Commit

Permalink
internal/frontend: update logic for truncated version strings
Browse files Browse the repository at this point in the history
The logic for formatVersion is updated.

For pseudo versions, the version string will use a short commit hash
of 7 characters to identify the version, and hide timestamp using
ellipses:

1. vX.0.0-yyyymmddhhmmss-abcdefabcdef
    formatVersion("v0.0.0-20200710095922-abcdefabcdef") =>
      "v0.0.0-...-abcdefa"

2. vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef
    formatVersion("v1.5.2-pre.0.20200331155302-abcdefabcdef") =>
      "v1.5.2-pre.0...-abcdefa"

3. vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef
    formatVersion("v1.5.2-0.20200201180026-77c1076d39f7") =>
      "v1.5.2-0...-abcdefa"

For any version string longer than 25 characters, the pre-release string
will be truncated, such that the string displayed is exactly 25
characters, including the ellipses:

  formatVersion("v1.0.0-longprereleasestring") =>
    "v1.0.0-longprereleasestri..."

  formatVersion("v1.0.0-pre-release.0.20200420093620-87861123c523") =>
    "v1.0.0-pre-rel...-abcdefa"

For golang/go#38542

Change-Id: I07441bc17799f5e445f36834556aa15dc87506e3
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/254578
Trust: Julie Qiu <julie@golang.org>
Run-TryBot: Julie Qiu <julie@golang.org>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
  • Loading branch information
julieqiu committed Sep 14, 2020
1 parent 9e4a53b commit 2d8c44f
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 32 deletions.
6 changes: 3 additions & 3 deletions internal/frontend/server_test.go
Expand Up @@ -48,7 +48,7 @@ func TestHTMLInjection(t *testing.T) {
}
}

const pseudoVersion = "v0.0.0-20190101-123456789012"
const pseudoVersion = "v0.0.0-20140414041502-123456789012"

type testModule struct {
path string
Expand Down Expand Up @@ -228,7 +228,7 @@ func serverTestCases() []serverTestCase {

pp := *pkgV100
pp.Version = pseudoVersion
pp.FormattedVersion = "v0.0.0 (20190101-123456789012)"
pp.FormattedVersion = "v0.0.0-...-1234567"
pp.IsLatest = false
pkgPseudo := &pp

Expand Down Expand Up @@ -280,7 +280,7 @@ func serverTestCases() []serverTestCase {
}
mp := *mod
mp.Version = pseudoVersion
mp.FormattedVersion = "v0.0.0 (20190101-123456789012)"
mp.FormattedVersion = "v0.0.0-...-1234567"
mp.IsLatest = false
modPseudo := &mp

Expand Down
83 changes: 59 additions & 24 deletions internal/frontend/versions.go
Expand Up @@ -190,39 +190,74 @@ func buildVersionDetails(currentModulePath string, modInfos []*internal.ModuleIn
// formatVersion formats a more readable representation of the given version
// string. On any parsing error, it simply returns the input unmodified.
//
// For prerelease versions, formatVersion separates the prerelease portion of
// the version string into a parenthetical. i.e.
// formatVersion("v1.2.3-alpha") = "v1.2.3 (alpha)"
// For pseudo versions, the version string will use a shorten commit hash of 7
// characters to identify the version, and hide timestamp using ellipses.
//
// For pseudo versions, formatVersion uses a short commit hash to identify the
// version. i.e.
// formatVersion("v1.2.3-20190311183353-d8887717615a") = "v.1.2.3 (d888771)"
// For any version string longer than 25 characters, the pre-release string will be
// truncated, such that the string displayed is exactly 25 characters, including the ellipses.
//
// See TestFormatVersion for examples.
func formatVersion(v string) string {
const maxLen = 25
if len(v) <= maxLen {
return v
}
vType, err := version.ParseType(v)
if err != nil {
log.Errorf(context.TODO(), "Error parsing version %q: %v", v, err)
log.Errorf(context.TODO(), "formatVersion(%q): error parsing version: %v", v, err)
return v
}
pre := semver.Prerelease(v)
base := strings.TrimSuffix(v, pre)
pre = strings.TrimPrefix(pre, "-")
switch vType {
case version.TypePrerelease:
return fmt.Sprintf("%s (%s)", base, pre)
case version.TypePseudo:
rev := pseudoVersionRev(v)
commitLen := 7
if len(rev) < commitLen {
commitLen = len(rev)
}
return fmt.Sprintf("%s (%s)", base, rev[0:commitLen])
default:
return v
if vType != version.TypePseudo {
// If the version is release or prerelease, return a version string of
// maxLen by truncating the end of the string. maxLen is inclusive of
// the "..." characters.
return v[:maxLen-3] + "..."
}

// The version string will have a max length of 25:
// base: "vX.Y.Z-prerelease.0" = up to 15
// ellipse: "..." = 3
// commit: "-abcdefa" = 7
commit := shorten(pseudoVersionRev(v), 7)
base := shorten(pseudoVersionBase(v), 15)
return fmt.Sprintf("%s...-%s", base, commit)
}

// shorten shortens the string s to maxLen by removing the trailing characters.
func shorten(s string, maxLen int) string {
if len(s) > maxLen {
return s[:maxLen]
}
return s
}

// pseudoVersionRev extracts the pseudo version base, excluding the timestamp.
// It assumes the pseudo version is correctly formatted.
//
// See TestPseudoVersionBase for examples.
func pseudoVersionBase(v string) string {
parts := strings.Split(v, "-")
if len(parts) != 3 {
mid := strings.Join(parts[1:len(parts)-1], "-")
parts = []string{parts[0], mid, parts[2]}
}
// The version string will always be split into one
// of these 3 parts:
// 1. [vX.0.0, yyyymmddhhmmss, abcdefabcdef]
// 2. [vX.Y.Z, pre.0.yyyymmddhhmmss, abcdefabcdef]
// 3. [vX.Y.Z, 0.yyyymmddhhmmss, abcdefabcdef]
p := strings.Split(parts[1], ".")
var suffix string
if len(p) > 0 {
// There is a "pre.0" or "0" prefix in the second element.
suffix = strings.Join(p[0:len(p)-1], ".")
}
return fmt.Sprintf("%s-%s", parts[0], suffix)
}

// pseudoVersionRev extracts the commit identifier from a pseudo version
// string. It assumes the pseudo version is correctly formatted.
// pseudoVersionRev extracts the first 7 characters of the commit identifier
// from a pseudo version string. It assumes the pseudo version is correctly
// formatted.
func pseudoVersionRev(v string) string {
v = strings.TrimSuffix(v, "+incompatible")
j := strings.LastIndex(v, "-")
Expand Down
31 changes: 26 additions & 5 deletions internal/frontend/versions_test.go
Expand Up @@ -311,11 +311,14 @@ func TestFormatVersion(t *testing.T) {
}{
{"v1.2.3", "v1.2.3"},
{"v2.0.0", "v2.0.0"},
{"v1.2.3-alpha.1", "v1.2.3 (alpha.1)"},
{"v1.0.0-20190311183353-d8887717615a", "v1.0.0 (d888771)"},
{"v1.2.3-pre.0.20190311183353-d8887717615a", "v1.2.3 (d888771)"},
{"v1.2.4-0.20190311183353-d8887717615a", "v1.2.4 (d888771)"},
{"v1.0.0-20190311183353-d88877", "v1.0.0 (d88877)"},
{"v1.2.3-alpha.1", "v1.2.3-alpha.1"},
{"v1.0.0-20190311183353-d8887717615a", "v1.0.0-...-d888771"},
{"v1.2.3-pre.0.20190311183353-d8887717615a", "v1.2.3-pre.0...-d888771"},
{"v1.2.4-0.20190311183353-d8887717615a", "v1.2.4-0...-d888771"},
{"v1.0.0-20190311183353-d88877", "v1.0.0-...-d88877"},
{"v1.0.0-longprereleasestring", "v1.0.0-longprereleases..."},
{"v1.0.0-pre-release.0.20200420093620-87861123c523", "v1.0.0-pre-rele...-8786112"},
{"v0.0.0-20190101-123456789012", "v0.0.0-20190101-123456..."}, // prelease version that looks like pseudoversion
}

for _, test := range tests {
Expand All @@ -326,3 +329,21 @@ func TestFormatVersion(t *testing.T) {
})
}
}

func TestPseudoVersionBase(t *testing.T) {
tests := []struct {
version, want string
}{
{"v1.0.0-20190311183353-d8887717615a", "v1.0.0-"},
{"v1.2.3-pre.0.20190311183353-d8887717615a", "v1.2.3-pre.0"},
{"v1.2.4-0.20190311183353-d8887717615a", "v1.2.4-0"},
}

for _, test := range tests {
t.Run(test.version, func(t *testing.T) {
if got := pseudoVersionBase(test.version); got != test.want {
t.Errorf("pseudoVersionBase(%q) = %q, want %q", test.version, got, test.want)
}
})
}
}

0 comments on commit 2d8c44f

Please sign in to comment.