Skip to content

Commit eda1652

Browse files
committed
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.
1 parent ddc21ea commit eda1652

File tree

2 files changed

+51
-13
lines changed

2 files changed

+51
-13
lines changed

src/bin/cargo/cli.rs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use anyhow::anyhow;
2+
use cargo::core::shell::Shell;
23
use cargo::core::{features, CliUnstable};
34
use cargo::{self, drop_print, drop_println, CliResult, Config};
45
use clap::{AppSettings, Arg, ArgMatches};
@@ -21,12 +22,13 @@ lazy_static::lazy_static! {
2122
]);
2223
}
2324

24-
pub fn main(config: &mut Config) -> CliResult {
25+
pub fn main(config: &mut LazyConfig) -> CliResult {
26+
let args = cli().try_get_matches()?;
27+
2528
// CAUTION: Be careful with using `config` until it is configured below.
2629
// In general, try to avoid loading config values unless necessary (like
2730
// the [alias] table).
28-
29-
let args = cli().try_get_matches()?;
31+
let config = config.get_mut();
3032

3133
// Global args need to be extracted before expanding aliases because the
3234
// clap code for extracting a subcommand discards global options
@@ -463,6 +465,49 @@ See 'cargo help <command>' for more information on a specific command.\n",
463465
.subcommands(commands::builtin())
464466
}
465467

468+
/// Delay loading [`Config`] until access.
469+
///
470+
/// In the common path, the [`Config`] is dependent on CLI parsing and shouldn't be loaded until
471+
/// after that is done but some other paths (like fix or earlier errors) might need access to it,
472+
/// so this provides a way to share the instance and the implementation across these different
473+
/// accesses.
474+
pub struct LazyConfig {
475+
config: Option<Config>,
476+
}
477+
478+
impl LazyConfig {
479+
pub fn new() -> Self {
480+
Self { config: None }
481+
}
482+
483+
/// Check whether the config is loaded
484+
///
485+
/// This is useful for asserts in case the environment needs to be setup before loading
486+
pub fn is_init(&self) -> bool {
487+
self.config.is_some()
488+
}
489+
490+
/// Get the config, loading it if needed
491+
///
492+
/// On error, the process is terminated
493+
pub fn get(&mut self) -> &Config {
494+
self.get_mut()
495+
}
496+
497+
/// Get the config, loading it if needed
498+
///
499+
/// On error, the process is terminated
500+
pub fn get_mut(&mut self) -> &mut Config {
501+
self.config.get_or_insert_with(|| match Config::default() {
502+
Ok(cfg) => cfg,
503+
Err(e) => {
504+
let mut shell = Shell::new();
505+
cargo::exit_with_error(e.into(), &mut shell)
506+
}
507+
})
508+
}
509+
}
510+
466511
#[test]
467512
fn verify_cli() {
468513
cli().debug_assert();

src/bin/cargo/main.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#![warn(rust_2018_idioms)] // while we're getting used to 2018
22
#![allow(clippy::all)]
33

4-
use cargo::core::shell::Shell;
54
use cargo::util::toml::StringOrVec;
65
use cargo::util::CliError;
76
use cargo::util::{self, closest_msg, command_prelude, CargoResult, CliResult, Config};
@@ -22,23 +21,17 @@ fn main() {
2221
#[cfg(not(feature = "pretty-env-logger"))]
2322
env_logger::init_from_env("CARGO_LOG");
2423

25-
let mut config = match Config::default() {
26-
Ok(cfg) => cfg,
27-
Err(e) => {
28-
let mut shell = Shell::new();
29-
cargo::exit_with_error(e.into(), &mut shell)
30-
}
31-
};
24+
let mut config = cli::LazyConfig::new();
3225

3326
let result = if let Some(lock_addr) = cargo::ops::fix_get_proxy_lock_addr() {
34-
cargo::ops::fix_exec_rustc(&config, &lock_addr).map_err(|e| CliError::from(e))
27+
cargo::ops::fix_exec_rustc(config.get(), &lock_addr).map_err(|e| CliError::from(e))
3528
} else {
3629
let _token = cargo::util::job::setup();
3730
cli::main(&mut config)
3831
};
3932

4033
match result {
41-
Err(e) => cargo::exit_with_error(e, &mut *config.shell()),
34+
Err(e) => cargo::exit_with_error(e, &mut config.get_mut().shell()),
4235
Ok(()) => {}
4336
}
4437
}

0 commit comments

Comments
 (0)