Skip to content

Commit f6f12a1

Browse files
committed
dist: move update_from_dist() to DistOptions::install_into()
1 parent e49e655 commit f6f12a1

File tree

2 files changed

+149
-152
lines changed

2 files changed

+149
-152
lines changed

src/dist/mod.rs

Lines changed: 147 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -950,173 +950,170 @@ impl<'cfg, 'a> DistOptions<'cfg, 'a> {
950950

951951
self
952952
}
953-
}
954-
955-
// Installs or updates a toolchain from a dist server. If an initial
956-
// install then it will be installed with the default components. If
957-
// an upgrade then all the existing components will be upgraded.
958-
//
959-
// Returns the manifest's hash if anything changed.
960-
#[tracing::instrument(level = "trace", err(level = "trace"), skip_all, fields(profile = ?opts.profile, prefix = %prefix.path().display()))]
961-
pub(crate) async fn update_from_dist(
962-
prefix: &InstallPrefix,
963-
opts: &DistOptions<'_, '_>,
964-
) -> Result<Option<String>> {
965-
let fresh_install = !prefix.path().exists();
966-
// fresh_install means the toolchain isn't present, but hash_exists means there is a stray hash file
967-
if fresh_install && opts.update_hash.exists() {
968-
warn!(
969-
"removing stray hash file in order to continue: {}",
970-
opts.update_hash.display()
971-
);
972-
std::fs::remove_file(&opts.update_hash)?;
973-
}
974953

975-
let mut fetched = String::new();
976-
let mut first_err = None;
977-
let backtrack = opts.toolchain.channel == Channel::Nightly && opts.toolchain.date.is_none();
978-
// We want to limit backtracking if we do not already have a toolchain
979-
let mut backtrack_limit: Option<i32> = if opts.toolchain.date.is_some() {
980-
None
981-
} else {
982-
// We limit the backtracking to 21 days by default (half a release cycle).
983-
// The limit of 21 days is an arbitrary selection, so we let the user override it.
984-
const BACKTRACK_LIMIT_DEFAULT: i32 = 21;
985-
let provided = opts
986-
.dl_cfg
987-
.process
988-
.var("RUSTUP_BACKTRACK_LIMIT")
989-
.ok()
990-
.and_then(|v| v.parse().ok())
991-
.unwrap_or(BACKTRACK_LIMIT_DEFAULT);
992-
Some(if provided < 1 { 1 } else { provided })
993-
};
994-
995-
// In case there is no allow-downgrade option set
996-
// we never want to backtrack further back than the nightly that's already installed.
997-
//
998-
// If no nightly is installed, it makes no sense to backtrack beyond the first ever manifest,
999-
// which is 2014-12-20 according to
1000-
// https://static.rust-lang.org/cargo-dist/index.html.
954+
// Installs or updates a toolchain from a dist server. If an initial
955+
// install then it will be installed with the default components. If
956+
// an upgrade then all the existing components will be upgraded.
1001957
//
1002-
// We could arguably use the date of the first rustup release here, but that would break a
1003-
// bunch of the tests, which (inexplicably) use 2015-01-01 as their manifest dates.
1004-
let first_manifest = date_from_manifest_date("2014-12-20").unwrap();
1005-
let old_manifest = opts
1006-
.old_date_version
1007-
.as_ref()
1008-
.and_then(|(d, _)| date_from_manifest_date(d))
1009-
.unwrap_or(first_manifest);
1010-
let last_manifest = if opts.allow_downgrade {
1011-
first_manifest
1012-
} else {
1013-
old_manifest
1014-
};
958+
// Returns the manifest's hash if anything changed.
959+
#[tracing::instrument(level = "trace", err(level = "trace"), skip_all, fields(profile = ?self.profile, prefix = %prefix.path().display()))]
960+
pub(crate) async fn install_into(&self, prefix: &InstallPrefix) -> Result<Option<String>> {
961+
let fresh_install = !prefix.path().exists();
962+
// fresh_install means the toolchain isn't present, but hash_exists means there is a stray hash file
963+
if fresh_install && self.update_hash.exists() {
964+
warn!(
965+
"removing stray hash file in order to continue: {}",
966+
self.update_hash.display()
967+
);
968+
std::fs::remove_file(&self.update_hash)?;
969+
}
1015970

1016-
let current_manifest = {
1017-
let manifestation = Manifestation::open(prefix.clone(), opts.toolchain.target.clone())?;
1018-
manifestation.load_manifest()?
1019-
};
971+
let mut fetched = String::new();
972+
let mut first_err = None;
973+
let backtrack = self.toolchain.channel == Channel::Nightly && self.toolchain.date.is_none();
974+
// We want to limit backtracking if we do not already have a toolchain
975+
let mut backtrack_limit: Option<i32> = if self.toolchain.date.is_some() {
976+
None
977+
} else {
978+
// We limit the backtracking to 21 days by default (half a release cycle).
979+
// The limit of 21 days is an arbitrary selection, so we let the user override it.
980+
const BACKTRACK_LIMIT_DEFAULT: i32 = 21;
981+
let provided = self
982+
.dl_cfg
983+
.process
984+
.var("RUSTUP_BACKTRACK_LIMIT")
985+
.ok()
986+
.and_then(|v| v.parse().ok())
987+
.unwrap_or(BACKTRACK_LIMIT_DEFAULT);
988+
Some(if provided < 1 { 1 } else { provided })
989+
};
1020990

1021-
let mut toolchain = opts.toolchain.clone();
1022-
let res = loop {
1023-
let result = try_update_from_dist_(
1024-
&opts.dl_cfg,
1025-
&opts.update_hash,
1026-
&toolchain,
1027-
match opts.exists {
1028-
false => Some(opts.profile),
1029-
true => None,
1030-
},
1031-
prefix,
1032-
opts.force,
1033-
opts.components,
1034-
opts.targets,
1035-
&mut fetched,
1036-
opts.cfg,
1037-
)
1038-
.await;
991+
// In case there is no allow-downgrade option set
992+
// we never want to backtrack further back than the nightly that's already installed.
993+
//
994+
// If no nightly is installed, it makes no sense to backtrack beyond the first ever manifest,
995+
// which is 2014-12-20 according to
996+
// https://static.rust-lang.org/cargo-dist/index.html.
997+
//
998+
// We could arguably use the date of the first rustup release here, but that would break a
999+
// bunch of the tests, which (inexplicably) use 2015-01-01 as their manifest dates.
1000+
let first_manifest = date_from_manifest_date("2014-12-20").unwrap();
1001+
let old_manifest = self
1002+
.old_date_version
1003+
.as_ref()
1004+
.and_then(|(d, _)| date_from_manifest_date(d))
1005+
.unwrap_or(first_manifest);
1006+
let last_manifest = if self.allow_downgrade {
1007+
first_manifest
1008+
} else {
1009+
old_manifest
1010+
};
10391011

1040-
let e = match result {
1041-
Ok(v) => break Ok(v),
1042-
Err(e) if !backtrack => break Err(e),
1043-
Err(e) => e,
1012+
let current_manifest = {
1013+
let manifestation = Manifestation::open(prefix.clone(), self.toolchain.target.clone())?;
1014+
manifestation.load_manifest()?
10441015
};
10451016

1046-
let cause = e.downcast_ref::<DistError>();
1047-
match cause {
1048-
Some(DistError::ToolchainComponentsMissing(components, manifest, ..)) => {
1049-
let plural = if components.len() > 1 { "s" } else { "" };
1050-
let manifest = current_manifest.as_ref().unwrap_or(manifest);
1051-
let components = components
1052-
.iter()
1053-
.map(
1054-
|component| match component.target.as_ref() == Some(&toolchain.target) {
1055-
true => component.short_name(manifest),
1056-
false => component.name(manifest),
1057-
},
1058-
)
1059-
.join(", ");
1060-
info!("skipping nightly with missing component{plural}: {components}");
1017+
let mut toolchain = self.toolchain.clone();
1018+
let res = loop {
1019+
let result = try_update_from_dist_(
1020+
&self.dl_cfg,
1021+
&self.update_hash,
1022+
&toolchain,
1023+
match self.exists {
1024+
false => Some(self.profile),
1025+
true => None,
1026+
},
1027+
prefix,
1028+
self.force,
1029+
self.components,
1030+
self.targets,
1031+
&mut fetched,
1032+
self.cfg,
1033+
)
1034+
.await;
1035+
1036+
let e = match result {
1037+
Ok(v) => break Ok(v),
1038+
Err(e) if !backtrack => break Err(e),
1039+
Err(e) => e,
1040+
};
10611041

1062-
if first_err.is_none() {
1063-
first_err = Some(e);
1042+
let cause = e.downcast_ref::<DistError>();
1043+
match cause {
1044+
Some(DistError::ToolchainComponentsMissing(components, manifest, ..)) => {
1045+
let plural = if components.len() > 1 { "s" } else { "" };
1046+
let manifest = current_manifest.as_ref().unwrap_or(manifest);
1047+
let components = components
1048+
.iter()
1049+
.map(|component| {
1050+
match component.target.as_ref() == Some(&toolchain.target) {
1051+
true => component.short_name(manifest),
1052+
false => component.name(manifest),
1053+
}
1054+
})
1055+
.join(", ");
1056+
info!("skipping nightly with missing component{plural}: {components}");
1057+
1058+
if first_err.is_none() {
1059+
first_err = Some(e);
1060+
}
1061+
// We decrement the backtrack count only on unavailable component errors
1062+
// so that the limit only applies to nightlies that were indeed available,
1063+
// and ignores missing ones.
1064+
backtrack_limit = backtrack_limit.map(|n| n - 1);
10641065
}
1065-
// We decrement the backtrack count only on unavailable component errors
1066-
// so that the limit only applies to nightlies that were indeed available,
1067-
// and ignores missing ones.
1068-
backtrack_limit = backtrack_limit.map(|n| n - 1);
1069-
}
10701066

1071-
Some(DistError::MissingReleaseForToolchain(..)) => {
1072-
// no need to even print anything for missing nightlies,
1073-
// since we don't really "skip" them
1067+
Some(DistError::MissingReleaseForToolchain(..)) => {
1068+
// no need to even print anything for missing nightlies,
1069+
// since we don't really "skip" them
1070+
}
1071+
_ => {
1072+
// All other errors break the loop
1073+
break Err(e);
1074+
}
1075+
};
1076+
1077+
if let Some(backtrack_limit) = backtrack_limit
1078+
&& backtrack_limit < 1
1079+
{
1080+
// This unwrap is safe because we can only hit this if we've
1081+
// had a chance to set first_err
1082+
break Err(first_err.unwrap());
10741083
}
1075-
_ => {
1076-
// All other errors break the loop
1077-
break Err(e);
1084+
1085+
// The user asked to update their nightly, but the latest nightly does not have all
1086+
// the components that the user currently has installed. Let's try the previous
1087+
// nightlies in reverse chronological order until we find a nightly that does,
1088+
// starting at one date earlier than the current manifest's date.
1089+
let toolchain_date = toolchain.date.as_ref().unwrap_or(&fetched);
1090+
let try_next = date_from_manifest_date(toolchain_date)
1091+
.unwrap_or_else(|| panic!("Malformed manifest date: {toolchain_date:?}"))
1092+
.pred_opt()
1093+
.unwrap();
1094+
1095+
if try_next < last_manifest {
1096+
// Wouldn't be an update if we go further back than the user's current nightly.
1097+
if let Some(e) = first_err {
1098+
break Err(e);
1099+
} else {
1100+
// In this case, all newer nightlies are missing, which means there are no
1101+
// updates, so the user is already at the latest nightly.
1102+
break Ok(None);
1103+
}
10781104
}
1079-
};
10801105

1081-
if let Some(backtrack_limit) = backtrack_limit
1082-
&& backtrack_limit < 1
1083-
{
1084-
// This unwrap is safe because we can only hit this if we've
1085-
// had a chance to set first_err
1086-
break Err(first_err.unwrap());
1087-
}
1106+
toolchain.date = Some(try_next.format("%Y-%m-%d").to_string());
1107+
};
10881108

1089-
// The user asked to update their nightly, but the latest nightly does not have all
1090-
// the components that the user currently has installed. Let's try the previous
1091-
// nightlies in reverse chronological order until we find a nightly that does,
1092-
// starting at one date earlier than the current manifest's date.
1093-
let toolchain_date = toolchain.date.as_ref().unwrap_or(&fetched);
1094-
let try_next = date_from_manifest_date(toolchain_date)
1095-
.unwrap_or_else(|| panic!("Malformed manifest date: {toolchain_date:?}"))
1096-
.pred_opt()
1097-
.unwrap();
1098-
1099-
if try_next < last_manifest {
1100-
// Wouldn't be an update if we go further back than the user's current nightly.
1101-
if let Some(e) = first_err {
1102-
break Err(e);
1103-
} else {
1104-
// In this case, all newer nightlies are missing, which means there are no
1105-
// updates, so the user is already at the latest nightly.
1106-
break Ok(None);
1107-
}
1109+
// Don't leave behind an empty / broken installation directory
1110+
if res.is_err() && fresh_install {
1111+
// FIXME Ignoring cascading errors
1112+
let _ = utils::remove_dir("toolchain", prefix.path());
11081113
}
11091114

1110-
toolchain.date = Some(try_next.format("%Y-%m-%d").to_string());
1111-
};
1112-
1113-
// Don't leave behind an empty / broken installation directory
1114-
if res.is_err() && fresh_install {
1115-
// FIXME Ignoring cascading errors
1116-
let _ = utils::remove_dir("toolchain", prefix.path());
1115+
res
11171116
}
1118-
1119-
res
11201117
}
11211118

11221119
#[allow(clippy::too_many_arguments)]

src/install.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use tracing::debug;
77

88
use crate::{
99
config::Cfg,
10-
dist::{self, DistOptions, prefix::InstallPrefix},
10+
dist::{DistOptions, prefix::InstallPrefix},
1111
errors::RustupError,
1212
toolchain::{CustomToolchainName, LocalToolchainName, Toolchain},
1313
utils,
@@ -104,7 +104,7 @@ impl InstallMethod<'_, '_> {
104104
}
105105
InstallMethod::Dist(opts) => {
106106
let prefix = &InstallPrefix::from(path.to_owned());
107-
let maybe_new_hash = dist::update_from_dist(prefix, opts).await?;
107+
let maybe_new_hash = opts.install_into(prefix).await?;
108108

109109
if let Some(hash) = maybe_new_hash {
110110
utils::write_file("update hash", &opts.update_hash, &hash)?;

0 commit comments

Comments
 (0)