@@ -121,6 +121,20 @@ macro_rules! get_value_typed {
121121 } ;
122122}
123123
124+ /// Indicates why a config value is being loaded.
125+ #[ derive( Clone , Copy , Debug ) ]
126+ enum WhyLoad {
127+ /// Loaded due to a request from the global cli arg `--config`
128+ ///
129+ /// Indirect configs loaded via [`config-include`] are also seen as from cli args,
130+ /// if the initial config is being loaded from cli.
131+ ///
132+ /// [`config-include`]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#config-include
133+ Cli ,
134+ /// Loaded due to config file discovery.
135+ FileDiscovery ,
136+ }
137+
124138/// Configuration information for cargo. This is not specific to a build, it is information
125139/// relating to cargo itself.
126140#[ derive( Debug ) ]
@@ -1005,12 +1019,15 @@ impl Config {
10051019 self . load_values_from ( & self . cwd )
10061020 }
10071021
1022+ /// Like [`load_values`](Config::load_values) but without merging config values.
1023+ ///
1024+ /// This is primarily crafted for `cargo config` command.
10081025 pub ( crate ) fn load_values_unmerged ( & self ) -> CargoResult < Vec < ConfigValue > > {
10091026 let mut result = Vec :: new ( ) ;
10101027 let mut seen = HashSet :: new ( ) ;
10111028 let home = self . home_path . clone ( ) . into_path_unlocked ( ) ;
10121029 self . walk_tree ( & self . cwd , & home, |path| {
1013- let mut cv = self . _load_file ( path, & mut seen, false ) ?;
1030+ let mut cv = self . _load_file ( path, & mut seen, false , WhyLoad :: FileDiscovery ) ?;
10141031 if self . cli_unstable ( ) . config_include {
10151032 self . load_unmerged_include ( & mut cv, & mut seen, & mut result) ?;
10161033 }
@@ -1021,6 +1038,9 @@ impl Config {
10211038 Ok ( result)
10221039 }
10231040
1041+ /// Like [`load_includes`](Config::load_includes) but without merging config values.
1042+ ///
1043+ /// This is primarily crafted for `cargo config` command.
10241044 fn load_unmerged_include (
10251045 & self ,
10261046 cv : & mut CV ,
@@ -1029,23 +1049,26 @@ impl Config {
10291049 ) -> CargoResult < ( ) > {
10301050 let includes = self . include_paths ( cv, false ) ?;
10311051 for ( path, abs_path, def) in includes {
1032- let mut cv = self . _load_file ( & abs_path, seen, false ) . with_context ( || {
1033- format ! ( "failed to load config include `{}` from `{}`" , path, def)
1034- } ) ?;
1052+ let mut cv = self
1053+ . _load_file ( & abs_path, seen, false , WhyLoad :: FileDiscovery )
1054+ . with_context ( || {
1055+ format ! ( "failed to load config include `{}` from `{}`" , path, def)
1056+ } ) ?;
10351057 self . load_unmerged_include ( & mut cv, seen, output) ?;
10361058 output. push ( cv) ;
10371059 }
10381060 Ok ( ( ) )
10391061 }
10401062
1063+ /// Start a config file discovery from a path and merges all config values found.
10411064 fn load_values_from ( & self , path : & Path ) -> CargoResult < HashMap < String , ConfigValue > > {
10421065 // This definition path is ignored, this is just a temporary container
10431066 // representing the entire file.
10441067 let mut cfg = CV :: Table ( HashMap :: new ( ) , Definition :: Path ( PathBuf :: from ( "." ) ) ) ;
10451068 let home = self . home_path . clone ( ) . into_path_unlocked ( ) ;
10461069
10471070 self . walk_tree ( path, & home, |path| {
1048- let value = self . load_file ( path, true ) ?;
1071+ let value = self . load_file ( path) ?;
10491072 cfg. merge ( value, false ) . with_context ( || {
10501073 format ! ( "failed to merge configuration at `{}`" , path. display( ) )
10511074 } ) ?;
@@ -1059,15 +1082,28 @@ impl Config {
10591082 }
10601083 }
10611084
1062- fn load_file ( & self , path : & Path , includes : bool ) -> CargoResult < ConfigValue > {
1063- self . _load_file ( path, & mut HashSet :: new ( ) , includes)
1085+ /// Loads a config value from a path.
1086+ ///
1087+ /// This is used during config file discovery.
1088+ fn load_file ( & self , path : & Path ) -> CargoResult < ConfigValue > {
1089+ self . _load_file ( path, & mut HashSet :: new ( ) , true , WhyLoad :: FileDiscovery )
10641090 }
10651091
1092+ /// Loads a config value from a path with options.
1093+ ///
1094+ /// This is actual implementation of loading a config value from a path.
1095+ ///
1096+ /// * `includes` determines whether to load configs from [`config-include`].
1097+ /// * `seen` is used to check for cyclic includes.
1098+ /// * `why_load` tells why a config is being loaded.
1099+ ///
1100+ /// [`config-include`]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#config-include
10661101 fn _load_file (
10671102 & self ,
10681103 path : & Path ,
10691104 seen : & mut HashSet < PathBuf > ,
10701105 includes : bool ,
1106+ why_load : WhyLoad ,
10711107 ) -> CargoResult < ConfigValue > {
10721108 if !seen. insert ( path. to_path_buf ( ) ) {
10731109 bail ! (
@@ -1080,15 +1116,18 @@ impl Config {
10801116 let toml = cargo_toml:: parse ( & contents, path, self ) . with_context ( || {
10811117 format ! ( "could not parse TOML configuration in `{}`" , path. display( ) )
10821118 } ) ?;
1083- let value =
1084- CV :: from_toml ( Definition :: Path ( path. to_path_buf ( ) ) , toml) . with_context ( || {
1085- format ! (
1086- "failed to load TOML configuration from `{}`" ,
1087- path. display( )
1088- )
1089- } ) ?;
1119+ let def = match why_load {
1120+ WhyLoad :: Cli => Definition :: Cli ( Some ( path. into ( ) ) ) ,
1121+ WhyLoad :: FileDiscovery => Definition :: Path ( path. into ( ) ) ,
1122+ } ;
1123+ let value = CV :: from_toml ( def, toml) . with_context ( || {
1124+ format ! (
1125+ "failed to load TOML configuration from `{}`" ,
1126+ path. display( )
1127+ )
1128+ } ) ?;
10901129 if includes {
1091- self . load_includes ( value, seen)
1130+ self . load_includes ( value, seen, why_load )
10921131 } else {
10931132 Ok ( value)
10941133 }
@@ -1098,8 +1137,14 @@ impl Config {
10981137 ///
10991138 /// Returns `value` with the given include files merged into it.
11001139 ///
1101- /// `seen` is used to check for cyclic includes.
1102- fn load_includes ( & self , mut value : CV , seen : & mut HashSet < PathBuf > ) -> CargoResult < CV > {
1140+ /// * `seen` is used to check for cyclic includes.
1141+ /// * `why_load` tells why a config is being loaded.
1142+ fn load_includes (
1143+ & self ,
1144+ mut value : CV ,
1145+ seen : & mut HashSet < PathBuf > ,
1146+ why_load : WhyLoad ,
1147+ ) -> CargoResult < CV > {
11031148 // Get the list of files to load.
11041149 let includes = self . include_paths ( & mut value, true ) ?;
11051150 // Check unstable.
@@ -1109,7 +1154,7 @@ impl Config {
11091154 // Accumulate all values here.
11101155 let mut root = CV :: Table ( HashMap :: new ( ) , value. definition ( ) . clone ( ) ) ;
11111156 for ( path, abs_path, def) in includes {
1112- self . _load_file ( & abs_path, seen, true )
1157+ self . _load_file ( & abs_path, seen, true , why_load )
11131158 . and_then ( |include| root. merge ( include, true ) )
11141159 . with_context ( || {
11151160 format ! ( "failed to load config include `{}` from `{}`" , path, def)
@@ -1127,8 +1172,8 @@ impl Config {
11271172 ) -> CargoResult < Vec < ( String , PathBuf , Definition ) > > {
11281173 let abs = |path : & str , def : & Definition | -> ( String , PathBuf , Definition ) {
11291174 let abs_path = match def {
1130- Definition :: Path ( p) => p. parent ( ) . unwrap ( ) . join ( & path) ,
1131- Definition :: Environment ( _) | Definition :: Cli => self . cwd ( ) . join ( & path) ,
1175+ Definition :: Path ( p) | Definition :: Cli ( Some ( p ) ) => p. parent ( ) . unwrap ( ) . join ( & path) ,
1176+ Definition :: Environment ( _) | Definition :: Cli ( None ) => self . cwd ( ) . join ( & path) ,
11321177 } ;
11331178 ( path. to_string ( ) , abs_path, def. clone ( ) )
11341179 } ;
@@ -1162,7 +1207,7 @@ impl Config {
11621207
11631208 /// Parses the CLI config args and returns them as a table.
11641209 pub ( crate ) fn cli_args_as_table ( & self ) -> CargoResult < ConfigValue > {
1165- let mut loaded_args = CV :: Table ( HashMap :: new ( ) , Definition :: Cli ) ;
1210+ let mut loaded_args = CV :: Table ( HashMap :: new ( ) , Definition :: Cli ( None ) ) ;
11661211 let cli_args = match & self . cli_config {
11671212 Some ( cli_args) => cli_args,
11681213 None => return Ok ( loaded_args) ,
@@ -1178,7 +1223,7 @@ impl Config {
11781223 anyhow:: format_err!( "config path {:?} is not utf-8" , arg_as_path)
11791224 } ) ?
11801225 . to_string ( ) ;
1181- self . _load_file ( & self . cwd ( ) . join ( & str_path) , & mut seen, true )
1226+ self . _load_file ( & self . cwd ( ) . join ( & str_path) , & mut seen, true , WhyLoad :: Cli )
11821227 . with_context ( || format ! ( "failed to load config from `{}`" , str_path) ) ?
11831228 } else {
11841229 // We only want to allow "dotted key" (see https://toml.io/en/v1.0.0#keys)
@@ -1273,11 +1318,11 @@ impl Config {
12731318 ) ;
12741319 }
12751320
1276- CV :: from_toml ( Definition :: Cli , toml_v)
1321+ CV :: from_toml ( Definition :: Cli ( None ) , toml_v)
12771322 . with_context ( || format ! ( "failed to convert --config argument `{arg}`" ) ) ?
12781323 } ;
12791324 let tmp_table = self
1280- . load_includes ( tmp_table, & mut HashSet :: new ( ) )
1325+ . load_includes ( tmp_table, & mut HashSet :: new ( ) , WhyLoad :: Cli )
12811326 . with_context ( || "failed to load --config include" . to_string ( ) ) ?;
12821327 loaded_args
12831328 . merge ( tmp_table, true )
@@ -1431,7 +1476,7 @@ impl Config {
14311476 None => return Ok ( ( ) ) ,
14321477 } ;
14331478
1434- let mut value = self . load_file ( & credentials, true ) ?;
1479+ let mut value = self . load_file ( & credentials) ?;
14351480 // Backwards compatibility for old `.cargo/credentials` layout.
14361481 {
14371482 let ( value_map, def) = match value {
0 commit comments