Skip to content

Commit 2d61f60

Browse files
authored
fix(add): Focus on error, rather than large feature lists (#15200)
### What does this PR try to resolve? Inspired by #11100 and previous work to collapse feature lists down. ### How should we test and review this PR? ### Additional information
2 parents 73a925a + 524d123 commit 2d61f60

File tree

12 files changed

+312
-29
lines changed

12 files changed

+312
-29
lines changed

src/cargo/ops/cargo_add/mod.rs

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ use crate::CargoResult;
4343
use crate::GlobalContext;
4444
use crate_spec::CrateSpec;
4545

46+
const MAX_FEATURE_PRINTS: usize = 30;
47+
4648
/// Information on what dependencies should be added
4749
#[derive(Clone, Debug)]
4850
pub struct AddOptions<'a> {
@@ -166,36 +168,44 @@ pub fn add(workspace: &Workspace<'_>, options: &AddOptions<'_>) -> CargoResult<(
166168
write!(message, "no features available for crate {}", dep.name)?;
167169
} else {
168170
if !deactivated.is_empty() {
169-
writeln!(
170-
message,
171-
"disabled features:\n {}",
172-
deactivated
173-
.iter()
174-
.map(|s| s.to_string())
175-
.coalesce(|x, y| if x.len() + y.len() < 78 {
176-
Ok(format!("{x}, {y}"))
177-
} else {
178-
Err((x, y))
179-
})
180-
.into_iter()
181-
.format("\n ")
182-
)?
171+
if deactivated.len() <= MAX_FEATURE_PRINTS {
172+
writeln!(
173+
message,
174+
"disabled features:\n {}",
175+
deactivated
176+
.iter()
177+
.map(|s| s.to_string())
178+
.coalesce(|x, y| if x.len() + y.len() < 78 {
179+
Ok(format!("{x}, {y}"))
180+
} else {
181+
Err((x, y))
182+
})
183+
.into_iter()
184+
.format("\n ")
185+
)?;
186+
} else {
187+
writeln!(message, "{} disabled features available", deactivated.len())?;
188+
}
183189
}
184190
if !activated.is_empty() {
185-
writeln!(
186-
message,
187-
"enabled features:\n {}",
188-
activated
189-
.iter()
190-
.map(|s| s.to_string())
191-
.coalesce(|x, y| if x.len() + y.len() < 78 {
192-
Ok(format!("{x}, {y}"))
193-
} else {
194-
Err((x, y))
195-
})
196-
.into_iter()
197-
.format("\n ")
198-
)?
191+
if deactivated.len() + activated.len() <= MAX_FEATURE_PRINTS {
192+
writeln!(
193+
message,
194+
"enabled features:\n {}",
195+
activated
196+
.iter()
197+
.map(|s| s.to_string())
198+
.coalesce(|x, y| if x.len() + y.len() < 78 {
199+
Ok(format!("{x}, {y}"))
200+
} else {
201+
Err((x, y))
202+
})
203+
.into_iter()
204+
.format("\n ")
205+
)?;
206+
} else {
207+
writeln!(message, "{} enabled features available", activated.len())?;
208+
}
199209
}
200210
}
201211
anyhow::bail!(message.trim().to_owned());
@@ -1114,7 +1124,6 @@ fn print_dep_table_msg(shell: &mut Shell, dep: &DependencyUI) -> CargoResult<()>
11141124

11151125
writeln!(stderr, "{prefix}Features{suffix}:")?;
11161126

1117-
const MAX_FEATURE_PRINTS: usize = 30;
11181127
let total_activated = activated.len();
11191128
let total_deactivated = deactivated.len();
11201129

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
[workspace]
2+
3+
[package]
4+
name = "cargo-list-test-fixture"
5+
version = "0.0.0"
6+
edition = "2015"
7+
8+
[dependencies.your-face]
9+
version = "99999.0.0"
10+
features = [
11+
"eyes000",
12+
"eyes001",
13+
"eyes002",
14+
"eyes003",
15+
"eyes004",
16+
"eyes005",
17+
"eyes006",
18+
"eyes007",
19+
"eyes008",
20+
"eyes009",
21+
"eyes010",
22+
"eyes011",
23+
"eyes012",
24+
"eyes013",
25+
"eyes014",
26+
"eyes015",
27+
"eyes016",
28+
"eyes017",
29+
"eyes018",
30+
"eyes019",
31+
"eyes020",
32+
"eyes021",
33+
"eyes022",
34+
"eyes023",
35+
"eyes024",
36+
"eyes025",
37+
"eyes026",
38+
"eyes027",
39+
"eyes028",
40+
"eyes029",
41+
"eyes030",
42+
"eyes031",
43+
"eyes032",
44+
"eyes033",
45+
"eyes034",
46+
"eyes035",
47+
"eyes036",
48+
"eyes037",
49+
"eyes038",
50+
"eyes039",
51+
]

tests/testsuite/cargo_add/features_error_activated_over_limit/in/src/lib.rs

Whitespace-only changes.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use cargo_test_support::compare::assert_ui;
2+
use cargo_test_support::current_dir;
3+
use cargo_test_support::file;
4+
use cargo_test_support::prelude::*;
5+
use cargo_test_support::str;
6+
use cargo_test_support::Project;
7+
8+
#[cargo_test]
9+
fn case() {
10+
const MANY_FEATURES_COUNT: usize = 50;
11+
12+
cargo_test_support::registry::init();
13+
let mut test_package =
14+
cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package");
15+
for i in 0..MANY_FEATURES_COUNT {
16+
test_package.feature(format!("eyes{i:03}").as_str(), &[]);
17+
}
18+
test_package.publish();
19+
20+
let project = Project::from_template(current_dir!().join("in"));
21+
let project_root = project.root();
22+
let cwd = &project_root;
23+
24+
let features = "eees100,eees101";
25+
snapbox::cmd::Command::cargo_ui()
26+
.arg("add")
27+
.arg_line(format!("your-face --features {features}").as_str())
28+
.current_dir(cwd)
29+
.assert()
30+
.failure()
31+
.stdout_eq(str![""])
32+
.stderr_eq(file!["stderr.term.svg"]);
33+
34+
assert_ui().subset_matches(current_dir!().join("out"), &project_root);
35+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
[workspace]
2+
3+
[package]
4+
name = "cargo-list-test-fixture"
5+
version = "0.0.0"
6+
edition = "2015"
7+
8+
[dependencies.your-face]
9+
version = "99999.0.0"
10+
features = [
11+
"eyes000",
12+
"eyes001",
13+
"eyes002",
14+
"eyes003",
15+
"eyes004",
16+
"eyes005",
17+
"eyes006",
18+
"eyes007",
19+
"eyes008",
20+
"eyes009",
21+
"eyes010",
22+
"eyes011",
23+
"eyes012",
24+
"eyes013",
25+
"eyes014",
26+
"eyes015",
27+
"eyes016",
28+
"eyes017",
29+
"eyes018",
30+
"eyes019",
31+
"eyes020",
32+
"eyes021",
33+
"eyes022",
34+
"eyes023",
35+
"eyes024",
36+
"eyes025",
37+
"eyes026",
38+
"eyes027",
39+
"eyes028",
40+
"eyes029",
41+
"eyes030",
42+
"eyes031",
43+
"eyes032",
44+
"eyes033",
45+
"eyes034",
46+
"eyes035",
47+
"eyes036",
48+
"eyes037",
49+
"eyes038",
50+
"eyes039",
51+
]
Lines changed: 40 additions & 0 deletions
Loading
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[workspace]
2+
3+
[package]
4+
name = "cargo-list-test-fixture"
5+
version = "0.0.0"
6+
edition = "2015"
7+
8+
[dependencies.your-face]
9+
version = "99999.0.0"
10+
features = [
11+
"eyes000",
12+
]

tests/testsuite/cargo_add/features_error_deactivated_over_limit/in/src/lib.rs

Whitespace-only changes.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use cargo_test_support::compare::assert_ui;
2+
use cargo_test_support::current_dir;
3+
use cargo_test_support::file;
4+
use cargo_test_support::prelude::*;
5+
use cargo_test_support::str;
6+
use cargo_test_support::Project;
7+
8+
#[cargo_test]
9+
fn case() {
10+
const MANY_FEATURES_COUNT: usize = 200;
11+
12+
cargo_test_support::registry::init();
13+
let mut test_package =
14+
cargo_test_support::registry::Package::new("your-face", "99999.0.0+my-package");
15+
for i in 0..MANY_FEATURES_COUNT {
16+
test_package.feature(format!("eyes{i:03}").as_str(), &[]);
17+
}
18+
test_package.publish();
19+
20+
let project = Project::from_template(current_dir!().join("in"));
21+
let project_root = project.root();
22+
let cwd = &project_root;
23+
24+
let features = "eees100,eees101";
25+
snapbox::cmd::Command::cargo_ui()
26+
.arg("add")
27+
.arg_line(format!("your-face --features {features}").as_str())
28+
.current_dir(cwd)
29+
.assert()
30+
.failure()
31+
.stdout_eq(str![""])
32+
.stderr_eq(file!["stderr.term.svg"]);
33+
34+
assert_ui().subset_matches(current_dir!().join("out"), &project_root);
35+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[workspace]
2+
3+
[package]
4+
name = "cargo-list-test-fixture"
5+
version = "0.0.0"
6+
edition = "2015"
7+
8+
[dependencies.your-face]
9+
version = "99999.0.0"
10+
features = [
11+
"eyes000",
12+
]
Lines changed: 36 additions & 0 deletions
Loading

tests/testsuite/cargo_add/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ mod features;
2525
mod features_activated_over_limit;
2626
mod features_deactivated_over_limit;
2727
mod features_empty;
28+
mod features_error_activated_over_limit;
29+
mod features_error_deactivated_over_limit;
2830
mod features_multiple_occurrences;
2931
mod features_preserve;
3032
mod features_spaced_values;

0 commit comments

Comments
 (0)