• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2015 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Implements the environment JSON file handling for serializing the
16// environment variables that were used in soong_build so that soong_ui can
17// check whether they have changed
18package shared
19
20import (
21	"encoding/json"
22	"fmt"
23	"io/ioutil"
24	"sort"
25)
26
27type envFileEntry struct{ Key, Value string }
28type envFileData []envFileEntry
29
30// Serializes the given environment variable name/value map into JSON formatted bytes by converting
31// to envFileEntry values and marshaling them.
32//
33// e.g. OUT_DIR = "out"
34// is converted to:
35//
36//	{
37//	    "Key": "OUT_DIR",
38//	    "Value": "out",
39//	},
40func EnvFileContents(envDeps map[string]string) ([]byte, error) {
41	contents := make(envFileData, 0, len(envDeps))
42	for key, value := range envDeps {
43		contents = append(contents, envFileEntry{key, value})
44	}
45
46	sort.Sort(contents)
47
48	data, err := json.MarshalIndent(contents, "", "    ")
49	if err != nil {
50		return nil, err
51	}
52
53	data = append(data, '\n')
54
55	return data, nil
56}
57
58// Reads and deserializes a Soong environment file located at the given file path to determine its
59// staleness. If any environment variable values have changed, it prints them out and returns true.
60// Failing to read or parse the file also causes it to return true.
61func StaleEnvFile(filepath string, getenv func(string) string) (bool, error) {
62	data, err := ioutil.ReadFile(filepath)
63	if err != nil {
64		return true, err
65	}
66
67	var contents envFileData
68
69	err = json.Unmarshal(data, &contents)
70	if err != nil {
71		return true, err
72	}
73
74	var changed []string
75	for _, entry := range contents {
76		key := entry.Key
77		old := entry.Value
78		cur := getenv(key)
79		if old != cur {
80			changed = append(changed, fmt.Sprintf("%s (%q -> %q)", key, old, cur))
81		}
82	}
83
84	if len(changed) > 0 {
85		fmt.Printf("environment variables changed value:\n")
86		for _, s := range changed {
87			fmt.Printf("   %s\n", s)
88		}
89		return true, nil
90	}
91
92	return false, nil
93}
94
95// Deserializes and environment serialized by EnvFileContents() and returns it
96// as a map[string]string.
97func EnvFromFile(envFile string) (map[string]string, error) {
98	result := make(map[string]string)
99	data, err := ioutil.ReadFile(envFile)
100	if err != nil {
101		return result, err
102	}
103
104	var contents envFileData
105	err = json.Unmarshal(data, &contents)
106	if err != nil {
107		return result, err
108	}
109
110	for _, entry := range contents {
111		result[entry.Key] = entry.Value
112	}
113
114	return result, nil
115}
116
117// Implements sort.Interface so that we can use sort.Sort on envFileData arrays.
118func (e envFileData) Len() int {
119	return len(e)
120}
121
122func (e envFileData) Less(i, j int) bool {
123	return e[i].Key < e[j].Key
124}
125
126func (e envFileData) Swap(i, j int) {
127	e[i], e[j] = e[j], e[i]
128}
129
130var _ sort.Interface = envFileData{}
131