blob: b7d3bafb438fa6f213be0770050368cceb33614f [file] [log] [blame]
Colin Cross68f55102015-03-25 14:43:57 -07001// 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
Lukacs T. Berki3243aa52021-02-25 14:44:14 +010015// 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
Colin Cross68f55102015-03-25 14:43:57 -070019
20import (
21 "encoding/json"
22 "fmt"
23 "io/ioutil"
Colin Cross68f55102015-03-25 14:43:57 -070024 "sort"
25)
26
27type envFileEntry struct{ Key, Value string }
28type envFileData []envFileEntry
29
Jaewoong Jungf2200ad2020-11-16 16:01:27 -080030// 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:
Colin Crossd079e0b2022-08-16 10:27:33 -070035//
36// {
37// "Key": "OUT_DIR",
38// "Value": "out",
39// },
Colin Cross988414c2020-01-11 01:11:46 +000040func EnvFileContents(envDeps map[string]string) ([]byte, error) {
Colin Cross68f55102015-03-25 14:43:57 -070041 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 {
Colin Cross988414c2020-01-11 01:11:46 +000050 return nil, err
Colin Cross68f55102015-03-25 14:43:57 -070051 }
52
53 data = append(data, '\n')
54
Colin Cross988414c2020-01-11 01:11:46 +000055 return data, nil
Colin Cross68f55102015-03-25 14:43:57 -070056}
57
Jaewoong Jungf2200ad2020-11-16 16:01:27 -080058// 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.
Lukacs T. Berki3243aa52021-02-25 14:44:14 +010061func StaleEnvFile(filepath string, getenv func(string) string) (bool, error) {
Jaewoong Jungf2200ad2020-11-16 16:01:27 -080062 data, err := ioutil.ReadFile(filepath)
Colin Cross68f55102015-03-25 14:43:57 -070063 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
Lukacs T. Berki3243aa52021-02-25 14:44:14 +010078 cur := getenv(key)
Colin Cross68f55102015-03-25 14:43:57 -070079 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
Lukacs T. Berki7690c092021-02-26 14:27:36 +010095// 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
Jaewoong Jungf2200ad2020-11-16 16:01:27 -0800117// Implements sort.Interface so that we can use sort.Sort on envFileData arrays.
Colin Cross68f55102015-03-25 14:43:57 -0700118func (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}
Jaewoong Jungf2200ad2020-11-16 16:01:27 -0800129
130var _ sort.Interface = envFileData{}