Skip to content

Commit c035d82

Browse files
author
Bryan C. Mills
committed
cmd/dist: consistently set PWD when executing a command in a different directory
For #33598 Change-Id: If0de906ffa2fcc83bb2a90f9e80a5b29d7667398 Reviewed-on: https://go-review.googlesource.com/c/go/+/353449 Trust: Bryan C. Mills <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 8b2f583 commit c035d82

File tree

3 files changed

+80
-29
lines changed

3 files changed

+80
-29
lines changed

src/cmd/dist/exec.go

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package main
6+
7+
import (
8+
"os"
9+
"os/exec"
10+
"strings"
11+
)
12+
13+
// setDir sets cmd.Dir to dir, and also adds PWD=dir to cmd's environment.
14+
func setDir(cmd *exec.Cmd, dir string) {
15+
cmd.Dir = dir
16+
setEnv(cmd, "PWD", dir)
17+
}
18+
19+
// setEnv sets cmd.Env so that key = value.
20+
//
21+
// It first removes any existing values for key, so it is safe to call
22+
// even from within cmdbootstrap.
23+
func setEnv(cmd *exec.Cmd, key, value string) {
24+
kv := key + "=" + value
25+
if cmd.Env == nil {
26+
cmd.Env = os.Environ()
27+
}
28+
29+
prefix := kv[:len(key)+1]
30+
for i, entry := range cmd.Env {
31+
if strings.HasPrefix(entry, prefix) {
32+
cmd.Env[i] = kv
33+
return
34+
}
35+
}
36+
37+
cmd.Env = append(cmd.Env, kv)
38+
}
39+
40+
// unsetEnv sets cmd.Env so that key is not present in the environment.
41+
func unsetEnv(cmd *exec.Cmd, key string) {
42+
if cmd.Env == nil {
43+
cmd.Env = os.Environ()
44+
}
45+
46+
prefix := key + "="
47+
for i, entry := range cmd.Env {
48+
if strings.HasPrefix(entry, prefix) {
49+
cmd.Env = append(cmd.Env[:i], cmd.Env[i+1:]...)
50+
return
51+
}
52+
}
53+
}

src/cmd/dist/test.go

+26-28
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,8 @@ func (t *tester) registerTests() {
509509
heading: "GOOS=ios on darwin/amd64",
510510
fn: func(dt *distTest) error {
511511
cmd := t.addCmd(dt, "src", t.goTest(), t.timeout(300), "-run=SystemRoots", "crypto/x509")
512-
cmd.Env = append(os.Environ(), "GOOS=ios", "CGO_ENABLED=1")
512+
setEnv(cmd, "GOOS", "ios")
513+
setEnv(cmd, "CGO_ENABLED", "1")
513514
return nil
514515
},
515516
})
@@ -529,7 +530,7 @@ func (t *tester) registerTests() {
529530
cmd := t.addCmd(dt, "src", t.goTest(), t.timeout(300), "runtime", "-cpu=1,2,4", "-quick")
530531
// We set GOMAXPROCS=2 in addition to -cpu=1,2,4 in order to test runtime bootstrap code,
531532
// creation of first goroutines and first garbage collections in the parallel setting.
532-
cmd.Env = append(os.Environ(), "GOMAXPROCS=2")
533+
setEnv(cmd, "GOMAXPROCS", "2")
533534
return nil
534535
},
535536
})
@@ -550,7 +551,7 @@ func (t *tester) registerTests() {
550551
return nil
551552
}
552553
cmd := exec.Command("go", "test")
553-
cmd.Dir = filepath.Join(os.Getenv("GOROOT"), "src/cmd/go/testdata/testterminal18153")
554+
setDir(cmd, filepath.Join(os.Getenv("GOROOT"), "src/cmd/go/testdata/testterminal18153"))
554555
cmd.Stdout = os.Stdout
555556
cmd.Stderr = os.Stderr
556557
return cmd.Run()
@@ -587,16 +588,13 @@ func (t *tester) registerTests() {
587588
return err
588589
}
589590

590-
// Run `go test fmt` in the moved GOROOT.
591+
// Run `go test fmt` in the moved GOROOT, without explicitly setting
592+
// GOROOT in the environment. The 'go' command should find itself.
591593
cmd := exec.Command(filepath.Join(moved, "bin", "go"), "test", "fmt")
592594
cmd.Stdout = os.Stdout
593595
cmd.Stderr = os.Stderr
594-
// Don't set GOROOT in the environment.
595-
for _, e := range os.Environ() {
596-
if !strings.HasPrefix(e, "GOROOT=") && !strings.HasPrefix(e, "GOCACHE=") {
597-
cmd.Env = append(cmd.Env, e)
598-
}
599-
}
596+
unsetEnv(cmd, "GOROOT")
597+
unsetEnv(cmd, "GOCACHE") // TODO(bcmills): ...why‽
600598
err := cmd.Run()
601599

602600
if rerr := os.Rename(moved, goroot); rerr != nil {
@@ -723,11 +721,9 @@ func (t *tester) registerTests() {
723721
heading: "../misc/swig/callback",
724722
fn: func(dt *distTest) error {
725723
cmd := t.addCmd(dt, "misc/swig/callback", t.goTest())
726-
cmd.Env = append(os.Environ(),
727-
"CGO_CFLAGS=-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option",
728-
"CGO_CXXFLAGS=-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option",
729-
"CGO_LDFLAGS=-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option",
730-
)
724+
setEnv(cmd, "CGO_CFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option")
725+
setEnv(cmd, "CGO_CXXFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option")
726+
setEnv(cmd, "CGO_LDFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option")
731727
return nil
732728
},
733729
},
@@ -879,9 +875,9 @@ func (t *tester) registerSeqTest(name, dirBanner string, cmdline ...interface{})
879875
func (t *tester) bgDirCmd(dir, bin string, args ...string) *exec.Cmd {
880876
cmd := exec.Command(bin, args...)
881877
if filepath.IsAbs(dir) {
882-
cmd.Dir = dir
878+
setDir(cmd, dir)
883879
} else {
884-
cmd.Dir = filepath.Join(goroot, dir)
880+
setDir(cmd, filepath.Join(goroot, dir))
885881
}
886882
return cmd
887883
}
@@ -1114,7 +1110,8 @@ func (t *tester) runHostTest(dir, pkg string) error {
11141110
defer os.Remove(f.Name())
11151111

11161112
cmd := t.dirCmd(dir, t.goTest(), "-c", "-o", f.Name(), pkg)
1117-
cmd.Env = append(os.Environ(), "GOARCH="+gohostarch, "GOOS="+gohostos)
1113+
setEnv(cmd, "GOARCH", gohostarch)
1114+
setEnv(cmd, "GOOS", gohostos)
11181115
if err := cmd.Run(); err != nil {
11191116
return err
11201117
}
@@ -1123,15 +1120,15 @@ func (t *tester) runHostTest(dir, pkg string) error {
11231120

11241121
func (t *tester) cgoTest(dt *distTest) error {
11251122
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest())
1126-
cmd.Env = append(os.Environ(), "GOFLAGS=-ldflags=-linkmode=auto")
1123+
setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=auto")
11271124

11281125
// Skip internal linking cases on linux/arm64 to support GCC-9.4 and above.
11291126
// See issue #39466.
11301127
skipInternalLink := goarch == "arm64" && goos == "linux"
11311128

11321129
if t.internalLink() && !skipInternalLink {
11331130
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=internal")
1134-
cmd.Env = append(os.Environ(), "GOFLAGS=-ldflags=-linkmode=internal")
1131+
setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=internal")
11351132
}
11361133

11371134
pair := gohostos + "-" + goarch
@@ -1143,9 +1140,9 @@ func (t *tester) cgoTest(dt *distTest) error {
11431140
break
11441141
}
11451142
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest())
1146-
cmd.Env = append(os.Environ(), "GOFLAGS=-ldflags=-linkmode=external")
1143+
setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=external")
11471144

1148-
cmd = t.addCmd(dt, "misc/cgo/test", t.goTest(), "-ldflags", "-linkmode=external -s")
1145+
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-ldflags", "-linkmode=external -s")
11491146

11501147
if t.supportedBuildmode("pie") {
11511148
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie")
@@ -1163,10 +1160,10 @@ func (t *tester) cgoTest(dt *distTest) error {
11631160
"openbsd-386", "openbsd-amd64", "openbsd-arm", "openbsd-arm64", "openbsd-mips64":
11641161

11651162
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest())
1166-
cmd.Env = append(os.Environ(), "GOFLAGS=-ldflags=-linkmode=external")
1163+
setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=external")
11671164
// cgo should be able to cope with both -g arguments and colored
11681165
// diagnostics.
1169-
cmd.Env = append(cmd.Env, "CGO_CFLAGS=-g0 -fdiagnostics-color")
1166+
setEnv(cmd, "CGO_CFLAGS", "-g0 -fdiagnostics-color")
11701167

11711168
t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=auto")
11721169
t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=external")
@@ -1199,7 +1196,7 @@ func (t *tester) cgoTest(dt *distTest) error {
11991196
// than -static in -extldflags, so test both.
12001197
// See issue #16651.
12011198
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static")
1202-
cmd.Env = append(os.Environ(), "CGO_LDFLAGS=-static -pthread")
1199+
setEnv(cmd, "CGO_LDFLAGS", "-static -pthread")
12031200
}
12041201
}
12051202

@@ -1438,7 +1435,7 @@ func (t *tester) raceTest(dt *distTest) error {
14381435
// We shouldn't need to redo all of misc/cgo/test too.
14391436
// The race buildler will take care of this.
14401437
// cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-race")
1441-
// cmd.Env = append(os.Environ(), "GOTRACEBACK=2")
1438+
// setEnv(cmd, "GOTRACEBACK", "2")
14421439
}
14431440
if t.extLink() {
14441441
// Test with external linking; see issue 9133.
@@ -1468,7 +1465,8 @@ func (t *tester) testDirTest(dt *distTest, shard, shards int) error {
14681465
})
14691466

14701467
cmd := t.dirCmd("test", "go", "build", "-o", runtest.exe, "run.go")
1471-
cmd.Env = append(os.Environ(), "GOOS="+gohostos, "GOARCH="+gohostarch)
1468+
setEnv(cmd, "GOOS", gohostos)
1469+
setEnv(cmd, "GOARCH", gohostarch)
14721470
runtest.err = cmd.Run()
14731471
})
14741472
if runtest.err != nil {
@@ -1632,7 +1630,7 @@ func (t *tester) runPrecompiledStdTest(timeout time.Duration) error {
16321630
bin := t.prebuiltGoPackageTestBinary()
16331631
fmt.Fprintf(os.Stderr, "# %s: using pre-built %s...\n", stdMatches[0], bin)
16341632
cmd := exec.Command(bin, "-test.short="+short(), "-test.timeout="+timeout.String())
1635-
cmd.Dir = filepath.Dir(bin)
1633+
setDir(cmd, filepath.Dir(bin))
16361634
cmd.Stdout = os.Stdout
16371635
cmd.Stderr = os.Stderr
16381636
if err := cmd.Start(); err != nil {

src/cmd/dist/util.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func run(dir string, mode int, cmd ...string) string {
7272
}
7373

7474
xcmd := exec.Command(cmd[0], cmd[1:]...)
75-
xcmd.Dir = dir
75+
setDir(xcmd, dir)
7676
var data []byte
7777
var err error
7878

0 commit comments

Comments
 (0)