gotip: add $GOROOT/bin to $PATH before starting go binary
This change applies the fix from CL 143545 to the gotip command,
which does not use the golang.org/dl/internal/version package at
this time.
Copy the necessary dependencies for now. In the future, the API
of ./internal/version can be reworked to make it possible for
gotip and all other commands to share more code.
Also remove a blank line in ./internal/version code, because it was
breaking up a single logical block of code and reducing readability.
Fixes golang/go#35507
Change-Id: Ic10e561cccee5259673c76ad679029c68641615f
Reviewed-on: https://go-review.googlesource.com/c/dl/+/206537
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/gotip/main.go b/gotip/main.go
index 0423482..bad0210 100644
--- a/gotip/main.go
+++ b/gotip/main.go
@@ -18,6 +18,7 @@
"errors"
"fmt"
"log"
+ "net/http"
"os"
"os/exec"
"os/user"
@@ -26,6 +27,10 @@
"strings"
)
+func init() {
+ http.DefaultTransport = &userAgentTransport{http.DefaultTransport}
+}
+
func main() {
log.SetFlags(0)
@@ -51,6 +56,11 @@
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
+ newPath := filepath.Join(root, "bin")
+ if p := os.Getenv("PATH"); p != "" {
+ newPath += string(filepath.ListSeparator) + p
+ }
+ cmd.Env = dedupEnv(caseInsensitiveEnv, append(os.Environ(), "GOROOT="+root, "PATH="+newPath))
if err := cmd.Run(); err != nil {
if _, ok := err.(*exec.ExitError); ok {
// TODO: return the same exit status maybe.
@@ -105,7 +115,7 @@
return fmt.Errorf("failed to cleanup git repository: %v", err)
}
- cmd := exec.Command(filepath.Join(root, "src", make()))
+ cmd := exec.Command(filepath.Join(root, "src", makeScript()))
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = filepath.Join(root, "src")
@@ -124,7 +134,7 @@
return nil
}
-func make() string {
+func makeScript() string {
switch runtime.GOOS {
case "plan9":
return "make.rc"
@@ -135,6 +145,8 @@
}
}
+const caseInsensitiveEnv = runtime.GOOS == "windows"
+
func exe() string {
if runtime.GOOS == "windows" {
return ".exe"
@@ -173,3 +185,46 @@
return "", errors.New("can't find user home directory; $HOME is empty")
}
}
+
+type userAgentTransport struct {
+ rt http.RoundTripper
+}
+
+func (uat userAgentTransport) RoundTrip(r *http.Request) (*http.Response, error) {
+ r.Header.Set("User-Agent", "golang-x-build-version/devel")
+ return uat.rt.RoundTrip(r)
+}
+
+// dedupEnv returns a copy of env with any duplicates removed, in favor of
+// later values.
+// Items are expected to be on the normal environment "key=value" form.
+// If caseInsensitive is true, the case of keys is ignored.
+//
+// This function is unnecessary when the binary is
+// built with Go 1.9+, but keep it around for now until Go 1.8
+// is no longer seen in the wild in common distros.
+//
+// This is copied verbatim from golang.org/x/build/envutil.Dedup at CL 10301
+// (commit a91ae26).
+func dedupEnv(caseInsensitive bool, env []string) []string {
+ out := make([]string, 0, len(env))
+ saw := map[string]int{} // to index in the array
+ for _, kv := range env {
+ eq := strings.Index(kv, "=")
+ if eq < 1 {
+ out = append(out, kv)
+ continue
+ }
+ k := kv[:eq]
+ if caseInsensitive {
+ k = strings.ToLower(k)
+ }
+ if dupIdx, isDup := saw[k]; isDup {
+ out[dupIdx] = kv
+ } else {
+ saw[k] = len(out)
+ out = append(out, kv)
+ }
+ }
+ return out
+}
diff --git a/gotip/main_test.go b/gotip/main_test.go
new file mode 100644
index 0000000..d15f103
--- /dev/null
+++ b/gotip/main_test.go
@@ -0,0 +1,35 @@
+// Copyright 2019 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 main
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestDedupEnv(t *testing.T) {
+ tests := []struct {
+ noCase bool
+ in []string
+ want []string
+ }{
+ {
+ noCase: true,
+ in: []string{"k1=v1", "k2=v2", "K1=v3"},
+ want: []string{"K1=v3", "k2=v2"},
+ },
+ {
+ noCase: false,
+ in: []string{"k1=v1", "K1=V2", "k1=v3"},
+ want: []string{"k1=v3", "K1=V2"},
+ },
+ }
+ for _, tt := range tests {
+ got := dedupEnv(tt.noCase, tt.in)
+ if !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("Dedup(%v, %q) = %q; want %q", tt.noCase, tt.in, got, tt.want)
+ }
+ }
+}
diff --git a/internal/version/version.go b/internal/version/version.go
index 9509e1d..a63c649 100644
--- a/internal/version/version.go
+++ b/internal/version/version.go
@@ -55,7 +55,6 @@
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
-
newPath := filepath.Join(root, "bin")
if p := os.Getenv("PATH"); p != "" {
newPath += string(filepath.ListSeparator) + p