Skip to content

Commit a839ec1

Browse files
Bryan C. Millsgopherbot
Bryan C. Mills
authored andcommitted
cmd/go/internal/modload: classify "invalid pseudo-version" errors in Query
If we encounter an unclassified error in modload.Query, it takes precedence even if the package is found in some other module. (That is intentional, so that if a package exists in both a parent and a nested module the outcome is deterministic, and does not shift if a temporary error causes one of the modules to be unavailable.) A pseudo-version is formed from a base version and a commit hash. Each version tag is specific to the module in a particular directory of the repo (often the root directory), whereas the commit hash is the same for all subdirectories. When we go to check a particular subdirectory for the requested package, we may find that that version is not valid for that combination of <subdirectory, commit hash>, but we should keep looking to see whether it is valid for a module in some other subdirectory. Fixes #47650. Change-Id: Id48f590ce906a3d4cf4e82fc66137bf67613277d Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-longtest,gotip-windows-amd64-longtest Reviewed-on: https://go-review.googlesource.com/c/go/+/548475 Reviewed-by: Michael Matloob <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Bryan Mills <[email protected]>
1 parent e872807 commit a839ec1

File tree

4 files changed

+93
-6
lines changed

4 files changed

+93
-6
lines changed

Diff for: src/cmd/go/internal/modfetch/coderepo.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -514,10 +514,20 @@ func (r *codeRepo) convert(ctx context.Context, info *codehost.RevInfo, statVers
514514
// Determine version.
515515

516516
if module.IsPseudoVersion(statVers) {
517+
// Validate the go.mod location and major version before
518+
// we check for an ancestor tagged with the pseude-version base.
519+
//
520+
// We can rule out an invalid subdirectory or major version with only
521+
// shallow commit information, but checking the pseudo-version base may
522+
// require downloading a (potentially more expensive) full history.
523+
revInfo, err = checkCanonical(statVers)
524+
if err != nil {
525+
return revInfo, err
526+
}
517527
if err := r.validatePseudoVersion(ctx, info, statVers); err != nil {
518528
return nil, err
519529
}
520-
return checkCanonical(statVers)
530+
return revInfo, nil
521531
}
522532

523533
// statVers is not a pseudo-version, so we need to either resolve it to a

Diff for: src/cmd/go/internal/modload/query.go

+12-5
Original file line numberDiff line numberDiff line change
@@ -891,11 +891,12 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod
891891
// is most likely to find helpful: the most useful class of error at the
892892
// longest matching path.
893893
var (
894-
noPackage *PackageNotInModuleError
895-
noVersion *NoMatchingVersionError
896-
noPatchBase *NoPatchBaseError
897-
invalidPath *module.InvalidPathError // see comment in case below
898-
notExistErr error
894+
noPackage *PackageNotInModuleError
895+
noVersion *NoMatchingVersionError
896+
noPatchBase *NoPatchBaseError
897+
invalidPath *module.InvalidPathError // see comment in case below
898+
invalidVersion error
899+
notExistErr error
899900
)
900901
for _, r := range results {
901902
switch rErr := r.err.(type) {
@@ -931,6 +932,10 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod
931932
if notExistErr == nil {
932933
notExistErr = rErr
933934
}
935+
} else if iv := (*module.InvalidVersionError)(nil); errors.As(rErr, &iv) {
936+
if invalidVersion == nil {
937+
invalidVersion = rErr
938+
}
934939
} else if err == nil {
935940
if len(found) > 0 || noPackage != nil {
936941
// golang.org/issue/34094: If we have already found a module that
@@ -961,6 +966,8 @@ func queryPrefixModules(ctx context.Context, candidateModules []string, queryMod
961966
err = noPatchBase
962967
case invalidPath != nil:
963968
err = invalidPath
969+
case invalidVersion != nil:
970+
err = invalidVersion
964971
case notExistErr != nil:
965972
err = notExistErr
966973
default:

Diff for: src/cmd/go/testdata/script/mod_get_issue47650.txt

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Regression test for https://go.dev/issue/47650:
2+
# 'go get' with a pseudo-version of a non-root package within a module
3+
# erroneously rejected the pseudo-version as invalid, because it did not fetch
4+
# enough commit history to validate the pseudo-version base.
5+
6+
[short] skip 'creates and uses a git repository'
7+
[!git] skip
8+
9+
env GOPRIVATE=vcs-test.golang.org
10+
11+
# If we request a package in a subdirectory of a module by commit hash, we
12+
# successfully resolve it to a pseudo-version derived from a tag on the parent
13+
# commit.
14+
cp go.mod go.mod.orig
15+
go get -x vcs-test.golang.org/git/issue47650.git/cmd/issue47650@21535ef346c3
16+
stderr '^go: added vcs-test.golang.org/git/issue47650.git v0.1.1-0.20210811175200-21535ef346c3$'
17+
18+
# Explicitly requesting that same version should succeed, fetching additional
19+
# history for the requested commit as needed in order to validate the
20+
# pseudo-version base.
21+
go clean -modcache
22+
cp go.mod.orig go.mod
23+
go get -x vcs-test.golang.org/git/issue47650.git/cmd/[email protected]
24+
stderr '^go: added vcs-test.golang.org/git/issue47650.git v0.1.1-0.20210811175200-21535ef346c3$'
25+
26+
-- go.mod --
27+
module example
28+
29+
go 1.20

Diff for: src/cmd/go/testdata/vcstest/git/issue47650.txt

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
handle git
2+
3+
env GIT_AUTHOR_NAME='Bryan C. Mills'
4+
env GIT_AUTHOR_EMAIL='[email protected]'
5+
env GIT_COMMITTER_NAME=$GIT_AUTHOR_NAME
6+
env GIT_COMMITTER_EMAIL=$GIT_AUTHOR_EMAIL
7+
8+
git init
9+
10+
at 2021-08-11T13:52:00-04:00
11+
git add cmd
12+
git commit -m 'add cmd/issue47650'
13+
git tag v0.1.0
14+
15+
git add go.mod
16+
git commit -m 'add go.mod'
17+
18+
git show-ref --tags --heads
19+
cmp stdout .git-refs
20+
21+
git log --oneline --decorate=short
22+
cmp stdout .git-log
23+
24+
-- .git-refs --
25+
21535ef346c3e79fd09edd75bd4725f06c828e43 refs/heads/main
26+
4d237df2dbfc8a443af2f5e84be774f08a2aed0c refs/tags/v0.1.0
27+
-- .git-log --
28+
21535ef (HEAD -> main) add go.mod
29+
4d237df (tag: v0.1.0) add cmd/issue47650
30+
-- go.mod --
31+
module vcs-test.golang.org/git/issue47650.git
32+
33+
go 1.17
34+
-- cmd/issue47650/main.go --
35+
package main
36+
37+
import "os"
38+
39+
func main() {
40+
os.Stdout.WriteString("Hello, world!")
41+
}

0 commit comments

Comments
 (0)