Skip to content

Commit e82c234

Browse files
committed
Clean profile, patch, and replace in cargo remove
After a successful removal of a dependency, clean up the profile, patch, and replace sections to remove all references to the dependency.
1 parent 882c5dd commit e82c234

File tree

19 files changed

+275
-1
lines changed

19 files changed

+275
-1
lines changed

src/cargo/util/toml_mut/manifest.rs

+46-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use anyhow::Context as _;
99
use super::dependency::Dependency;
1010
use crate::core::dependency::DepKind;
1111
use crate::core::FeatureValue;
12+
use crate::core::PackageIdSpec;
1213
use crate::util::interning::InternedString;
1314
use crate::CargoResult;
1415

@@ -393,6 +394,7 @@ impl LocalManifest {
393394
let explicit_dep_activation = self.is_explicit_dep_activation(dep_key);
394395
let status = self.dep_status(dep_key);
395396

397+
// clean up features
396398
if let Some(toml_edit::Item::Table(feature_table)) =
397399
self.data.as_table_mut().get_mut("features")
398400
{
@@ -409,6 +411,49 @@ impl LocalManifest {
409411
}
410412
}
411413
}
414+
415+
// continue only if the dep is fully removed
416+
if status != DependencyStatus::None {
417+
return;
418+
}
419+
420+
// clean up profile sections
421+
let profile_table_path = [
422+
"profile".to_owned(),
423+
"dev".to_owned(),
424+
"package".to_owned(),
425+
dep_key.to_owned(),
426+
];
427+
if let Ok(item @ toml_edit::Item::Table(_)) = self.get_table_mut(&profile_table_path) {
428+
*item = toml_edit::Item::None
429+
}
430+
431+
// clean up patch sections
432+
if let Some(toml_edit::Item::Table(patch_table)) = self.data.get_mut("patch") {
433+
patch_table.set_implicit(true);
434+
for (_, item) in patch_table.iter_mut() {
435+
if let toml_edit::Item::Table(table) = item {
436+
table.set_implicit(true);
437+
for (key, item) in table.iter_mut() {
438+
if key.get() == dep_key {
439+
*item = toml_edit::Item::None;
440+
}
441+
}
442+
}
443+
}
444+
}
445+
446+
// clean up replace section
447+
if let Some(toml_edit::Item::Table(replace_table)) = self.data.get_mut("replace") {
448+
replace_table.set_implicit(true);
449+
for (key, item) in replace_table.iter_mut() {
450+
if let Ok(spec) = PackageIdSpec::parse(key.get()) {
451+
if spec.name() == dep_key {
452+
*item = toml_edit::Item::None;
453+
}
454+
}
455+
}
456+
}
412457
}
413458

414459
fn is_explicit_dep_activation(&self, dep_key: &str) -> bool {
@@ -500,7 +545,7 @@ fn fix_feature_activations(
500545
})
501546
.collect();
502547

503-
// Remove found idx in revers order so we don't invalidate the idx.
548+
// Remove found idx in reverse order so we don't invalidate the idx.
504549
for idx in remove_list.iter().rev() {
505550
feature_values.remove(*idx);
506551
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
use cargo_test_support::basic_manifest;
2+
use cargo_test_support::compare::assert_ui;
3+
use cargo_test_support::curr_dir;
4+
use cargo_test_support::git;
5+
use cargo_test_support::project;
6+
use cargo_test_support::CargoCommand;
7+
8+
use crate::cargo_remove::init_registry;
9+
10+
#[cargo_test]
11+
fn case() {
12+
init_registry();
13+
14+
let git_project1 = git::new("bar1", |project| {
15+
project
16+
.file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
17+
.file("src/lib.rs", "")
18+
})
19+
.url();
20+
21+
let git_project2 = git::new("bar2", |project| {
22+
project
23+
.file("Cargo.toml", &basic_manifest("bar", "0.1.0"))
24+
.file("src/lib.rs", "")
25+
})
26+
.url();
27+
28+
let in_project = project()
29+
.file(
30+
"Cargo.toml",
31+
&format!(
32+
"[package]\n\
33+
name = \"my-project\"\n\
34+
version = \"0.1.0\"\n\
35+
\n\
36+
[dependencies]\n\
37+
bar = {{ git = \"{git_project1}\" }}\n\
38+
\n\
39+
[patch.\"{git_project1}\"]\n\
40+
bar = {{ git = \"{git_project2}\" }}\n",
41+
),
42+
)
43+
.file("src/lib.rs", "")
44+
.build();
45+
46+
snapbox::cmd::Command::cargo_ui()
47+
.arg("remove")
48+
.args(["bar"])
49+
.current_dir(&in_project.root())
50+
.assert()
51+
.success()
52+
.stdout_matches_path(curr_dir!().join("stdout.log"))
53+
.stderr_matches_path(curr_dir!().join("stderr.log"));
54+
55+
assert_ui().subset_matches(curr_dir!().join("out"), &in_project.root());
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[package]
2+
name = "my-project"
3+
version = "0.1.0"

tests/testsuite/cargo_remove/gc_patch/out/src/lib.rs

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Removing bar from dependencies

tests/testsuite/cargo_remove/gc_patch/stdout.log

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[package]
2+
name = "cargo-remove-test-fixture"
3+
version = "0.1.0"
4+
5+
[[bin]]
6+
name = "main"
7+
path = "src/main.rs"
8+
9+
[build-dependencies]
10+
semver = "0.1.0"
11+
12+
[dependencies]
13+
docopt = "0.6"
14+
rustc-serialize = "0.4"
15+
semver = "0.1"
16+
toml = "0.1"
17+
clippy = "0.4"
18+
19+
[dev-dependencies]
20+
regex = "0.1.1"
21+
serde = "1.0.90"
22+
docopt = "0.6"
23+
24+
[features]
25+
std = ["serde/std", "semver/std"]
26+
27+
[profile.dev.package.docopt]
28+
opt-level = 3
29+
30+
[profile.dev.package.toml]
31+
opt-level = 3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use cargo_test_support::compare::assert_ui;
2+
use cargo_test_support::curr_dir;
3+
use cargo_test_support::CargoCommand;
4+
use cargo_test_support::Project;
5+
6+
use crate::cargo_remove::init_registry;
7+
8+
#[cargo_test]
9+
fn case() {
10+
init_registry();
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("remove")
17+
.args(["toml"])
18+
.current_dir(cwd)
19+
.assert()
20+
.success()
21+
.stdout_matches_path(curr_dir!().join("stdout.log"))
22+
.stderr_matches_path(curr_dir!().join("stderr.log"));
23+
24+
assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[package]
2+
name = "cargo-remove-test-fixture"
3+
version = "0.1.0"
4+
5+
[[bin]]
6+
name = "main"
7+
path = "src/main.rs"
8+
9+
[build-dependencies]
10+
semver = "0.1.0"
11+
12+
[dependencies]
13+
docopt = "0.6"
14+
rustc-serialize = "0.4"
15+
semver = "0.1"
16+
clippy = "0.4"
17+
18+
[dev-dependencies]
19+
regex = "0.1.1"
20+
serde = "1.0.90"
21+
docopt = "0.6"
22+
23+
[features]
24+
std = ["serde/std", "semver/std"]
25+
26+
[profile.dev.package.docopt]
27+
opt-level = 3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Removing toml from dependencies
2+
Updating `dummy-registry` index

tests/testsuite/cargo_remove/gc_profile/stdout.log

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[package]
2+
name = "cargo-remove-test-fixture"
3+
version = "0.1.0"
4+
5+
[[bin]]
6+
name = "main"
7+
path = "src/main.rs"
8+
9+
[build-dependencies]
10+
semver = "0.1.0"
11+
12+
[dependencies]
13+
docopt = "0.6"
14+
rustc-serialize = "0.4"
15+
semver = "0.1"
16+
toml = "0.1"
17+
clippy = "0.4"
18+
19+
[dev-dependencies]
20+
regex = "0.1.1"
21+
serde = "1.0.90"
22+
docopt = "0.6"
23+
24+
[features]
25+
std = ["serde/std", "semver/std"]
26+
27+
[replace]
28+
"toml:0.1.0" = { path = "../toml" }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use cargo_test_support::compare::assert_ui;
2+
use cargo_test_support::curr_dir;
3+
use cargo_test_support::CargoCommand;
4+
use cargo_test_support::Project;
5+
6+
use crate::cargo_remove::init_registry;
7+
8+
#[cargo_test]
9+
fn case() {
10+
init_registry();
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("remove")
17+
.args(["toml"])
18+
.current_dir(cwd)
19+
.assert()
20+
.success()
21+
.stdout_matches_path(curr_dir!().join("stdout.log"))
22+
.stderr_matches_path(curr_dir!().join("stderr.log"));
23+
24+
assert_ui().subset_matches(curr_dir!().join("out"), &project_root);
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[package]
2+
name = "cargo-remove-test-fixture"
3+
version = "0.1.0"
4+
5+
[[bin]]
6+
name = "main"
7+
path = "src/main.rs"
8+
9+
[build-dependencies]
10+
semver = "0.1.0"
11+
12+
[dependencies]
13+
docopt = "0.6"
14+
rustc-serialize = "0.4"
15+
semver = "0.1"
16+
clippy = "0.4"
17+
18+
[dev-dependencies]
19+
regex = "0.1.1"
20+
serde = "1.0.90"
21+
docopt = "0.6"
22+
23+
[features]
24+
std = ["serde/std", "semver/std"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Removing toml from dependencies
2+
Updating `dummy-registry` index

tests/testsuite/cargo_remove/gc_replace/stdout.log

Whitespace-only changes.

tests/testsuite/cargo_remove/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ mod avoid_empty_tables;
22
mod build;
33
mod dev;
44
mod dry_run;
5+
mod gc_patch;
6+
mod gc_profile;
7+
mod gc_replace;
58
mod invalid_arg;
69
mod invalid_dep;
710
mod invalid_package;

0 commit comments

Comments
 (0)