diff --git a/src/cmd/go/internal/modindex/read.go b/src/cmd/go/internal/modindex/read.go index daa85762be0..6ec3a6b3af6 100644 --- a/src/cmd/go/internal/modindex/read.go +++ b/src/cmd/go/internal/modindex/read.go @@ -112,6 +112,7 @@ func Get(modroot string) (*ModuleIndex, error) { if modroot == "" { panic("modindex.Get called with empty modroot") } + modroot = filepath.Clean(modroot) isModCache := str.HasFilePathPrefix(modroot, cfg.GOMODCACHE) return openIndex(modroot, isModCache) } @@ -217,7 +218,7 @@ func (mi *ModuleIndex) Packages() []string { // RelPath returns the path relative to the module's root. func (mi *ModuleIndex) RelPath(path string) string { - return str.TrimFilePathPrefix(path, mi.modroot) + return str.TrimFilePathPrefix(filepath.Clean(path), mi.modroot) // mi.modroot is already clean } // ImportPackage is the equivalent of build.Import given the information in ModuleIndex. diff --git a/src/cmd/go/testdata/script/list_replace_absolute_windows.txt b/src/cmd/go/testdata/script/list_replace_absolute_windows.txt new file mode 100644 index 00000000000..6f5d737aded --- /dev/null +++ b/src/cmd/go/testdata/script/list_replace_absolute_windows.txt @@ -0,0 +1,37 @@ +# Test a replacement with an absolute path (so the path isn't +# cleaned by having filepath.Abs called on it). This checks +# whether the modindex logic cleans the modroot path before using +# it. + +[!windows] [short] skip + +go run print_go_mod.go # use this program to write a go.mod with an absolute path +cp stdout go.mod + +go list -modfile=go.mod all +-- print_go_mod.go -- +//go:build ignore +package main + +import ( + "fmt" + "os" +) + +func main() { + work := os.Getenv("WORK") +fmt.Printf(`module example.com/mod + +require b.com v0.0.0 + +replace b.com => %s\gopath\src/modb +`, work) +} +-- a.go -- +package a + +import _ "b.com/b" +-- modb/go.mod -- +module b.com +-- modb/b/b.go -- +package b