all: add go.mod

Copy golang.org/x/build/envutil.Dedup locally to avoid pulling in all
of x/build.

Commands run:
	go mod init
	go mod edit -go=1.11
	go mod tidy
	go list -m all
	go test ./...

Updates golang/go#30228

Change-Id: I0fc24565c08a73db067daf080b46f4aa82a63c41
Reviewed-on: https://go-review.googlesource.com/c/dl/+/167703
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..63793e5
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,3 @@
+module golang.org/dl
+
+go 1.11
diff --git a/internal/version/version.go b/internal/version/version.go
index 3704b39..cfb7128 100644
--- a/internal/version/version.go
+++ b/internal/version/version.go
@@ -24,8 +24,6 @@
 	"runtime"
 	"strings"
 	"time"
-
-	"golang.org/x/build/envutil"
 )
 
 func init() {
@@ -62,10 +60,7 @@
 	if p := os.Getenv("PATH"); p != "" {
 		newPath += string(filepath.ListSeparator) + p
 	}
-	// This envutil.Dedup call 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.
-	cmd.Env = envutil.Dedup(caseInsensitiveEnv, append(os.Environ(), "GOROOT="+root, "PATH="+newPath))
+	cmd.Env = dedupEnv(caseInsensitiveEnv, append(os.Environ(), "GOROOT="+root, "PATH="+newPath))
 	if err := cmd.Run(); err != nil {
 		// TODO: return the same exit status maybe.
 		os.Exit(1)
@@ -456,3 +451,37 @@
 	r.Header.Set("User-Agent", "golang-x-build-version/"+version)
 	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/internal/version/version_test.go b/internal/version/version_test.go
new file mode 100644
index 0000000..c08e211
--- /dev/null
+++ b/internal/version/version_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 version
+
+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)
+		}
+	}
+}