v.io/x/lib/envvar: make it easier to manipulate envvars that are paths.

Change-Id: Ifef4dca534a699ba3021b718d3d3d3311e19123c
diff --git a/envvar/.api b/envvar/.api
index d88baae..ec7414e 100644
--- a/envvar/.api
+++ b/envvar/.api
@@ -1,3 +1,4 @@
+pkg envvar, func AppendUsingSeparator(string, string, string) string
 pkg envvar, func CopyMap(map[string]string) map[string]string
 pkg envvar, func CopySlice([]string) []string
 pkg envvar, func JoinKeyValue(string, string) string
@@ -7,6 +8,7 @@
 pkg envvar, func MapToSlice(map[string]string) []string
 pkg envvar, func MergeMaps(...map[string]string) map[string]string
 pkg envvar, func MergeSlices(...[]string) []string
+pkg envvar, func PrependUsingSeparator(string, string, string) string
 pkg envvar, func SliceToMap([]string) map[string]string
 pkg envvar, func SortByKey([]string)
 pkg envvar, func SplitKeyValue(string) (string, string)
diff --git a/envvar/envvar.go b/envvar/envvar.go
index f34df73..788f948 100644
--- a/envvar/envvar.go
+++ b/envvar/envvar.go
@@ -145,6 +145,24 @@
 	return value
 }
 
+// PrependUsingSeparator prepends the parameter val to parameter existing using
+// separator to split the tokens in existing  and to prepend val.
+// PrependUsingSeparator uses SplitTokens on the existing string
+// and hence filters out empty tokens, so "A::B:" becomes "A:B".
+func PrependUsingSeparator(val, existing, separator string) string {
+	tmp := SplitTokens(existing, separator)
+	return JoinTokens(append([]string{val}, tmp...), separator)
+}
+
+// AppendUsingSeparator appends the parameter val to parameter existing using
+// separator to split the tokens in existing string and to append val.
+// AppendUsingSeparator uses SplitTokens on the existing string
+// and hence filters out empty tokens, so "A::B:" becomes "A:B".
+func AppendUsingSeparator(val, existing, separator string) string {
+	tmp := SplitTokens(existing, separator)
+	return JoinTokens(append(tmp, val), separator)
+}
+
 // SortByKey sorts vars into ascending key order, where vars is expected to be
 // in the []"key=value" slice representation.
 func SortByKey(vars []string) {
diff --git a/envvar/envvar_test.go b/envvar/envvar_test.go
index e778c53..e2f9cc9 100644
--- a/envvar/envvar_test.go
+++ b/envvar/envvar_test.go
@@ -161,6 +161,40 @@
 	}
 }
 
+func TestAppendPrepend(t *testing.T) {
+	tests := []struct {
+		Sep, Value, Existing, Result string
+	}{
+		{":", "Z", "", "Z"},
+		{":", "", "Z", "Z"},
+		{":", "", "", ""},
+		{":", "X", ":A:B", "X:A:B"},
+		{":", "Y", "A:B", "Y:A:B"},
+		{":", "Z", "A:::B", "Z:A:B"},
+		{":", "Z", "A:::B:", "Z:A:B"},
+	}
+	for i, test := range tests {
+		if got, want := PrependUsingSeparator(test.Value, test.Existing, test.Sep), test.Result; got != want {
+			t.Errorf("SplitTokens(%d) got %v, want %v", i, got, want)
+		}
+	}
+	tests = []struct {
+		Sep, Value, Existing, Result string
+	}{
+		{":", "Z", "", "Z"},
+		{":", "", "Z", "Z"},
+		{":", "", "", ""},
+		{":", "X", ":A:B:", "A:B:X"},
+		{":", "Y", "A:B", "A:B:Y"},
+		{":", "Z", "A:::B", "A:B:Z"},
+	}
+	for i, test := range tests {
+		if got, want := AppendUsingSeparator(test.Value, test.Existing, test.Sep), test.Result; got != want {
+			t.Errorf("SplitTokens(%d) got %v, want %v", i, got, want)
+		}
+	}
+}
+
 func TestSortByKey(t *testing.T) {
 	tests := []struct {
 		In, Sorted []string