|
1 | 1 | use crate::experiments::{Assignee, CapLints, CrateSelect, Mode};
|
2 | 2 | use crate::toolchain::Toolchain;
|
| 3 | +use failure::{self, Fallible}; |
| 4 | +use reqwest; |
| 5 | +use url::Url; |
| 6 | + |
| 7 | +#[derive(Debug, PartialEq, Eq, Hash, Clone)] |
| 8 | +pub enum DeferredCrateSelect { |
| 9 | + Direct(CrateSelect), |
| 10 | + Indirect(Url), |
| 11 | +} |
| 12 | + |
| 13 | +impl From<CrateSelect> for DeferredCrateSelect { |
| 14 | + fn from(v: CrateSelect) -> Self { |
| 15 | + DeferredCrateSelect::Direct(v) |
| 16 | + } |
| 17 | +} |
| 18 | + |
| 19 | +impl DeferredCrateSelect { |
| 20 | + pub fn resolve(self) -> Fallible<CrateSelect> { |
| 21 | + let url = match self { |
| 22 | + DeferredCrateSelect::Direct(v) => return Ok(v), |
| 23 | + DeferredCrateSelect::Indirect(url) => url, |
| 24 | + }; |
| 25 | + |
| 26 | + let body = reqwest::get(url)?.text()?; |
| 27 | + if body.contains(",") { |
| 28 | + bail!("Crate identifiers must not contain a comma"); |
| 29 | + } |
| 30 | + |
| 31 | + let crates = body |
| 32 | + .split(|c: char| c.is_whitespace()) |
| 33 | + .map(|s| s.to_owned()) |
| 34 | + .collect(); |
| 35 | + Ok(CrateSelect::List(crates).into()) |
| 36 | + } |
| 37 | +} |
| 38 | + |
| 39 | +impl FromStr for DeferredCrateSelect { |
| 40 | + type Err = failure::Error; |
| 41 | + |
| 42 | + fn from_str(input: &str) -> Fallible<Self> { |
| 43 | + if input.starts_with("https://") || input.starts_with("http://") { |
| 44 | + Ok(DeferredCrateSelect::Indirect(input.parse()?)) |
| 45 | + } else { |
| 46 | + Ok(DeferredCrateSelect::Direct(input.parse()?)) |
| 47 | + } |
| 48 | + } |
| 49 | +} |
3 | 50 |
|
4 | 51 | #[derive(Debug, Fail)]
|
5 | 52 | #[cfg_attr(test, derive(PartialEq, Eq))]
|
@@ -107,7 +154,7 @@ generate_parser!(pub enum Command {
|
107 | 154 | start: Option<Toolchain> = "start",
|
108 | 155 | end: Option<Toolchain> = "end",
|
109 | 156 | mode: Option<Mode> = "mode",
|
110 |
| - crates: Option<CrateSelect> = "crates", |
| 157 | + crates: Option<DeferredCrateSelect> = "crates", |
111 | 158 | cap_lints: Option<CapLints> = "cap-lints",
|
112 | 159 | priority: Option<i32> = "p",
|
113 | 160 | ignore_blacklist: Option<bool> = "ignore-blacklist",
|
@@ -136,7 +183,7 @@ generate_parser!(pub enum Command {
|
136 | 183 | start: Option<Toolchain> = "start",
|
137 | 184 | end: Option<Toolchain> = "end",
|
138 | 185 | mode: Option<Mode> = "mode",
|
139 |
| - crates: Option<CrateSelect> = "crates", |
| 186 | + crates: Option<DeferredCrateSelect> = "crates", |
140 | 187 | cap_lints: Option<CapLints> = "cap-lints",
|
141 | 188 | priority: Option<i32> = "p",
|
142 | 189 | ignore_blacklist: Option<bool> = "ignore-blacklist",
|
|
0 commit comments