@@ -736,7 +736,7 @@ impl GlobalContext {
736
736
Ok ( Some ( CV :: List ( cv_list, cv_def) ) )
737
737
}
738
738
Some ( cv) => {
739
- // This can't assume StringList or UnmergedStringList .
739
+ // This can't assume StringList.
740
740
// Return an error, which is the behavior of merging
741
741
// multiple config.toml files with the same scenario.
742
742
bail ! (
@@ -910,21 +910,9 @@ impl GlobalContext {
910
910
}
911
911
912
912
/// Helper for `StringList` type to get something that is a string or list.
913
- fn get_list_or_string (
914
- & self ,
915
- key : & ConfigKey ,
916
- merge : bool ,
917
- ) -> CargoResult < Vec < ( String , Definition ) > > {
913
+ fn get_list_or_string ( & self , key : & ConfigKey ) -> CargoResult < Vec < ( String , Definition ) > > {
918
914
let mut res = Vec :: new ( ) ;
919
915
920
- if !merge {
921
- self . get_env_list ( key, & mut res) ?;
922
-
923
- if !res. is_empty ( ) {
924
- return Ok ( res) ;
925
- }
926
- }
927
-
928
916
match self . get_cv ( key) ? {
929
917
Some ( CV :: List ( val, _def) ) => res. extend ( val) ,
930
918
Some ( CV :: String ( val, def) ) => {
@@ -943,6 +931,7 @@ impl GlobalContext {
943
931
}
944
932
945
933
/// Internal method for getting an environment variable as a list.
934
+ /// If the key is a non-mergable list and a value is found in the environment, existing values are cleared.
946
935
fn get_env_list (
947
936
& self ,
948
937
key : & ConfigKey ,
@@ -953,6 +942,10 @@ impl GlobalContext {
953
942
return Ok ( ( ) ) ;
954
943
} ;
955
944
945
+ if is_nonmergable_list ( & key) {
946
+ output. clear ( ) ;
947
+ }
948
+
956
949
let def = Definition :: Environment ( key. as_env_key ( ) . to_string ( ) ) ;
957
950
if self . cli_unstable ( ) . advanced_env && env_val. starts_with ( '[' ) && env_val. ends_with ( ']' ) {
958
951
// Parse an environment string as a TOML array.
@@ -2227,13 +2220,31 @@ impl ConfigValue {
2227
2220
///
2228
2221
/// Container and non-container types cannot be mixed.
2229
2222
fn merge ( & mut self , from : ConfigValue , force : bool ) -> CargoResult < ( ) > {
2223
+ self . merge_helper ( from, force, & mut ConfigKey :: new ( ) )
2224
+ }
2225
+
2226
+ fn merge_helper (
2227
+ & mut self ,
2228
+ from : ConfigValue ,
2229
+ force : bool ,
2230
+ parts : & mut ConfigKey ,
2231
+ ) -> CargoResult < ( ) > {
2232
+ let is_higher_priority = from. definition ( ) . is_higher_priority ( self . definition ( ) ) ;
2230
2233
match ( self , from) {
2231
2234
( & mut CV :: List ( ref mut old, _) , CV :: List ( ref mut new, _) ) => {
2232
- if force {
2233
- old. append ( new) ;
2235
+ if is_nonmergable_list ( & parts) {
2236
+ // Use whichever list is higher priority.
2237
+ if force || is_higher_priority {
2238
+ mem:: swap ( new, old) ;
2239
+ }
2234
2240
} else {
2235
- new. append ( old) ;
2236
- mem:: swap ( new, old) ;
2241
+ // Merge the lists together.
2242
+ if force {
2243
+ old. append ( new) ;
2244
+ } else {
2245
+ new. append ( old) ;
2246
+ mem:: swap ( new, old) ;
2247
+ }
2237
2248
}
2238
2249
old. sort_by ( |a, b| a. 1 . cmp ( & b. 1 ) ) ;
2239
2250
}
@@ -2243,7 +2254,8 @@ impl ConfigValue {
2243
2254
Occupied ( mut entry) => {
2244
2255
let new_def = value. definition ( ) . clone ( ) ;
2245
2256
let entry = entry. get_mut ( ) ;
2246
- entry. merge ( value, force) . with_context ( || {
2257
+ parts. push ( & key) ;
2258
+ entry. merge_helper ( value, force, parts) . with_context ( || {
2247
2259
format ! (
2248
2260
"failed to merge key `{}` between \
2249
2261
{} and {}",
@@ -2273,7 +2285,7 @@ impl ConfigValue {
2273
2285
) ) ;
2274
2286
}
2275
2287
( old, mut new) => {
2276
- if force || new . definition ( ) . is_higher_priority ( old . definition ( ) ) {
2288
+ if force || is_higher_priority {
2277
2289
mem:: swap ( old, & mut new) ;
2278
2290
}
2279
2291
}
@@ -2348,6 +2360,17 @@ impl ConfigValue {
2348
2360
}
2349
2361
}
2350
2362
2363
+ /// List of which configuration lists cannot be merged.
2364
+ /// Instead of merging, these the higher priority list replaces the lower priority list.
2365
+ fn is_nonmergable_list ( key : & ConfigKey ) -> bool {
2366
+ key. matches ( "registry.credential-provider" )
2367
+ || key. matches ( "registries.*.credential-provider" )
2368
+ || key. matches ( "target.*.runner" )
2369
+ || key. matches ( "host.runner" )
2370
+ || key. matches ( "credential-alias.*" )
2371
+ || key. matches ( "doc.browser" )
2372
+ }
2373
+
2351
2374
pub fn homedir ( cwd : & Path ) -> Option < PathBuf > {
2352
2375
:: home:: cargo_home_with_cwd ( cwd) . ok ( )
2353
2376
}
@@ -2916,14 +2939,6 @@ impl StringList {
2916
2939
}
2917
2940
}
2918
2941
2919
- /// Alternative to [`StringList`] that follows precedence rules, rather than merging config values with environment values,
2920
- ///
2921
- /// e.g. a string list found in the environment will be used instead of one in a config file.
2922
- ///
2923
- /// This is currently only used by [`PathAndArgs`]
2924
- #[ derive( Debug , Deserialize ) ]
2925
- pub struct UnmergedStringList ( Vec < String > ) ;
2926
-
2927
2942
#[ macro_export]
2928
2943
macro_rules! __shell_print {
2929
2944
( $config: expr, $which: ident, $newline: literal, $( $arg: tt) * ) => ( {
0 commit comments