18
18
import com .google .common .collect .ImmutableMap ;
19
19
import com .google .common .collect .ImmutableSet ;
20
20
import com .google .devtools .build .lib .util .Fingerprint ;
21
- import java .util .LinkedHashMap ;
22
21
import java .util .Map ;
23
22
import java .util .Set ;
24
23
import java .util .TreeMap ;
45
44
*/
46
45
public final class ActionEnvironment {
47
46
48
- /** A map of environment variables. */
47
+ /**
48
+ * A map of environment variables together with a list of variables to inherit from the shell
49
+ * environment.
50
+ */
49
51
public interface EnvironmentVariables {
50
52
51
53
/**
52
- * Returns the environment variables as a map.
54
+ * Returns the fixed environment variables as a map.
53
55
*
54
- * <p>WARNING: this allocations additional objects if the underlying implementation is a {@link
56
+ * <p>WARNING: this allocates additional objects if the underlying implementation is a {@link
55
57
* CompoundEnvironmentVariables}; use sparingly.
56
58
*/
57
- ImmutableMap <String , String > toMap ();
59
+ ImmutableMap <String , String > getFixedEnvironment ();
60
+
61
+ /**
62
+ * Returns the inherited environment variables as a set.
63
+ *
64
+ * <p>WARNING: this allocates additional objects if the underlying implementation is a {@link
65
+ * CompoundEnvironmentVariables}; use sparingly.
66
+ */
67
+ ImmutableSet <String > getInheritedEnvironment ();
58
68
59
69
default boolean isEmpty () {
60
- return toMap ().isEmpty ();
70
+ return getFixedEnvironment (). isEmpty () && getInheritedEnvironment ().isEmpty ();
61
71
}
62
72
63
73
default int size () {
64
- return toMap ().size ();
74
+ return getFixedEnvironment (). size () + getInheritedEnvironment ().size ();
65
75
}
66
76
}
67
77
@@ -70,11 +80,21 @@ default int size() {
70
80
* allocation a new map.
71
81
*/
72
82
static class CompoundEnvironmentVariables implements EnvironmentVariables {
83
+
84
+ static EnvironmentVariables create (
85
+ Map <String , String > fixedVars , Set <String > inheritedVars , EnvironmentVariables base ) {
86
+ if (fixedVars .isEmpty () && inheritedVars .isEmpty () && base .isEmpty ()) {
87
+ return EMPTY_ENVIRONMENT_VARIABLES ;
88
+ }
89
+ return new CompoundEnvironmentVariables (fixedVars , inheritedVars , base );
90
+ }
91
+
73
92
private final EnvironmentVariables current ;
74
93
private final EnvironmentVariables base ;
75
94
76
- CompoundEnvironmentVariables (Map <String , String > vars , EnvironmentVariables base ) {
77
- this .current = new SimpleEnvironmentVariables (vars );
95
+ private CompoundEnvironmentVariables (
96
+ Map <String , String > fixedVars , Set <String > inheritedVars , EnvironmentVariables base ) {
97
+ this .current = SimpleEnvironmentVariables .create (fixedVars , inheritedVars );
78
98
this .base = base ;
79
99
}
80
100
@@ -84,48 +104,62 @@ public boolean isEmpty() {
84
104
}
85
105
86
106
@ Override
87
- public ImmutableMap <String , String > toMap () {
88
- Map <String , String > result = new LinkedHashMap <>();
89
- result .putAll (base .toMap ());
90
- result .putAll (current .toMap ());
91
- return ImmutableMap .copyOf (result );
107
+ public ImmutableMap <String , String > getFixedEnvironment () {
108
+ ImmutableMap .Builder <String , String > result = new ImmutableMap .Builder <>();
109
+ result .putAll (base .getFixedEnvironment ());
110
+ result .putAll (current .getFixedEnvironment ());
111
+ return result .buildKeepingLast ();
112
+ }
113
+
114
+ @ Override
115
+ public ImmutableSet <String > getInheritedEnvironment () {
116
+ ImmutableSet .Builder <String > result = new ImmutableSet .Builder <>();
117
+ result .addAll (base .getInheritedEnvironment ());
118
+ result .addAll (current .getInheritedEnvironment ());
119
+ return result .build ();
92
120
}
93
121
}
94
122
95
123
/** A simple {@link EnvironmentVariables}. */
96
124
static class SimpleEnvironmentVariables implements EnvironmentVariables {
97
125
98
- static EnvironmentVariables create (Map <String , String > vars ) {
99
- if (vars .isEmpty ()) {
126
+ static EnvironmentVariables create (Map <String , String > fixedVars , Set < String > inheritedVars ) {
127
+ if (fixedVars . isEmpty () && inheritedVars .isEmpty ()) {
100
128
return EMPTY_ENVIRONMENT_VARIABLES ;
101
129
}
102
- return new SimpleEnvironmentVariables (vars );
130
+ return new SimpleEnvironmentVariables (fixedVars , inheritedVars );
103
131
}
104
132
105
- private final ImmutableMap <String , String > vars ;
133
+ private final ImmutableMap <String , String > fixedVars ;
134
+ private final ImmutableSet <String > inheritedVars ;
106
135
107
- private SimpleEnvironmentVariables (Map <String , String > vars ) {
108
- this .vars = ImmutableMap .copyOf (vars );
136
+ private SimpleEnvironmentVariables (Map <String , String > fixedVars , Set <String > inheritedVars ) {
137
+ this .fixedVars = ImmutableMap .copyOf (fixedVars );
138
+ this .inheritedVars = ImmutableSet .copyOf (inheritedVars );
109
139
}
110
140
111
141
@ Override
112
- public ImmutableMap <String , String > toMap () {
113
- return vars ;
142
+ public ImmutableMap <String , String > getFixedEnvironment () {
143
+ return fixedVars ;
144
+ }
145
+
146
+ @ Override
147
+ public ImmutableSet <String > getInheritedEnvironment () {
148
+ return inheritedVars ;
114
149
}
115
150
}
116
151
117
152
/** An empty {@link EnvironmentVariables}. */
118
153
public static final EnvironmentVariables EMPTY_ENVIRONMENT_VARIABLES =
119
- new SimpleEnvironmentVariables (ImmutableMap .of ());
154
+ new SimpleEnvironmentVariables (ImmutableMap .of (), ImmutableSet . of () );
120
155
121
156
/**
122
157
* An empty environment, mainly for testing. Production code should never use this, but instead
123
158
* get the proper environment from the current configuration.
124
159
*/
125
160
// TODO(ulfjack): Migrate all production code to use the proper action environment, and then make
126
161
// this @VisibleForTesting or rename it to clarify.
127
- public static final ActionEnvironment EMPTY =
128
- new ActionEnvironment (EMPTY_ENVIRONMENT_VARIABLES , ImmutableSet .of ());
162
+ public static final ActionEnvironment EMPTY = new ActionEnvironment (EMPTY_ENVIRONMENT_VARIABLES );
129
163
130
164
/**
131
165
* Splits the given map into a map of variables with a fixed value, and a set of variables that
@@ -145,59 +179,66 @@ public static ActionEnvironment split(Map<String, String> env) {
145
179
inheritedEnv .add (key );
146
180
}
147
181
}
148
- return create (new SimpleEnvironmentVariables (fixedEnv ), ImmutableSet . copyOf ( inheritedEnv ));
182
+ return create (SimpleEnvironmentVariables . create (fixedEnv , inheritedEnv ));
149
183
}
150
184
151
- private final EnvironmentVariables fixedEnv ;
152
- private final ImmutableSet <String > inheritedEnv ;
185
+ private final EnvironmentVariables vars ;
153
186
154
- private ActionEnvironment (EnvironmentVariables fixedEnv , ImmutableSet <String > inheritedEnv ) {
155
- this .fixedEnv = fixedEnv ;
156
- this .inheritedEnv = inheritedEnv ;
187
+ private ActionEnvironment (EnvironmentVariables vars ) {
188
+ this .vars = vars ;
157
189
}
158
190
159
191
/**
160
192
* Creates a new action environment. The order in which the environments are combined is
161
193
* undefined, so callers need to take care that the key set of the {@code fixedEnv} map and the
162
194
* set of {@code inheritedEnv} elements are disjoint.
163
195
*/
164
- private static ActionEnvironment create (
165
- EnvironmentVariables fixedEnv , ImmutableSet <String > inheritedEnv ) {
166
- if (fixedEnv .isEmpty () && inheritedEnv .isEmpty ()) {
196
+ private static ActionEnvironment create (EnvironmentVariables vars ) {
197
+ if (vars .isEmpty ()) {
167
198
return EMPTY ;
168
199
}
169
- return new ActionEnvironment (fixedEnv , inheritedEnv );
200
+ return new ActionEnvironment (vars );
170
201
}
171
202
172
203
public static ActionEnvironment create (
173
204
Map <String , String > fixedEnv , ImmutableSet <String > inheritedEnv ) {
174
- return new ActionEnvironment (SimpleEnvironmentVariables .create (fixedEnv ) , inheritedEnv );
205
+ return ActionEnvironment . create (SimpleEnvironmentVariables .create (fixedEnv , inheritedEnv ) );
175
206
}
176
207
177
208
public static ActionEnvironment create (Map <String , String > fixedEnv ) {
178
- return new ActionEnvironment ( new SimpleEnvironmentVariables (fixedEnv ) , ImmutableSet .of ());
209
+ return ActionEnvironment . create ( SimpleEnvironmentVariables . create (fixedEnv , ImmutableSet .of () ));
179
210
}
180
211
181
212
/**
182
213
* Returns a copy of the environment with the given fixed variables added to it, <em>overwriting
183
214
* any existing occurrences of those variables</em>.
184
215
*/
185
- public ActionEnvironment addFixedVariables (Map <String , String > vars ) {
186
- return new ActionEnvironment (new CompoundEnvironmentVariables (vars , fixedEnv ), inheritedEnv );
216
+ public ActionEnvironment addFixedVariables (Map <String , String > fixedVars ) {
217
+ return ActionEnvironment .create (
218
+ CompoundEnvironmentVariables .create (fixedVars , ImmutableSet .of (), vars ));
219
+ }
220
+
221
+ /**
222
+ * Returns a copy of the environment with the given fixed and inherited variables added to it,
223
+ * <em>overwriting any existing occurrences of those variables</em>.
224
+ */
225
+ public ActionEnvironment addVariables (Map <String , String > fixedVars , Set <String > inheritedVars ) {
226
+ return ActionEnvironment .create (
227
+ CompoundEnvironmentVariables .create (fixedVars , inheritedVars , vars ));
187
228
}
188
229
189
230
/** Returns the combined size of the fixed and inherited environments. */
190
231
public int size () {
191
- return fixedEnv . size () + inheritedEnv .size ();
232
+ return vars .size ();
192
233
}
193
234
194
235
/**
195
236
* Returns the 'fixed' part of the environment, i.e., those environment variables that are set to
196
237
* fixed values and their values. This should only be used for testing and to compute the cache
197
238
* keys of actions. Use {@link #resolve} instead to get the complete environment.
198
239
*/
199
- public EnvironmentVariables getFixedEnv () {
200
- return fixedEnv ;
240
+ public ImmutableMap < String , String > getFixedEnv () {
241
+ return vars . getFixedEnvironment () ;
201
242
}
202
243
203
244
/**
@@ -207,7 +248,7 @@ public EnvironmentVariables getFixedEnv() {
207
248
* get the complete environment.
208
249
*/
209
250
public ImmutableSet <String > getInheritedEnv () {
210
- return inheritedEnv ;
251
+ return vars . getInheritedEnvironment () ;
211
252
}
212
253
213
254
/**
@@ -218,8 +259,8 @@ public ImmutableSet<String> getInheritedEnv() {
218
259
*/
219
260
public void resolve (Map <String , String > result , Map <String , String > clientEnv ) {
220
261
checkNotNull (clientEnv );
221
- result .putAll (fixedEnv . toMap ());
222
- for (String var : inheritedEnv ) {
262
+ result .putAll (vars . getFixedEnvironment ());
263
+ for (String var : vars . getInheritedEnvironment () ) {
223
264
String value = clientEnv .get (var );
224
265
if (value != null ) {
225
266
result .put (var , value );
@@ -228,7 +269,7 @@ public void resolve(Map<String, String> result, Map<String, String> clientEnv) {
228
269
}
229
270
230
271
public void addTo (Fingerprint f ) {
231
- f .addStringMap (fixedEnv . toMap ());
232
- f .addStrings (inheritedEnv );
272
+ f .addStringMap (vars . getFixedEnvironment ());
273
+ f .addStrings (vars . getInheritedEnvironment () );
233
274
}
234
275
}
0 commit comments