1
1
//! Cargo-like environment variables injection.
2
2
use base_db:: Env ;
3
+ use paths:: Utf8Path ;
3
4
use rustc_hash:: FxHashMap ;
4
5
use toolchain:: Tool ;
5
6
@@ -85,7 +86,7 @@ pub(crate) fn cargo_config_env(
85
86
// if successful we receive `env.key.value = "value" per entry
86
87
tracing:: debug!( "Discovering cargo config env by {:?}" , cargo_config) ;
87
88
utf8_stdout ( & mut cargo_config)
88
- . map ( parse_output_cargo_config_env)
89
+ . map ( |stdout| parse_output_cargo_config_env ( manifest , stdout ) )
89
90
. inspect ( |env| {
90
91
tracing:: debug!( "Discovered cargo config env: {:?}" , env) ;
91
92
} )
@@ -95,18 +96,38 @@ pub(crate) fn cargo_config_env(
95
96
. unwrap_or_default ( )
96
97
}
97
98
98
- fn parse_output_cargo_config_env ( stdout : String ) -> Env {
99
- stdout
100
- . lines ( )
101
- . filter_map ( |l| l. strip_prefix ( "env." ) )
102
- . filter_map ( |l| l. split_once ( " = " ) )
103
- . filter_map ( |( k, v) | {
104
- if k. contains ( '.' ) {
105
- k. strip_suffix ( ".value" ) . zip ( Some ( v) )
106
- } else {
107
- Some ( ( k, v) )
99
+ fn parse_output_cargo_config_env ( manifest : & ManifestPath , stdout : String ) -> Env {
100
+ let mut env = Env :: default ( ) ;
101
+ let mut relatives = vec ! [ ] ;
102
+ for ( key, val) in
103
+ stdout. lines ( ) . filter_map ( |l| l. strip_prefix ( "env." ) ) . filter_map ( |l| l. split_once ( " = " ) )
104
+ {
105
+ let val = val. trim_matches ( '"' ) . to_owned ( ) ;
106
+ if let Some ( ( key, modifier) ) = key. split_once ( '.' ) {
107
+ match modifier {
108
+ "relative" => relatives. push ( ( key, val) ) ,
109
+ "value" => _ = env. insert ( key, val) ,
110
+ _ => {
111
+ tracing:: warn!(
112
+ "Unknown modifier in cargo config env: {}, expected `relative` or `value`" ,
113
+ modifier
114
+ ) ;
115
+ continue ;
116
+ }
108
117
}
109
- } )
110
- . map ( |( key, value) | ( key. to_owned ( ) , value. trim_matches ( '"' ) . to_owned ( ) ) )
111
- . collect ( )
118
+ } else {
119
+ env. insert ( key, val) ;
120
+ }
121
+ }
122
+ // FIXME: The base here should be the parent of the `.cargo/config` file, not the manifest.
123
+ // But cargo does not provide this information.
124
+ let base = <_ as AsRef < Utf8Path > >:: as_ref ( manifest. parent ( ) ) ;
125
+ for ( key, val) in relatives {
126
+ if let Some ( val) = env. get ( & val) {
127
+ env. insert ( key, base. join ( val) . to_string ( ) ) ;
128
+ } else {
129
+ env. insert ( key, base. to_string ( ) ) ;
130
+ }
131
+ }
132
+ env
112
133
}
0 commit comments