diff --git a/src/cargo/ops/registry/publish.rs b/src/cargo/ops/registry/publish.rs index 8ff92920c16..de0f9ac4e0a 100644 --- a/src/cargo/ops/registry/publish.rs +++ b/src/cargo/ops/registry/publish.rs @@ -133,7 +133,7 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> { .acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?; for (pkg, _) in &pkgs { - verify_unpublished(pkg, &mut source, &source_ids)?; + verify_unpublished(pkg, &mut source, &source_ids, opts.dry_run, opts.gctx)?; verify_dependencies(pkg, ®istry, source_ids.original)?; } } @@ -368,6 +368,8 @@ fn verify_unpublished( pkg: &Package, source: &mut RegistrySource<'_>, source_ids: &RegistrySourceIds, + dry_run: bool, + gctx: &GlobalContext, ) -> CargoResult<()> { let query = Dependency::parse( pkg.name(), @@ -383,12 +385,24 @@ fn verify_unpublished( } }; if !duplicate_query.is_empty() { - bail!( - "crate {}@{} already exists on {}", - pkg.name(), - pkg.version(), - source.describe() - ); + // Move the registry error earlier in the publish process. + // Since dry-run wouldn't talk to the registry to get the error, we downgrade it to a + // warning. + if dry_run { + gctx.shell().warn(format!( + "crate {}@{} already exists on {}", + pkg.name(), + pkg.version(), + source.describe() + ))?; + } else { + bail!( + "crate {}@{} already exists on {}", + pkg.name(), + pkg.version(), + source.describe() + ); + } } Ok(()) diff --git a/tests/testsuite/publish.rs b/tests/testsuite/publish.rs index 88e78fae154..46f8eb248a3 100644 --- a/tests/testsuite/publish.rs +++ b/tests/testsuite/publish.rs @@ -150,6 +150,25 @@ fn duplicate_version() { .file("src/main.rs", "fn main() {}") .build(); + p.cargo("publish --dry-run") + .replace_crates_io(registry_dupl.index_url()) + .with_stderr_data(str![[r#" +[UPDATING] crates.io index +[WARNING] crate foo@0.0.1 already exists on crates.io index +[WARNING] manifest has no documentation, homepage or repository. +See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info. +[PACKAGING] foo v0.0.1 ([ROOT]/foo) +[PACKAGED] 4 files, [FILE_SIZE]B ([FILE_SIZE]B compressed) +[VERIFYING] foo v0.0.1 ([ROOT]/foo) +[WARNING] no edition set: defaulting to the 2015 edition while the latest is 2021 +[COMPILING] foo v0.0.1 ([ROOT]/foo/target/package/foo-0.0.1) +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s +[UPLOADING] foo v0.0.1 ([ROOT]/foo) +[WARNING] aborting upload due to dry run + +"#]]) + .run(); + p.cargo("publish") .replace_crates_io(registry_dupl.index_url()) .with_status(101)