Add metadata upgrade from version 2 to 12

This commit is contained in:
Brian Anderson
2016-02-25 22:46:31 +00:00
parent 095201386f
commit b3c19dbed5
4 changed files with 117 additions and 37 deletions

View File

@@ -2,7 +2,6 @@ use std::path::{Path, PathBuf};
use std::borrow::Cow;
use std::env;
use std::io;
use std::fs;
use std::process::Command;
use std::fmt::{self, Display};
@@ -155,9 +154,9 @@ impl Cfg {
}
}
pub fn upgrade_data(&self) -> Result<bool> {
pub fn upgrade_data(&self) -> Result<()> {
if !utils::is_file(&self.version_file) {
return Ok(false);
return Ok(());
}
let mut current_version = try!(utils::read_file("version", &self.version_file));
@@ -167,7 +166,7 @@ impl Cfg {
if current_version == METADATA_VERSION {
self.notify_handler
.call(Notification::MetadataUpgradeNotNeeded(METADATA_VERSION));
return Ok(false);
return Ok(());
}
self.notify_handler
@@ -175,15 +174,28 @@ impl Cfg {
match &*current_version {
"1" => {
// Ignore errors. These files may not exist.
let _ = fs::remove_dir_all(self.multirust_dir.join("available-updates"));
let _ = fs::remove_dir_all(self.multirust_dir.join("update-sums"));
let _ = fs::remove_dir_all(self.multirust_dir.join("channel-sums"));
let _ = fs::remove_dir_all(self.multirust_dir.join("manifests"));
// This corresponds to an old version of multirust.sh.
Err(Error::UnknownMetadataVersion(current_version))
}
"2" => {
// The toolchain installation format changed. Just delete them all.
let dirs = try!(utils::read_dir("toolchains", &self.toolchains_dir));
for dir in dirs {
let dir = try!(dir.map_err(|e| Error::UpgradeIoError(e)));
try!(utils::remove_dir("toolchain", &dir.path(),
utils::NotifyHandler::some(&self.notify_handler)));
}
// Also delete the update hashes
let files = try!(utils::read_dir("update hashes", &self.update_hash_dir));
for file in files {
let file = try!(file.map_err(|e| Error::UpgradeIoError(e)));
try!(utils::remove_file("update hash", &file.path()));
}
try!(utils::write_file("version", &self.version_file, METADATA_VERSION));
Ok(true)
Ok(())
}
_ => Err(Error::UnknownMetadataVersion(current_version)),
}
@@ -273,7 +285,7 @@ impl Cfg {
.collect())
}
pub fn check_metadata_version(&self) -> Result<bool> {
pub fn check_metadata_version(&self) -> Result<()> {
try!(utils::assert_is_directory(&self.multirust_dir));
if !utils::is_file(&self.version_file) {
@@ -281,13 +293,17 @@ impl Cfg {
try!(utils::write_file("metadata version", &self.version_file, METADATA_VERSION));
Ok(true)
Ok(())
} else {
let current_version = try!(utils::read_file("metadata version", &self.version_file));
self.notify_handler.call(Notification::ReadMetadataVersion(&current_version));
Ok(&*current_version == METADATA_VERSION)
if &*current_version == METADATA_VERSION {
Ok(())
} else {
Err(Error::NeedMetadataUpgrade)
}
}
}

View File

@@ -1,6 +1,7 @@
use std::path::Path;
use std::error;
use std::fmt::{self, Display};
use std::io;
use rust_install::{self, utils, temp};
use rust_install::notify::{self, NotificationLevel, Notifyable};
@@ -42,6 +43,8 @@ pub enum Error {
ToolchainNotInstalled(String),
UnknownHostTriple,
InfiniteRecursion,
NeedMetadataUpgrade,
UpgradeIoError(io::Error),
Custom {
id: String,
desc: String,
@@ -138,6 +141,8 @@ impl error::Error for Error {
ToolchainNotInstalled(_) => "toolchain is not installed",
UnknownHostTriple => "unknown host triple",
InfiniteRecursion => "infinite recursion detected",
NeedMetadataUpgrade => "multirust's metadata is out of date. run multirust upgrade-data.",
UpgradeIoError(_) => "I/O error during upgrade",
Custom { ref desc, .. } => desc,
}
}
@@ -148,6 +153,7 @@ impl error::Error for Error {
Install(ref e) => Some(e),
Utils(ref e) => Some(e),
Temp(ref e) => Some(e),
UpgradeIoError(ref e) => Some(e),
UnknownMetadataVersion(_) |
InvalidEnvironment |
NoDefaultToolchain |
@@ -155,6 +161,7 @@ impl error::Error for Error {
ToolchainNotInstalled(_) |
UnknownHostTriple |
InfiniteRecursion |
NeedMetadataUpgrade |
Custom {..} => None,
}
}
@@ -162,6 +169,7 @@ impl error::Error for Error {
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
use std::error::Error;
use self::Error::*;
match *self {
Install(ref n) => n.fmt(f),
@@ -177,6 +185,10 @@ impl Display for Error {
write!(f,
"infinite recursion detected: the command may not exist for this toolchain")
}
NeedMetadataUpgrade => write!(f, "{}", self.description()),
UpgradeIoError(ref e) => {
write!(f, "I/O error during upgrade: {}", e.description())
}
Custom { ref desc, .. } => write!(f, "{}", desc),
}
}

View File

@@ -243,6 +243,12 @@ fn run_multirust() -> Result<()> {
return Err(Error::InfiniteRecursion);
}
let need_metadata = try!(command_requires_metadata());
if need_metadata {
let cfg = try!(Cfg::from_env(shared_ntfy!(move |_: Notification| { })));
try!(cfg.check_metadata_version());
}
// If the executable name is not multirust*, then go straight
// to proxying
if try!(maybe_direct_proxy()) {
@@ -250,31 +256,24 @@ fn run_multirust() -> Result<()> {
}
let app_matches = cli::get().get_matches();
let cfg = try!(set_globals(Some(&app_matches)));
match app_matches.subcommand_name() {
Some("upgrade-data") | Some("delete-data") | Some("install") |
Some("uninstall") | None => {} // Don't need consistent metadata
Some(_) => {
try!(cfg.check_metadata_version());
}
}
// Make sure everything is set-up correctly
match app_matches.subcommand_name() {
Some("self") | Some("proxy") => {}
_ => {
if !test_proxies() {
if !test_installed(&cfg) {
warn!("multirust is not installed for the current user: `rustc` invocations \
will not be proxied.\n\nFor more information, run `multirust install \
--help`\n");
} else {
warn!("multirust is installed but is not set up correctly: `rustc` \
invocations will not be proxied.\n\nEnsure '{}' is on your PATH, and \
has priority.\n",
cfg.multirust_dir.join("bin").display());
if need_metadata {
match app_matches.subcommand_name() {
Some("self") | Some("proxy") => {}
_ => {
if !test_proxies() {
if !test_installed(&cfg) {
warn!("multirust is not installed for the current user: `rustc` invocations \
will not be proxied.\n\nFor more information, run `multirust install \
--help`\n");
} else {
warn!("multirust is installed but is not set up correctly: `rustc` \
invocations will not be proxied.\n\nEnsure '{}' is on your PATH, and \
has priority.\n",
cfg.multirust_dir.join("bin").display());
}
}
}
}
@@ -326,6 +325,23 @@ fn run_multirust() -> Result<()> {
}
}
fn command_requires_metadata() -> Result<bool> {
let args = env::args().collect::<Vec<_>>();
let arg1 = args.get(1).map(|s| &**s);
let arg2 = args.get(2).map(|s| &**s);
match (arg1, arg2) {
(Some("upgrade-data"), _) |
(Some("delete-data"), _) |
(Some("self"), Some("install")) => {
Ok(false)
}
(_, _) => {
Ok(true)
}
}
}
fn maybe_install(cfg: &Cfg) -> Result<()> {
let exe_path = try!(utils::current_exe());
if !test_installed(&cfg) {

View File

@@ -4,8 +4,9 @@
extern crate rust_install;
use rust_install::mock::dist::ManifestVersion;
use rust_install::mock::clitools::{self, Config,
expect_ok, run};
use rust_install::mock::clitools::{self, Config, expect_stdout_ok,
expect_ok, expect_err, run};
use rust_install::utils;
pub fn setup(f: &Fn(&Config)) {
clitools::setup(&[ManifestVersion::V2], f);
@@ -171,3 +172,38 @@ fn custom_dir_invalid_name() {
fn custom_without_rustc() {
}
#[test]
fn running_with_v2_metadata() {
setup(&|config| {
expect_ok(config, &["multirust", "default", "nightly"]);
// Replace the metadata version
utils::raw::write_file(&config.homedir.path().join("version"),
"2").unwrap();
expect_err(config, &["multirust", "default", "nightly"],
"multirust's metadata is out of date. run multirust upgrade-data");
expect_err(config, &["rustc", "--version"],
"multirust's metadata is out of date. run multirust upgrade-data");
});
}
// The thing that changed in the version bump from 2 -> 12 was the
// toolchain format. Check that on the upgrade all the toolchains.
// are deleted.
#[test]
fn upgrade_v2_metadata_to_v12() {
setup(&|config| {
expect_ok(config, &["multirust", "default", "nightly"]);
// Replace the metadata version
utils::raw::write_file(&config.homedir.path().join("version"),
"2").unwrap();
expect_ok(config, &["multirust", "upgrade-data"]);
expect_err(config, &["multirust", "show-default"],
"toolchain 'nightly' is not installed");
expect_err(config, &["rustc", "--version"],
"toolchain 'nightly' is not installed");
expect_ok(config, &["multirust", "update", "nightly"]);
expect_stdout_ok(config, &["rustc", "--version"],
"hash-n-2");
});
}