Skip to content

Commit 5e7f650

Browse files
committed
Introduce InstalledToolchain
And use it to move update_hash to DistributableToolchain
1 parent 53fca75 commit 5e7f650

File tree

1 file changed

+73
-18
lines changed

1 file changed

+73
-18
lines changed

src/toolchain.rs

Lines changed: 73 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ use std::time::Duration;
2525
use url::Url;
2626
use wait_timeout::ChildExt;
2727

28+
/// An installed toolchain
29+
trait InstalledToolchain<'a> {
30+
/// What (root) paths are associated with this installed toolchain.
31+
fn installed_paths(&self) -> Result<Vec<InstalledPath<'a>>>;
32+
}
33+
34+
/// Installed paths
35+
enum InstalledPath<'a> {
36+
File { name: &'static str, path: PathBuf },
37+
Dir { path: &'a Path },
38+
}
39+
2840
/// A fully resolved reference to a toolchain which may or may not exist
2941
pub struct Toolchain<'a> {
3042
cfg: &'a Cfg,
@@ -59,6 +71,17 @@ impl<'a> Toolchain<'a> {
5971
dist_handler: Box::new(move |n| (cfg.notify_handler)(n.into())),
6072
})
6173
}
74+
75+
fn as_installed(&'a self) -> Result<Box<dyn InstalledToolchain<'a> + 'a>> {
76+
if self.is_custom() {
77+
let toolchain = CustomToolchain::new(self)?;
78+
Ok(Box::new(toolchain) as Box<dyn InstalledToolchain<'a>>)
79+
} else {
80+
let toolchain = DistributableToolchain::new(self)?;
81+
Ok(Box::new(toolchain) as Box<dyn InstalledToolchain<'a>>)
82+
}
83+
}
84+
6285
pub fn name(&self) -> &str {
6386
&self.name
6487
}
@@ -99,14 +122,19 @@ impl<'a> Toolchain<'a> {
99122
(self.cfg.notify_handler)(Notification::ToolchainNotInstalled(&self.name));
100123
return Ok(());
101124
}
102-
if let Some(update_hash) = self.update_hash()? {
103-
utils::ensure_file_removed("update hash", &update_hash)?;
125+
let installed = self.as_installed()?;
126+
for path in installed.installed_paths()? {
127+
match path {
128+
InstalledPath::File { name, path } => utils::ensure_file_removed(&name, &path)?,
129+
InstalledPath::Dir { path } => {
130+
install::uninstall(path, &|n| (self.cfg.notify_handler)(n.into()))?
131+
}
132+
}
104133
}
105-
let result = install::uninstall(&self.path, &|n| (self.cfg.notify_handler)(n.into()));
106134
if !self.exists() {
107135
(self.cfg.notify_handler)(Notification::UninstalledToolchain(&self.name));
108136
}
109-
result
137+
Ok(())
110138
}
111139
// Custom and Distributable. Installed and not installed.
112140
fn install(&self, install_method: InstallMethod<'_>) -> Result<UpdateStatus> {
@@ -160,14 +188,6 @@ impl<'a> Toolchain<'a> {
160188
InstallMethod::Dist(..) => !self.is_custom(),
161189
}
162190
}
163-
// Distributable only probably (once update_hash is only called appropriately). Installed only.
164-
fn update_hash(&self) -> Result<Option<PathBuf>> {
165-
if self.is_custom() {
166-
Ok(None)
167-
} else {
168-
Ok(Some(self.cfg.get_hash_file(&self.name, true)?))
169-
}
170-
}
171191

172192
// XXX: Move to Config with a notify handler parameter
173193
fn download_cfg(&self) -> DownloadCfg<'_> {
@@ -538,6 +558,23 @@ impl<'a> Toolchain<'a> {
538558
/// Newtype to facilitate splitting out custom-toolchain specific code.
539559
pub struct CustomToolchain<'a>(&'a Toolchain<'a>);
540560

561+
impl<'a> CustomToolchain<'a> {
562+
pub fn new(toolchain: &'a Toolchain<'a>) -> Result<CustomToolchain<'a>> {
563+
if toolchain.is_custom() {
564+
Ok(CustomToolchain(&toolchain))
565+
} else {
566+
Err(format!("{} is not a custom toolchain", toolchain.name()).into())
567+
}
568+
}
569+
}
570+
571+
impl<'a> InstalledToolchain<'a> for CustomToolchain<'a> {
572+
fn installed_paths(&self) -> Result<Vec<InstalledPath<'a>>> {
573+
let path = &self.0.path;
574+
Ok(vec![InstalledPath::Dir { path }])
575+
}
576+
}
577+
541578
/// Newtype to facilitate splitting out distributable-toolchain specific code.
542579
pub struct DistributableToolchain<'a>(&'a Toolchain<'a>);
543580

@@ -726,12 +763,12 @@ impl<'a> DistributableToolchain<'a> {
726763
components: &[&str],
727764
targets: &[&str],
728765
) -> Result<UpdateStatus> {
729-
let update_hash = self.0.update_hash()?;
766+
let update_hash = self.update_hash()?;
730767
let old_date = self.get_manifest().ok().and_then(|m| m.map(|m| m.date));
731768
self.0.install(InstallMethod::Dist(
732769
&self.desc()?,
733770
self.0.cfg.get_profile()?,
734-
update_hash.as_ref().map(|p| &**p),
771+
Some(&update_hash),
735772
self.0.download_cfg(),
736773
force_update,
737774
allow_downgrade,
@@ -744,11 +781,11 @@ impl<'a> DistributableToolchain<'a> {
744781

745782
// Installed or not installed.
746783
pub fn install_from_dist_if_not_installed(&self) -> Result<UpdateStatus> {
747-
let update_hash = self.0.update_hash()?;
784+
let update_hash = self.update_hash()?;
748785
self.0.install_if_not_installed(InstallMethod::Dist(
749786
&self.desc()?,
750787
self.0.cfg.get_profile()?,
751-
update_hash.as_ref().map(|p| &**p),
788+
Some(&update_hash),
752789
self.0.download_cfg(),
753790
false,
754791
false,
@@ -884,11 +921,11 @@ impl<'a> DistributableToolchain<'a> {
884921

885922
// Installed only.
886923
pub fn show_dist_version(&self) -> Result<Option<String>> {
887-
let update_hash = self.0.update_hash()?;
924+
let update_hash = self.update_hash()?;
888925

889926
match crate::dist::dist::dl_v2_manifest(
890927
self.0.download_cfg(),
891-
update_hash.as_ref().map(|p| &**p),
928+
Some(&update_hash),
892929
&self.desc()?,
893930
)? {
894931
Some((manifest, _)) => Ok(Some(manifest.get_rust_version()?.to_string())),
@@ -903,4 +940,22 @@ impl<'a> DistributableToolchain<'a> {
903940
None => Ok(None),
904941
}
905942
}
943+
944+
// Installed only.
945+
fn update_hash(&self) -> Result<PathBuf> {
946+
Ok(self.0.cfg.get_hash_file(&self.0.name, true)?)
947+
}
948+
}
949+
950+
impl<'a> InstalledToolchain<'a> for DistributableToolchain<'a> {
951+
fn installed_paths(&self) -> Result<Vec<InstalledPath<'a>>> {
952+
let path = &self.0.path;
953+
Ok(vec![
954+
InstalledPath::File {
955+
name: "update hash",
956+
path: self.update_hash()?,
957+
},
958+
InstalledPath::Dir { path },
959+
])
960+
}
906961
}

0 commit comments

Comments
 (0)