Skip to content

Commit

Permalink
refactor: Make placeholders explicit in VersionRange
Browse files Browse the repository at this point in the history
  • Loading branch information
epage authored and taiki-e committed Sep 6, 2023
1 parent 069699e commit 6decbf3
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 25 deletions.
60 changes: 43 additions & 17 deletions src/rustup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use anyhow::{bail, format_err, Result};
use crate::{
cargo,
context::Context,
version::{Version, VersionRange},
version::{MaybeVersion, Version, VersionRange},
};

pub(crate) struct Rustup {
Expand Down Expand Up @@ -41,39 +41,65 @@ pub(crate) fn version_range(
Ok(())
};

let VersionRange { start_inclusive, end_inclusive } = range;
let mut stable_version = None;
let mut get_stable_version = || -> Result<Version> {
if let Some(stable_version) = stable_version {
Ok(stable_version)
} else {
install_toolchain("stable", &[], false)?;
let version = cargo::version(cmd!("cargo", "+stable"))?;
stable_version = Some(version);
Ok(version)
}
};

let start_inclusive = match start_inclusive {
Some(start) => start,
None => {
let mut rust_version = None;
let mut rust_version = None;
let mut get_rust_version = || -> Result<Version> {
if let Some(rust_version) = rust_version {
Ok(rust_version)
} else {
let mut version = None;
for id in cx.workspace_members() {
let v = cx.rust_version(id);
if v.is_none() || v == rust_version {
if v.is_none() || v == version {
// no-op
} else if rust_version.is_none() {
rust_version = v;
} else if version.is_none() {
version = v;
} else {
bail!("automatic detection of the lower bound of the version range is not yet supported when the minimum supported Rust version of the crates in the workspace do not match")
}
}
match rust_version {
let version = match version {
Some(v) => v.parse()?,
None => bail!("no rust-version field in Cargo.toml is specified"),
}
};
rust_version = Some(version);
Ok(version)
}
};
check(&start_inclusive)?;

let VersionRange { start_inclusive, end_inclusive } = range;

let start_inclusive = match start_inclusive {
MaybeVersion::Version(start) => {
check(&start)?;
start
}
MaybeVersion::Msrv => {
let start = get_rust_version()?;
check(&start)?;
start
}
MaybeVersion::Stable => get_stable_version()?,
};

let end_inclusive = match end_inclusive {
Some(end) => {
MaybeVersion::Version(end) => {
check(&end)?;
end
}
None => {
install_toolchain("stable", &[], false)?;
cargo::version(cmd!("cargo", "+stable"))?
}
MaybeVersion::Msrv => get_rust_version()?,
MaybeVersion::Stable => get_stable_version()?,
};

let step = step.map(str::parse::<u8>).transpose()?.unwrap_or(1);
Expand Down
24 changes: 16 additions & 8 deletions src/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,26 @@ impl FromStr for Version {
}
}

#[derive(Copy, Clone)]
pub(crate) enum MaybeVersion {
Version(Version),
Msrv,
Stable,
}

#[derive(Copy, Clone)]
pub(crate) struct VersionRange {
pub(crate) start_inclusive: Option<Version>,
pub(crate) end_inclusive: Option<Version>,
pub(crate) start_inclusive: MaybeVersion,
pub(crate) end_inclusive: MaybeVersion,
}

impl fmt::Display for VersionRange {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(start) = self.start_inclusive {
if let MaybeVersion::Version(start) = self.start_inclusive {
write!(f, "{start}")?;
}
write!(f, "..=")?;
if let Some(end) = self.end_inclusive {
if let MaybeVersion::Version(end) = self.end_inclusive {
write!(f, "{end}")?;
}
Ok(())
Expand All @@ -56,7 +63,7 @@ impl FromStr for VersionRange {
type Err = Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let (start, end_inclusive) = if let Some((start, end)) = s.split_once("..") {
let (start, end) = if let Some((start, end)) = s.split_once("..") {
let end = match end.strip_prefix('=') {
Some(end) => end,
None => {
Expand All @@ -71,15 +78,16 @@ impl FromStr for VersionRange {
} else {
(s, None)
};
let start_inclusive = maybe_version(start)?;
let start_inclusive = maybe_version(start)?.unwrap_or(MaybeVersion::Msrv);
let end_inclusive = end.unwrap_or(MaybeVersion::Stable);
Ok(Self { start_inclusive, end_inclusive })
}
}

fn maybe_version(s: &str) -> Result<Option<Version>, Error> {
fn maybe_version(s: &str) -> Result<Option<MaybeVersion>, Error> {
if s.is_empty() {
Ok(None)
} else {
s.parse().map(Some)
s.parse().map(MaybeVersion::Version).map(Some)
}
}

0 comments on commit 6decbf3

Please sign in to comment.