|
1 | 1 | use cargo::core::dependency::DepKind; |
2 | 2 | use cargo::core::PackageIdSpec; |
| 3 | +use cargo::core::Resolve; |
3 | 4 | use cargo::core::Workspace; |
4 | 5 | use cargo::ops::cargo_remove::remove; |
5 | 6 | use cargo::ops::cargo_remove::RemoveOptions; |
@@ -109,9 +110,14 @@ pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult { |
109 | 110 |
|
110 | 111 | // Reload the workspace since we've changed dependencies |
111 | 112 | let ws = args.workspace(config)?; |
112 | | - resolve_ws(&ws)?; |
113 | | - } |
| 113 | + let (_, resolve) = resolve_ws(&ws)?; |
114 | 114 |
|
| 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 | + } |
115 | 121 | Ok(()) |
116 | 122 | } |
117 | 123 |
|
@@ -229,31 +235,6 @@ fn gc_workspace(workspace: &Workspace<'_>) -> CargoResult<()> { |
229 | 235 | } |
230 | 236 | } |
231 | 237 |
|
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 | | - |
257 | 238 | // Clean up the replace section |
258 | 239 | if let Some(toml_edit::Item::Table(table)) = manifest.get_mut("replace") { |
259 | 240 | table.set_implicit(true); |
@@ -310,35 +291,46 @@ fn spec_has_match( |
310 | 291 | Ok(false) |
311 | 292 | } |
312 | 293 |
|
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; |
324 | 299 |
|
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())? |
330 | 314 | { |
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; |
336 | 325 | } |
337 | 326 | } |
338 | 327 | } |
339 | | - MaybeWorkspace::Workspace(_) => {} |
340 | 328 | } |
341 | 329 | } |
342 | 330 |
|
343 | | - Ok(false) |
| 331 | + if modified { |
| 332 | + cargo_util::paths::write(workspace.root_manifest(), manifest.to_string().as_bytes())?; |
| 333 | + } |
| 334 | + |
| 335 | + Ok(modified) |
344 | 336 | } |
0 commit comments