// 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 } // Deserializes and environment serialized by EnvFileContents() and returns it // as a map[string]string. func EnvFromFile(envFile string) (map[string]string, error) { result := make(map[string]string) data, err := ioutil.ReadFile(envFile) if err != nil { return result, err } var contents envFileData err = json.Unmarshal(data, &contents) if err != nil { return result, err } for _, entry := range contents { result[entry.Key] = entry.Value } return result, 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{}