Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --public for cargo add #13046

Merged
merged 10 commits into from
Dec 1, 2023
19 changes: 19 additions & 0 deletions src/bin/cargo/commands/add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ The package name will be exposed as feature of your crate.")
The package will be removed from your features.")
.conflicts_with("dev")
.overrides_with("optional"),
flag("public", "Mark the dependency as public")
.conflicts_with("dev")
.conflicts_with("build")
.long_help("Mark the dependency as public

The dependency can be referenced in your library's public API."),
flag("no-public", "Mark the dependency as private")
.conflicts_with("dev")
.conflicts_with("build")
.overrides_with("public")
.long_help("Mark the dependency as private

While you can use the crate in your implementation, it cannot be referenced in your public API."),
clap::Arg::new("rename")
.long("rename")
.action(ArgAction::Set)
Expand Down Expand Up @@ -235,6 +248,7 @@ fn parse_dependencies(config: &Config, matches: &ArgMatches) -> CargoResult<Vec<
};
let default_features = default_features(matches);
let optional = optional(matches);
let public = public(matches);

let mut crates = matches
.get_many::<String>("crates")
Expand Down Expand Up @@ -325,6 +339,7 @@ fn parse_dependencies(config: &Config, matches: &ArgMatches) -> CargoResult<Vec<
features,
default_features,
optional,
public,
registry: registry.clone(),
path: path.map(String::from),
git: git.map(String::from),
Expand Down Expand Up @@ -353,6 +368,10 @@ fn optional(matches: &ArgMatches) -> Option<bool> {
resolve_bool_arg(matches.flag("optional"), matches.flag("no-optional"))
}

fn public(matches: &ArgMatches) -> Option<bool> {
resolve_bool_arg(matches.flag("public"), matches.flag("no-public"))
}

fn resolve_bool_arg(yes: bool, no: bool) -> Option<bool> {
match (yes, no) {
(true, false) => Some(true),
Expand Down
13 changes: 13 additions & 0 deletions src/cargo/ops/cargo_add/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,9 @@ pub struct DepOp {
/// Whether dependency is optional
pub optional: Option<bool>,

/// Whether dependency is public
pub public: Option<bool>,

/// Registry for looking up dependency version
pub registry: Option<String>,

Expand Down Expand Up @@ -758,6 +761,13 @@ fn populate_dependency(mut dependency: Dependency, arg: &DepOp) -> Dependency {
dependency.optional = None;
}
}
if let Some(value) = arg.public {
if value {
dependency.public = Some(true);
} else {
dependency.public = None;
}
}
epage marked this conversation as resolved.
Show resolved Hide resolved
if let Some(value) = arg.default_features {
if value {
dependency.default_features = None;
Expand Down Expand Up @@ -945,6 +955,9 @@ fn print_action_msg(shell: &mut Shell, dep: &DependencyUI, section: &[String]) -
if dep.optional().unwrap_or(false) {
write!(message, " optional")?;
}
if dep.public().unwrap_or(false) {
write!(message, " public")?;
}
let section = if section.len() == 1 {
section[0].clone()
} else {
Expand Down
39 changes: 32 additions & 7 deletions src/cargo/util/toml_mut/dependency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ pub struct Dependency {
/// Whether the dependency is opted-in with a feature flag.
pub optional: Option<bool>,

/// Whether the dependency is marked as public.
pub public: Option<bool>,

/// List of features to add (or None to keep features unchanged).
pub features: Option<IndexSet<String>>,
/// Whether default features are enabled.
Expand All @@ -48,6 +51,7 @@ impl Dependency {
Self {
name: name.into(),
optional: None,
public: None,
features: None,
default_features: None,
inherited_features: None,
Expand Down Expand Up @@ -163,6 +167,11 @@ impl Dependency {
self.optional
}

/// Get whether the dep is public.
pub fn public(&self) -> Option<bool> {
self.public
}

/// Get the SourceID for this dependency.
pub fn source_id(&self, config: &Config) -> CargoResult<MaybeWorkspace<SourceId>> {
match &self.source.as_ref() {
Expand Down Expand Up @@ -325,16 +334,18 @@ impl Dependency {
};

let optional = table.get("optional").and_then(|v| v.as_bool());
let public = table.get("public").and_then(|v| v.as_bool());

let dep = Self {
name,
rename,
source: Some(source),
registry,
default_features,
features,
optional,
public,
features,
default_features,
inherited_features: None,
source: Some(source),
registry,
rename,
};
Ok(dep)
} else {
Expand Down Expand Up @@ -366,6 +377,7 @@ impl Dependency {
crate_root.display()
);
let table: toml_edit::Item = match (
linyihai marked this conversation as resolved.
Show resolved Hide resolved
self.public.unwrap_or(false),
self.optional.unwrap_or(false),
self.features.as_ref(),
self.default_features.unwrap_or(true),
Expand All @@ -375,21 +387,22 @@ impl Dependency {
) {
// Extra short when version flag only
(
false,
false,
None,
true,
Some(Source::Registry(RegistrySource { version: v })),
None,
None,
) => toml_edit::value(v),
(false, None, true, Some(Source::Workspace(WorkspaceSource {})), None, None) => {
(false, false, None, true, Some(Source::Workspace(WorkspaceSource {})), None, None) => {
let mut table = toml_edit::InlineTable::default();
table.set_dotted(true);
table.insert("workspace", true.into());
toml_edit::value(toml_edit::Value::InlineTable(table))
}
// Other cases are represented as an inline table
(_, _, _, _, _, _) => {
(_, _, _, _, _, _, _) => {
let mut table = toml_edit::InlineTable::default();

match &self.source {
Expand Down Expand Up @@ -442,6 +455,9 @@ impl Dependency {
if let Some(v) = self.optional {
table.insert("optional", v.into());
}
if let Some(v) = self.public {
table.insert("public", v.into());
}

toml_edit::value(toml_edit::Value::InlineTable(table))
}
Expand Down Expand Up @@ -579,6 +595,15 @@ impl Dependency {
table.remove("optional");
}
}
match self.public {
Some(v) => {
table.set_dotted(false);
overwrite_value(table, "public", v);
}
None => {
table.remove("public");
}
}
} else {
unreachable!("Invalid dependency type: {}", item.type_name());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[workspace]
members = ["primary", "dependency"]

[workspace.dependencies]
foo = { version = "0.0.0", path = "./dependency"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[package]
name = "foo"
version = "0.0.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cargo-features = ["public-dependency"]
[package]
name = "bar"
version = "0.0.0"
26 changes: 26 additions & 0 deletions tests/testsuite/cargo_add/detect_workspace_inherit_public/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use cargo_test_support::compare::assert_ui;
use cargo_test_support::prelude::*;
use cargo_test_support::Project;

use cargo_test_support::curr_dir;

#[cargo_test]
fn case() {
cargo_test_support::registry::init();

let project = Project::from_template(curr_dir!().join("in"));
let project_root = project.root();
let cwd = &project_root;

snapbox::cmd::Command::cargo_ui()
.arg("add")
.args(["foo", "-p", "bar", "--public"])
.masquerade_as_nightly_cargo(&["public-dependency"])
.current_dir(cwd)
.assert()
.success()
.stdout_matches_path(curr_dir!().join("stdout.log"))
.stderr_matches_path(curr_dir!().join("stderr.log"));

assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[workspace]
members = ["primary", "dependency"]

[workspace.dependencies]
foo = { version = "0.0.0", path = "./dependency"}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[package]
name = "foo"
version = "0.0.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cargo-features = ["public-dependency"]
[package]
name = "bar"
version = "0.0.0"

[dependencies]
foo = { workspace = true, public = true }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Adding foo (workspace) to public dependencies.
Empty file.
11 changes: 11 additions & 0 deletions tests/testsuite/cargo_add/help/stdout.log
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ Options:

The package will be removed from your features.

--public
Mark the dependency as public

The dependency can be referenced in your library's public API.

--no-public
Mark the dependency as private

While you can use the crate in your implementation, it cannot be referenced in your public
API.

--rename <NAME>
Rename the dependency

Expand Down
7 changes: 7 additions & 0 deletions tests/testsuite/cargo_add/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod deprecated_section;
mod detect_workspace_inherit;
mod detect_workspace_inherit_features;
mod detect_workspace_inherit_optional;
mod detect_workspace_inherit_public;
mod dev;
mod dev_build_conflict;
mod dev_prefer_existing_version;
Expand Down Expand Up @@ -65,6 +66,7 @@ mod namever;
mod no_args;
epage marked this conversation as resolved.
Show resolved Hide resolved
mod no_default_features;
mod no_optional;
mod no_public;
mod offline_empty_cache;
mod optional;
mod overwrite_default_features;
Expand All @@ -81,11 +83,15 @@ mod overwrite_no_default_features;
mod overwrite_no_default_features_with_default_features;
mod overwrite_no_optional;
mod overwrite_no_optional_with_optional;
mod overwrite_no_public;
mod overwrite_no_public_with_public;
mod overwrite_optional;
mod overwrite_optional_with_no_optional;
mod overwrite_path_noop;
mod overwrite_path_with_version;
mod overwrite_preserves_inline_table;
mod overwrite_public;
mod overwrite_public_with_no_public;
mod overwrite_rename_with_no_rename;
mod overwrite_rename_with_rename;
mod overwrite_rename_with_rename_noop;
Expand All @@ -103,6 +109,7 @@ mod preserve_dep_std_table;
mod preserve_features_table;
mod preserve_sorted;
mod preserve_unsorted;
mod public;
mod quiet;
mod registry;
mod rename;
Expand Down
6 changes: 6 additions & 0 deletions tests/testsuite/cargo_add/no_public/in/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
cargo-features = ["public-dependency"]
[workspace]

[package]
name = "cargo-list-test-fixture"
version = "0.0.0"
Empty file.
26 changes: 26 additions & 0 deletions tests/testsuite/cargo_add/no_public/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use cargo_test_support::compare::assert_ui;
use cargo_test_support::prelude::*;
use cargo_test_support::Project;

use cargo_test_support::curr_dir;

#[cargo_test]
fn case() {
cargo_test_support::registry::init();
cargo_test_support::registry::Package::new("my-package", "0.1.0").publish();
let project = Project::from_template(curr_dir!().join("in"));
let project_root = project.root();
let cwd = &project_root;

snapbox::cmd::Command::cargo_ui()
.arg("add")
.arg_line("my-package --no-public")
.current_dir(cwd)
.masquerade_as_nightly_cargo(&["public-dependency"])
.assert()
.success()
.stdout_matches_path(curr_dir!().join("stdout.log"))
.stderr_matches_path(curr_dir!().join("stderr.log"));

assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
}
9 changes: 9 additions & 0 deletions tests/testsuite/cargo_add/no_public/out/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
cargo-features = ["public-dependency"]
[workspace]

[package]
name = "cargo-list-test-fixture"
version = "0.0.0"

[dependencies]
my-package = "0.1.0"
2 changes: 2 additions & 0 deletions tests/testsuite/cargo_add/no_public/stderr.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Updating `dummy-registry` index
Adding my-package v0.1.0 to dependencies.
Empty file.
9 changes: 9 additions & 0 deletions tests/testsuite/cargo_add/overwrite_no_public/in/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
cargo-features = ["public-dependency"]
[workspace]

[package]
name = "cargo-list-test-fixture"
version = "0.0.0"

[dependencies]
my-package = "0.1.0"
Empty file.
Loading