Skip to content

Commit 87d9c47

Browse files
committed
fix: add gc unused patches logic and fix tests
1 parent 35d968b commit 87d9c47

File tree

3 files changed

+50
-50
lines changed

3 files changed

+50
-50
lines changed

src/bin/cargo/commands/remove.rs

+42-50
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use cargo::core::dependency::DepKind;
22
use cargo::core::PackageIdSpec;
3+
use cargo::core::Resolve;
34
use cargo::core::Workspace;
45
use cargo::ops::cargo_remove::remove;
56
use cargo::ops::cargo_remove::RemoveOptions;
@@ -109,9 +110,14 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
109110

110111
// Reload the workspace since we've changed dependencies
111112
let ws = args.workspace(config)?;
112-
resolve_ws(&ws)?;
113-
}
113+
let (_, resolve) = resolve_ws(&ws)?;
114114

115+
// Attempt to gc unused patches and re-resolve if anything is removed
116+
if gc_unused_patches(&workspace, &resolve)? {
117+
let ws = args.workspace(config)?;
118+
resolve_ws(&ws)?;
119+
}
120+
}
115121
Ok(())
116122
}
117123

@@ -229,31 +235,6 @@ fn gc_workspace(workspace: &Workspace<'_>) -> CargoResult<()> {
229235
}
230236
}
231237

232-
// Clean up the patch section
233-
if let Some(toml_edit::Item::Table(patch_section_table)) = manifest.get_mut("patch") {
234-
patch_section_table.set_implicit(true);
235-
236-
// The key in each of the subtables is a source (either a registry or a URL)
237-
for (source, item) in patch_section_table.iter_mut() {
238-
if let toml_edit::Item::Table(patch_table) = item {
239-
patch_table.set_implicit(true);
240-
241-
for (key, item) in patch_table.iter_mut() {
242-
let package_name =
243-
Dependency::from_toml(&workspace.root_manifest(), key.get(), item)?.name;
244-
if !source_has_match(
245-
&package_name,
246-
source.get(),
247-
&dependencies,
248-
workspace.config(),
249-
)? {
250-
*item = toml_edit::Item::None;
251-
}
252-
}
253-
}
254-
}
255-
}
256-
257238
// Clean up the replace section
258239
if let Some(toml_edit::Item::Table(table)) = manifest.get_mut("replace") {
259240
table.set_implicit(true);
@@ -310,35 +291,46 @@ fn spec_has_match(
310291
Ok(false)
311292
}
312293

313-
/// Check whether or not a source (URL or registry name) matches any non-workspace dependencies.
314-
fn source_has_match(
315-
name: &str,
316-
source: &str,
317-
dependencies: &[Dependency],
318-
config: &Config,
319-
) -> CargoResult<bool> {
320-
for dep in dependencies {
321-
if &dep.name != name {
322-
continue;
323-
}
294+
/// Removes unused patches from the manifest
295+
fn gc_unused_patches(workspace: &Workspace<'_>, resolve: &Resolve) -> CargoResult<bool> {
296+
let mut manifest: toml_edit::Document =
297+
cargo_util::paths::read(workspace.root_manifest())?.parse()?;
298+
let mut modified = false;
324299

325-
match dep.source_id(config)? {
326-
MaybeWorkspace::Other(source_id) => {
327-
if source_id.is_registry() {
328-
if source_id.display_registry_name() == source
329-
|| source_id.url().as_str() == source
300+
// Clean up the patch section
301+
if let Some(toml_edit::Item::Table(patch_section_table)) = manifest.get_mut("patch") {
302+
patch_section_table.set_implicit(true);
303+
304+
for (_, item) in patch_section_table.iter_mut() {
305+
if let toml_edit::Item::Table(patch_table) = item {
306+
patch_table.set_implicit(true);
307+
308+
for (key, item) in patch_table.iter_mut() {
309+
let dep = Dependency::from_toml(&workspace.root_manifest(), key.get(), item)?;
310+
311+
// Generate a PackageIdSpec url for querying
312+
let url = if let MaybeWorkspace::Other(source_id) =
313+
dep.source_id(workspace.config())?
330314
{
331-
return Ok(true);
332-
}
333-
} else if source_id.is_git() {
334-
if source_id.url().as_str() == source {
335-
return Ok(true);
315+
format!("{}#{}", source_id.url(), dep.name)
316+
} else {
317+
continue;
318+
};
319+
320+
if PackageIdSpec::query_str(&url, resolve.unused_patches().iter().cloned())
321+
.is_ok()
322+
{
323+
*item = toml_edit::Item::None;
324+
modified = true;
336325
}
337326
}
338327
}
339-
MaybeWorkspace::Workspace(_) => {}
340328
}
341329
}
342330

343-
Ok(false)
331+
if modified {
332+
cargo_util::paths::write(workspace.root_manifest(), manifest.to_string().as_bytes())?;
333+
}
334+
335+
Ok(modified)
344336
}
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
Removing bar from dependencies
22
Updating git repository `[ROOTURL]/bar[..]`
3+
Updating git repository `[ROOTURL]/bar[..]`
34
Updating `dummy-registry` index
5+
warning: Patch `bar v0.1.0 ([..])` was not used in the crate graph.
6+
Perhaps you misspelled the source URL being patched.
7+
Possible URLs for `[patch.<URL>]`:
8+
[ROOT]/bar2

tests/testsuite/cargo_remove/invalid_gc_patch/out/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33
[workspace]
44
members = ["serde", "serde_derive"]
55

6+
[patch.crates-io]
7+
serde = { path = "serde" }
8+

0 commit comments

Comments
 (0)