Skip to content

Commit 5cee333

Browse files
committed
WIP: Thoughts on #2458
Signed-off-by: Daniel Silverstone (WSL2) <dsilvers@digital-scurf.org>
1 parent c89d1ed commit 5cee333

File tree

3 files changed

+70
-10
lines changed

3 files changed

+70
-10
lines changed

src/config.rs

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ impl OverrideFile {
3333
#[derive(Debug, Default, Deserialize, PartialEq, Eq)]
3434
struct ToolchainSection {
3535
channel: Option<String>,
36+
path: Option<String>,
3637
components: Option<Vec<String>>,
3738
targets: Option<Vec<String>>,
3839
}
@@ -45,11 +46,21 @@ impl ToolchainSection {
4546

4647
impl<T: Into<String>> From<T> for OverrideFile {
4748
fn from(channel: T) -> Self {
48-
Self {
49-
toolchain: ToolchainSection {
50-
channel: Some(channel.into()),
51-
..Default::default()
52-
},
49+
let channel = channel.into();
50+
if channel.contains('/') || channel.contains('\\') {
51+
Self {
52+
toolchain: ToolchainSection {
53+
path: Some(channel),
54+
..Default::default()
55+
},
56+
}
57+
} else {
58+
Self {
59+
toolchain: ToolchainSection {
60+
channel: Some(channel),
61+
..Default::default()
62+
},
63+
}
5364
}
5465
}
5566
}
@@ -73,7 +84,7 @@ impl Display for OverrideReason {
7384
}
7485
}
7586

76-
#[derive(Default)]
87+
#[derive(Default, Debug)]
7788
struct OverrideCfg<'a> {
7889
toolchain: Option<Toolchain<'a>>,
7990
components: Vec<String>,
@@ -83,9 +94,13 @@ struct OverrideCfg<'a> {
8394
impl<'a> OverrideCfg<'a> {
8495
fn from_file(cfg: &'a Cfg, file: OverrideFile) -> Result<Self> {
8596
Ok(Self {
86-
toolchain: match file.toolchain.channel {
87-
Some(name) => Some(Toolchain::from(cfg, &name)?),
88-
None => None,
97+
toolchain: match (file.toolchain.channel, file.toolchain.path) {
98+
(Some(name), None) => Some(Toolchain::from(cfg, &name)?),
99+
(None, Some(path)) => Some(Toolchain::from_path(cfg, &path)?),
100+
(Some(channel), Some(path)) => {
101+
return Err(ErrorKind::CannotSpecifyChannelAndPath(channel, path.into()).into())
102+
}
103+
(None, None) => None,
89104
},
90105
components: file.toolchain.components.unwrap_or_default(),
91106
targets: file.toolchain.targets.unwrap_or_default(),
@@ -514,7 +529,6 @@ impl Cfg {
514529
path.display()
515530
),
516531
};
517-
518532
let override_cfg = OverrideCfg::from_file(self, file)?;
519533
if let Some(toolchain) = &override_cfg.toolchain {
520534
// Overridden toolchains can be literally any string, but only
@@ -882,6 +896,7 @@ mod tests {
882896
OverrideFile {
883897
toolchain: ToolchainSection {
884898
channel: Some(contents.into()),
899+
path: None,
885900
components: None,
886901
targets: None,
887902
}
@@ -903,6 +918,7 @@ targets = [ "wasm32-unknown-unknown", "thumbv2-none-eabi" ]
903918
OverrideFile {
904919
toolchain: ToolchainSection {
905920
channel: Some("nightly-2020-07-10".into()),
921+
path: None,
906922
components: Some(vec!["rustfmt".into(), "rustc-dev".into()]),
907923
targets: Some(vec![
908924
"wasm32-unknown-unknown".into(),
@@ -925,6 +941,7 @@ channel = "nightly-2020-07-10"
925941
OverrideFile {
926942
toolchain: ToolchainSection {
927943
channel: Some("nightly-2020-07-10".into()),
944+
path: None,
928945
components: None,
929946
targets: None,
930947
}
@@ -945,6 +962,7 @@ components = []
945962
OverrideFile {
946963
toolchain: ToolchainSection {
947964
channel: Some("nightly-2020-07-10".into()),
965+
path: None,
948966
components: Some(vec![]),
949967
targets: None,
950968
}
@@ -965,6 +983,7 @@ targets = []
965983
OverrideFile {
966984
toolchain: ToolchainSection {
967985
channel: Some("nightly-2020-07-10".into()),
986+
path: None,
968987
components: None,
969988
targets: Some(vec![]),
970989
}
@@ -984,6 +1003,7 @@ components = [ "rustfmt" ]
9841003
OverrideFile {
9851004
toolchain: ToolchainSection {
9861005
channel: None,
1006+
path: None,
9871007
components: Some(vec!["rustfmt".into()]),
9881008
targets: None,
9891009
}

src/errors.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,14 @@ error_chain! {
188188
description("invalid toolchain name")
189189
display("invalid toolchain name: '{}'", t)
190190
}
191+
InvalidToolchainPath(p: PathBuf) {
192+
description("invalid toolchain path"),
193+
display("invalid toolchain path: '{}'", p.display())
194+
}
195+
CannotSpecifyChannelAndPath(channel: String, path: PathBuf) {
196+
description("cannot specify channel and path simultaneously"),
197+
display("cannot specify both channel ({}) and path ({}) simultaneously", channel, path.display())
198+
}
191199
InvalidProfile(t: String) {
192200
description("invalid profile name")
193201
display("invalid profile name: '{}'; valid names are: {}", t, valid_profile_names())

src/toolchain.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ pub enum UpdateStatus {
6363

6464
impl<'a> Toolchain<'a> {
6565
pub fn from(cfg: &'a Cfg, name: &str) -> Result<Self> {
66+
if name.contains('/') || name.contains('\\') {
67+
return Self::from_path(cfg, name);
68+
}
6669
let resolved_name = cfg.resolve_toolchain(name)?;
6770
let path = cfg.toolchains_dir.join(&resolved_name);
6871
Ok(Toolchain {
@@ -73,6 +76,26 @@ impl<'a> Toolchain<'a> {
7376
})
7477
}
7578

79+
pub fn from_path(cfg: &'a Cfg, path: impl AsRef<Path>) -> Result<Self> {
80+
let path = path.as_ref();
81+
let base = path
82+
.components()
83+
.last()
84+
.ok_or_else(|| ErrorKind::InvalidToolchainPath(path.into()))?
85+
.as_os_str()
86+
.to_string_lossy();
87+
// Perform minimal validation - that there's a `bin/` which might contain things for us to run
88+
if !path.join("bin").is_dir() {
89+
return Err(ErrorKind::InvalidToolchainPath(path.into()).into());
90+
}
91+
Ok(Toolchain {
92+
cfg,
93+
name: base.into(),
94+
path: path.to_path_buf(),
95+
dist_handler: Box::new(move |n| (cfg.notify_handler)(n.into())),
96+
})
97+
}
98+
7699
pub fn as_installed_common(&'a self) -> Result<InstalledCommonToolchain<'a>> {
77100
if !self.exists() {
78101
// Should be verify perhaps?
@@ -250,6 +273,15 @@ impl<'a> Toolchain<'a> {
250273
}
251274
}
252275

276+
impl<'a> std::fmt::Debug for Toolchain<'a> {
277+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
278+
f.debug_struct("Toolchain")
279+
.field("name", &self.name)
280+
.field("path", &self.path)
281+
.finish()
282+
}
283+
}
284+
253285
/// Newtype hosting functions that apply to both custom and distributable toolchains that are installed.
254286
pub struct InstalledCommonToolchain<'a>(&'a Toolchain<'a>);
255287

0 commit comments

Comments
 (0)