|
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,24 @@ 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 = { |
| 114 | + // HACK: Avoid unused patch warnings by temporarily changing the verbosity. |
| 115 | + // In rare cases, this might cause index update messages to not show up |
| 116 | + let verbosity = ws.config().shell().verbosity(); |
| 117 | + ws.config() |
| 118 | + .shell() |
| 119 | + .set_verbosity(cargo::core::Verbosity::Quiet); |
| 120 | + let resolve = resolve_ws(&ws); |
| 121 | + ws.config().shell().set_verbosity(verbosity); |
| 122 | + resolve?.1 |
| 123 | + }; |
114 | 124 |
|
| 125 | + // Attempt to gc unused patches and re-resolve if anything is removed |
| 126 | + if gc_unused_patches(&workspace, &resolve)? { |
| 127 | + let ws = args.workspace(config)?; |
| 128 | + resolve_ws(&ws)?; |
| 129 | + } |
| 130 | + } |
115 | 131 | Ok(())
|
116 | 132 | }
|
117 | 133 |
|
@@ -229,31 +245,6 @@ fn gc_workspace(workspace: &Workspace<'_>) -> CargoResult<()> {
|
229 | 245 | }
|
230 | 246 | }
|
231 | 247 |
|
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 | 248 | // Clean up the replace section
|
258 | 249 | if let Some(toml_edit::Item::Table(table)) = manifest.get_mut("replace") {
|
259 | 250 | table.set_implicit(true);
|
@@ -310,35 +301,46 @@ fn spec_has_match(
|
310 | 301 | Ok(false)
|
311 | 302 | }
|
312 | 303 |
|
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 |
| - } |
| 304 | +/// Removes unused patches from the manifest |
| 305 | +fn gc_unused_patches(workspace: &Workspace<'_>, resolve: &Resolve) -> CargoResult<bool> { |
| 306 | + let mut manifest: toml_edit::Document = |
| 307 | + cargo_util::paths::read(workspace.root_manifest())?.parse()?; |
| 308 | + let mut modified = false; |
324 | 309 |
|
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 |
| 310 | + // Clean up the patch section |
| 311 | + if let Some(toml_edit::Item::Table(patch_section_table)) = manifest.get_mut("patch") { |
| 312 | + patch_section_table.set_implicit(true); |
| 313 | + |
| 314 | + for (_, item) in patch_section_table.iter_mut() { |
| 315 | + if let toml_edit::Item::Table(patch_table) = item { |
| 316 | + patch_table.set_implicit(true); |
| 317 | + |
| 318 | + for (key, item) in patch_table.iter_mut() { |
| 319 | + let dep = Dependency::from_toml(&workspace.root_manifest(), key.get(), item)?; |
| 320 | + |
| 321 | + // Generate a PackageIdSpec url for querying |
| 322 | + let url = if let MaybeWorkspace::Other(source_id) = |
| 323 | + dep.source_id(workspace.config())? |
330 | 324 | {
|
331 |
| - return Ok(true); |
332 |
| - } |
333 |
| - } else if source_id.is_git() { |
334 |
| - if source_id.url().as_str() == source { |
335 |
| - return Ok(true); |
| 325 | + format!("{}#{}", source_id.url(), dep.name) |
| 326 | + } else { |
| 327 | + continue; |
| 328 | + }; |
| 329 | + |
| 330 | + if PackageIdSpec::query_str(&url, resolve.unused_patches().iter().cloned()) |
| 331 | + .is_ok() |
| 332 | + { |
| 333 | + *item = toml_edit::Item::None; |
| 334 | + modified = true; |
336 | 335 | }
|
337 | 336 | }
|
338 | 337 | }
|
339 |
| - MaybeWorkspace::Workspace(_) => {} |
340 | 338 | }
|
341 | 339 | }
|
342 | 340 |
|
343 |
| - Ok(false) |
| 341 | + if modified { |
| 342 | + cargo_util::paths::write(workspace.root_manifest(), manifest.to_string().as_bytes())?; |
| 343 | + } |
| 344 | + |
| 345 | + Ok(modified) |
344 | 346 | }
|
0 commit comments