Skip to content

Commit

Permalink
Support omitting lower bound of --version-range
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Dec 29, 2021
1 parent 7e5db5c commit 9f201ba
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 14 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ jobs:
with:
persist-credentials: false
- uses: taiki-e/github-actions/install-rust@main
with:
toolchain: stable
- run: CARGO_HACK_TEST_TOOLCHAIN=${{ matrix.rust }} cargo test --all
# Remove stable toolchain to disable https://github.com/taiki-e/cargo-hack/pull/138's behavior.
- run: rustup toolchain remove stable
- run: CARGO_HACK_TEST_TOOLCHAIN=${{ matrix.rust }} cargo test --all

build:
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Note: In this file, do not use the hard wrap in the middle of a sentence for com

- Fix an error when using old cargo with a dependency graph containing 2021 edition crates. ([#138](https://github.com/taiki-e/cargo-hack/pull/138))

- Support omitting lower bound of --version-range. ([#139](https://github.com/taiki-e/cargo-hack/pull/139))

## [0.5.8] - 2021-10-13

- Distribute statically linked binary on Windows MSVC. ([#131](https://github.com/taiki-e/cargo-hack/pull/131))
Expand Down
11 changes: 6 additions & 5 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{

use anyhow::{bail, format_err, Error, Result};

use crate::{rustup, term, Feature, Rustup};
use crate::{term, Feature, Rustup};

pub(crate) struct Args<'a> {
pub(crate) leading_args: Vec<&'a str>,
Expand Down Expand Up @@ -40,8 +40,10 @@ pub(crate) struct Args<'a> {
pub(crate) clean_per_run: bool,
/// --clean-per-version
pub(crate) clean_per_version: bool,
/// --version-range and --version-step
pub(crate) version_range: Option<Vec<String>>,
/// --version-range
pub(crate) version_range: Option<&'a str>,
/// --version-step
pub(crate) version_step: Option<&'a str>,

// options for --each-feature and --feature-powerset
/// --optional-deps [DEPS]...
Expand Down Expand Up @@ -361,8 +363,6 @@ pub(crate) fn parse_args<'a>(raw: &'a [String], cargo: &OsStr) -> Result<Args<'a
v.push(Feature::group(g));
Ok(v)
})?;
let version_range =
version_range.map(|range| rustup::version_range(range, version_step)).transpose()?;

if let Some(subcommand) = subcommand {
match subcommand {
Expand Down Expand Up @@ -499,6 +499,7 @@ pub(crate) fn parse_args<'a>(raw: &'a [String], cargo: &OsStr) -> Result<Args<'a
include_features: include_features.into_iter().map(Into::into).collect(),
include_deps_features,
version_range,
version_step,

depth,
group_features,
Expand Down
9 changes: 8 additions & 1 deletion src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::{
features::Features,
manifest::Manifest,
metadata::{Metadata, Package, PackageId},
restore, term, ProcessBuilder,
restore, rustup, term, ProcessBuilder,
};

pub(crate) struct Context<'a> {
Expand All @@ -25,6 +25,7 @@ pub(crate) struct Context<'a> {
cargo: PathBuf,
pub(crate) restore: restore::Manager,
pub(crate) current_dir: PathBuf,
pub(crate) version_range: Option<Vec<String>>,
}

impl<'a> Context<'a> {
Expand All @@ -45,6 +46,11 @@ impl<'a> Context<'a> {
bail!("--include-deps-features requires Cargo 1.41 or later");
}

let version_range = args
.version_range
.map(|range| rustup::version_range(range, args.version_step, &metadata))
.transpose()?;

let mut pkg_features = HashMap::with_capacity(metadata.workspace_members.len());
for id in &metadata.workspace_members {
let features = Features::new(&metadata, id);
Expand All @@ -59,6 +65,7 @@ impl<'a> Context<'a> {
cargo: cargo.into(),
restore,
current_dir: env::current_dir()?,
version_range,
};

// Only a few options require information from cargo manifest.
Expand Down
29 changes: 26 additions & 3 deletions src/rustup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::str;

use anyhow::{bail, format_err, Result};

use crate::{cargo, version::Version};
use crate::{cargo, metadata::Metadata, version::Version};

pub(crate) struct Rustup {
pub(crate) version: u32,
Expand All @@ -19,7 +19,11 @@ impl Rustup {
}
}

pub(crate) fn version_range(range: &str, step: Option<&str>) -> Result<Vec<String>> {
pub(crate) fn version_range(
range: &str,
step: Option<&str>,
metadata: &Metadata,
) -> Result<Vec<String>> {
let check = |version: &Version| {
if version.major != 1 {
bail!("major version must be 1");
Expand All @@ -35,7 +39,26 @@ pub(crate) fn version_range(range: &str, step: Option<&str>) -> Result<Vec<Strin
};

let mut split = range.splitn(2, "..");
let start = split.next().map(str::parse).unwrap()?;
let start = match split.next().unwrap() {
"" => {
let mut rust_version = None;
for id in &metadata.workspace_members {
let v = metadata.packages[id].rust_version.as_deref();
if v.is_none() || v == rust_version {
// no-op
} else if rust_version.is_none() {
rust_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 {
Some(v) => v.parse()?,
None => bail!("no rust-version field in Cargo.toml is specified"),
}
}
s => s.parse()?,
};
check(&start)?;

let end = match split.next() {
Expand Down
8 changes: 8 additions & 0 deletions tests/auxiliary/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ fn test_version() -> Option<u32> {
*TEST_VERSION
}

pub fn has_stable_toolchain() -> bool {
static HAS_STABLE_TOOLCHAIN: Lazy<Option<bool>> = Lazy::new(|| {
let output = Command::new("rustup").args(&["toolchain", "list"]).output().ok()?;
Some(String::from_utf8(output.stdout).ok()?.contains("stable"))
});
HAS_STABLE_TOOLCHAIN.unwrap_or_default()
}

pub fn cargo_hack<O: AsRef<OsStr>>(args: impl AsRef<[O]>) -> Command {
let args = args.as_ref();
let mut cmd = cargo_bin_exe();
Expand Down
8 changes: 5 additions & 3 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ mod auxiliary;

use std::env;

use auxiliary::{cargo_bin_exe, cargo_hack, target_triple, CommandExt, SEPARATOR};
use auxiliary::{
cargo_bin_exe, cargo_hack, has_stable_toolchain, target_triple, CommandExt, SEPARATOR,
};

#[test]
fn failures() {
Expand Down Expand Up @@ -590,7 +592,7 @@ fn powerset_deduplication_include_deps_features() {
// TODO: Since easytime/default depends on easytime/std, their combination should be excluded,
// but it's not working yet because include-deps-features itself isn't fully implemented.
cargo_hack(["check", "--feature-powerset", "--include-deps-features"])
.assert_success2("powerset_deduplication", Some(41))
.assert_success2("powerset_deduplication", Some(if has_stable_toolchain() { 34 } else { 41 }))
.stderr_contains(
"
running `cargo check --no-default-features` on deduplication (1/41)
Expand Down Expand Up @@ -985,7 +987,7 @@ fn each_feature_all() {
#[test]
fn include_deps_features() {
cargo_hack(["check", "--each-feature", "--include-deps-features"])
.assert_success2("powerset_deduplication", Some(41))
.assert_success2("powerset_deduplication", Some(if has_stable_toolchain() { 34 } else { 41 }))
.stderr_contains(
"
running `cargo check --no-default-features` on deduplication (1/9)
Expand Down

0 comments on commit 9f201ba

Please sign in to comment.