tg.run("test", "testcache", "-run=DirList")
tg.grepStdout(`\(cached\)`, "did not cache")
+ tg.tempFile("file.txt", "")
+ tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/testcachetmp_test.go"), []byte(`package testcache
+
+ import (
+ "os"
+ "testing"
+ )
+
+ func TestExternalFile(t *testing.T) {
+ os.Open(`+fmt.Sprintf("%q", tg.path("file.txt"))+`)
+ _, err := os.Stat(`+fmt.Sprintf("%q", tg.path("file.txt"))+`)
+ if err != nil {
+ t.Fatal(err)
+ }
+ }
+ `), 0666))
+ defer os.Remove(filepath.Join(tg.pwd(), "testdata/src/testcache/testcachetmp_test.go"))
+ tg.run("test", "testcache", "-run=ExternalFile")
+ tg.run("test", "testcache", "-run=ExternalFile")
+ tg.grepStdout(`\(cached\)`, "did not cache")
+ tg.must(os.Remove(filepath.Join(tg.tempdir, "file.txt")))
+ tg.run("test", "testcache", "-run=ExternalFile")
+ tg.grepStdout(`\(cached\)`, "did not cache")
+
switch runtime.GOOS {
case "nacl", "plan9", "windows":
// no shell scripts
}
return p
}
-
-// hasFilePathPrefix reports whether the filesystem path s begins with the
-// elements in prefix.
-func hasFilePathPrefix(s, prefix string) bool {
- sv := strings.ToUpper(filepath.VolumeName(s))
- pv := strings.ToUpper(filepath.VolumeName(prefix))
- s = s[len(sv):]
- prefix = prefix[len(pv):]
- switch {
- default:
- return false
- case sv != pv:
- return false
- case len(s) == len(prefix):
- return s == prefix
- case len(s) > len(prefix):
- if prefix != "" && prefix[len(prefix)-1] == filepath.Separator {
- return strings.HasPrefix(s, prefix)
- }
- return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix
- }
-}
dir := filepath.Clean(parent.Dir)
root := filepath.Join(parent.Root, "src")
- if !hasFilePathPrefix(dir, root) || parent.ImportPath != "command-line-arguments" && filepath.Join(root, parent.ImportPath) != dir {
+ if !str.HasFilePathPrefix(dir, root) || parent.ImportPath != "command-line-arguments" && filepath.Join(root, parent.ImportPath) != dir {
// Look for symlinks before reporting error.
dir = expandPath(dir)
root = expandPath(root)
}
- if !hasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || parent.ImportPath != "command-line-arguments" && !parent.Internal.Local && filepath.Join(root, parent.ImportPath) != dir {
+ if !str.HasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator || parent.ImportPath != "command-line-arguments" && !parent.Internal.Local && filepath.Join(root, parent.ImportPath) != dir {
base.Fatalf("unexpected directory layout:\n"+
" import path: %s\n"+
" root: %s\n"+
i-- // rewind over slash in ".../internal"
}
parent := p.Dir[:i+len(p.Dir)-len(p.ImportPath)]
- if hasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
+ if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
return p
}
// Look for symlinks before reporting error.
srcDir = expandPath(srcDir)
parent = expandPath(parent)
- if hasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
+ if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
return p
}
return p
}
parent := p.Dir[:truncateTo]
- if hasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
+ if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
return p
}
// Look for symlinks before reporting error.
srcDir = expandPath(srcDir)
parent = expandPath(parent)
- if hasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
+ if str.HasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
return p
}
--- /dev/null
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package str
+
+import (
+ "path/filepath"
+ "strings"
+)
+
+// HasFilePathPrefix reports whether the filesystem path s begins with the
+// elements in prefix.
+func HasFilePathPrefix(s, prefix string) bool {
+ sv := strings.ToUpper(filepath.VolumeName(s))
+ pv := strings.ToUpper(filepath.VolumeName(prefix))
+ s = s[len(sv):]
+ prefix = prefix[len(pv):]
+ switch {
+ default:
+ return false
+ case sv != pv:
+ return false
+ case len(s) == len(prefix):
+ return s == prefix
+ case len(s) > len(prefix):
+ if prefix != "" && prefix[len(prefix)-1] == filepath.Separator {
+ return strings.HasPrefix(s, prefix)
+ }
+ return s[len(prefix)] == filepath.Separator && s[:len(prefix)] == prefix
+ }
+}
if !filepath.IsAbs(name) {
name = filepath.Join(pwd, name)
}
+ if !inDir(name, a.Package.Root) {
+ // Do not recheck files outside the GOPATH or GOROOT root.
+ break
+ }
fmt.Fprintf(h, "stat %s %x\n", name, hashStat(name))
case "open":
if !filepath.IsAbs(name) {
name = filepath.Join(pwd, name)
}
+ if !inDir(name, a.Package.Root) {
+ // Do not recheck files outside the GOPATH or GOROOT root.
+ break
+ }
fh, err := hashOpen(name)
if err != nil {
if cache.DebugTest {
return sum, nil
}
+func inDir(path, dir string) bool {
+ if str.HasFilePathPrefix(path, dir) {
+ return true
+ }
+ xpath, err1 := filepath.EvalSymlinks(path)
+ xdir, err2 := filepath.EvalSymlinks(dir)
+ if err1 == nil && err2 == nil && str.HasFilePathPrefix(xpath, xdir) {
+ return true
+ }
+ return false
+}
+
func hashGetenv(name string) cache.ActionID {
h := cache.NewHash("getenv")
v, ok := os.LookupEnv(name)