1
1
use crate :: { CrossToml , Result , Target , TargetList } ;
2
2
3
- use crate :: errors:: * ;
4
3
use std:: collections:: HashMap ;
5
4
use std:: env;
5
+ use std:: str:: FromStr ;
6
6
7
7
#[ derive( Debug ) ]
8
8
struct Environment ( & ' static str , Option < HashMap < & ' static str , & ' static str > > ) ;
@@ -23,6 +23,19 @@ impl Environment {
23
23
. or_else ( || env:: var ( name) . ok ( ) )
24
24
}
25
25
26
+ fn get_values_for < T > (
27
+ & self ,
28
+ var : & str ,
29
+ target : & Target ,
30
+ convert : impl Fn ( & str ) -> T ,
31
+ ) -> ( Option < T > , Option < T > ) {
32
+ let target_values = self . get_target_var ( target, var) . map ( |ref s| convert ( s) ) ;
33
+
34
+ let build_values = self . get_build_var ( var) . map ( |ref s| convert ( s) ) ;
35
+
36
+ ( build_values, target_values)
37
+ }
38
+
26
39
fn target_path ( target : & Target , key : & str ) -> String {
27
40
format ! ( "TARGET_{target}_{key}" )
28
41
}
@@ -39,27 +52,8 @@ impl Environment {
39
52
self . get_var ( & self . build_var_name ( & Self :: target_path ( target, key) ) )
40
53
}
41
54
42
- fn xargo ( & self , target : & Target ) -> Result < ( Option < bool > , Option < bool > ) > {
43
- let ( build_xargo, target_xargo) = (
44
- self . get_build_var ( "XARGO" ) ,
45
- self . get_target_var ( target, "XARGO" ) ,
46
- ) ;
47
- let build_env = if let Some ( value) = build_xargo {
48
- Some ( value. parse :: < bool > ( ) . wrap_err_with ( || {
49
- format ! ( "error parsing {value} from XARGO environment variable" )
50
- } ) ?)
51
- } else {
52
- None
53
- } ;
54
- let target_env = if let Some ( value) = target_xargo {
55
- Some ( value. parse :: < bool > ( ) . wrap_err_with ( || {
56
- format ! ( "error parsing {} from XARGO environment variable" , value)
57
- } ) ?)
58
- } else {
59
- None
60
- } ;
61
-
62
- Ok ( ( build_env, target_env) )
55
+ fn xargo ( & self , target : & Target ) -> ( Option < bool > , Option < bool > ) {
56
+ self . get_values_for ( "XARGO" , target, bool_from_envvar)
63
57
}
64
58
65
59
fn image ( & self , target : & Target ) -> Option < String > {
@@ -71,38 +65,32 @@ impl Environment {
71
65
}
72
66
73
67
fn passthrough ( & self , target : & Target ) -> ( Option < Vec < String > > , Option < Vec < String > > ) {
74
- self . get_values_for ( "ENV_PASSTHROUGH" , target)
68
+ self . get_values_for ( "ENV_PASSTHROUGH" , target, split_to_cloned_by_ws )
75
69
}
76
70
77
71
fn volumes ( & self , target : & Target ) -> ( Option < Vec < String > > , Option < Vec < String > > ) {
78
- self . get_values_for ( "ENV_VOLUMES" , target)
72
+ self . get_values_for ( "ENV_VOLUMES" , target, split_to_cloned_by_ws )
79
73
}
80
74
81
75
fn target ( & self ) -> Option < String > {
82
76
self . get_build_var ( "TARGET" )
83
77
}
84
-
85
- fn get_values_for (
86
- & self ,
87
- var : & str ,
88
- target : & Target ,
89
- ) -> ( Option < Vec < String > > , Option < Vec < String > > ) {
90
- let target_values = self
91
- . get_target_var ( target, var)
92
- . map ( |ref s| split_to_cloned_by_ws ( s) ) ;
93
-
94
- let build_values = self
95
- . get_build_var ( var)
96
- . map ( |ref s| split_to_cloned_by_ws ( s) ) ;
97
-
98
- ( build_values, target_values)
99
- }
100
78
}
101
79
102
80
fn split_to_cloned_by_ws ( string : & str ) -> Vec < String > {
103
81
string. split_whitespace ( ) . map ( String :: from) . collect ( )
104
82
}
105
83
84
+ pub fn bool_from_envvar ( envvar : & str ) -> bool {
85
+ if let Ok ( value) = bool:: from_str ( envvar) {
86
+ value
87
+ } else if let Ok ( value) = i32:: from_str ( envvar) {
88
+ value != 0
89
+ } else {
90
+ !envvar. is_empty ( )
91
+ }
92
+ }
93
+
106
94
#[ derive( Debug ) ]
107
95
pub struct Config {
108
96
toml : Option < CrossToml > ,
@@ -136,72 +124,97 @@ impl Config {
136
124
}
137
125
}
138
126
139
- # [ cfg ( test ) ]
140
- fn new_with ( toml : Option < CrossToml > , env : Environment ) -> Self {
141
- Config { toml , env }
142
- }
143
-
144
- pub fn xargo ( & self , target : & Target ) -> Result < Option < bool > > {
145
- let ( build_xargo , target_xargo ) = self . env . xargo ( target) ? ;
146
- let ( toml_build_xargo , toml_target_xargo ) = if let Some ( ref toml) = self . toml {
147
- toml . xargo ( target)
127
+ fn bool_from_config (
128
+ & self ,
129
+ target : & Target ,
130
+ env : impl Fn ( & Environment , & Target ) -> ( Option < bool > , Option < bool > ) ,
131
+ config : impl Fn ( & CrossToml , & Target ) -> ( Option < bool > , Option < bool > ) ,
132
+ ) -> Option < bool > {
133
+ let ( env_build , env_target ) = env ( & self . env , target) ;
134
+ let ( toml_build , toml_target ) = if let Some ( ref toml) = self . toml {
135
+ config ( toml , target)
148
136
} else {
149
137
( None , None )
150
138
} ;
151
139
152
- match ( build_xargo , toml_build_xargo ) {
153
- ( xargo @ Some ( _ ) , _) => return Ok ( xargo ) ,
154
- ( None , xargo @ Some ( _ ) ) => return Ok ( xargo ) ,
140
+ match ( env_build , toml_build ) {
141
+ ( Some ( value ) , _) => return Some ( value ) ,
142
+ ( None , Some ( value ) ) => return Some ( value ) ,
155
143
( None , None ) => { }
156
144
} ;
157
145
158
- match ( target_xargo , toml_target_xargo ) {
159
- ( xargo @ Some ( _ ) , _) => return Ok ( xargo ) ,
160
- ( None , xargo @ Some ( _ ) ) => return Ok ( xargo ) ,
146
+ match ( env_target , toml_target ) {
147
+ ( Some ( value ) , _) => return Some ( value ) ,
148
+ ( None , Some ( value ) ) => return Some ( value ) ,
161
149
( None , None ) => { }
162
150
} ;
163
- Ok ( None )
164
- }
165
151
166
- pub fn image ( & self , target : & Target ) -> Result < Option < String > > {
167
- let env_value = self . env . image ( target) ;
168
- if let Some ( env_value) = env_value {
169
- return Ok ( Some ( env_value) ) ;
170
- }
171
- self . toml . as_ref ( ) . map_or ( Ok ( None ) , |t| Ok ( t. image ( target) ) )
152
+ None
172
153
}
173
154
174
- pub fn runner ( & self , target : & Target ) -> Result < Option < String > > {
175
- let env_value = self . env . runner ( target) ;
155
+ fn string_from_config (
156
+ & self ,
157
+ target : & Target ,
158
+ env : impl Fn ( & Environment , & Target ) -> Option < String > ,
159
+ config : impl Fn ( & CrossToml , & Target ) -> Option < String > ,
160
+ ) -> Result < Option < String > > {
161
+ let env_value = env ( & self . env , target) ;
176
162
if let Some ( env_value) = env_value {
177
163
return Ok ( Some ( env_value) ) ;
178
164
}
179
165
self . toml
180
166
. as_ref ( )
181
- . map_or ( Ok ( None ) , |t| Ok ( t . runner ( target) ) )
167
+ . map_or ( Ok ( None ) , |t| Ok ( config ( t , target) ) )
182
168
}
183
169
184
- pub fn env_passthrough ( & self , target : & Target ) -> Result < Vec < String > > {
185
- let ( env_build, env_target) = self . env . passthrough ( target) ;
186
-
187
- let toml_getter = || self . toml . as_ref ( ) . map ( |t| t. env_passthrough_build ( ) ) ;
188
- let mut collected = Self :: sum_of_env_toml_values ( toml_getter, env_build) ?;
170
+ fn vec_from_config (
171
+ & self ,
172
+ target : & Target ,
173
+ env : impl Fn ( & Environment , & Target ) -> ( Option < Vec < String > > , Option < Vec < String > > ) ,
174
+ config_build : impl for < ' a > Fn ( & ' a CrossToml ) -> & ' a [ String ] ,
175
+ config_target : impl for < ' a > Fn ( & ' a CrossToml , & Target ) -> & ' a [ String ] ,
176
+ ) -> Result < Vec < String > > {
177
+ let ( env_build, env_target) = env ( & self . env , target) ;
189
178
190
- let toml_getter = || self . toml . as_ref ( ) . map ( |t| t . env_passthrough_target ( target ) ) ;
191
- collected. extend ( Self :: sum_of_env_toml_values ( toml_getter , env_target ) ?) ;
179
+ let mut collected = self . sum_of_env_toml_values ( env_build , config_build ) ? ;
180
+ collected. extend ( self . sum_of_env_toml_values ( env_target , |t| config_target ( t , target ) ) ?) ;
192
181
193
182
Ok ( collected)
194
183
}
195
184
196
- pub fn env_volumes ( & self , target : & Target ) -> Result < Vec < String > > {
197
- let ( env_build , env_target ) = self . env . volumes ( target ) ;
198
- let toml_getter = || self . toml . as_ref ( ) . map ( |t| t . env_volumes_build ( ) ) ;
199
- let mut collected = Self :: sum_of_env_toml_values ( toml_getter , env_build ) ? ;
185
+ # [ cfg ( test ) ]
186
+ fn new_with ( toml : Option < CrossToml > , env : Environment ) -> Self {
187
+ Config { toml, env }
188
+ }
200
189
201
- let toml_getter = || self . toml . as_ref ( ) . map ( |t| t. env_volumes_target ( target) ) ;
202
- collected. extend ( Self :: sum_of_env_toml_values ( toml_getter, env_target) ?) ;
190
+ pub fn xargo ( & self , target : & Target ) -> Option < bool > {
191
+ self . bool_from_config ( target, Environment :: xargo, CrossToml :: xargo)
192
+ }
203
193
204
- Ok ( collected)
194
+ pub fn image ( & self , target : & Target ) -> Result < Option < String > > {
195
+ self . string_from_config ( target, Environment :: image, CrossToml :: image)
196
+ }
197
+
198
+ pub fn runner ( & self , target : & Target ) -> Result < Option < String > > {
199
+ self . string_from_config ( target, Environment :: runner, CrossToml :: runner)
200
+ }
201
+
202
+ pub fn env_passthrough ( & self , target : & Target ) -> Result < Vec < String > > {
203
+ self . vec_from_config (
204
+ target,
205
+ Environment :: passthrough,
206
+ CrossToml :: env_passthrough_build,
207
+ CrossToml :: env_passthrough_target,
208
+ )
209
+ }
210
+
211
+ pub fn env_volumes ( & self , target : & Target ) -> Result < Vec < String > > {
212
+ self . vec_from_config (
213
+ target,
214
+ Environment :: volumes,
215
+ CrossToml :: env_volumes_build,
216
+ CrossToml :: env_volumes_target,
217
+ )
205
218
}
206
219
207
220
pub fn target ( & self , target_list : & TargetList ) -> Option < Target > {
@@ -213,15 +226,16 @@ impl Config {
213
226
. and_then ( |t| t. default_target ( target_list) )
214
227
}
215
228
216
- fn sum_of_env_toml_values (
217
- toml_getter : impl FnOnce ( ) -> Option < Vec < String > > ,
229
+ fn sum_of_env_toml_values < ' a > (
230
+ & ' a self ,
218
231
env_values : Option < Vec < String > > ,
232
+ toml_getter : impl FnOnce ( & ' a CrossToml ) -> & ' a [ String ] ,
219
233
) -> Result < Vec < String > > {
220
234
let mut collect = vec ! [ ] ;
221
235
if let Some ( mut vars) = env_values {
222
236
collect. append ( & mut vars) ;
223
- } else if let Some ( toml_values) = toml_getter ( ) {
224
- collect. extend ( toml_values. into_iter ( ) ) ;
237
+ } else if let Some ( toml_values) = self . toml . as_ref ( ) . map ( toml_getter ) {
238
+ collect. extend ( toml_values. iter ( ) . cloned ( ) ) ;
225
239
}
226
240
227
241
Ok ( collect)
@@ -231,6 +245,7 @@ impl Config {
231
245
#[ cfg( test) ]
232
246
mod tests {
233
247
use super :: * ;
248
+ use crate :: errors:: * ;
234
249
use crate :: { Target , TargetList } ;
235
250
236
251
fn target_list ( ) -> TargetList {
@@ -257,24 +272,17 @@ mod tests {
257
272
map. insert ( "CROSS_BUILD_XARGO" , "tru" ) ;
258
273
259
274
let env = Environment :: new ( Some ( map) ) ;
260
-
261
- let res = env. xargo ( & target ( ) ) ;
262
- if res. is_ok ( ) {
263
- panic ! ( "invalid bool string parsing should fail" ) ;
264
- }
275
+ assert_eq ! ( env. xargo( & target( ) ) , ( Some ( true ) , None ) ) ;
265
276
}
266
277
267
278
#[ test]
268
- pub fn build_and_target_set_returns_tuple ( ) -> Result < ( ) > {
279
+ pub fn build_and_target_set_returns_tuple ( ) {
269
280
let mut map = std:: collections:: HashMap :: new ( ) ;
270
281
map. insert ( "CROSS_BUILD_XARGO" , "true" ) ;
271
282
map. insert ( "CROSS_TARGET_AARCH64_UNKNOWN_LINUX_GNU_XARGO" , "false" ) ;
272
283
273
284
let env = Environment :: new ( Some ( map) ) ;
274
-
275
- assert_eq ! ( env. xargo( & target( ) ) ?, ( Some ( true ) , Some ( false ) ) ) ;
276
-
277
- Ok ( ( ) )
285
+ assert_eq ! ( env. xargo( & target( ) ) , ( Some ( true ) , Some ( false ) ) ) ;
278
286
}
279
287
280
288
#[ test]
@@ -329,7 +337,7 @@ mod tests {
329
337
330
338
let env = Environment :: new ( Some ( map) ) ;
331
339
let config = Config :: new_with ( Some ( toml ( TOML_BUILD_XARGO_FALSE ) ?) , env) ;
332
- assert ! ( matches!( config. xargo( & target( ) ) , Ok ( Some ( true ) ) ) ) ;
340
+ assert ! ( matches!( config. xargo( & target( ) ) , Some ( true ) ) ) ;
333
341
334
342
Ok ( ( ) )
335
343
}
@@ -341,7 +349,7 @@ mod tests {
341
349
let env = Environment :: new ( Some ( map) ) ;
342
350
343
351
let config = Config :: new_with ( Some ( toml ( TOML_TARGET_XARGO_FALSE ) ?) , env) ;
344
- assert ! ( matches!( config. xargo( & target( ) ) , Ok ( Some ( true ) ) ) ) ;
352
+ assert ! ( matches!( config. xargo( & target( ) ) , Some ( true ) ) ) ;
345
353
346
354
Ok ( ( ) )
347
355
}
@@ -352,7 +360,7 @@ mod tests {
352
360
map. insert ( "CROSS_TARGET_AARCH64_UNKNOWN_LINUX_GNU_XARGO" , "true" ) ;
353
361
let env = Environment :: new ( Some ( map) ) ;
354
362
let config = Config :: new_with ( Some ( toml ( TOML_BUILD_XARGO_FALSE ) ?) , env) ;
355
- assert ! ( matches!( config. xargo( & target( ) ) , Ok ( Some ( false ) ) ) ) ;
363
+ assert ! ( matches!( config. xargo( & target( ) ) , Some ( false ) ) ) ;
356
364
357
365
Ok ( ( ) )
358
366
}
0 commit comments