module: allow '+' in package import paths (but not module paths)
For golang/go#44776.
Change-Id: I1bc3df2800a1765296c5164aa8bece495d8f9221
Reviewed-on: https://go-review.googlesource.com/c/mod/+/300149
Trust: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
diff --git a/module/module.go b/module/module.go
index 272baee..0e03014 100644
--- a/module/module.go
+++ b/module/module.go
@@ -224,12 +224,16 @@
'a' <= r && r <= 'z'
}
-// pathOK reports whether r can appear in an import path element.
+// modPathOK reports whether r can appear in a module path element.
// Paths can be ASCII letters, ASCII digits, and limited ASCII punctuation: - . _ and ~.
-// This matches what "go get" has historically recognized in import paths.
+//
+// This matches what "go get" has historically recognized in import paths,
+// and avoids confusing sequences like '%20' or '+' that would change meaning
+// if used in a URL.
+//
// TODO(rsc): We would like to allow Unicode letters, but that requires additional
// care in the safe encoding (see "escaped paths" above).
-func pathOK(r rune) bool {
+func modPathOK(r rune) bool {
if r < utf8.RuneSelf {
return r == '-' || r == '.' || r == '_' || r == '~' ||
'0' <= r && r <= '9' ||
@@ -239,6 +243,17 @@
return false
}
+// modPathOK reports whether r can appear in a package import path element.
+//
+// Import paths are intermediate between module paths and file paths: we allow
+// disallow characters that would be confusing or ambiguous as arguments to
+// 'go get' (such as '@' and ' ' ), but allow certain characters that are
+// otherwise-unambiguous on the command line and historically used for some
+// binary names (such as '++' as a suffix for compiler binaries and wrappers).
+func importPathOK(r rune) bool {
+ return modPathOK(r) || r == '+'
+}
+
// fileNameOK reports whether r can appear in a file name.
// For now we allow all Unicode letters but otherwise limit to pathOK plus a few more punctuation characters.
// If we expand the set of allowed characters here, we have to
@@ -394,12 +409,19 @@
if elem[len(elem)-1] == '.' {
return fmt.Errorf("trailing dot in path element")
}
- charOK := pathOK
- if kind == filePath {
- charOK = fileNameOK
- }
for _, r := range elem {
- if !charOK(r) {
+ ok := false
+ switch kind {
+ case modulePath:
+ ok = modPathOK(r)
+ case importPath:
+ ok = importPathOK(r)
+ case filePath:
+ ok = fileNameOK(r)
+ default:
+ panic(fmt.Sprintf("internal error: invalid kind %v", kind))
+ }
+ if !ok {
return fmt.Errorf("invalid char %q", r)
}
}
diff --git a/module/module_test.go b/module/module_test.go
index 4fc462b..5e8193d 100644
--- a/module/module_test.go
+++ b/module/module_test.go
@@ -104,7 +104,7 @@
{"x.y(/z", false, false, true},
{"x.y)/z", false, false, true},
{"x.y*/z", false, false, false},
- {"x.y+/z", false, false, true},
+ {"x.y+/z", false, true, true},
{"x.y,/z", false, false, true},
{"x.y-/z", true, true, true},
{"x.y./zt", false, false, false},
@@ -134,7 +134,7 @@
{"x.y/z(", false, false, true},
{"x.y/z)", false, false, true},
{"x.y/z*", false, false, false},
- {"x.y/z+", false, false, true},
+ {"x.y/z++", false, true, true},
{"x.y/z,", false, false, true},
{"x.y/z-", true, true, true},
{"x.y/z.t", true, true, true},