Skip to content

Commit f3e82e0

Browse files
committed
cmd/go: report possibly-relevant ignored symlinks during pattern match
We can't follow symlinks for fear of directory cycles and other problems, but we can at least notice potentially-relevant symlinks that are being ignored and report them. Fixes #17662. Change-Id: I1fce00bd5b80ea8df45dac8b61bfa08076ec5f4b Reviewed-on: https://go-review.googlesource.com/46425 Run-TryBot: Russ Cox <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 78a11c2 commit f3e82e0

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

src/cmd/go/go_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2070,6 +2070,31 @@ func TestCaseCollisions(t *testing.T) {
20702070
tg.grepStderr("case-insensitive import collision", "go build example/a/pkg example/a/Pkg did not report import collision")
20712071
}
20722072

2073+
// Issue 17451, 17662.
2074+
func TestSymlinkWarning(t *testing.T) {
2075+
tg := testgo(t)
2076+
defer tg.cleanup()
2077+
tg.parallel()
2078+
tg.makeTempdir()
2079+
tg.setenv("GOPATH", tg.path("."))
2080+
2081+
tg.tempDir("src/example/xx")
2082+
tg.tempDir("yy/zz")
2083+
tg.tempFile("yy/zz/zz.go", "package zz\n")
2084+
if err := os.Symlink(tg.path("yy"), tg.path("src/example/xx/yy")); err != nil {
2085+
t.Skip("symlink failed: %v", err)
2086+
}
2087+
tg.run("list", "example/xx/z...")
2088+
tg.grepStdoutNot(".", "list should not have matched anything")
2089+
tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
2090+
tg.grepStderrNot("symlink", "list should not have reported symlink")
2091+
2092+
tg.run("list", "example/xx/...")
2093+
tg.grepStdoutNot(".", "list should not have matched anything")
2094+
tg.grepStderr("matched no packages", "list should have reported that pattern matched no packages")
2095+
tg.grepStderr("ignoring symlink", "list should have reported symlink")
2096+
}
2097+
20732098
// Issue 8181.
20742099
func TestGoGetDashTIssue8181(t *testing.T) {
20752100
testenv.MustHaveExternalNetwork(t)

src/cmd/go/internal/load/search.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,25 +67,39 @@ func MatchPackages(pattern string) []string {
6767
root += "cmd" + string(filepath.Separator)
6868
}
6969
filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
70-
if err != nil || !fi.IsDir() || path == src {
70+
if err != nil || path == src {
7171
return nil
7272
}
7373

74+
want := true
7475
// Avoid .foo, _foo, and testdata directory trees.
7576
_, elem := filepath.Split(path)
7677
if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
77-
return filepath.SkipDir
78+
want = false
7879
}
7980

8081
name := filepath.ToSlash(path[len(src):])
8182
if pattern == "std" && (!isStandardImportPath(name) || name == "cmd") {
8283
// The name "std" is only the standard library.
8384
// If the name is cmd, it's the root of the command tree.
84-
return filepath.SkipDir
85+
want = false
8586
}
8687
if !treeCanMatch(name) {
88+
want = false
89+
}
90+
91+
if !fi.IsDir() {
92+
if fi.Mode()&os.ModeSymlink != 0 && want {
93+
if target, err := os.Stat(path); err == nil && target.IsDir() {
94+
fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path)
95+
}
96+
}
97+
return nil
98+
}
99+
if !want {
87100
return filepath.SkipDir
88101
}
102+
89103
if have[name] {
90104
return nil
91105
}

0 commit comments

Comments
 (0)