@@ -736,7 +736,7 @@ impl GlobalContext {
736736 Ok ( Some ( CV :: List ( cv_list, cv_def) ) )
737737 }
738738 Some ( cv) => {
739- // This can't assume StringList or UnmergedStringList .
739+ // This can't assume StringList.
740740 // Return an error, which is the behavior of merging
741741 // multiple config.toml files with the same scenario.
742742 bail ! (
@@ -910,21 +910,9 @@ impl GlobalContext {
910910 }
911911
912912 /// 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 ) > > {
918914 let mut res = Vec :: new ( ) ;
919915
920- if !merge {
921- self . get_env_list ( key, & mut res) ?;
922-
923- if !res. is_empty ( ) {
924- return Ok ( res) ;
925- }
926- }
927-
928916 match self . get_cv ( key) ? {
929917 Some ( CV :: List ( val, _def) ) => res. extend ( val) ,
930918 Some ( CV :: String ( val, def) ) => {
@@ -943,6 +931,7 @@ impl GlobalContext {
943931 }
944932
945933 /// 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.
946935 fn get_env_list (
947936 & self ,
948937 key : & ConfigKey ,
@@ -953,6 +942,10 @@ impl GlobalContext {
953942 return Ok ( ( ) ) ;
954943 } ;
955944
945+ if is_nonmergable_list ( & key) {
946+ output. clear ( ) ;
947+ }
948+
956949 let def = Definition :: Environment ( key. as_env_key ( ) . to_string ( ) ) ;
957950 if self . cli_unstable ( ) . advanced_env && env_val. starts_with ( '[' ) && env_val. ends_with ( ']' ) {
958951 // Parse an environment string as a TOML array.
@@ -2227,13 +2220,31 @@ impl ConfigValue {
22272220 ///
22282221 /// Container and non-container types cannot be mixed.
22292222 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 ( ) ) ;
22302233 match ( self , from) {
22312234 ( & 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+ }
22342240 } 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+ }
22372248 }
22382249 old. sort_by ( |a, b| a. 1 . cmp ( & b. 1 ) ) ;
22392250 }
@@ -2243,7 +2254,8 @@ impl ConfigValue {
22432254 Occupied ( mut entry) => {
22442255 let new_def = value. definition ( ) . clone ( ) ;
22452256 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 ( || {
22472259 format ! (
22482260 "failed to merge key `{}` between \
22492261 {} and {}",
@@ -2273,7 +2285,7 @@ impl ConfigValue {
22732285 ) ) ;
22742286 }
22752287 ( old, mut new) => {
2276- if force || new . definition ( ) . is_higher_priority ( old . definition ( ) ) {
2288+ if force || is_higher_priority {
22772289 mem:: swap ( old, & mut new) ;
22782290 }
22792291 }
@@ -2348,6 +2360,17 @@ impl ConfigValue {
23482360 }
23492361}
23502362
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+
23512374pub fn homedir ( cwd : & Path ) -> Option < PathBuf > {
23522375 :: home:: cargo_home_with_cwd ( cwd) . ok ( )
23532376}
@@ -2916,14 +2939,6 @@ impl StringList {
29162939 }
29172940}
29182941
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-
29272942#[ macro_export]
29282943macro_rules! __shell_print {
29292944 ( $config: expr, $which: ident, $newline: literal, $( $arg: tt) * ) => ( {
0 commit comments