From 4e56636ee515b6407b3c92e95e6bc927554001ef Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 29 Aug 2022 12:06:19 -0500 Subject: [PATCH] refactor(cli): Lazily do first-pass config loading This will be a help for cases like #10952 which I would expect would assert that the config is not loaded before changing the current_dir. --- src/bin/cargo/cli.rs | 36 +++++++++++++++++++++++++++++++++--- src/bin/cargo/main.rs | 13 +++---------- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/bin/cargo/cli.rs b/src/bin/cargo/cli.rs index d5a3a72e065f..77c65fdac96d 100644 --- a/src/bin/cargo/cli.rs +++ b/src/bin/cargo/cli.rs @@ -1,4 +1,5 @@ use anyhow::anyhow; +use cargo::core::shell::Shell; use cargo::core::{features, CliUnstable}; use cargo::{self, drop_print, drop_println, CliResult, Config}; use clap::{AppSettings, Arg, ArgMatches}; @@ -21,12 +22,13 @@ lazy_static::lazy_static! { ]); } -pub fn main(config: &mut Config) -> CliResult { +pub fn main(config: &mut LazyConfig) -> CliResult { + let args = cli().try_get_matches()?; + // CAUTION: Be careful with using `config` until it is configured below. // In general, try to avoid loading config values unless necessary (like // the [alias] table). - - let args = cli().try_get_matches()?; + let config = config.get_mut(); // Global args need to be extracted before expanding aliases because the // clap code for extracting a subcommand discards global options @@ -463,6 +465,34 @@ See 'cargo help ' for more information on a specific command.\n", .subcommands(commands::builtin()) } +pub struct LazyConfig { + config: Option, +} + +impl LazyConfig { + pub fn new() -> Self { + Self { config: None } + } + + pub fn is_init(&self) -> bool { + self.config.is_some() + } + + pub fn get(&mut self) -> &Config { + self.get_mut() + } + + pub fn get_mut(&mut self) -> &mut Config { + self.config.get_or_insert_with(|| match Config::default() { + Ok(cfg) => cfg, + Err(e) => { + let mut shell = Shell::new(); + cargo::exit_with_error(e.into(), &mut shell) + } + }) + } +} + #[test] fn verify_cli() { cli().debug_assert(); diff --git a/src/bin/cargo/main.rs b/src/bin/cargo/main.rs index bd439f8f193d..e4f224031cdf 100644 --- a/src/bin/cargo/main.rs +++ b/src/bin/cargo/main.rs @@ -1,7 +1,6 @@ #![warn(rust_2018_idioms)] // while we're getting used to 2018 #![allow(clippy::all)] -use cargo::core::shell::Shell; use cargo::util::toml::StringOrVec; use cargo::util::CliError; use cargo::util::{self, closest_msg, command_prelude, CargoResult, CliResult, Config}; @@ -22,23 +21,17 @@ fn main() { #[cfg(not(feature = "pretty-env-logger"))] env_logger::init_from_env("CARGO_LOG"); - let mut config = match Config::default() { - Ok(cfg) => cfg, - Err(e) => { - let mut shell = Shell::new(); - cargo::exit_with_error(e.into(), &mut shell) - } - }; + let mut config = cli::LazyConfig::new(); let result = if let Some(lock_addr) = cargo::ops::fix_get_proxy_lock_addr() { - cargo::ops::fix_exec_rustc(&config, &lock_addr).map_err(|e| CliError::from(e)) + cargo::ops::fix_exec_rustc(config.get(), &lock_addr).map_err(|e| CliError::from(e)) } else { let _token = cargo::util::job::setup(); cli::main(&mut config) }; match result { - Err(e) => cargo::exit_with_error(e, &mut *config.shell()), + Err(e) => cargo::exit_with_error(e, &mut config.get_mut().shell()), Ok(()) => {} } }