envutil: move dedupEnv function from gomote to new package

Change-Id: Ib6856cdfced65e1bec818ac3a80d03a5269e2bd0
Reviewed-on: https://go-review.googlesource.com/10301
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/cmd/gomote/run.go b/cmd/gomote/run.go
index 2162ea8..f455c89 100644
--- a/cmd/gomote/run.go
+++ b/cmd/gomote/run.go
@@ -11,6 +11,7 @@
 	"strings"
 
 	"golang.org/x/build/buildlet"
+	"golang.org/x/build/envutil"
 )
 
 func run(args []string) error {
@@ -47,7 +48,7 @@
 		SystemLevel: sys || strings.HasPrefix(cmd, "/"),
 		Output:      os.Stdout,
 		Args:        fs.Args()[2:],
-		ExtraEnv:    dedupEnv(conf.GOOS() == "windows", append(conf.Env(), []string(env)...)),
+		ExtraEnv:    envutil.Dedup(conf.GOOS() == "windows", append(conf.Env(), []string(env)...)),
 		Debug:       debug,
 	})
 	if execErr != nil {
@@ -56,35 +57,6 @@
 	return remoteErr
 }
 
-// dedupEnv 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.
-//
-// TODO(bradfitz): move this somewhere else.
-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
-}
-
 // stringSlice implements flag.Value, specifically for storing environment
 // variable key=value pairs.
 type stringSlice []string
diff --git a/envutil/dedup.go b/envutil/dedup.go
new file mode 100644
index 0000000..067ff94
--- /dev/null
+++ b/envutil/dedup.go
@@ -0,0 +1,35 @@
+// Copyright 2015 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 envutil provides utilities for working with environment variables.
+package envutil
+
+import "strings"
+
+// Dedup 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.
+func Dedup(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/cmd/gomote/gomote_test.go b/envutil/dedup_test.go
similarity index 77%
rename from cmd/gomote/gomote_test.go
rename to envutil/dedup_test.go
index 97b5e00..50621e1 100644
--- a/cmd/gomote/gomote_test.go
+++ b/envutil/dedup_test.go
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-package main
+package envutil
 
 import (
 	"reflect"
 	"testing"
 )
 
-func TestDedupEnv(t *testing.T) {
+func TestDedup(t *testing.T) {
 	tests := []struct {
 		noCase bool
 		in     []string
@@ -27,9 +27,9 @@
 		},
 	}
 	for _, tt := range tests {
-		got := dedupEnv(tt.noCase, tt.in)
+		got := Dedup(tt.noCase, tt.in)
 		if !reflect.DeepEqual(got, tt.want) {
-			t.Errorf("dedupEnv(%v, %q) = %q; want %q", tt.noCase, tt.in, got, tt.want)
+			t.Errorf("Dedup(%v, %q) = %q; want %q", tt.noCase, tt.in, got, tt.want)
 		}
 	}
 }