Skip to content

Commit de1349a

Browse files
committed
Fix issue-11010
1 parent 35ea623 commit de1349a

File tree

21 files changed

+148
-0
lines changed

21 files changed

+148
-0
lines changed

src/cargo/ops/cargo_add/mod.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::collections::BTreeSet;
77
use std::collections::VecDeque;
88
use std::fmt::Write;
99
use std::path::Path;
10+
use std::str::FromStr;
1011

1112
use anyhow::Context as _;
1213
use cargo_util::paths;
@@ -196,6 +197,13 @@ pub fn add(workspace: &Workspace<'_>, options: &AddOptions<'_>) -> CargoResult<(
196197
print_dep_table_msg(&mut options.config.shell(), &dep)?;
197198

198199
manifest.insert_into_table(&dep_table, &dep)?;
200+
if dep.optional == Some(true) {
201+
let is_namespaced_features_supported =
202+
check_rust_version_for_optional_dependency(options.spec.rust_version())?;
203+
if is_namespaced_features_supported {
204+
manifest.explicit_activate_optional_dependency_as_feature(&dep)?;
205+
}
206+
}
199207
manifest.gc_dep(dep.toml_key());
200208
}
201209

@@ -469,6 +477,26 @@ fn check_invalid_ws_keys(toml_key: &str, arg: &DepOp) -> CargoResult<()> {
469477
Ok(())
470478
}
471479

480+
/// When the `--optional` option is added using `cargo add`, we need to
481+
/// check the current rust-version. As the `dep:` syntax is only avaliable
482+
/// starting with Rust 1.60.0
483+
///
484+
/// `true` means that the rust-version is None or the rust-version is higher
485+
/// than the version needed.
486+
///
487+
/// Note: Previous versions can only use the implicit feature name.
488+
fn check_rust_version_for_optional_dependency(
489+
rust_version: Option<&RustVersion>,
490+
) -> CargoResult<bool> {
491+
match rust_version {
492+
Some(version) => {
493+
let syntax_support_version = RustVersion::from_str("1.60.0")?;
494+
Ok(&syntax_support_version <= version)
495+
}
496+
None => Ok(true),
497+
}
498+
}
499+
472500
/// Provide the existing dependency for the target table
473501
///
474502
/// If it doesn't exist but exists in another table, let's use that as most likely users

src/cargo/util/toml_mut/manifest.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,23 @@ impl LocalManifest {
363363
Ok(())
364364
}
365365

366+
/// Add feature entry to a Cargo.toml.
367+
pub fn explicit_activate_optional_dependency_as_feature(
368+
&mut self,
369+
dep: &Dependency,
370+
) -> CargoResult<()> {
371+
let dep_key = dep.toml_key();
372+
// Check whether `dep:<dep>` is defined in the [features] section.
373+
if !self.is_explicit_dep_activation(dep_key) {
374+
let table = self.get_table_mut(&vec![String::from("features")])?;
375+
let dep_name = dep.rename.as_deref().unwrap_or(&dep.name);
376+
let new_feature: toml_edit::Value = [format!("dep:{dep_name}")].iter().collect();
377+
table[dep_key] = toml_edit::value(new_feature);
378+
}
379+
380+
Ok(())
381+
}
382+
366383
/// Remove entry from a Cargo.toml.
367384
pub fn remove_from_table(&mut self, table_path: &[String], name: &str) -> CargoResult<()> {
368385
let parent_table = self.get_table_mut(table_path)?;

tests/testsuite/cargo_add/change_rename_target/out/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ version = "0.0.0"
66

77
[dependencies]
88
some-package = { package = "my-package2", version = "99999.0.0", optional = true }
9+
10+
[features]
11+
some-package = ["dep:some-package"]

tests/testsuite/cargo_add/detect_workspace_inherit_optional/out/primary/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@ version = "0.0.0"
44

55
[dependencies]
66
foo = { workspace = true, optional = true }
7+
8+
[features]
9+
foo = ["dep:foo"]

tests/testsuite/cargo_add/optional/out/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@ version = "0.0.0"
77
[dependencies]
88
my-package1 = { version = "99999.0.0", optional = true }
99
my-package2 = { version = "0.4.1", optional = true }
10+
11+
[features]
12+
my-package1 = ["dep:my-package1"]
13+
my-package2 = ["dep:my-package2"]

tests/testsuite/cargo_add/overwrite_git_with_path/out/primary/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ version = "0.0.0"
66

77
[dependencies]
88
cargo-list-test-fixture-dependency = { optional = true, path = "../dependency", version = "0.0.0" }
9+
10+
[features]
11+
cargo-list-test-fixture-dependency = ["dep:cargo-list-test-fixture-dependency"]

tests/testsuite/cargo_add/overwrite_inherit_optional_noop/out/primary/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@ version = "0.0.0"
44

55
[dependencies]
66
foo = { workspace = true, optional = true }
7+
8+
[features]
9+
foo = ["dep:foo"]

tests/testsuite/cargo_add/overwrite_name_noop/out/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ version = "0.0.0"
77

88
[dependencies]
99
your-face = { version = "0.0.0", path = "dependency", optional = true, default-features = false, features = ["nose", "mouth"], registry = "alternative" }
10+
11+
[features]
12+
your-face = ["dep:your-face"]

tests/testsuite/cargo_add/overwrite_no_optional_with_optional/out/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@ version = "0.0.0"
77
[dependencies]
88
my-package1 = { version = "99999.0.0", optional = true }
99
my-package2 = { version = "0.4.1", optional = true }
10+
11+
[features]
12+
my-package1 = ["dep:my-package1"]
13+
my-package2 = ["dep:my-package2"]

tests/testsuite/cargo_add/overwrite_optional/out/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@ version = "0.0.0"
77
[dependencies]
88
my-package1 = { version = "99999.0.0", optional = true }
99
my-package2 = { version = "0.4.1", optional = true }
10+
11+
[features]
12+
my-package1 = ["dep:my-package1"]
13+
my-package2 = ["dep:my-package2"]

0 commit comments

Comments
 (0)