Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/dist/manifestation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,13 @@ use crate::{
config::Config,
download::{DownloadCfg, DownloadStatus, File},
manifest::{Component, CompressionKind, HashedBinary, Manifest},
prefix::InstallPrefix,
prefix::{DIST_MANIFEST, InstallPrefix},
temp,
},
errors::RustupError,
utils,
};

pub(crate) const DIST_MANIFEST: &str = "multirust-channel-manifest.toml";
pub(crate) const CONFIG_FILE: &str = "multirust-config.toml";

#[derive(Debug)]
Expand Down Expand Up @@ -396,8 +395,7 @@ impl Manifestation {
#[tracing::instrument(level = "trace")]
pub fn load_manifest(&self) -> Result<Option<Manifest>> {
let prefix = self.installation.prefix();
let old_manifest_path = prefix.manifest_file(DIST_MANIFEST);
if utils::path_exists(&old_manifest_path) {
if let Some(old_manifest_path) = prefix.dist_manifest() {
let manifest_str = utils::read_file("installed manifest", &old_manifest_path)?;
Ok(Some(Manifest::parse(&manifest_str).with_context(|| {
RustupError::ParsingFile {
Expand Down
7 changes: 3 additions & 4 deletions src/dist/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1125,10 +1125,9 @@ async fn try_update_from_dist_(
} else {
download
.dl_v2_manifest(
// Even if manifest has not changed, we must continue to install requested components.
// So if components or targets is not empty, we skip passing `update_hash` so that
// we essentially degenerate to `rustup component add` / `rustup target add`
if components.is_empty() && targets.is_empty() {
// Skip the update hash when the installed manifest is missing or when components
// or targets were requested, since either case still requires the channel manifest.
if prefix.dist_manifest().is_some() && components.is_empty() && targets.is_empty() {
Some(update_hash)
} else {
None
Expand Down
6 changes: 6 additions & 0 deletions src/dist/prefix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const REL_MANIFEST_DIR: &str = match std::path::MAIN_SEPARATOR {
};

static V1_COMMON_COMPONENT_LIST: &[&str] = &["cargo", "rustc", "rust-docs"];
pub(crate) const DIST_MANIFEST: &str = "multirust-channel-manifest.toml";

#[derive(Clone, Debug)]
pub struct InstallPrefix {
Expand All @@ -37,6 +38,11 @@ impl InstallPrefix {
path
}

pub(crate) fn dist_manifest(&self) -> Option<PathBuf> {
let path = self.manifest_file(DIST_MANIFEST);
utils::path_exists(&path).then_some(path)
}

pub(crate) fn rel_manifest_file(&self, name: &str) -> PathBuf {
let mut path = PathBuf::from(REL_MANIFEST_DIR);
path.push(name);
Expand Down
12 changes: 7 additions & 5 deletions src/toolchain/distributable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,12 +439,14 @@ impl<'a> DistributableToolchain<'a> {
}

pub async fn fetch_dist_manifest(&self) -> anyhow::Result<Option<ManifestWithHash>> {
let prefix = InstallPrefix::from(self.toolchain.path());
let update_hash = if prefix.dist_manifest().is_some() {
Some(self.toolchain.cfg.get_hash_file(&self.desc, false)?)
} else {
None
};
DownloadCfg::new(self.toolchain.cfg)
.dl_v2_manifest(
Some(&self.toolchain.cfg.get_hash_file(&self.desc, false)?),
&self.desc,
self.toolchain.cfg,
)
.dl_v2_manifest(update_hash.as_deref(), &self.desc, self.toolchain.cfg)
.await
}

Expand Down
57 changes: 49 additions & 8 deletions tests/suite/cli_rustup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4201,14 +4201,7 @@ async fn missing_manifest_shows_reinstall_help() {
.await
.is_ok();

let manifest_path = cx
.config
.rustupdir
.join("toolchains")
.join(format!("nightly-{}", this_host_tuple()))
.join("lib")
.join("rustlib")
.join("multirust-channel-manifest.toml");
let manifest_path = nightly_manifest_path(&cx);

fs::remove_file(&manifest_path).unwrap();

Expand All @@ -4223,3 +4216,51 @@ help: try reinstalling or updating the toolchain
"#]])
.is_err();
}

#[tokio::test]
async fn reinstall_restores_missing_manifest() {
let cx = CliTestContext::new(Scenario::SimpleV2).await;

cx.config
.expect(["rustup", "toolchain", "install", "nightly"])
.await
.is_ok();

let manifest_path = nightly_manifest_path(&cx);

fs::remove_file(&manifest_path).unwrap();

cx.config
.expect(["rustup", "toolchain", "install", "nightly"])
.await
.is_ok();

assert!(manifest_path.exists());
}

#[tokio::test]
async fn update_all_restores_missing_manifest() {
let cx = CliTestContext::new(Scenario::SimpleV2).await;

cx.config
.expect(["rustup", "toolchain", "install", "nightly"])
.await
.is_ok();

let manifest_path = nightly_manifest_path(&cx);
fs::remove_file(&manifest_path).unwrap();

cx.config.expect(["rustup", "update"]).await.is_ok();

assert!(manifest_path.exists());
}

fn nightly_manifest_path(cx: &CliTestContext) -> PathBuf {
cx.config
.rustupdir
.join("toolchains")
.join(format!("nightly-{}", this_host_tuple()))
.join("lib")
.join("rustlib")
.join("multirust-channel-manifest.toml")
}
Loading