Skip to content

Commit 60e65ee

Browse files
committed
Auto merge of #13046 - linyihai:cargo-add-public, r=epage
Add `--public` for `cargo add` ## What does this PR try to resolve? Complete #13037 This PR want to add `--public/--no public` flag for `cargo add` Note: this assumes we'll remove workspace inheritance support for `public` as it sounds like we'll be reverting it rust-lang/rust#44663 (comment). If we decide to keep workspace inheritance, we'll need to come back and update this. ## How should we test and review this PR? Most of Code were reference `cargo add --optional`, So can reviewed the new code based on the part of `optional` code. The new testcases were origin from the `cargo add --optional` part. - `public` testcase:there is no dependencies and will be add `public` dependencies. - `no_public` testcase: there is no dependencies and will be add `no_public` dependencies. - `overwrite_public` testcase: the dependencies already exists but will be overwrite with `public`. - `overwrite_no_public` testcase: the dependencies already exists but will be overwrite with `no_public`. - `overwrite_public_with_no_public` testcase: the dependencies already marked as `no_public` and will be overwrite with `public`. - `overwrite_no_public_with_public` testcase: the dependencies already marked as `public` and will be overwrite with `no_public`.
2 parents 3d98b5e + 48c998f commit 60e65ee

File tree

52 files changed

+406
-7
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+406
-7
lines changed

src/bin/cargo/commands/add.rs

+19
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,19 @@ The package name will be exposed as feature of your crate.")
6262
The package will be removed from your features.")
6363
.conflicts_with("dev")
6464
.overrides_with("optional"),
65+
flag("public", "Mark the dependency as public")
66+
.conflicts_with("dev")
67+
.conflicts_with("build")
68+
.long_help("Mark the dependency as public
69+
70+
The dependency can be referenced in your library's public API."),
71+
flag("no-public", "Mark the dependency as private")
72+
.conflicts_with("dev")
73+
.conflicts_with("build")
74+
.overrides_with("public")
75+
.long_help("Mark the dependency as private
76+
77+
While you can use the crate in your implementation, it cannot be referenced in your public API."),
6578
clap::Arg::new("rename")
6679
.long("rename")
6780
.action(ArgAction::Set)
@@ -235,6 +248,7 @@ fn parse_dependencies(config: &Config, matches: &ArgMatches) -> CargoResult<Vec<
235248
};
236249
let default_features = default_features(matches);
237250
let optional = optional(matches);
251+
let public = public(matches);
238252

239253
let mut crates = matches
240254
.get_many::<String>("crates")
@@ -325,6 +339,7 @@ fn parse_dependencies(config: &Config, matches: &ArgMatches) -> CargoResult<Vec<
325339
features,
326340
default_features,
327341
optional,
342+
public,
328343
registry: registry.clone(),
329344
path: path.map(String::from),
330345
git: git.map(String::from),
@@ -353,6 +368,10 @@ fn optional(matches: &ArgMatches) -> Option<bool> {
353368
resolve_bool_arg(matches.flag("optional"), matches.flag("no-optional"))
354369
}
355370

371+
fn public(matches: &ArgMatches) -> Option<bool> {
372+
resolve_bool_arg(matches.flag("public"), matches.flag("no-public"))
373+
}
374+
356375
fn resolve_bool_arg(yes: bool, no: bool) -> Option<bool> {
357376
match (yes, no) {
358377
(true, false) => Some(true),

src/cargo/ops/cargo_add/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,9 @@ pub struct DepOp {
244244
/// Whether dependency is optional
245245
pub optional: Option<bool>,
246246

247+
/// Whether dependency is public
248+
pub public: Option<bool>,
249+
247250
/// Registry for looking up dependency version
248251
pub registry: Option<String>,
249252

@@ -758,6 +761,13 @@ fn populate_dependency(mut dependency: Dependency, arg: &DepOp) -> Dependency {
758761
dependency.optional = None;
759762
}
760763
}
764+
if let Some(value) = arg.public {
765+
if value {
766+
dependency.public = Some(true);
767+
} else {
768+
dependency.public = None;
769+
}
770+
}
761771
if let Some(value) = arg.default_features {
762772
if value {
763773
dependency.default_features = None;
@@ -945,6 +955,9 @@ fn print_action_msg(shell: &mut Shell, dep: &DependencyUI, section: &[String]) -
945955
if dep.optional().unwrap_or(false) {
946956
write!(message, " optional")?;
947957
}
958+
if dep.public().unwrap_or(false) {
959+
write!(message, " public")?;
960+
}
948961
let section = if section.len() == 1 {
949962
section[0].clone()
950963
} else {

src/cargo/util/toml_mut/dependency.rs

+32-7
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ pub struct Dependency {
2525
/// Whether the dependency is opted-in with a feature flag.
2626
pub optional: Option<bool>,
2727

28+
/// Whether the dependency is marked as public.
29+
pub public: Option<bool>,
30+
2831
/// List of features to add (or None to keep features unchanged).
2932
pub features: Option<IndexSet<String>>,
3033
/// Whether default features are enabled.
@@ -48,6 +51,7 @@ impl Dependency {
4851
Self {
4952
name: name.into(),
5053
optional: None,
54+
public: None,
5155
features: None,
5256
default_features: None,
5357
inherited_features: None,
@@ -163,6 +167,11 @@ impl Dependency {
163167
self.optional
164168
}
165169

170+
/// Get whether the dep is public.
171+
pub fn public(&self) -> Option<bool> {
172+
self.public
173+
}
174+
166175
/// Get the SourceID for this dependency.
167176
pub fn source_id(&self, config: &Config) -> CargoResult<MaybeWorkspace<SourceId>> {
168177
match &self.source.as_ref() {
@@ -325,16 +334,18 @@ impl Dependency {
325334
};
326335

327336
let optional = table.get("optional").and_then(|v| v.as_bool());
337+
let public = table.get("public").and_then(|v| v.as_bool());
328338

329339
let dep = Self {
330340
name,
331-
rename,
332-
source: Some(source),
333-
registry,
334-
default_features,
335-
features,
336341
optional,
342+
public,
343+
features,
344+
default_features,
337345
inherited_features: None,
346+
source: Some(source),
347+
registry,
348+
rename,
338349
};
339350
Ok(dep)
340351
} else {
@@ -366,6 +377,7 @@ impl Dependency {
366377
crate_root.display()
367378
);
368379
let table: toml_edit::Item = match (
380+
self.public.unwrap_or(false),
369381
self.optional.unwrap_or(false),
370382
self.features.as_ref(),
371383
self.default_features.unwrap_or(true),
@@ -375,21 +387,22 @@ impl Dependency {
375387
) {
376388
// Extra short when version flag only
377389
(
390+
false,
378391
false,
379392
None,
380393
true,
381394
Some(Source::Registry(RegistrySource { version: v })),
382395
None,
383396
None,
384397
) => toml_edit::value(v),
385-
(false, None, true, Some(Source::Workspace(WorkspaceSource {})), None, None) => {
398+
(false, false, None, true, Some(Source::Workspace(WorkspaceSource {})), None, None) => {
386399
let mut table = toml_edit::InlineTable::default();
387400
table.set_dotted(true);
388401
table.insert("workspace", true.into());
389402
toml_edit::value(toml_edit::Value::InlineTable(table))
390403
}
391404
// Other cases are represented as an inline table
392-
(_, _, _, _, _, _) => {
405+
(_, _, _, _, _, _, _) => {
393406
let mut table = toml_edit::InlineTable::default();
394407

395408
match &self.source {
@@ -442,6 +455,9 @@ impl Dependency {
442455
if let Some(v) = self.optional {
443456
table.insert("optional", v.into());
444457
}
458+
if let Some(v) = self.public {
459+
table.insert("public", v.into());
460+
}
445461

446462
toml_edit::value(toml_edit::Value::InlineTable(table))
447463
}
@@ -579,6 +595,15 @@ impl Dependency {
579595
table.remove("optional");
580596
}
581597
}
598+
match self.public {
599+
Some(v) => {
600+
table.set_dotted(false);
601+
overwrite_value(table, "public", v);
602+
}
603+
None => {
604+
table.remove("public");
605+
}
606+
}
582607
} else {
583608
unreachable!("Invalid dependency type: {}", item.type_name());
584609
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[workspace]
2+
members = ["primary", "dependency"]
3+
4+
[workspace.dependencies]
5+
foo = { version = "0.0.0", path = "./dependency"}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[package]
2+
name = "foo"
3+
version = "0.0.0"

tests/testsuite/cargo_add/detect_workspace_inherit_public/in/dependency/src/lib.rs

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
cargo-features = ["public-dependency"]
2+
[package]
3+
name = "bar"
4+
version = "0.0.0"

tests/testsuite/cargo_add/detect_workspace_inherit_public/in/primary/src/lib.rs

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use cargo_test_support::compare::assert_ui;
2+
use cargo_test_support::prelude::*;
3+
use cargo_test_support::Project;
4+
5+
use cargo_test_support::curr_dir;
6+
7+
#[cargo_test]
8+
fn case() {
9+
cargo_test_support::registry::init();
10+
11+
let project = Project::from_template(curr_dir!().join("in"));
12+
let project_root = project.root();
13+
let cwd = &project_root;
14+
15+
snapbox::cmd::Command::cargo_ui()
16+
.arg("add")
17+
.args(["foo", "-p", "bar", "--public"])
18+
.masquerade_as_nightly_cargo(&["public-dependency"])
19+
.current_dir(cwd)
20+
.assert()
21+
.success()
22+
.stdout_matches_path(curr_dir!().join("stdout.log"))
23+
.stderr_matches_path(curr_dir!().join("stderr.log"));
24+
25+
assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[workspace]
2+
members = ["primary", "dependency"]
3+
4+
[workspace.dependencies]
5+
foo = { version = "0.0.0", path = "./dependency"}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[package]
2+
name = "foo"
3+
version = "0.0.0"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
cargo-features = ["public-dependency"]
2+
[package]
3+
name = "bar"
4+
version = "0.0.0"
5+
6+
[dependencies]
7+
foo = { workspace = true, public = true }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Adding foo (workspace) to public dependencies.

tests/testsuite/cargo_add/detect_workspace_inherit_public/stdout.log

Whitespace-only changes.

tests/testsuite/cargo_add/help/stdout.log

+11
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@ Options:
3232

3333
The package will be removed from your features.
3434

35+
--public
36+
Mark the dependency as public
37+
38+
The dependency can be referenced in your library's public API.
39+
40+
--no-public
41+
Mark the dependency as private
42+
43+
While you can use the crate in your implementation, it cannot be referenced in your public
44+
API.
45+
3546
--rename <NAME>
3647
Rename the dependency
3748

tests/testsuite/cargo_add/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod deprecated_section;
1212
mod detect_workspace_inherit;
1313
mod detect_workspace_inherit_features;
1414
mod detect_workspace_inherit_optional;
15+
mod detect_workspace_inherit_public;
1516
mod dev;
1617
mod dev_build_conflict;
1718
mod dev_prefer_existing_version;
@@ -65,6 +66,7 @@ mod namever;
6566
mod no_args;
6667
mod no_default_features;
6768
mod no_optional;
69+
mod no_public;
6870
mod offline_empty_cache;
6971
mod optional;
7072
mod overwrite_default_features;
@@ -81,11 +83,15 @@ mod overwrite_no_default_features;
8183
mod overwrite_no_default_features_with_default_features;
8284
mod overwrite_no_optional;
8385
mod overwrite_no_optional_with_optional;
86+
mod overwrite_no_public;
87+
mod overwrite_no_public_with_public;
8488
mod overwrite_optional;
8589
mod overwrite_optional_with_no_optional;
8690
mod overwrite_path_noop;
8791
mod overwrite_path_with_version;
8892
mod overwrite_preserves_inline_table;
93+
mod overwrite_public;
94+
mod overwrite_public_with_no_public;
8995
mod overwrite_rename_with_no_rename;
9096
mod overwrite_rename_with_rename;
9197
mod overwrite_rename_with_rename_noop;
@@ -103,6 +109,7 @@ mod preserve_dep_std_table;
103109
mod preserve_features_table;
104110
mod preserve_sorted;
105111
mod preserve_unsorted;
112+
mod public;
106113
mod quiet;
107114
mod registry;
108115
mod rename;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
cargo-features = ["public-dependency"]
2+
[workspace]
3+
4+
[package]
5+
name = "cargo-list-test-fixture"
6+
version = "0.0.0"

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

Whitespace-only changes.
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use cargo_test_support::compare::assert_ui;
2+
use cargo_test_support::prelude::*;
3+
use cargo_test_support::Project;
4+
5+
use cargo_test_support::curr_dir;
6+
7+
#[cargo_test]
8+
fn case() {
9+
cargo_test_support::registry::init();
10+
cargo_test_support::registry::Package::new("my-package", "0.1.0").publish();
11+
let project = Project::from_template(curr_dir!().join("in"));
12+
let project_root = project.root();
13+
let cwd = &project_root;
14+
15+
snapbox::cmd::Command::cargo_ui()
16+
.arg("add")
17+
.arg_line("my-package --no-public")
18+
.current_dir(cwd)
19+
.masquerade_as_nightly_cargo(&["public-dependency"])
20+
.assert()
21+
.success()
22+
.stdout_matches_path(curr_dir!().join("stdout.log"))
23+
.stderr_matches_path(curr_dir!().join("stderr.log"));
24+
25+
assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
cargo-features = ["public-dependency"]
2+
[workspace]
3+
4+
[package]
5+
name = "cargo-list-test-fixture"
6+
version = "0.0.0"
7+
8+
[dependencies]
9+
my-package = "0.1.0"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Updating `dummy-registry` index
2+
Adding my-package v0.1.0 to dependencies.

tests/testsuite/cargo_add/no_public/stdout.log

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
cargo-features = ["public-dependency"]
2+
[workspace]
3+
4+
[package]
5+
name = "cargo-list-test-fixture"
6+
version = "0.0.0"
7+
8+
[dependencies]
9+
my-package = "0.1.0"

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

Whitespace-only changes.

0 commit comments

Comments
 (0)