@@ -31,11 +31,13 @@ use crate::core::PackageIdSpecQuery;
3131use crate :: core:: SourceId ;
3232use crate :: core:: Workspace ;
3333use crate :: ops;
34+ use crate :: ops:: registry:: RegistrySourceIds ;
3435use crate :: ops:: PackageOpts ;
3536use crate :: ops:: Packages ;
3637use crate :: ops:: RegistryOrIndex ;
3738use crate :: sources:: source:: QueryKind ;
3839use crate :: sources:: source:: Source ;
40+ use crate :: sources:: RegistrySource ;
3941use crate :: sources:: SourceConfigMap ;
4042use crate :: sources:: CRATES_IO_REGISTRY ;
4143use crate :: util:: auth;
@@ -45,6 +47,7 @@ use crate::util::toml::prepare_for_publish;
4547use crate :: util:: Graph ;
4648use crate :: util:: Progress ;
4749use crate :: util:: ProgressStyle ;
50+ use crate :: util:: VersionExt as _;
4851use crate :: CargoResult ;
4952use crate :: GlobalContext ;
5053
@@ -115,7 +118,7 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
115118 // This is only used to confirm that we can create a token before we build the package.
116119 // This causes the credential provider to be called an extra time, but keeps the same order of errors.
117120 let source_ids = super :: get_source_id ( opts. gctx , reg_or_index. as_ref ( ) ) ?;
118- let mut registry = super :: registry (
121+ let ( mut registry, mut source ) = super :: registry (
119122 opts. gctx ,
120123 & source_ids,
121124 opts. token . as_ref ( ) . map ( Secret :: as_deref) ,
@@ -124,9 +127,15 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
124127 Some ( Operation :: Read ) . filter ( |_| !opts. dry_run ) ,
125128 ) ?;
126129
127- // Validate all the packages before publishing any of them.
128- for ( pkg, _) in & pkgs {
129- verify_dependencies ( pkg, & registry, source_ids. original ) ?;
130+ {
131+ let _lock = opts
132+ . gctx
133+ . acquire_package_cache_lock ( CacheLockMode :: DownloadExclusive ) ?;
134+
135+ for ( pkg, _) in & pkgs {
136+ verify_unpublished ( pkg, & mut source, & source_ids) ?;
137+ verify_dependencies ( pkg, & registry, source_ids. original ) ?;
138+ }
130139 }
131140
132141 let pkg_dep_graph = ops:: cargo_package:: package_with_dep_graph (
@@ -355,6 +364,36 @@ fn poll_one_package(
355364 Ok ( !summaries. is_empty ( ) )
356365}
357366
367+ fn verify_unpublished (
368+ pkg : & Package ,
369+ source : & mut RegistrySource < ' _ > ,
370+ source_ids : & RegistrySourceIds ,
371+ ) -> CargoResult < ( ) > {
372+ let query = Dependency :: parse (
373+ pkg. name ( ) ,
374+ Some ( & pkg. version ( ) . to_exact_req ( ) . to_string ( ) ) ,
375+ source_ids. replacement ,
376+ ) ?;
377+ let duplicate_query = loop {
378+ match source. query_vec ( & query, QueryKind :: Exact ) {
379+ std:: task:: Poll :: Ready ( res) => {
380+ break res?;
381+ }
382+ std:: task:: Poll :: Pending => source. block_until_ready ( ) ?,
383+ }
384+ } ;
385+ if !duplicate_query. is_empty ( ) {
386+ bail ! (
387+ "crate {}@{} already exists on {}" ,
388+ pkg. name( ) ,
389+ pkg. version( ) ,
390+ source. describe( )
391+ ) ;
392+ }
393+
394+ Ok ( ( ) )
395+ }
396+
358397fn verify_dependencies (
359398 pkg : & Package ,
360399 registry : & Registry ,
0 commit comments