Repository: rust-lang/cargo (rust)

Issue:
Can't `cargo publish --workspace --dry-run` if the versions already exist
### Problem

In testing #1169 on `cargo release` now that #14721 is fixed, I came across another way you can't dry-run existing versions: the overlay registry blocks it
```
[2024-11-06T21:50:26Z TRACE cargo_release::ops::cmd] /home/epage/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/b
in/cargo publish --manifest-path /home/epage/src/personal/clap/clap_lex/Cargo.toml -Zpackage-workspace --package clap_
lex --package clap_builder --package clap_derive --package clap --package clap_complete --package clap_complete_fig --
package clap_complete_nushell --package clap_mangen --dry-run --allow-dirty
    Updating crates.io index
warning: crate clap@4.5.20 already exists on crates.io index
warning: crate clap_builder@4.5.20 already exists on crates.io index
warning: crate clap_lex@0.7.2 already exists on crates.io index
warning: crate clap_derive@4.5.18 already exists on crates.io index
warning: crate clap_complete@4.5.37 already exists on crates.io index
warning: crate clap_complete_fig@4.5.2 already exists on crates.io index
warning: crate clap_complete_nushell@4.5.4 already exists on crates.io index
warning: crate clap_mangen@0.2.24 already exists on crates.io index
   Packaging clap_lex v0.7.2 (/home/epage/src/personal/clap/clap_lex)
warning: ignoring test `testsuite` as `tests/testsuite/main.rs` is not included in the published package
    Packaged 8 files, 42.9KiB (12.5KiB compressed)
   Packaging clap_builder v4.5.20 (/home/epage/src/personal/clap/clap_builder)
    Packaged 62 files, 914.9KiB (160.0KiB compressed)
   Packaging clap_derive v4.5.18 (/home/epage/src/personal/clap/clap_derive)
    Packaged 22 files, 162.1KiB (29.4KiB compressed)
   Packaging clap v4.5.20 (/home/epage/src/personal/clap)
warning: ignoring test `builder` as `tests/builder/main.rs` is not included in the published package
warning: ignoring test `derive` as `tests/derive/main.rs` is not included in the published package
warning: ignoring test `derive_ui` as `tests/derive_ui.rs` is not included in the published package
warning: ignoring test `examples` as `tests/examples.rs` is not included in the published package
warning: ignoring test `macros` as `tests/macros.rs` is not included in the published package
warning: ignoring test `ui` as `tests/ui.rs` is not included in the published package
    Updating crates.io index
error: failed to prepare local package for uploading

Caused by:
  failed to get `clap_builder` as a dependency of package `clap v4.5.20 (/home/epage/src/personal/clap)`

Caused by:
  found a package in the remote registry and the local overlay: clap_builder@4.5.20
```

### Steps

```console
$ cargo install cargo-release
$ git clone git@github.com:clap-rs/clap.git
$ cd clap
$ cargo +nightly publish -Zpackage-workspace --package clap_
lex --package clap_builder --package clap_derive --package clap --package clap_complete --package clap_complete_fig --
package clap_complete_nushell --package clap_mangen --dry-run --allow-dirty
```

### Possible Solution(s)

Remove the restriction on the overlay which comes at the risk of it being abused.

### Notes

_No response_

### Version

cargo 1.84.0-nightly (031049782 2024-11-01)

Pull request:
fix(publish): Allow dry-run of a non-bumped workspace 
### What does this PR try to resolve?

A dry-run release process won't be bumping the versions, making it so it can't do a dry-run publish because the local/remote registries will collide.  This switches it to give the local registry precedence over the remote registry to make the dry-run release process work.

Fixes #14789

### How should we test and review this PR?


### Additional information



Patch:
diff --git a/src/cargo/sources/overlay.rs b/src/cargo/sources/overlay.rs
index fcdca88df..8031d9151 100644
--- a/src/cargo/sources/overlay.rs
+++ b/src/cargo/sources/overlay.rs
@@ -63,24 +63,16 @@ impl<'gctx> Source for DependencyConfusionThreatOverlaySource<'gctx> {
         };
         ready!(self.local.query(&local_dep, kind, &mut local_callback))?;
 
-        let mut package_collision = None;
         let mut remote_callback = |index: IndexSummary| {
             if local_packages.contains(index.as_summary()) {
-                package_collision = Some(index.as_summary().clone());
+                tracing::debug!(?local_source, ?remote_source, ?index, "package collision");
+            } else {
+                f(index)
             }
-            f(index)
         };
         ready!(self.remote.query(dep, kind, &mut remote_callback))?;
 
-        if let Some(collision) = package_collision {
-            std::task::Poll::Ready(Err(anyhow::anyhow!(
-                "found a package in the remote registry and the local overlay: {}@{}",
-                collision.name(),
-                collision.version()
-            )))
-        } else {
-            std::task::Poll::Ready(Ok(()))
-        }
+        std::task::Poll::Ready(Ok(()))
     }
 
     fn invalidate_cache(&mut self) {


Test patch:
diff --git a/tests/testsuite/package.rs b/tests/testsuite/package.rs
index fc24db911..5a27cc349 100644
--- a/tests/testsuite/package.rs
+++ b/tests/testsuite/package.rs
@@ -6056,20 +6056,21 @@ fn workspace_with_local_dep_already_published_nightly() {
     p.cargo("package -Zpackage-workspace")
         .masquerade_as_nightly_cargo(&["package-workspace"])
         .replace_crates_io(reg.index_url())
-        .with_status(101)
         .with_stderr_data(
             str![[r#"
 [PACKAGING] dep v0.1.0 ([ROOT]/foo/dep)
 [PACKAGING] main v0.0.1 ([ROOT]/foo/main)
 [UPDATING] crates.io index
-[ERROR] failed to prepare local package for uploading
-
-Caused by:
-  failed to get `dep` as a dependency of package `main v0.0.1 ([ROOT]/foo/main)`
-
-Caused by:
-  found a package in the remote registry and the local overlay: dep@0.1.0
 [PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)
+[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed)
+[VERIFYING] dep v0.1.0 ([ROOT]/foo/dep)
+[COMPILING] dep v0.1.0 ([ROOT]/foo/target/package/dep-0.1.0)
+[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
+[VERIFYING] main v0.0.1 ([ROOT]/foo/main)
+[UNPACKING] dep v0.1.0 (registry `[ROOT]/foo/target/package/tmp-registry`)
+[COMPILING] dep v0.1.0
+[COMPILING] main v0.0.1 ([ROOT]/foo/target/package/main-0.0.1)
+[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
 
 "#]]
             .unordered(),
diff --git a/tests/testsuite/registry_overlay.rs b/tests/testsuite/registry_overlay.rs
index 65acb8f7e..923296b42 100644
--- a/tests/testsuite/registry_overlay.rs
+++ b/tests/testsuite/registry_overlay.rs
@@ -3,6 +3,7 @@
 use cargo_test_support::prelude::*;
 use cargo_test_support::project;
 use cargo_test_support::registry::{Package, RegistryBuilder, TestRegistry};
+use cargo_test_support::str;
 
 fn setup() -> (TestRegistry, String) {
     let alt = RegistryBuilder::new().alternative().build();
@@ -77,17 +78,16 @@ fn registry_version_wins() {
 
     p.cargo("check")
         .overlay_registry(&reg.index_url(), &alt_path)
-        .with_stderr_data(
-            "\
-[UPDATING] [..]
+        .with_stderr_data(str![[r#"
+[UPDATING] `sparse+http://127.0.0.1:[..]/index/` index
 [LOCKING] 1 package to latest compatible version
 [DOWNLOADING] crates ...
-[DOWNLOADED] baz v0.1.1 (registry [..])
+[DOWNLOADED] baz v0.1.1 (registry `sparse+http://127.0.0.1:[..]/index/`)
 [CHECKING] baz v0.1.1
 [CHECKING] foo v0.0.1 ([ROOT]/foo)
 [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
-",
-        )
+
+"#]])
         .run();
 }
 
@@ -120,21 +120,20 @@ fn overlay_version_wins() {
 
     p.cargo("check")
         .overlay_registry(&reg.index_url(), &alt_path)
-        .with_stderr_data(
-            "\
-[UPDATING] [..]
+        .with_stderr_data(str![[r#"
+[UPDATING] `sparse+http://127.0.0.1:[..]/index/` index
 [LOCKING] 1 package to latest compatible version
-[UNPACKING] baz v0.1.1 (registry [..])
+[UNPACKING] baz v0.1.1 (registry `[ROOT]/alternative-registry`)
 [CHECKING] baz v0.1.1
 [CHECKING] foo v0.0.1 ([ROOT]/foo)
 [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
-",
-        )
+
+"#]])
         .run();
 }
 
 #[cargo_test]
-fn version_collision() {
+fn version_precedence() {
     let (reg, alt_path) = setup();
     let p = project()
         .file(
@@ -162,19 +161,15 @@ fn version_collision() {
 
     p.cargo("check")
         .overlay_registry(&reg.index_url(), &alt_path)
-        .with_status(101)
-        .with_stderr_data(
-            "\
-[UPDATING] [..]
-[ERROR] failed to get `baz` [..]
-
-Caused by:
-  failed to query replaced source registry `crates-io`
-
-Caused by:
-  found a package in the remote registry and the local overlay: baz@0.1.1
-",
-        )
+        .with_stderr_data(str![[r#"
+[UPDATING] `sparse+http://127.0.0.1:[..]/index/` index
+[LOCKING] 1 package to latest compatible version
+[UNPACKING] baz v0.1.1 (registry `[ROOT]/alternative-registry`)
+[CHECKING] baz v0.1.1
+[CHECKING] foo v0.0.1 ([ROOT]/foo)
+[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
+
+"#]])
         .run();
 }
 
@@ -248,22 +243,21 @@ fn registry_dep_depends_on_new_local_package() {
 
     p.cargo("check")
         .overlay_registry(&reg.index_url(), &alt_path)
-        .with_stderr_data(
-            "\
-[UPDATING] [..]
+        .with_stderr_data(str![[r#"
+[UPDATING] `sparse+http://127.0.0.1:[..]/index/` index
 [LOCKING] 3 packages to latest compatible versions
 [ADDING] workspace-package v0.0.1 (available: v0.1.1)
 [DOWNLOADING] crates ...
-[UNPACKING] [..]
-[DOWNLOADED] [..]
-[DOWNLOADED] [..]
+[UNPACKING] workspace-package v0.1.1 (registry `[ROOT]/alternative-registry`)
+[DOWNLOADED] registry-package v0.1.0 (registry `sparse+http://127.0.0.1:[..]/index/`)
+[DOWNLOADED] workspace-package v0.0.1 (registry `sparse+http://127.0.0.1:[..]/index/`)
 [CHECKING] workspace-package v0.1.1
 [CHECKING] workspace-package v0.0.1
 [CHECKING] registry-package v0.1.0
-[CHECKING] foo v0.0.1 [..]
+[CHECKING] foo v0.0.1 ([ROOT]/foo)
 [FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
-",
-        )
+
+"#]])
         .run();
 }