Skip to content

Commit

Permalink
Clean profile, patch, and replace in cargo remove
Browse files Browse the repository at this point in the history
After a successful removal of a dependency, clean up the profile, patch,
and replace sections to remove all references to the dependency.
  • Loading branch information
cassaundra committed Oct 9, 2022
1 parent 882c5dd commit 081d656
Show file tree
Hide file tree
Showing 19 changed files with 283 additions and 1 deletion.
51 changes: 50 additions & 1 deletion src/cargo/util/toml_mut/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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")
{
Expand All @@ -409,6 +411,53 @@ impl LocalManifest {
}
}
}

// continue only if the dep is fully removed
if status != DependencyStatus::None {
return;
}

// clean up profile sections
self.get_table_mut(table_path)
if let Some(toml_edit::Item::Table(profile_table)) = self.data.get_mut("profile") {
profile_table.set_implicit(true);
for (_, item) in profile_table.iter_mut() {
if let toml_edit::Item::Table(profile_table) = item {
profile_table.set_implicit(true);
if let Some(toml_edit::Item::Table(package_table)) = profile_table.get_mut("package") {
package_table.set_implicit(true);
package_table.remove(dep_key);
}
}
}
}

// 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 {
Expand Down Expand Up @@ -500,7 +549,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);
}
Expand Down
56 changes: 56 additions & 0 deletions tests/testsuite/cargo_remove/gc_patch/mod.rs
Original file line number Diff line number Diff line change
@@ -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());
}
3 changes: 3 additions & 0 deletions tests/testsuite/cargo_remove/gc_patch/out/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[package]
name = "my-project"
version = "0.1.0"
Empty file.
1 change: 1 addition & 0 deletions tests/testsuite/cargo_remove/gc_patch/stderr.log
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Removing bar from dependencies
Empty file.
35 changes: 35 additions & 0 deletions tests/testsuite/cargo_remove/gc_profile/in/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[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

[profile.release.package.toml]
opt-level = 1
overflow-checks = false
1 change: 1 addition & 0 deletions tests/testsuite/cargo_remove/gc_profile/in/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

25 changes: 25 additions & 0 deletions tests/testsuite/cargo_remove/gc_profile/mod.rs
Original file line number Diff line number Diff line change
@@ -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);
}
27 changes: 27 additions & 0 deletions tests/testsuite/cargo_remove/gc_profile/out/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions tests/testsuite/cargo_remove/gc_profile/stderr.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Removing toml from dependencies
Updating `dummy-registry` index
Empty file.
28 changes: 28 additions & 0 deletions tests/testsuite/cargo_remove/gc_replace/in/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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" }
1 change: 1 addition & 0 deletions tests/testsuite/cargo_remove/gc_replace/in/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

25 changes: 25 additions & 0 deletions tests/testsuite/cargo_remove/gc_replace/mod.rs
Original file line number Diff line number Diff line change
@@ -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);
}
24 changes: 24 additions & 0 deletions tests/testsuite/cargo_remove/gc_replace/out/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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"]
2 changes: 2 additions & 0 deletions tests/testsuite/cargo_remove/gc_replace/stderr.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Removing toml from dependencies
Updating `dummy-registry` index
Empty file.
3 changes: 3 additions & 0 deletions tests/testsuite/cargo_remove/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 081d656

Please sign in to comment.