Revert "Enable new behavior of --feature"

This reverts commit 038eec5cb3bd25a0855b0be6ad2aeba5391c6c6e.
This commit is contained in:
Aleksey Kladov 2018-04-28 17:28:39 +03:00
parent c24a09772c
commit d369f97c19
6 changed files with 160 additions and 66 deletions

View File

@ -299,6 +299,7 @@ pub struct CliUnstable {
pub no_index_update: bool, pub no_index_update: bool,
pub avoid_dev_deps: bool, pub avoid_dev_deps: bool,
pub minimal_versions: bool, pub minimal_versions: bool,
pub package_features: bool,
} }
impl CliUnstable { impl CliUnstable {
@ -332,6 +333,7 @@ impl CliUnstable {
"no-index-update" => self.no_index_update = true, "no-index-update" => self.no_index_update = true,
"avoid-dev-deps" => self.avoid_dev_deps = true, "avoid-dev-deps" => self.avoid_dev_deps = true,
"minimal-versions" => self.minimal_versions = true, "minimal-versions" => self.minimal_versions = true,
"package-features" => self.package_features = true,
_ => bail!("unknown `-Z` flag specified: {}", k), _ => bail!("unknown `-Z` flag specified: {}", k),
} }

View File

@ -155,7 +155,7 @@ impl<'a> RegistryQueryer<'a> {
} }
} }
#[derive(Clone, Copy, Eq, PartialEq)] #[derive(Clone, Copy)]
pub enum Method<'a> { pub enum Method<'a> {
Everything, // equivalent to Required { dev_deps: true, all_features: true, .. } Everything, // equivalent to Required { dev_deps: true, all_features: true, .. }
Required { Required {

View File

@ -118,7 +118,6 @@ pub struct WorkspaceRootConfig {
/// An iterator over the member packages of a workspace, returned by /// An iterator over the member packages of a workspace, returned by
/// `Workspace::members` /// `Workspace::members`
#[derive(Clone)]
pub struct Members<'a, 'cfg: 'a> { pub struct Members<'a, 'cfg: 'a> {
ws: &'a Workspace<'cfg>, ws: &'a Workspace<'cfg>,
iter: slice::Iter<'a, PathBuf>, iter: slice::Iter<'a, PathBuf>,

View File

@ -217,43 +217,86 @@ pub fn resolve_with_previous<'a, 'cfg>(
registry.add_sources(&[member.package_id().source_id().clone()])?; registry.add_sources(&[member.package_id().source_id().clone()])?;
} }
let method = match method { let mut summaries = Vec::new();
Method::Everything => Method::Everything, if ws.config().cli_unstable().package_features {
Method::Required { let mut members = Vec::new();
features, match method {
all_features, Method::Everything => members.extend(ws.members()),
uses_default_features, Method::Required {
.. features,
} => { all_features,
if specs.len() > 1 && !features.is_empty() { uses_default_features,
bail!("cannot specify features for more than one package"); ..
} } => {
let members_requested = ws.members() if specs.len() > 1 && !features.is_empty() {
.filter(|m| specs.iter().any(|spec| spec.matches(m.package_id()))) bail!("cannot specify features for more than one package");
.count(); }
if members_requested == 0 { members.extend(
// Edge case: running `cargo build -p foo`, where `foo` is not a member ws.members()
// of current workspace. Resolve whole workspace to get `foo` into the .filter(|m| specs.iter().any(|spec| spec.matches(m.package_id()))),
// resolution graph. );
if !(features.is_empty() && !all_features && uses_default_features) { // Edge case: running `cargo build -p foo`, where `foo` is not a member
bail!("cannot specify features for packages outside of workspace"); // of current workspace. Add all packages from workspace to get `foo`
// into the resolution graph.
if members.is_empty() {
if !(features.is_empty() && !all_features && uses_default_features) {
bail!("cannot specify features for packages outside of workspace");
}
members.extend(ws.members());
} }
Method::Everything
} else {
method
} }
} }
}; for member in members {
let summaries = ws.members()
.filter(|m| {
method == Method::Everything || specs.iter().any(|spec| spec.matches(m.package_id()))
})
.map(|member| {
let summary = registry.lock(member.summary().clone()); let summary = registry.lock(member.summary().clone());
(summary, method) summaries.push((summary, method))
}) }
.collect::<Vec<_>>(); } else {
for member in ws.members() {
let method_to_resolve = match method {
// When everything for a workspace we want to be sure to resolve all
// members in the workspace, so propagate the `Method::Everything`.
Method::Everything => Method::Everything,
// If we're not resolving everything though then we're constructing the
// exact crate graph we're going to build. Here we don't necessarily
// want to keep around all workspace crates as they may not all be
// built/tested.
//
// Additionally, the `method` specified represents command line
// flags, which really only matters for the current package
// (determined by the cwd). If other packages are specified (via
// `-p`) then the command line flags like features don't apply to
// them.
//
// As a result, if this `member` is the current member of the
// workspace, then we use `method` specified. Otherwise we use a
// base method with no features specified but using default features
// for any other packages specified with `-p`.
Method::Required { dev_deps, .. } => {
let base = Method::Required {
dev_deps,
features: &[],
all_features: false,
uses_default_features: true,
};
let member_id = member.package_id();
match ws.current_opt() {
Some(current) if member_id == current.package_id() => method,
_ => {
if specs.iter().any(|spec| spec.matches(member_id)) {
base
} else {
continue;
}
}
}
}
};
let summary = registry.lock(member.summary().clone());
summaries.push((summary, method_to_resolve));
}
};
let root_replace = ws.root_replace(); let root_replace = ws.root_replace();

View File

@ -1674,42 +1674,46 @@ fn combining_features_and_package() {
.build(); .build();
assert_that( assert_that(
p.cargo("build --all --features main") p.cargo("build -Z package-features --all --features main")
.masquerade_as_nightly_cargo(),
execs()
.with_status(101)
.with_stderr_contains("[ERROR] cannot specify features for more than one package"),
);
assert_that(
p.cargo("build --package dep --features main")
.masquerade_as_nightly_cargo(), .masquerade_as_nightly_cargo(),
execs().with_status(101).with_stderr_contains( execs().with_status(101).with_stderr_contains(
"[ERROR] cannot specify features for packages outside of workspace", "\
), [ERROR] cannot specify features for more than one package",
);
assert_that(
p.cargo("build --package dep --all-features")
.masquerade_as_nightly_cargo(),
execs().with_status(101).with_stderr_contains(
"[ERROR] cannot specify features for packages outside of workspace",
),
);
assert_that(
p.cargo("build --package dep --no-default-features")
.masquerade_as_nightly_cargo(),
execs().with_status(101).with_stderr_contains(
"[ERROR] cannot specify features for packages outside of workspace",
), ),
); );
assert_that( assert_that(
p.cargo("build --all --all-features") p.cargo("build -Z package-features --package dep --features main")
.masquerade_as_nightly_cargo(),
execs().with_status(101).with_stderr_contains(
"\
[ERROR] cannot specify features for packages outside of workspace",
),
);
assert_that(
p.cargo("build -Z package-features --package dep --all-features")
.masquerade_as_nightly_cargo(),
execs().with_status(101).with_stderr_contains(
"\
[ERROR] cannot specify features for packages outside of workspace",
),
);
assert_that(
p.cargo("build -Z package-features --package dep --no-default-features")
.masquerade_as_nightly_cargo(),
execs().with_status(101).with_stderr_contains(
"\
[ERROR] cannot specify features for packages outside of workspace",
),
);
assert_that(
p.cargo("build -Z package-features --all --all-features")
.masquerade_as_nightly_cargo(), .masquerade_as_nightly_cargo(),
execs().with_status(0), execs().with_status(0),
); );
assert_that( assert_that(
p.cargo("run --package foo --features main") p.cargo("run -Z package-features --package foo --features main")
.masquerade_as_nightly_cargo(), .masquerade_as_nightly_cargo(),
execs().with_status(0), execs().with_status(0),
); );

View File

@ -2863,7 +2863,13 @@ fn selective_test_optional_dep() {
let p = p.build(); let p = p.build();
assert_that( assert_that(
p.cargo("test -v --no-run --package a"), p.cargo("test")
.arg("-v")
.arg("--no-run")
.arg("--features")
.arg("a")
.arg("-p")
.arg("a"),
execs().with_status(0).with_stderr( execs().with_status(0).with_stderr(
"\ "\
[COMPILING] a v0.0.1 ([..]) [COMPILING] a v0.0.1 ([..])
@ -3050,8 +3056,6 @@ fn pass_correct_cfgs_flags_to_rustdoc() {
version = "0.1.0" version = "0.1.0"
authors = [] authors = []
[workspace]
[features] [features]
default = ["feature_a/default"] default = ["feature_a/default"]
nightly = ["feature_a/nightly"] nightly = ["feature_a/nightly"]
@ -3129,7 +3133,10 @@ fn pass_correct_cfgs_flags_to_rustdoc() {
let p = p.build(); let p = p.build();
assert_that( assert_that(
p.cargo("test --package feature_a --verbose"), p.cargo("test")
.arg("--package")
.arg("feature_a")
.arg("--verbose"),
execs().with_status(0).with_stderr_contains( execs().with_status(0).with_stderr_contains(
"\ "\
[DOCTEST] feature_a [DOCTEST] feature_a
@ -3138,7 +3145,7 @@ fn pass_correct_cfgs_flags_to_rustdoc() {
); );
assert_that( assert_that(
p.cargo("test --verbose"), p.cargo("test").arg("--verbose"),
execs().with_status(0).with_stderr_contains( execs().with_status(0).with_stderr_contains(
"\ "\
[DOCTEST] foo [DOCTEST] foo
@ -3188,6 +3195,45 @@ fn test_release_ignore_panic() {
assert_that(p.cargo("bench").arg("-v"), execs().with_status(0)); assert_that(p.cargo("bench").arg("-v"), execs().with_status(0));
} }
#[test]
fn test_many_with_features() {
let p = project("foo")
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
authors = []
[dependencies]
a = { path = "a" }
[features]
foo = []
[workspace]
"#,
)
.file("src/lib.rs", "")
.file(
"a/Cargo.toml",
r#"
[package]
name = "a"
version = "0.0.1"
authors = []
"#,
)
.file("a/src/lib.rs", "")
.build();
assert_that(
p.cargo("test -v -p a -p foo --features foo"),
execs().with_status(0),
);
}
#[test] #[test]
fn test_all_workspace() { fn test_all_workspace() {
let p = project("foo") let p = project("foo")