@@ -190,28 +190,119 @@ fn resolve_file(path: &Path, dir: &Path) -> PathBuf {
190190}
191191
192192fn expand_vars ( string : & str ) -> String {
193- let mut buf = String :: new ( ) ;
193+ let mut result = String :: new ( ) ;
194+ let mut chars = string. chars ( ) . peekable ( ) ;
194195
195- let mut expanding = false ;
196- for segment in string. split ( '%' ) {
197- if expanding {
198- if let Ok ( replacement) = std:: env:: var ( segment) {
199- buf. push_str ( & replacement[ ..] ) ;
196+ while let Some ( ch) = chars. next ( ) {
197+ if ch == '$' {
198+ if let Some ( & next_ch) = chars. peek ( ) {
199+ if next_ch == '{' {
200+ // ${VAR} format
201+ chars. next ( ) ; // consume '{'
202+ let mut var_name = String :: new ( ) ;
203+ let mut found_close = false ;
204+
205+ while let Some ( var_ch) = chars. next ( ) {
206+ if var_ch == '}' {
207+ found_close = true ;
208+ break ;
209+ }
210+ var_name. push ( var_ch) ;
211+ }
212+
213+ if found_close && !var_name. is_empty ( ) {
214+ if let Ok ( value) = std:: env:: var ( & var_name) {
215+ result. push_str ( & value) ;
216+ } else {
217+ // If variable not found, panic
218+ panic ! ( "Environment variable '{}' not found" , var_name) ;
219+ }
220+ } else {
221+ // Malformed ${...}, keep as is
222+ result. push ( '$' ) ;
223+ result. push ( '{' ) ;
224+ result. push_str ( & var_name) ;
225+ if found_close {
226+ result. push ( '}' ) ;
227+ }
228+ }
229+ } else if next_ch. is_ascii_alphabetic ( ) || next_ch == '_' {
230+ // $VAR format (alphanumeric and underscore)
231+ let mut var_name = String :: new ( ) ;
232+
233+ while let Some ( & var_ch) = chars. peek ( ) {
234+ if var_ch. is_ascii_alphanumeric ( ) || var_ch == '_' {
235+ var_name. push ( chars. next ( ) . unwrap ( ) ) ;
236+ } else {
237+ break ;
238+ }
239+ }
240+
241+ if !var_name. is_empty ( ) {
242+ if let Ok ( value) = std:: env:: var ( & var_name) {
243+ result. push_str ( & value) ;
244+ } else {
245+ // If variable not found, panic
246+ panic ! ( "Environment variable '{}' not found" , var_name) ;
247+ }
248+ } else {
249+ result. push ( '$' ) ;
250+ }
251+ } else {
252+ // $ followed by something else, keep as is
253+ result. push ( '$' ) ;
254+ }
200255 } else {
201- println ! ( "cargo:rerun-if-env-changed={segment}" ) ;
202- buf. push ( '%' ) ;
203- buf. push_str ( segment) ;
204- buf. push ( '%' ) ;
256+ // $ at end of string
257+ result. push ( '$' ) ;
205258 }
206259 } else {
207- buf . push_str ( segment ) ;
260+ result . push ( ch ) ;
208261 }
209- expanding = !expanding;
210262 }
211- assert ! (
212- expanding,
213- "Uneven number of %s in path: {:?}, would mis-expand into: {:?}" ,
214- & string, & buf
215- ) ;
216- buf
263+
264+ result
265+ }
266+
267+ #[ cfg( test) ]
268+ mod tests {
269+ use super :: * ;
270+
271+ #[ test]
272+ fn test_expand_vars ( ) {
273+ // Test ${VAR} format
274+ unsafe { std:: env:: set_var ( "TEST_VAR" , "hello" ) } ;
275+ assert_eq ! ( expand_vars( "${TEST_VAR}" ) , "hello" ) ;
276+ assert_eq ! ( expand_vars( "prefix_${TEST_VAR}_suffix" ) , "prefix_hello_suffix" ) ;
277+
278+ // Test $VAR format
279+ assert_eq ! ( expand_vars( "$TEST_VAR" ) , "hello" ) ;
280+ // Note: In shell, $VAR_suffix would try to expand VAR_suffix, not VAR + _suffix
281+ // This is correct behavior - use ${VAR}_suffix for the latter
282+ assert_eq ! ( expand_vars( "prefix_${TEST_VAR}/suffix" ) , "prefix_hello/suffix" ) ;
283+
284+ // Test literal $ characters
285+ assert_eq ! ( expand_vars( "$" ) , "$" ) ;
286+ assert_eq ! ( expand_vars( "$$" ) , "$$" ) ;
287+ assert_eq ! ( expand_vars( "$123" ) , "$123" ) ;
288+
289+ // Test malformed syntax
290+ assert_eq ! ( expand_vars( "${" ) , "${" ) ;
291+ assert_eq ! ( expand_vars( "${unclosed" ) , "${unclosed" ) ;
292+
293+ // Clean up
294+ unsafe { std:: env:: remove_var ( "TEST_VAR" ) } ;
295+ }
296+
297+ #[ test]
298+ #[ should_panic( expected = "Environment variable 'NONEXISTENT' not found" ) ]
299+ fn test_expand_vars_panic_on_missing_var_braces ( ) {
300+ expand_vars ( "${NONEXISTENT}" ) ;
301+ }
302+
303+ #[ test]
304+ #[ should_panic( expected = "Environment variable 'NONEXISTENT' not found" ) ]
305+ fn test_expand_vars_panic_on_missing_var_dollar ( ) {
306+ expand_vars ( "$NONEXISTENT" ) ;
307+ }
217308}
0 commit comments