diff --git a/src/cargo/util/toml_mut/manifest.rs b/src/cargo/util/toml_mut/manifest.rs index 9d98d581b636..f281634b1214 100644 --- a/src/cargo/util/toml_mut/manifest.rs +++ b/src/cargo/util/toml_mut/manifest.rs @@ -9,6 +9,7 @@ use anyhow::Context as _; use super::dependency::Dependency; use crate::core::dependency::DepKind; use crate::core::FeatureValue; +use crate::core::PackageIdSpec; use crate::util::interning::InternedString; use crate::CargoResult; @@ -393,6 +394,7 @@ impl LocalManifest { let explicit_dep_activation = self.is_explicit_dep_activation(dep_key); let status = self.dep_status(dep_key); + // clean up features if let Some(toml_edit::Item::Table(feature_table)) = self.data.as_table_mut().get_mut("features") { @@ -409,6 +411,49 @@ impl LocalManifest { } } } + + // continue only if the dep is fully removed + if status != DependencyStatus::None { + return; + } + + // clean up profile sections + let profile_table_path = [ + "profile".to_owned(), + "dev".to_owned(), + "package".to_owned(), + dep_key.to_owned(), + ]; + if let Ok(item @ toml_edit::Item::Table(_)) = self.get_table_mut(&profile_table_path) { + *item = toml_edit::Item::None + } + + // clean up patch sections + if let Some(toml_edit::Item::Table(patch_table)) = self.data.get_mut("patch") { + patch_table.set_implicit(true); + for (_, item) in patch_table.iter_mut() { + if let toml_edit::Item::Table(table) = item { + table.set_implicit(true); + for (key, item) in table.iter_mut() { + if key.get() == dep_key { + *item = toml_edit::Item::None; + } + } + } + } + } + + // clean up replace section + if let Some(toml_edit::Item::Table(replace_table)) = self.data.get_mut("replace") { + replace_table.set_implicit(true); + for (key, item) in replace_table.iter_mut() { + if let Ok(spec) = PackageIdSpec::parse(key.get()) { + if spec.name() == dep_key { + *item = toml_edit::Item::None; + } + } + } + } } fn is_explicit_dep_activation(&self, dep_key: &str) -> bool { @@ -500,7 +545,7 @@ fn fix_feature_activations( }) .collect(); - // Remove found idx in revers order so we don't invalidate the idx. + // Remove found idx in reverse order so we don't invalidate the idx. for idx in remove_list.iter().rev() { feature_values.remove(*idx); } diff --git a/tests/testsuite/cargo_remove/gc_patch/mod.rs b/tests/testsuite/cargo_remove/gc_patch/mod.rs new file mode 100644 index 000000000000..12dab988077a --- /dev/null +++ b/tests/testsuite/cargo_remove/gc_patch/mod.rs @@ -0,0 +1,56 @@ +use cargo_test_support::basic_manifest; +use cargo_test_support::compare::assert_ui; +use cargo_test_support::curr_dir; +use cargo_test_support::git; +use cargo_test_support::project; +use cargo_test_support::CargoCommand; + +use crate::cargo_remove::init_registry; + +#[cargo_test] +fn case() { + init_registry(); + + let git_project1 = git::new("bar1", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + }) + .url(); + + let git_project2 = git::new("bar2", |project| { + project + .file("Cargo.toml", &basic_manifest("bar", "0.1.0")) + .file("src/lib.rs", "") + }) + .url(); + + let in_project = project() + .file( + "Cargo.toml", + &format!( + "[package]\n\ + name = \"my-project\"\n\ + version = \"0.1.0\"\n\ + \n\ + [dependencies]\n\ + bar = {{ git = \"{git_project1}\" }}\n\ + \n\ + [patch.\"{git_project1}\"]\n\ + bar = {{ git = \"{git_project2}\" }}\n", + ), + ) + .file("src/lib.rs", "") + .build(); + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["bar"]) + .current_dir(&in_project.root()) + .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"), &in_project.root()); +} diff --git a/tests/testsuite/cargo_remove/gc_patch/out/Cargo.toml b/tests/testsuite/cargo_remove/gc_patch/out/Cargo.toml new file mode 100644 index 000000000000..0697d477bf61 --- /dev/null +++ b/tests/testsuite/cargo_remove/gc_patch/out/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "my-project" +version = "0.1.0" diff --git a/tests/testsuite/cargo_remove/gc_patch/out/src/lib.rs b/tests/testsuite/cargo_remove/gc_patch/out/src/lib.rs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/testsuite/cargo_remove/gc_patch/stderr.log b/tests/testsuite/cargo_remove/gc_patch/stderr.log new file mode 100644 index 000000000000..ba519ba1b912 --- /dev/null +++ b/tests/testsuite/cargo_remove/gc_patch/stderr.log @@ -0,0 +1 @@ + Removing bar from dependencies diff --git a/tests/testsuite/cargo_remove/gc_patch/stdout.log b/tests/testsuite/cargo_remove/gc_patch/stdout.log new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/testsuite/cargo_remove/gc_profile/in/Cargo.toml b/tests/testsuite/cargo_remove/gc_profile/in/Cargo.toml new file mode 100644 index 000000000000..09a3e16264f1 --- /dev/null +++ b/tests/testsuite/cargo_remove/gc_profile/in/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "cargo-remove-test-fixture" +version = "0.1.0" + +[[bin]] +name = "main" +path = "src/main.rs" + +[build-dependencies] +semver = "0.1.0" + +[dependencies] +docopt = "0.6" +rustc-serialize = "0.4" +semver = "0.1" +toml = "0.1" +clippy = "0.4" + +[dev-dependencies] +regex = "0.1.1" +serde = "1.0.90" +docopt = "0.6" + +[features] +std = ["serde/std", "semver/std"] + +[profile.dev.package.docopt] +opt-level = 3 + +[profile.dev.package.toml] +opt-level = 3 diff --git a/tests/testsuite/cargo_remove/gc_profile/in/src/lib.rs b/tests/testsuite/cargo_remove/gc_profile/in/src/lib.rs new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/tests/testsuite/cargo_remove/gc_profile/in/src/lib.rs @@ -0,0 +1 @@ + diff --git a/tests/testsuite/cargo_remove/gc_profile/mod.rs b/tests/testsuite/cargo_remove/gc_profile/mod.rs new file mode 100644 index 000000000000..7047c92e2f38 --- /dev/null +++ b/tests/testsuite/cargo_remove/gc_profile/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::curr_dir; +use cargo_test_support::CargoCommand; +use cargo_test_support::Project; + +use crate::cargo_remove::init_registry; + +#[cargo_test] +fn case() { + init_registry(); + let project = Project::from_template(curr_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["toml"]) + .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); +} diff --git a/tests/testsuite/cargo_remove/gc_profile/out/Cargo.toml b/tests/testsuite/cargo_remove/gc_profile/out/Cargo.toml new file mode 100644 index 000000000000..244e46679511 --- /dev/null +++ b/tests/testsuite/cargo_remove/gc_profile/out/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "cargo-remove-test-fixture" +version = "0.1.0" + +[[bin]] +name = "main" +path = "src/main.rs" + +[build-dependencies] +semver = "0.1.0" + +[dependencies] +docopt = "0.6" +rustc-serialize = "0.4" +semver = "0.1" +clippy = "0.4" + +[dev-dependencies] +regex = "0.1.1" +serde = "1.0.90" +docopt = "0.6" + +[features] +std = ["serde/std", "semver/std"] + +[profile.dev.package.docopt] +opt-level = 3 diff --git a/tests/testsuite/cargo_remove/gc_profile/stderr.log b/tests/testsuite/cargo_remove/gc_profile/stderr.log new file mode 100644 index 000000000000..0e2e38f266e0 --- /dev/null +++ b/tests/testsuite/cargo_remove/gc_profile/stderr.log @@ -0,0 +1,2 @@ + Removing toml from dependencies + Updating `dummy-registry` index diff --git a/tests/testsuite/cargo_remove/gc_profile/stdout.log b/tests/testsuite/cargo_remove/gc_profile/stdout.log new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/testsuite/cargo_remove/gc_replace/in/Cargo.toml b/tests/testsuite/cargo_remove/gc_replace/in/Cargo.toml new file mode 100644 index 000000000000..a245d7d02f4a --- /dev/null +++ b/tests/testsuite/cargo_remove/gc_replace/in/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "cargo-remove-test-fixture" +version = "0.1.0" + +[[bin]] +name = "main" +path = "src/main.rs" + +[build-dependencies] +semver = "0.1.0" + +[dependencies] +docopt = "0.6" +rustc-serialize = "0.4" +semver = "0.1" +toml = "0.1" +clippy = "0.4" + +[dev-dependencies] +regex = "0.1.1" +serde = "1.0.90" +docopt = "0.6" + +[features] +std = ["serde/std", "semver/std"] + +[replace] +"toml:0.1.0" = { path = "../toml" } diff --git a/tests/testsuite/cargo_remove/gc_replace/in/src/lib.rs b/tests/testsuite/cargo_remove/gc_replace/in/src/lib.rs new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/tests/testsuite/cargo_remove/gc_replace/in/src/lib.rs @@ -0,0 +1 @@ + diff --git a/tests/testsuite/cargo_remove/gc_replace/mod.rs b/tests/testsuite/cargo_remove/gc_replace/mod.rs new file mode 100644 index 000000000000..7047c92e2f38 --- /dev/null +++ b/tests/testsuite/cargo_remove/gc_replace/mod.rs @@ -0,0 +1,25 @@ +use cargo_test_support::compare::assert_ui; +use cargo_test_support::curr_dir; +use cargo_test_support::CargoCommand; +use cargo_test_support::Project; + +use crate::cargo_remove::init_registry; + +#[cargo_test] +fn case() { + init_registry(); + let project = Project::from_template(curr_dir!().join("in")); + let project_root = project.root(); + let cwd = &project_root; + + snapbox::cmd::Command::cargo_ui() + .arg("remove") + .args(["toml"]) + .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); +} diff --git a/tests/testsuite/cargo_remove/gc_replace/out/Cargo.toml b/tests/testsuite/cargo_remove/gc_replace/out/Cargo.toml new file mode 100644 index 000000000000..35e6f085694f --- /dev/null +++ b/tests/testsuite/cargo_remove/gc_replace/out/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "cargo-remove-test-fixture" +version = "0.1.0" + +[[bin]] +name = "main" +path = "src/main.rs" + +[build-dependencies] +semver = "0.1.0" + +[dependencies] +docopt = "0.6" +rustc-serialize = "0.4" +semver = "0.1" +clippy = "0.4" + +[dev-dependencies] +regex = "0.1.1" +serde = "1.0.90" +docopt = "0.6" + +[features] +std = ["serde/std", "semver/std"] diff --git a/tests/testsuite/cargo_remove/gc_replace/stderr.log b/tests/testsuite/cargo_remove/gc_replace/stderr.log new file mode 100644 index 000000000000..0e2e38f266e0 --- /dev/null +++ b/tests/testsuite/cargo_remove/gc_replace/stderr.log @@ -0,0 +1,2 @@ + Removing toml from dependencies + Updating `dummy-registry` index diff --git a/tests/testsuite/cargo_remove/gc_replace/stdout.log b/tests/testsuite/cargo_remove/gc_replace/stdout.log new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/testsuite/cargo_remove/mod.rs b/tests/testsuite/cargo_remove/mod.rs index 75178531ee33..5448fe43530f 100644 --- a/tests/testsuite/cargo_remove/mod.rs +++ b/tests/testsuite/cargo_remove/mod.rs @@ -2,6 +2,9 @@ mod avoid_empty_tables; mod build; mod dev; mod dry_run; +mod gc_patch; +mod gc_profile; +mod gc_replace; mod invalid_arg; mod invalid_dep; mod invalid_package;