The POSIX standard requires the PWD variable to be an absolute path.
Fixes #46832
Change-Id: I1938592538633e1a0a0958276f1fefc3c4808399
Reviewed-on: https://go-review.googlesource.com/c/go/+/378396
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Michael Matloob <matloob@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
package base
+import (
+ "fmt"
+ "path/filepath"
+)
+
// AppendPWD returns the result of appending PWD=dir to the environment base.
//
// The resulting environment makes os.Getwd more efficient for a subprocess
// running in dir.
func AppendPWD(base []string, dir string) []string {
- // Internally we only use absolute paths, so dir is absolute.
- // Even if dir is not absolute, no harm done.
+ // POSIX requires PWD to be absolute.
+ // Internally we only use absolute paths, so dir should already be absolute.
+ if !filepath.IsAbs(dir) {
+ panic(fmt.Sprintf("AppendPWD with relative path %q", dir))
+ }
return append(base, "PWD="+dir)
}
package generate
import (
+ "internal/testenv"
"os"
+ "path/filepath"
"reflect"
"runtime"
"testing"
}
func TestGenerateCommandParse(t *testing.T) {
+ dir := filepath.Join(testenv.GOROOT(t), "src", "sys")
g := &Generator{
r: nil, // Unused here.
- path: "/usr/ken/sys/proc.go",
- dir: "/usr/ken/sys",
+ path: filepath.Join(dir, "proc.go"),
+ dir: dir,
file: "proc.go",
pkg: "sys",
commands: make(map[string][]string),
// before executing the test. i.e., execute the split as if it
// processing that source line.
func TestGenerateCommandShorthand(t *testing.T) {
+ dir := filepath.Join(testenv.GOROOT(t), "src", "sys")
g := &Generator{
r: nil, // Unused here.
- path: "/usr/ken/sys/proc.go",
- dir: "/usr/ken/sys",
+ path: filepath.Join(dir, "proc.go"),
+ dir: dir,
file: "proc.go",
pkg: "sys",
commands: make(map[string][]string),
// before executing the test. i.e., execute the split as if it
// processing that source line.
func TestGenerateCommandShortHand2(t *testing.T) {
+ dir := filepath.Join(testenv.GOROOT(t), "src", "sys")
g := &Generator{
r: nil, // Unused here.
- path: "/usr/ken/sys/proc.go",
- dir: "/usr/ken/sys",
+ path: filepath.Join(dir, "proc.go"),
+ dir: dir,
file: "proc.go",
pkg: "sys",
commands: make(map[string][]string),
if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {
os.Stderr.Write(ee.Stderr)
} else {
- fmt.Fprintf(os.Stderr, err.Error())
+ fmt.Fprintln(os.Stderr, err.Error())
}
}
}
// Ping pings to determine scheme to use.
func (v *Cmd) Ping(scheme, repo string) error {
- return v.runVerboseOnly(".", v.PingCmd, "scheme", scheme, "repo", repo)
+ // Run the ping command in an arbitrary working directory,
+ // but don't let the current working directory pollute the results.
+ // In module mode, we expect GOMODCACHE to exist and be a safe place for
+ // commands; in GOPATH mode, we expect that to be true of GOPATH/src.
+ dir := cfg.GOMODCACHE
+ if !cfg.ModulesEnabled {
+ dir = filepath.Join(cfg.BuildContext.GOPATH, "src")
+ }
+ os.MkdirAll(dir, 0777) // Ignore errors — if unsuccessful, the command will likely fail.
+
+ return v.runVerboseOnly(dir, v.PingCmd, "scheme", scheme, "repo", repo)
}
// Create creates a new copy of repo in dir.
// The parent of dir must exist; dir must not.
func (v *Cmd) Create(dir, repo string) error {
for _, cmd := range v.CreateCmd {
- if err := v.run(".", cmd, "dir", dir, "repo", repo); err != nil {
+ if err := v.run(filepath.Dir(dir), cmd, "dir", dir, "repo", repo); err != nil {
return err
}
}
cmdline := str.StringList(cfg.BuildToolexec, path, "-V=full")
cmd := exec.Command(cmdline[0], cmdline[1:]...)
- cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir)
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
// compile an empty file on standard input.
cmdline := str.StringList(cfg.BuildToolexec, name, "-###", "-x", language, "-c", "-")
cmd := exec.Command(cmdline[0], cmdline[1:]...)
- cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir)
// Force untranslated output so that we see the string "version".
- cmd.Env = append(cmd.Env, "LC_ALL=C")
+ cmd.Env = append(os.Environ(), "LC_ALL=C")
out, err := cmd.CombinedOutput()
if err != nil {
return "", fmt.Errorf("%s: %v; output: %q", name, err, out)
cmd.Stderr = &buf
cleanup := passLongArgsInResponseFiles(cmd)
defer cleanup()
- cmd.Dir = dir
- cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir)
+ cmd.Env = os.Environ()
+ if dir != "." {
+ cmd.Dir = dir
+ cmd.Env = base.AppendPWD(cmd.Env, dir)
+ }
// Add the TOOLEXEC_IMPORTPATH environment variable for -toolexec tools.
// It doesn't really matter if -toolexec isn't being used.
)
func (b *Builder) swigDoVersionCheck() error {
- out, err := b.runOut(nil, "", nil, "swig", "-version")
+ out, err := b.runOut(nil, ".", nil, "swig", "-version")
if err != nil {
return err
}
# For a while, (*modfetch.codeRepo).Stat was not checking for a go.mod file,
# which would produce a hard error at the subsequent call to GoMod.
-go get
+go get -v
-- go.mod --
module example.com