Skip to content

Commit a2a9a7b

Browse files
tpaschalisJay Conrod
authored and
Jay Conrod
committed
cmd/go: make mod init disallow invalid major version suffixes
This CL reuses the SplitPathVersion function from the module package to detect invalid major version suffixes and return a relevant error message along with a suggested fix. Fixes #44052 Fixes #46085 Change-Id: I6c06f31a134e864a1d9b6e00c048ca1c59b4365e Reviewed-on: https://go-review.googlesource.com/c/go/+/288712 Reviewed-by: Jay Conrod <[email protected]> Trust: Jay Conrod <[email protected]> Trust: Bryan C. Mills <[email protected]> Run-TryBot: Jay Conrod <[email protected]> TryBot-Result: Go Bot <[email protected]>
1 parent 3848488 commit a2a9a7b

File tree

2 files changed

+142
-0
lines changed

2 files changed

+142
-0
lines changed

src/cmd/go/internal/modload/init.go

+60
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,13 @@ func CreateModFile(ctx context.Context, modPath string) {
523523
}
524524
}
525525
base.Fatalf("go: %v", err)
526+
} else if _, _, ok := module.SplitPathVersion(modPath); !ok {
527+
if strings.HasPrefix(modPath, "gopkg.in/") {
528+
invalidMajorVersionMsg := fmt.Errorf("module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN:\n\tgo mod init %s", suggestGopkgIn(modPath))
529+
base.Fatalf(`go: invalid module path "%v": %v`, modPath, invalidMajorVersionMsg)
530+
}
531+
invalidMajorVersionMsg := fmt.Errorf("major version suffixes must be in the form of /vN and are only allowed for v2 or later:\n\tgo mod init %s", suggestModulePath(modPath))
532+
base.Fatalf(`go: invalid module path "%v": %v`, modPath, invalidMajorVersionMsg)
526533
}
527534

528535
fmt.Fprintf(os.Stderr, "go: creating new go.mod: module %s\n", modPath)
@@ -1197,3 +1204,56 @@ const (
11971204
func modkey(m module.Version) module.Version {
11981205
return module.Version{Path: m.Path, Version: m.Version + "/go.mod"}
11991206
}
1207+
1208+
func suggestModulePath(path string) string {
1209+
var m string
1210+
1211+
i := len(path)
1212+
for i > 0 && ('0' <= path[i-1] && path[i-1] <= '9' || path[i-1] == '.') {
1213+
i--
1214+
}
1215+
url := path[:i]
1216+
url = strings.TrimSuffix(url, "/v")
1217+
url = strings.TrimSuffix(url, "/")
1218+
1219+
f := func(c rune) bool {
1220+
return c > '9' || c < '0'
1221+
}
1222+
s := strings.FieldsFunc(path[i:], f)
1223+
if len(s) > 0 {
1224+
m = s[0]
1225+
}
1226+
m = strings.TrimLeft(m, "0")
1227+
if m == "" || m == "1" {
1228+
return url + "/v2"
1229+
}
1230+
1231+
return url + "/v" + m
1232+
}
1233+
1234+
func suggestGopkgIn(path string) string {
1235+
var m string
1236+
i := len(path)
1237+
for i > 0 && (('0' <= path[i-1] && path[i-1] <= '9') || (path[i-1] == '.')) {
1238+
i--
1239+
}
1240+
url := path[:i]
1241+
url = strings.TrimSuffix(url, ".v")
1242+
url = strings.TrimSuffix(url, "/v")
1243+
url = strings.TrimSuffix(url, "/")
1244+
1245+
f := func(c rune) bool {
1246+
return c > '9' || c < '0'
1247+
}
1248+
s := strings.FieldsFunc(path, f)
1249+
if len(s) > 0 {
1250+
m = s[0]
1251+
}
1252+
1253+
m = strings.TrimLeft(m, "0")
1254+
1255+
if m == "" {
1256+
return url + ".v1"
1257+
}
1258+
return url + ".v" + m
1259+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
env GO111MODULE=on
2+
env GOFLAGS=-mod=mod
3+
4+
! go mod init example.com/user/repo/v0
5+
stderr '(?s)^go: invalid module path "example.com/user/repo/v0": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$'
6+
7+
! go mod init example.com/user/repo/v02
8+
stderr '(?s)^go: invalid module path "example.com/user/repo/v02": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$'
9+
10+
! go mod init example.com/user/repo/v023
11+
stderr '(?s)^go: invalid module path "example.com/user/repo/v023": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v23$'
12+
13+
! go mod init example.com/user/repo/v1
14+
stderr '(?s)^go: invalid module path "example.com/user/repo/v1": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$'
15+
16+
! go mod init example.com/user/repo/v2.0
17+
stderr '(?s)^go: invalid module path "example.com/user/repo/v2.0": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$'
18+
19+
! go mod init example.com/user/repo/v2.1.4
20+
stderr '(?s)^go: invalid module path "example.com/user/repo/v2.1.4": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$'
21+
22+
! go mod init example.com/user/repo/v3.5
23+
stderr '(?s)^go: invalid module path "example.com/user/repo/v3.5": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v3$'
24+
25+
! go mod init example.com/user/repo/v4.1.4
26+
stderr '(?s)^go: invalid module path "example.com/user/repo/v4.1.4": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v4$'
27+
28+
! go mod init example.com/user/repo/v.2.3
29+
stderr '(?s)^go: invalid module path "example.com/user/repo/v.2.3": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v2$'
30+
31+
! go mod init example.com/user/repo/v.5.3
32+
stderr '(?s)^go: invalid module path "example.com/user/repo/v.5.3": major version suffixes must be in the form of /vN and are only allowed for v2 or later(.*)go mod init example.com/user/repo/v5$'
33+
34+
! go mod init gopkg.in/pkg
35+
stderr '(?s)^go: invalid module path "gopkg.in/pkg": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/pkg.v1$'
36+
37+
! go mod init gopkg.in/user/pkg
38+
stderr '(?s)^go: invalid module path "gopkg.in/user/pkg": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$'
39+
40+
! go mod init gopkg.in/user/pkg/v0
41+
stderr '(?s)^go: invalid module path "gopkg.in/user/pkg/v0": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$'
42+
43+
! go mod init gopkg.in/user/pkg/v1
44+
stderr '(?s)^go: invalid module path "gopkg.in/user/pkg/v1": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$'
45+
46+
! go mod init gopkg.in/user/pkg/v2
47+
stderr '(?s)^go: invalid module path "gopkg.in/user/pkg/v2": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v2$'
48+
49+
! go mod init gopkg.in/user/pkg.v
50+
stderr '(?s)^go: invalid module path "gopkg.in/user/pkg.v": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$'
51+
52+
! go mod init gopkg.in/user/pkg.v0.1
53+
stderr '(?s)^go: invalid module path "gopkg.in/user/pkg.v0.1": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$'
54+
55+
! go mod init gopkg.in/user/pkg.v.1
56+
stderr '(?s)^go: invalid module path "gopkg.in/user/pkg.v.1": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$'
57+
58+
! go mod init gopkg.in/user/pkg.v01
59+
stderr '(?s)^go: invalid module path "gopkg.in/user/pkg.v01": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v1$'
60+
61+
! go mod init gopkg.in/user/pkg.v.2.3
62+
stderr '(?s)^go: invalid module path "gopkg.in/user/pkg.v.2.3": module paths beginning with gopkg.in/ must always have a major version suffix in the form of .vN(.*)go mod init gopkg.in/user/pkg.v2$'
63+
64+
# module paths with a trailing dot are rejected as invalid import paths
65+
! go mod init example.com/user/repo/v2.
66+
stderr '(?s)^go: malformed module path "example.com/user/repo/v2.": trailing dot in path element$'
67+
68+
! go mod init example.com/user/repo/v2..
69+
stderr '(?s)^go: malformed module path "example.com/user/repo/v2..": trailing dot in path element$'
70+
71+
! go mod init gopkg.in/user/pkg.v.2.
72+
stderr '(?s)^go: malformed module path "gopkg.in/user/pkg.v.2.": trailing dot in path element$'
73+
74+
! go mod init gopkg.in/user/pkg.v.2..
75+
stderr '(?s)^go: malformed module path "gopkg.in/user/pkg.v.2..": trailing dot in path element$'
76+
77+
# module paths with spaces are also rejected
78+
! go mod init 'foo bar'
79+
stderr '(?s)^go: malformed module path "foo bar": invalid char '' ''$'
80+
81+
! go mod init 'foo bar baz'
82+
stderr '(?s)^go: malformed module path "foo bar baz": invalid char '' ''$'

0 commit comments

Comments
 (0)