Skip to content

Commit 39f9f34

Browse files
committed
fix!(config): re-enable active toolchain installation in Cfg::find_active_toolchain() with optional opt-out
1 parent f00c3d1 commit 39f9f34

File tree

8 files changed

+123
-73
lines changed

8 files changed

+123
-73
lines changed

src/cli/common.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ pub(super) fn list_items(
406406
Ok(utils::ExitCode(0))
407407
}
408408

409-
pub(crate) fn list_toolchains(
409+
pub(crate) async fn list_toolchains(
410410
cfg: &Cfg<'_>,
411411
verbose: bool,
412412
quiet: bool,
@@ -418,7 +418,7 @@ pub(crate) fn list_toolchains(
418418
let default_toolchain_name = cfg.get_default()?;
419419
let active_toolchain_name: Option<ToolchainName> =
420420
if let Ok(Some((LocalToolchainName::Named(toolchain), _reason))) =
421-
cfg.find_active_toolchain()
421+
cfg.find_active_toolchain(None).await
422422
{
423423
Some(toolchain)
424424
} else {

src/cli/proxy_mode.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ pub async fn main(arg0: &str, current_dir: PathBuf, process: &Process) -> Result
3232
.collect();
3333

3434
let cfg = set_globals(current_dir, true, process)?;
35-
let cmd = cfg.resolve_local_toolchain(toolchain)?.command(arg0)?;
35+
let cmd = cfg
36+
.resolve_local_toolchain(toolchain)
37+
.await?
38+
.command(arg0)?;
3639
run_command_for_dir(cmd, arg0, &cmd_args)
3740
}

src/cli/rustup_mode.rs

+29-22
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ pub async fn main(
560560
write!(process.stdout().lock(), "{err}")?;
561561
info!("This is the version for the rustup toolchain manager, not the rustc compiler.");
562562
let mut cfg = common::set_globals(current_dir, true, process)?;
563-
match cfg.active_rustc_version() {
563+
match cfg.active_rustc_version().await {
564564
Ok(Some(version)) => info!("The currently active `rustc` version is `{version}`"),
565565
Ok(None) => info!("No `rustc` is currently active"),
566566
Err(err) => trace!("Failed to display the current `rustc` version: {err}"),
@@ -601,10 +601,12 @@ pub async fn main(
601601
match subcmd {
602602
RustupSubcmd::DumpTestament => common::dump_testament(process),
603603
RustupSubcmd::Install { opts } => update(cfg, opts, true).await,
604-
RustupSubcmd::Uninstall { opts } => toolchain_remove(cfg, opts),
604+
RustupSubcmd::Uninstall { opts } => toolchain_remove(cfg, opts).await,
605605
RustupSubcmd::Show { verbose, subcmd } => handle_epipe(match subcmd {
606-
None => show(cfg, verbose),
607-
Some(ShowSubcmd::ActiveToolchain { verbose }) => show_active_toolchain(cfg, verbose),
606+
None => show(cfg, verbose).await,
607+
Some(ShowSubcmd::ActiveToolchain { verbose }) => {
608+
show_active_toolchain(cfg, verbose).await
609+
}
608610
Some(ShowSubcmd::Home) => show_rustup_home(cfg),
609611
Some(ShowSubcmd::Profile) => {
610612
writeln!(process.stdout().lock(), "{}", cfg.get_profile()?)?;
@@ -633,12 +635,12 @@ pub async fn main(
633635
RustupSubcmd::Toolchain { subcmd } => match subcmd {
634636
ToolchainSubcmd::Install { opts } => update(cfg, opts, true).await,
635637
ToolchainSubcmd::List { verbose, quiet } => {
636-
handle_epipe(common::list_toolchains(cfg, verbose, quiet))
638+
handle_epipe(common::list_toolchains(cfg, verbose, quiet).await)
637639
}
638640
ToolchainSubcmd::Link { toolchain, path } => {
639641
toolchain_link(cfg, &toolchain, &path).await
640642
}
641-
ToolchainSubcmd::Uninstall { opts } => toolchain_remove(cfg, opts),
643+
ToolchainSubcmd::Uninstall { opts } => toolchain_remove(cfg, opts).await,
642644
},
643645
RustupSubcmd::Check => check_updates(cfg).await,
644646
RustupSubcmd::Default {
@@ -751,7 +753,7 @@ async fn default_(
751753
}
752754
};
753755

754-
if let Some((toolchain, reason)) = cfg.find_active_toolchain()? {
756+
if let Some((toolchain, reason)) = cfg.find_active_toolchain(None).await? {
755757
if !matches!(reason, ActiveReason::Default) {
756758
info!("note that the toolchain '{toolchain}' is currently in use ({reason})");
757759
}
@@ -928,7 +930,7 @@ async fn which(
928930
binary: &str,
929931
toolchain: Option<ResolvableToolchainName>,
930932
) -> Result<utils::ExitCode> {
931-
let binary_path = cfg.resolve_toolchain(toolchain)?.binary_file(binary);
933+
let binary_path = cfg.resolve_toolchain(toolchain).await?.binary_file(binary);
932934

933935
utils::assert_is_file(&binary_path)?;
934936

@@ -937,7 +939,7 @@ async fn which(
937939
}
938940

939941
#[tracing::instrument(level = "trace", skip_all)]
940-
fn show(cfg: &Cfg<'_>, verbose: bool) -> Result<utils::ExitCode> {
942+
async fn show(cfg: &Cfg<'_>, verbose: bool) -> Result<utils::ExitCode> {
941943
common::warn_if_host_is_emulated(cfg.process);
942944

943945
// Print host triple
@@ -962,7 +964,7 @@ fn show(cfg: &Cfg<'_>, verbose: bool) -> Result<utils::ExitCode> {
962964
let installed_toolchains = cfg.list_toolchains()?;
963965
let active_toolchain_and_reason: Option<(ToolchainName, ActiveReason)> =
964966
if let Ok(Some((LocalToolchainName::Named(toolchain_name), reason))) =
965-
cfg.find_active_toolchain()
967+
cfg.find_active_toolchain(None).await
966968
{
967969
Some((toolchain_name, reason))
968970
} else {
@@ -1081,8 +1083,8 @@ fn show(cfg: &Cfg<'_>, verbose: bool) -> Result<utils::ExitCode> {
10811083
}
10821084

10831085
#[tracing::instrument(level = "trace", skip_all)]
1084-
fn show_active_toolchain(cfg: &Cfg<'_>, verbose: bool) -> Result<utils::ExitCode> {
1085-
match cfg.find_active_toolchain()? {
1086+
async fn show_active_toolchain(cfg: &Cfg<'_>, verbose: bool) -> Result<utils::ExitCode> {
1087+
match cfg.find_active_toolchain(None).await? {
10861088
Some((toolchain_name, reason)) => {
10871089
let toolchain = Toolchain::with_reason(cfg, toolchain_name.clone(), &reason)?;
10881090
writeln!(
@@ -1118,7 +1120,7 @@ async fn target_list(
11181120
quiet: bool,
11191121
) -> Result<utils::ExitCode> {
11201122
// downcasting required because the toolchain files can name any toolchain
1121-
let distributable = DistributableToolchain::from_partial(toolchain, cfg)?;
1123+
let distributable = DistributableToolchain::from_partial(toolchain, cfg).await?;
11221124
common::list_items(
11231125
distributable,
11241126
|c| {
@@ -1145,7 +1147,7 @@ async fn target_add(
11451147
// isn't a feature yet.
11461148
// list_components *and* add_component would both be inappropriate for
11471149
// custom toolchains.
1148-
let distributable = DistributableToolchain::from_partial(toolchain, cfg)?;
1150+
let distributable = DistributableToolchain::from_partial(toolchain, cfg).await?;
11491151
let components = distributable.components()?;
11501152

11511153
if targets.contains(&"all".to_string()) {
@@ -1189,7 +1191,7 @@ async fn target_remove(
11891191
targets: Vec<String>,
11901192
toolchain: Option<PartialToolchainDesc>,
11911193
) -> Result<utils::ExitCode> {
1192-
let distributable = DistributableToolchain::from_partial(toolchain, cfg)?;
1194+
let distributable = DistributableToolchain::from_partial(toolchain, cfg).await?;
11931195

11941196
for target in targets {
11951197
let target = TargetTriple::new(target);
@@ -1227,7 +1229,7 @@ async fn component_list(
12271229
quiet: bool,
12281230
) -> Result<utils::ExitCode> {
12291231
// downcasting required because the toolchain files can name any toolchain
1230-
let distributable = DistributableToolchain::from_partial(toolchain, cfg)?;
1232+
let distributable = DistributableToolchain::from_partial(toolchain, cfg).await?;
12311233
common::list_items(
12321234
distributable,
12331235
|c| Some(&c.name),
@@ -1243,7 +1245,7 @@ async fn component_add(
12431245
toolchain: Option<PartialToolchainDesc>,
12441246
target: Option<String>,
12451247
) -> Result<utils::ExitCode> {
1246-
let distributable = DistributableToolchain::from_partial(toolchain, cfg)?;
1248+
let distributable = DistributableToolchain::from_partial(toolchain, cfg).await?;
12471249
let target = get_target(target, &distributable);
12481250

12491251
for component in &components {
@@ -1269,7 +1271,7 @@ async fn component_remove(
12691271
toolchain: Option<PartialToolchainDesc>,
12701272
target: Option<String>,
12711273
) -> Result<utils::ExitCode> {
1272-
let distributable = DistributableToolchain::from_partial(toolchain, cfg)?;
1274+
let distributable = DistributableToolchain::from_partial(toolchain, cfg).await?;
12731275
let target = get_target(target, &distributable);
12741276

12751277
for component in &components {
@@ -1311,9 +1313,14 @@ async fn toolchain_link(
13111313
Ok(utils::ExitCode(0))
13121314
}
13131315

1314-
fn toolchain_remove(cfg: &mut Cfg<'_>, opts: UninstallOpts) -> Result<utils::ExitCode> {
1316+
async fn toolchain_remove(cfg: &mut Cfg<'_>, opts: UninstallOpts) -> Result<utils::ExitCode> {
13151317
let default_toolchain = cfg.get_default().ok().flatten();
1316-
let active_toolchain = cfg.find_active_toolchain().ok().flatten().map(|(it, _)| it);
1318+
let active_toolchain = cfg
1319+
.find_active_toolchain(Some(false))
1320+
.await
1321+
.ok()
1322+
.flatten()
1323+
.map(|(it, _)| it);
13171324

13181325
for toolchain_name in &opts.toolchain {
13191326
let toolchain_name = toolchain_name.resolve(&cfg.get_default_host_triple()?)?;
@@ -1556,7 +1563,7 @@ async fn doc(
15561563
mut topic: Option<&str>,
15571564
doc_page: &DocPage,
15581565
) -> Result<utils::ExitCode> {
1559-
let toolchain = cfg.toolchain_from_partial(toolchain)?;
1566+
let toolchain = cfg.toolchain_from_partial(toolchain).await?;
15601567

15611568
if let Ok(distributable) = DistributableToolchain::try_from(&toolchain) {
15621569
if let [_] = distributable
@@ -1625,7 +1632,7 @@ async fn man(
16251632
command: &str,
16261633
toolchain: Option<PartialToolchainDesc>,
16271634
) -> Result<utils::ExitCode> {
1628-
let toolchain = cfg.toolchain_from_partial(toolchain)?;
1635+
let toolchain = cfg.toolchain_from_partial(toolchain).await?;
16291636
let path = toolchain.man_path();
16301637
utils::assert_is_directory(&path)?;
16311638

src/config.rs

+67-18
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ impl<'a> Cfg<'a> {
500500
.transpose()?)
501501
}
502502

503-
pub(crate) fn toolchain_from_partial(
503+
pub(crate) async fn toolchain_from_partial(
504504
&self,
505505
toolchain: Option<PartialToolchainDesc>,
506506
) -> anyhow::Result<Toolchain<'_>> {
@@ -511,20 +511,68 @@ impl<'a> Cfg<'a> {
511511
)))
512512
})
513513
.transpose()?;
514-
self.local_toolchain(toolchain)
514+
self.local_toolchain(toolchain).await
515515
}
516516

517-
pub(crate) fn find_active_toolchain(
517+
pub(crate) async fn find_active_toolchain(
518518
&self,
519+
force_install_active: Option<bool>,
519520
) -> Result<Option<(LocalToolchainName, ActiveReason)>> {
520-
Ok(
521-
if let Some((override_config, reason)) = self.find_override_config()? {
521+
Ok(match self.find_override_config()? {
522+
Some((
523+
OverrideCfg::Official {
524+
components,
525+
targets,
526+
profile,
527+
ref toolchain,
528+
},
529+
reason,
530+
)) => {
531+
let should_install_active = force_install_active.unwrap_or_else(|| {
532+
self.process
533+
.var("RUSTUP_AUTO_INSTALL")
534+
.map_or(true, |it| it != "0")
535+
});
536+
if should_install_active {
537+
let components: Vec<_> = components.iter().map(AsRef::as_ref).collect();
538+
let targets: Vec<_> = targets.iter().map(AsRef::as_ref).collect();
539+
match DistributableToolchain::new(self, toolchain.clone()) {
540+
Err(RustupError::ToolchainNotInstalled { .. }) => {
541+
DistributableToolchain::install(
542+
self,
543+
toolchain,
544+
&components,
545+
&targets,
546+
profile.unwrap_or(Profile::Default),
547+
false,
548+
)
549+
.await?
550+
.1
551+
}
552+
Ok(mut distributable) => {
553+
if !distributable.components_exist(&components, &targets)? {
554+
distributable
555+
.update(
556+
&components,
557+
&targets,
558+
profile.unwrap_or(Profile::Default),
559+
)
560+
.await?;
561+
}
562+
distributable
563+
}
564+
Err(e) => return Err(e.into()),
565+
};
566+
}
567+
Some((toolchain.into(), reason))
568+
}
569+
Some((override_config, reason)) => {
522570
Some((override_config.into_local_toolchain_name(), reason))
523-
} else {
524-
self.get_default()?
525-
.map(|x| (x.into(), ActiveReason::Default))
526-
},
527-
)
571+
}
572+
None => self
573+
.get_default()?
574+
.map(|x| (x.into(), ActiveReason::Default)),
575+
})
528576
}
529577

530578
fn find_override_config(&self) -> Result<Option<(OverrideCfg, ActiveReason)>> {
@@ -703,43 +751,44 @@ impl<'a> Cfg<'a> {
703751
}
704752

705753
#[tracing::instrument(level = "trace")]
706-
pub(crate) fn active_rustc_version(&mut self) -> Result<Option<String>> {
754+
pub(crate) async fn active_rustc_version(&mut self) -> Result<Option<String>> {
707755
if let Some(t) = self.process.args().find(|x| x.starts_with('+')) {
708756
trace!("Fetching rustc version from toolchain `{}`", t);
709757
self.set_toolchain_override(&ResolvableToolchainName::try_from(&t[1..])?);
710758
}
711759

712-
let Some((name, _)) = self.find_active_toolchain()? else {
760+
let Some((name, _)) = self.find_active_toolchain(None).await? else {
713761
return Ok(None);
714762
};
715763
Ok(Some(Toolchain::new(self, name)?.rustc_version()))
716764
}
717765

718-
pub(crate) fn resolve_toolchain(
766+
pub(crate) async fn resolve_toolchain(
719767
&self,
720768
name: Option<ResolvableToolchainName>,
721769
) -> Result<Toolchain<'_>> {
722770
let toolchain = name
723771
.map(|name| anyhow::Ok(name.resolve(&self.get_default_host_triple()?)?.into()))
724772
.transpose()?;
725-
self.local_toolchain(toolchain)
773+
self.local_toolchain(toolchain).await
726774
}
727775

728-
pub(crate) fn resolve_local_toolchain(
776+
pub(crate) async fn resolve_local_toolchain(
729777
&self,
730778
name: Option<ResolvableLocalToolchainName>,
731779
) -> Result<Toolchain<'_>> {
732780
let local = name
733781
.map(|name| name.resolve(&self.get_default_host_triple()?))
734782
.transpose()?;
735-
self.local_toolchain(local)
783+
self.local_toolchain(local).await
736784
}
737785

738-
fn local_toolchain(&self, name: Option<LocalToolchainName>) -> Result<Toolchain<'_>> {
786+
async fn local_toolchain(&self, name: Option<LocalToolchainName>) -> Result<Toolchain<'_>> {
739787
let toolchain = match name {
740788
Some(tc) => tc,
741789
None => {
742-
self.find_active_toolchain()?
790+
self.find_active_toolchain(None)
791+
.await?
743792
.ok_or_else(|| no_toolchain_error(self.process))?
744793
.0
745794
}

src/toolchain/distributable.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ pub(crate) struct DistributableToolchain<'a> {
3232
}
3333

3434
impl<'a> DistributableToolchain<'a> {
35-
pub(crate) fn from_partial(
35+
pub(crate) async fn from_partial(
3636
toolchain: Option<PartialToolchainDesc>,
3737
cfg: &'a Cfg<'a>,
3838
) -> anyhow::Result<Self> {
39-
Ok(Self::try_from(&cfg.toolchain_from_partial(toolchain)?)?)
39+
Ok(Self::try_from(
40+
&cfg.toolchain_from_partial(toolchain).await?,
41+
)?)
4042
}
4143

4244
pub(crate) fn new(cfg: &'a Cfg<'a>, desc: ToolchainDesc) -> Result<Self, RustupError> {

0 commit comments

Comments
 (0)