blob: 75190cc0321aadc1d0af9727ff67a099352d6fd5 [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
Jason Wu2520f5e2023-05-30 19:45:36 -040058// Reads and deserializes a Soong environment file located at the given file
59// path to determine its staleness. If any environment variable values have
60// changed, it prints and returns changed environment variable values and
61// returns true.
Jaewoong Jungf2200ad2020-11-16 16:01:27 -080062// Failing to read or parse the file also causes it to return true.
Jason Wu2520f5e2023-05-30 19:45:36 -040063func StaleEnvFile(filepath string, getenv func(string) string) (isStale bool,
64 changedEnvironmentVariable []string, err error) {
Jaewoong Jungf2200ad2020-11-16 16:01:27 -080065 data, err := ioutil.ReadFile(filepath)
Colin Cross68f55102015-03-25 14:43:57 -070066 if err != nil {
Jason Wu2520f5e2023-05-30 19:45:36 -040067 return true, nil, err
Colin Cross68f55102015-03-25 14:43:57 -070068 }
69
70 var contents envFileData
71
72 err = json.Unmarshal(data, &contents)
73 if err != nil {
Jason Wu2520f5e2023-05-30 19:45:36 -040074 return true, nil, err
Colin Cross68f55102015-03-25 14:43:57 -070075 }
76
77 var changed []string
78 for _, entry := range contents {
79 key := entry.Key
80 old := entry.Value
Lukacs T. Berki3243aa52021-02-25 14:44:14 +010081 cur := getenv(key)
Colin Cross68f55102015-03-25 14:43:57 -070082 if old != cur {
83 changed = append(changed, fmt.Sprintf("%s (%q -> %q)", key, old, cur))
Jason Wu2520f5e2023-05-30 19:45:36 -040084 changedEnvironmentVariable = append(changedEnvironmentVariable, key)
Colin Cross68f55102015-03-25 14:43:57 -070085 }
86 }
87
88 if len(changed) > 0 {
89 fmt.Printf("environment variables changed value:\n")
90 for _, s := range changed {
91 fmt.Printf(" %s\n", s)
92 }
Jason Wu2520f5e2023-05-30 19:45:36 -040093 return true, changedEnvironmentVariable, nil
Colin Cross68f55102015-03-25 14:43:57 -070094 }
95
Jason Wu2520f5e2023-05-30 19:45:36 -040096 return false, nil, nil
Colin Cross68f55102015-03-25 14:43:57 -070097}
98
Lukacs T. Berki7690c092021-02-26 14:27:36 +010099// Deserializes and environment serialized by EnvFileContents() and returns it
100// as a map[string]string.
101func EnvFromFile(envFile string) (map[string]string, error) {
102 result := make(map[string]string)
103 data, err := ioutil.ReadFile(envFile)
104 if err != nil {
105 return result, err
106 }
107
108 var contents envFileData
109 err = json.Unmarshal(data, &contents)
110 if err != nil {
111 return result, err
112 }
113
114 for _, entry := range contents {
115 result[entry.Key] = entry.Value
116 }
117
118 return result, nil
119}
120
Jaewoong Jungf2200ad2020-11-16 16:01:27 -0800121// Implements sort.Interface so that we can use sort.Sort on envFileData arrays.
Colin Cross68f55102015-03-25 14:43:57 -0700122func (e envFileData) Len() int {
123 return len(e)
124}
125
126func (e envFileData) Less(i, j int) bool {
127 return e[i].Key < e[j].Key
128}
129
130func (e envFileData) Swap(i, j int) {
131 e[i], e[j] = e[j], e[i]
132}
Jaewoong Jungf2200ad2020-11-16 16:01:27 -0800133
134var _ sort.Interface = envFileData{}