Move environment staleness check to soong_ui.

Also delete the now-unnecessary soong_env binary.

Test: Manually. Also checked what happens when a used environment
variable changes.

Change-Id: Ib393e7f444e94819198c6cce4bcd8719d9fd9441
diff --git a/shared/env.go b/shared/env.go
new file mode 100644
index 0000000..7900daa
--- /dev/null
+++ b/shared/env.go
@@ -0,0 +1,107 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Implements the environment JSON file handling for serializing the
+// environment variables that were used in soong_build so that soong_ui can
+// check whether they have changed
+package shared
+
+import (
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"sort"
+)
+
+type envFileEntry struct{ Key, Value string }
+type envFileData []envFileEntry
+
+// Serializes the given environment variable name/value map into JSON formatted bytes by converting
+// to envFileEntry values and marshaling them.
+//
+// e.g. OUT_DIR = "out"
+// is converted to:
+// {
+//     "Key": "OUT_DIR",
+//     "Value": "out",
+// },
+func EnvFileContents(envDeps map[string]string) ([]byte, error) {
+	contents := make(envFileData, 0, len(envDeps))
+	for key, value := range envDeps {
+		contents = append(contents, envFileEntry{key, value})
+	}
+
+	sort.Sort(contents)
+
+	data, err := json.MarshalIndent(contents, "", "    ")
+	if err != nil {
+		return nil, err
+	}
+
+	data = append(data, '\n')
+
+	return data, nil
+}
+
+// Reads and deserializes a Soong environment file located at the given file path to determine its
+// staleness. If any environment variable values have changed, it prints them out and returns true.
+// Failing to read or parse the file also causes it to return true.
+func StaleEnvFile(filepath string, getenv func(string) string) (bool, error) {
+	data, err := ioutil.ReadFile(filepath)
+	if err != nil {
+		return true, err
+	}
+
+	var contents envFileData
+
+	err = json.Unmarshal(data, &contents)
+	if err != nil {
+		return true, err
+	}
+
+	var changed []string
+	for _, entry := range contents {
+		key := entry.Key
+		old := entry.Value
+		cur := getenv(key)
+		if old != cur {
+			changed = append(changed, fmt.Sprintf("%s (%q -> %q)", key, old, cur))
+		}
+	}
+
+	if len(changed) > 0 {
+		fmt.Printf("environment variables changed value:\n")
+		for _, s := range changed {
+			fmt.Printf("   %s\n", s)
+		}
+		return true, nil
+	}
+
+	return false, nil
+}
+
+// Implements sort.Interface so that we can use sort.Sort on envFileData arrays.
+func (e envFileData) Len() int {
+	return len(e)
+}
+
+func (e envFileData) Less(i, j int) bool {
+	return e[i].Key < e[j].Key
+}
+
+func (e envFileData) Swap(i, j int) {
+	e[i], e[j] = e[j], e[i]
+}
+
+var _ sort.Interface = envFileData{}