Skip to content

Commit d369f97

Browse files
committed
Revert "Enable new behavior of --feature"
This reverts commit 038eec5.
1 parent c24a097 commit d369f97

File tree

6 files changed

+144
-50
lines changed

6 files changed

+144
-50
lines changed

src/cargo/core/features.rs

+2
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ pub struct CliUnstable {
299299
pub no_index_update: bool,
300300
pub avoid_dev_deps: bool,
301301
pub minimal_versions: bool,
302+
pub package_features: bool,
302303
}
303304

304305
impl CliUnstable {
@@ -332,6 +333,7 @@ impl CliUnstable {
332333
"no-index-update" => self.no_index_update = true,
333334
"avoid-dev-deps" => self.avoid_dev_deps = true,
334335
"minimal-versions" => self.minimal_versions = true,
336+
"package-features" => self.package_features = true,
335337
_ => bail!("unknown `-Z` flag specified: {}", k),
336338
}
337339

src/cargo/core/resolver/types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ impl<'a> RegistryQueryer<'a> {
155155
}
156156
}
157157

158-
#[derive(Clone, Copy, Eq, PartialEq)]
158+
#[derive(Clone, Copy)]
159159
pub enum Method<'a> {
160160
Everything, // equivalent to Required { dev_deps: true, all_features: true, .. }
161161
Required {

src/cargo/core/workspace.rs

-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ pub struct WorkspaceRootConfig {
118118

119119
/// An iterator over the member packages of a workspace, returned by
120120
/// `Workspace::members`
121-
#[derive(Clone)]
122121
pub struct Members<'a, 'cfg: 'a> {
123122
ws: &'a Workspace<'cfg>,
124123
iter: slice::Iter<'a, PathBuf>,

src/cargo/ops/resolve.rs

+74-31
Original file line numberDiff line numberDiff line change
@@ -217,43 +217,86 @@ pub fn resolve_with_previous<'a, 'cfg>(
217217
registry.add_sources(&[member.package_id().source_id().clone()])?;
218218
}
219219

220-
let method = match method {
221-
Method::Everything => Method::Everything,
222-
Method::Required {
223-
features,
224-
all_features,
225-
uses_default_features,
226-
..
227-
} => {
228-
if specs.len() > 1 && !features.is_empty() {
229-
bail!("cannot specify features for more than one package");
230-
}
231-
let members_requested = ws.members()
232-
.filter(|m| specs.iter().any(|spec| spec.matches(m.package_id())))
233-
.count();
234-
if members_requested == 0 {
220+
let mut summaries = Vec::new();
221+
if ws.config().cli_unstable().package_features {
222+
let mut members = Vec::new();
223+
match method {
224+
Method::Everything => members.extend(ws.members()),
225+
Method::Required {
226+
features,
227+
all_features,
228+
uses_default_features,
229+
..
230+
} => {
231+
if specs.len() > 1 && !features.is_empty() {
232+
bail!("cannot specify features for more than one package");
233+
}
234+
members.extend(
235+
ws.members()
236+
.filter(|m| specs.iter().any(|spec| spec.matches(m.package_id()))),
237+
);
235238
// Edge case: running `cargo build -p foo`, where `foo` is not a member
236-
// of current workspace. Resolve whole workspace to get `foo` into the
237-
// resolution graph.
238-
if !(features.is_empty() && !all_features && uses_default_features) {
239-
bail!("cannot specify features for packages outside of workspace");
239+
// of current workspace. Add all packages from workspace to get `foo`
240+
// into the resolution graph.
241+
if members.is_empty() {
242+
if !(features.is_empty() && !all_features && uses_default_features) {
243+
bail!("cannot specify features for packages outside of workspace");
244+
}
245+
members.extend(ws.members());
240246
}
241-
Method::Everything
242-
} else {
243-
method
244247
}
245248
}
246-
};
249+
for member in members {
250+
let summary = registry.lock(member.summary().clone());
251+
summaries.push((summary, method))
252+
}
253+
} else {
254+
for member in ws.members() {
255+
let method_to_resolve = match method {
256+
// When everything for a workspace we want to be sure to resolve all
257+
// members in the workspace, so propagate the `Method::Everything`.
258+
Method::Everything => Method::Everything,
259+
260+
// If we're not resolving everything though then we're constructing the
261+
// exact crate graph we're going to build. Here we don't necessarily
262+
// want to keep around all workspace crates as they may not all be
263+
// built/tested.
264+
//
265+
// Additionally, the `method` specified represents command line
266+
// flags, which really only matters for the current package
267+
// (determined by the cwd). If other packages are specified (via
268+
// `-p`) then the command line flags like features don't apply to
269+
// them.
270+
//
271+
// As a result, if this `member` is the current member of the
272+
// workspace, then we use `method` specified. Otherwise we use a
273+
// base method with no features specified but using default features
274+
// for any other packages specified with `-p`.
275+
Method::Required { dev_deps, .. } => {
276+
let base = Method::Required {
277+
dev_deps,
278+
features: &[],
279+
all_features: false,
280+
uses_default_features: true,
281+
};
282+
let member_id = member.package_id();
283+
match ws.current_opt() {
284+
Some(current) if member_id == current.package_id() => method,
285+
_ => {
286+
if specs.iter().any(|spec| spec.matches(member_id)) {
287+
base
288+
} else {
289+
continue;
290+
}
291+
}
292+
}
293+
}
294+
};
247295

248-
let summaries = ws.members()
249-
.filter(|m| {
250-
method == Method::Everything || specs.iter().any(|spec| spec.matches(m.package_id()))
251-
})
252-
.map(|member| {
253296
let summary = registry.lock(member.summary().clone());
254-
(summary, method)
255-
})
256-
.collect::<Vec<_>>();
297+
summaries.push((summary, method_to_resolve));
298+
}
299+
};
257300

258301
let root_replace = ws.root_replace();
259302

tests/testsuite/features.rs

+16-12
Original file line numberDiff line numberDiff line change
@@ -1674,42 +1674,46 @@ fn combining_features_and_package() {
16741674
.build();
16751675

16761676
assert_that(
1677-
p.cargo("build --all --features main")
1677+
p.cargo("build -Z package-features --all --features main")
16781678
.masquerade_as_nightly_cargo(),
1679-
execs()
1680-
.with_status(101)
1681-
.with_stderr_contains("[ERROR] cannot specify features for more than one package"),
1679+
execs().with_status(101).with_stderr_contains(
1680+
"\
1681+
[ERROR] cannot specify features for more than one package",
1682+
),
16821683
);
16831684

16841685
assert_that(
1685-
p.cargo("build --package dep --features main")
1686+
p.cargo("build -Z package-features --package dep --features main")
16861687
.masquerade_as_nightly_cargo(),
16871688
execs().with_status(101).with_stderr_contains(
1688-
"[ERROR] cannot specify features for packages outside of workspace",
1689+
"\
1690+
[ERROR] cannot specify features for packages outside of workspace",
16891691
),
16901692
);
16911693
assert_that(
1692-
p.cargo("build --package dep --all-features")
1694+
p.cargo("build -Z package-features --package dep --all-features")
16931695
.masquerade_as_nightly_cargo(),
16941696
execs().with_status(101).with_stderr_contains(
1695-
"[ERROR] cannot specify features for packages outside of workspace",
1697+
"\
1698+
[ERROR] cannot specify features for packages outside of workspace",
16961699
),
16971700
);
16981701
assert_that(
1699-
p.cargo("build --package dep --no-default-features")
1702+
p.cargo("build -Z package-features --package dep --no-default-features")
17001703
.masquerade_as_nightly_cargo(),
17011704
execs().with_status(101).with_stderr_contains(
1702-
"[ERROR] cannot specify features for packages outside of workspace",
1705+
"\
1706+
[ERROR] cannot specify features for packages outside of workspace",
17031707
),
17041708
);
17051709

17061710
assert_that(
1707-
p.cargo("build --all --all-features")
1711+
p.cargo("build -Z package-features --all --all-features")
17081712
.masquerade_as_nightly_cargo(),
17091713
execs().with_status(0),
17101714
);
17111715
assert_that(
1712-
p.cargo("run --package foo --features main")
1716+
p.cargo("run -Z package-features --package foo --features main")
17131717
.masquerade_as_nightly_cargo(),
17141718
execs().with_status(0),
17151719
);

tests/testsuite/test.rs

+51-5
Original file line numberDiff line numberDiff line change
@@ -2863,7 +2863,13 @@ fn selective_test_optional_dep() {
28632863
let p = p.build();
28642864

28652865
assert_that(
2866-
p.cargo("test -v --no-run --package a"),
2866+
p.cargo("test")
2867+
.arg("-v")
2868+
.arg("--no-run")
2869+
.arg("--features")
2870+
.arg("a")
2871+
.arg("-p")
2872+
.arg("a"),
28672873
execs().with_status(0).with_stderr(
28682874
"\
28692875
[COMPILING] a v0.0.1 ([..])
@@ -3050,8 +3056,6 @@ fn pass_correct_cfgs_flags_to_rustdoc() {
30503056
version = "0.1.0"
30513057
authors = []
30523058
3053-
[workspace]
3054-
30553059
[features]
30563060
default = ["feature_a/default"]
30573061
nightly = ["feature_a/nightly"]
@@ -3129,7 +3133,10 @@ fn pass_correct_cfgs_flags_to_rustdoc() {
31293133
let p = p.build();
31303134

31313135
assert_that(
3132-
p.cargo("test --package feature_a --verbose"),
3136+
p.cargo("test")
3137+
.arg("--package")
3138+
.arg("feature_a")
3139+
.arg("--verbose"),
31333140
execs().with_status(0).with_stderr_contains(
31343141
"\
31353142
[DOCTEST] feature_a
@@ -3138,7 +3145,7 @@ fn pass_correct_cfgs_flags_to_rustdoc() {
31383145
);
31393146

31403147
assert_that(
3141-
p.cargo("test --verbose"),
3148+
p.cargo("test").arg("--verbose"),
31423149
execs().with_status(0).with_stderr_contains(
31433150
"\
31443151
[DOCTEST] foo
@@ -3188,6 +3195,45 @@ fn test_release_ignore_panic() {
31883195
assert_that(p.cargo("bench").arg("-v"), execs().with_status(0));
31893196
}
31903197

3198+
#[test]
3199+
fn test_many_with_features() {
3200+
let p = project("foo")
3201+
.file(
3202+
"Cargo.toml",
3203+
r#"
3204+
[package]
3205+
name = "foo"
3206+
version = "0.0.1"
3207+
authors = []
3208+
3209+
[dependencies]
3210+
a = { path = "a" }
3211+
3212+
[features]
3213+
foo = []
3214+
3215+
[workspace]
3216+
"#,
3217+
)
3218+
.file("src/lib.rs", "")
3219+
.file(
3220+
"a/Cargo.toml",
3221+
r#"
3222+
[package]
3223+
name = "a"
3224+
version = "0.0.1"
3225+
authors = []
3226+
"#,
3227+
)
3228+
.file("a/src/lib.rs", "")
3229+
.build();
3230+
3231+
assert_that(
3232+
p.cargo("test -v -p a -p foo --features foo"),
3233+
execs().with_status(0),
3234+
);
3235+
}
3236+
31913237
#[test]
31923238
fn test_all_workspace() {
31933239
let p = project("foo")

0 commit comments

Comments
 (0)