@@ -1257,11 +1257,15 @@ impl GlobalContext {
12571257 output : & mut Vec < CV > ,
12581258 ) -> CargoResult < ( ) > {
12591259 let includes = self . include_paths ( cv, false ) ?;
1260- for ( path , abs_path , def ) in includes {
1260+ for include in includes {
12611261 let mut cv = self
1262- . _load_file ( & abs_path, seen, false , WhyLoad :: FileDiscovery )
1262+ . _load_file ( & include . abs_path ( self ) , seen, false , WhyLoad :: FileDiscovery )
12631263 . with_context ( || {
1264- format ! ( "failed to load config include `{}` from `{}`" , path, def)
1264+ format ! (
1265+ "failed to load config include `{}` from `{}`" ,
1266+ include. path. display( ) ,
1267+ include. def
1268+ )
12651269 } ) ?;
12661270 self . load_unmerged_include ( & mut cv, seen, output) ?;
12671271 output. push ( cv) ;
@@ -1364,32 +1368,23 @@ impl GlobalContext {
13641368 }
13651369 // Accumulate all values here.
13661370 let mut root = CV :: Table ( HashMap :: new ( ) , value. definition ( ) . clone ( ) ) ;
1367- for ( path , abs_path , def ) in includes {
1368- self . _load_file ( & abs_path, seen, true , why_load)
1371+ for include in includes {
1372+ self . _load_file ( & include . abs_path ( self ) , seen, true , why_load)
13691373 . and_then ( |include| root. merge ( include, true ) )
13701374 . with_context ( || {
1371- format ! ( "failed to load config include `{}` from `{}`" , path, def)
1375+ format ! (
1376+ "failed to load config include `{}` from `{}`" ,
1377+ include. path. display( ) ,
1378+ include. def
1379+ )
13721380 } ) ?;
13731381 }
13741382 root. merge ( value, true ) ?;
13751383 Ok ( root)
13761384 }
13771385
13781386 /// Converts the `include` config value to a list of absolute paths.
1379- fn include_paths (
1380- & self ,
1381- cv : & mut CV ,
1382- remove : bool ,
1383- ) -> CargoResult < Vec < ( String , PathBuf , Definition ) > > {
1384- let abs = |path, def| -> ( String , PathBuf , Definition ) {
1385- let abs_path = match & def {
1386- Definition :: Path ( p) | Definition :: Cli ( Some ( p) ) => p. parent ( ) . unwrap ( ) . join ( & path) ,
1387- Definition :: Environment ( _) | Definition :: Cli ( None ) | Definition :: BuiltIn => {
1388- self . cwd ( ) . join ( & path)
1389- }
1390- } ;
1391- ( path, abs_path, def)
1392- } ;
1387+ fn include_paths ( & self , cv : & mut CV , remove : bool ) -> CargoResult < Vec < ConfigInclude > > {
13931388 let CV :: Table ( table, _def) = cv else {
13941389 unreachable ! ( )
13951390 } ;
@@ -1399,13 +1394,11 @@ impl GlobalContext {
13991394 table. get ( "include" ) . map ( Cow :: Borrowed )
14001395 } ;
14011396 let includes = match include. map ( |c| c. into_owned ( ) ) {
1402- Some ( CV :: String ( s, def) ) => {
1403- vec ! [ abs( s, def) ]
1404- }
1397+ Some ( CV :: String ( s, def) ) => vec ! [ ConfigInclude :: new( s, def) ] ,
14051398 Some ( CV :: List ( list, _def) ) => list
14061399 . into_iter ( )
14071400 . map ( |cv| match cv {
1408- CV :: String ( s, def) => Ok ( abs ( s, def) ) ,
1401+ CV :: String ( s, def) => Ok ( ConfigInclude :: new ( s, def) ) ,
14091402 other => bail ! (
14101403 "`include` expected a string or list of strings, but found {} in list" ,
14111404 other. desc( )
@@ -1422,11 +1415,13 @@ impl GlobalContext {
14221415 }
14231416 } ;
14241417
1425- for ( path , abs_path , def ) in & includes {
1426- if abs_path . extension ( ) != Some ( OsStr :: new ( "toml" ) ) {
1418+ for include in & includes {
1419+ if include . path . extension ( ) != Some ( OsStr :: new ( "toml" ) ) {
14271420 bail ! (
14281421 "expected a config include path ending with `.toml`, \
1429- but found `{path}` from `{def}`",
1422+ but found `{}` from `{}`",
1423+ include. path. display( ) ,
1424+ include. def,
14301425 )
14311426 }
14321427 }
@@ -2476,6 +2471,39 @@ pub fn save_credentials(
24762471 }
24772472}
24782473
2474+ struct ConfigInclude {
2475+ /// Path to a config-include configuration file.
2476+ /// Could be either relative or absolute.
2477+ path : PathBuf ,
2478+ def : Definition ,
2479+ }
2480+
2481+ impl ConfigInclude {
2482+ fn new ( p : impl Into < PathBuf > , def : Definition ) -> Self {
2483+ Self {
2484+ path : p. into ( ) ,
2485+ def,
2486+ }
2487+ }
2488+
2489+ /// Gets the absolute path of the config-include config file.
2490+ ///
2491+ /// For file based include,
2492+ /// it is relative to parent directory of the config file includes it.
2493+ /// For example, if `.cargo/config.toml has a `include = "foo.toml"`,
2494+ /// Cargo will load `.cargo/foo.toml`.
2495+ ///
2496+ /// For CLI based include (e.g., `--config 'include = "foo.toml"'`),
2497+ /// it is relative to the current working directory.
2498+ fn abs_path ( & self , gctx : & GlobalContext ) -> PathBuf {
2499+ match & self . def {
2500+ Definition :: Path ( p) | Definition :: Cli ( Some ( p) ) => p. parent ( ) . unwrap ( ) ,
2501+ Definition :: Environment ( _) | Definition :: Cli ( None ) | Definition :: BuiltIn => gctx. cwd ( ) ,
2502+ }
2503+ . join ( & self . path )
2504+ }
2505+ }
2506+
24792507#[ derive( Debug , Default , Deserialize , PartialEq ) ]
24802508#[ serde( rename_all = "kebab-case" ) ]
24812509pub struct CargoHttpConfig {
0 commit comments