Skip to content

Commit 6bf2767

Browse files
author
Bryan C. Mills
committed
cmd/go: tighten the check for pseudo-version base tags
Do not allow a pseudo-version derived from a canonical tag to refer to the same revision as the tag itself. It's unnecessary (because canonical tags already have a total ordering) and confusing (the pseudo-version appears to come after the tag, but actually refers to the exact same revision). Updates #32879 Updates #27173 Change-Id: I02befedbe89c8819bdd93e470783ce63fc813193 Reviewed-on: https://go-review.googlesource.com/c/go/+/184720 Run-TryBot: Bryan C. Mills <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Jay Conrod <[email protected]>
1 parent 0da58d0 commit 6bf2767

File tree

4 files changed

+64
-12
lines changed

4 files changed

+64
-12
lines changed

doc/go1.13.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,8 +302,10 @@ <h4 id="version-validation">Version validation</h4><!-- CL 181881 -->
302302
between <a href="/cmd/go#hdr-Pseudo_versions">pseudo-versions</a> and
303303
version-control metadata. Specifically:
304304
<ul>
305-
<li>The version prefix must be derived from a tag on the named revision or
306-
one of its ancestors, or be of the form <code>vX.0.0</code>.</li>
305+
<li>The version prefix must be of the form <code>vX.0.0</code>, or derived
306+
from a tag on an ancestor of the named revision, or derived from a tag that
307+
includes <a href="https://semver.org/#spec-item-10">build metadata</a> on
308+
the named revision itself.</li>
307309

308310
<li>The date string must match the UTC timestamp of the revision.</li>
309311

src/cmd/go/internal/modfetch/coderepo.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,11 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string)
479479
return fmt.Errorf("does not match version-control timestamp (%s)", info.Time.UTC().Format(time.RFC3339))
480480
}
481481

482+
tagPrefix := ""
483+
if r.codeDir != "" {
484+
tagPrefix = r.codeDir + "/"
485+
}
486+
482487
// A pseudo-version should have a precedence just above its parent revisions,
483488
// and no higher. Otherwise, it would be possible for library authors to "pin"
484489
// dependency versions (and bypass the usual minimum version selection) by
@@ -504,11 +509,26 @@ func (r *codeRepo) validatePseudoVersion(info *codehost.RevInfo, version string)
504509
return fmt.Errorf("major version without preceding tag must be v0, not v1")
505510
}
506511
return nil
507-
}
508-
509-
tagPrefix := ""
510-
if r.codeDir != "" {
511-
tagPrefix = r.codeDir + "/"
512+
} else {
513+
for _, tag := range info.Tags {
514+
versionOnly := strings.TrimPrefix(tag, tagPrefix)
515+
if versionOnly == base {
516+
// The base version is canonical, so if the version from the tag is
517+
// literally equal (not just equivalent), then the tag is canonical too.
518+
//
519+
// We allow pseudo-versions to be derived from non-canonical tags on the
520+
// same commit, so that tags like "v1.1.0+some-metadata" resolve as
521+
// close as possible to the canonical version ("v1.1.0") while still
522+
// enforcing a total ordering ("v1.1.1-0.[…]" with a unique suffix).
523+
//
524+
// However, canonical tags already have a total ordering, so there is no
525+
// reason not to use the canonical tag directly, and we know that the
526+
// canonical tag must already exist because the pseudo-version is
527+
// derived from it. In that case, referring to the revision by a
528+
// pseudo-version derived from its own canonical tag is just confusing.
529+
return fmt.Errorf("tag (%s) found on revision %s is already canonical, so should not be replaced with a pseudo-version derived from that tag", tag, rev)
530+
}
531+
}
512532
}
513533

514534
tags, err := r.code.Tags(tagPrefix + base)

src/cmd/go/internal/modfetch/coderepo_test.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,26 @@ var codeRepoTests = []codeRepoTest{
8383
"pkg/p.go",
8484
},
8585
},
86+
{
87+
vcs: "git",
88+
path: "github.com/rsc/vgotest1",
89+
rev: "v0.0.0-20180219231006-80d85c5d4d17",
90+
version: "v0.0.0-20180219231006-80d85c5d4d17",
91+
name: "80d85c5d4d17598a0e9055e7c175a32b415d6128",
92+
short: "80d85c5d4d17",
93+
time: time.Date(2018, 2, 19, 23, 10, 6, 0, time.UTC),
94+
zip: []string{
95+
"LICENSE",
96+
"README.md",
97+
"pkg/p.go",
98+
},
99+
},
100+
{
101+
vcs: "git",
102+
path: "github.com/rsc/vgotest1",
103+
rev: "v0.0.1-0.20180219231006-80d85c5d4d17",
104+
err: `github.com/rsc/[email protected]: invalid pseudo-version: tag (v0.0.0) found on revision 80d85c5d4d17 is already canonical, so should not be replaced with a pseudo-version derived from that tag`,
105+
},
86106
{
87107
vcs: "git",
88108
path: "github.com/rsc/vgotest1",
@@ -515,7 +535,7 @@ func TestCodeRepo(t *testing.T) {
515535
}
516536

517537
var hgmap = map[string]string{
518-
"github.com/rsc/vgotest1/": "vcs-test.golang.org/hg/vgotest1.hg/",
538+
"github.com/rsc/vgotest1": "vcs-test.golang.org/hg/vgotest1.hg",
519539
"f18795870fb14388a21ef3ebc1d75911c8694f31": "a9ad6d1d14eb544f459f446210c7eb3b009807c6",
520540
"ea65f87c8f52c15ea68f3bdd9925ef17e20d91e9": "f1fc0f22021b638d073d31c752847e7bf385def7",
521541
"b769f2de407a4db81af9c5de0a06016d60d2ea09": "92c7eb888b4fac17f1c6bd2e1060a1b881a3b832",

src/cmd/go/testdata/script/mod_invalid_version.txt

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,16 @@ cd ..
144144
! go list -m golang.org/x/text
145145
stderr 'golang.org/x/[email protected]: invalid pseudo-version: revision 14c0d48ead0c is not a descendent of preceding tag \(v0.2.0\)'
146146

147+
# A pseudo-version derived from a canonical tag on the same revision is invalid.
148+
cp go.mod.orig go.mod
149+
go mod edit -require golang.org/x/[email protected]
150+
cd outside
151+
! go list -m golang.org/x/text
152+
stderr 'go: [email protected] requires\n\tgolang.org/x/[email protected]: invalid pseudo-version: tag \(v0.2.0\) found on revision c4d099d611ac is already canonical, so should not be replaced with a pseudo-version derived from that tag'
153+
cd ..
154+
! go list -m golang.org/x/text
155+
stderr 'golang.org/x/[email protected]: invalid pseudo-version: tag \(v0.2.0\) found on revision c4d099d611ac is already canonical, so should not be replaced with a pseudo-version derived from that tag'
156+
147157
# A +incompatible suffix is not allowed on a version that is actually compatible.
148158
cp go.mod.orig go.mod
149159
go mod edit -require golang.org/x/[email protected]+incompatible
@@ -165,15 +175,15 @@ go list -m github.com/pierrec/lz4
165175
stdout 'github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1'
166176
cd ..
167177

168-
# A +incompatible version for a module that has an explicit go.mod file is invalid.
178+
# A +incompatible pseudo-version for a module that has an explicit go.mod file is invalid.
169179
cp go.mod.orig go.mod
170-
go mod edit -require github.com/pierrec/[email protected].20190131084431-473cd7ce01a1+incompatible
180+
go mod edit -require github.com/pierrec/[email protected].20190209155647-9a39efadad3d+incompatible
171181
cd outside
172182
! go list -m github.com/pierrec/lz4
173-
stderr 'go: [email protected] requires\n\tgithub.com/pierrec/[email protected].20190131084431-473cd7ce01a1\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
183+
stderr 'go: [email protected] requires\n\tgithub.com/pierrec/[email protected].20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
174184
cd ..
175185
! go list -m github.com/pierrec/lz4
176-
stderr 'github.com/pierrec/[email protected].20190131084431-473cd7ce01a1\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
186+
stderr 'github.com/pierrec/[email protected].20190209155647-9a39efadad3d\+incompatible: invalid version: \+incompatible suffix not allowed: module contains a go.mod file, so semantic import versioning is required'
177187

178188
# A +incompatible pseudo-version is valid for a revision of the module
179189
# that lacks a go.mod file.

0 commit comments

Comments
 (0)