@@ -20,6 +20,7 @@ use toml_edit::Item as TomlItem;
2020
2121use crate :: CargoResult ;
2222use crate :: GlobalContext ;
23+ use crate :: core:: Feature ;
2324use crate :: core:: FeatureValue ;
2425use crate :: core:: Features ;
2526use crate :: core:: Package ;
@@ -29,6 +30,7 @@ use crate::core::Summary;
2930use crate :: core:: Workspace ;
3031use crate :: core:: dependency:: DepKind ;
3132use crate :: core:: registry:: PackageRegistry ;
33+ use crate :: ops:: resolve_ws;
3234use crate :: sources:: source:: QueryKind ;
3335use crate :: util:: cache_lock:: CacheLockMode ;
3436use crate :: util:: edit_distance;
@@ -38,6 +40,7 @@ use crate::util::toml_mut::dependency::Dependency;
3840use crate :: util:: toml_mut:: dependency:: GitSource ;
3941use crate :: util:: toml_mut:: dependency:: MaybeWorkspace ;
4042use crate :: util:: toml_mut:: dependency:: PathSource ;
43+ use crate :: util:: toml_mut:: dependency:: RegistrySource ;
4144use crate :: util:: toml_mut:: dependency:: Source ;
4245use crate :: util:: toml_mut:: dependency:: WorkspaceSource ;
4346use crate :: util:: toml_mut:: manifest:: DepTable ;
@@ -471,6 +474,13 @@ fn resolve_dependency(
471474 src = src. set_version ( v) ;
472475 }
473476 dependency = dependency. set_source ( src) ;
477+ } else if let Some ( ( registry, public_source) ) =
478+ get_public_dependency ( spec, manifest, ws, section, gctx, & dependency) ?
479+ {
480+ if let Some ( registry) = registry {
481+ dependency = dependency. set_registry ( registry) ;
482+ }
483+ dependency = dependency. set_source ( public_source) ;
474484 } else {
475485 let latest =
476486 get_latest_dependency ( spec, & dependency, honor_rust_version, gctx, registry) ?;
@@ -507,11 +517,107 @@ fn resolve_dependency(
507517 Ok ( dependency)
508518}
509519
520+ fn get_public_dependency (
521+ spec : & Package ,
522+ manifest : & LocalManifest ,
523+ ws : & Workspace < ' _ > ,
524+ section : & DepTable ,
525+ gctx : & GlobalContext ,
526+ dependency : & Dependency ,
527+ ) -> CargoResult < Option < ( Option < String > , Source ) > > {
528+ if spec
529+ . manifest ( )
530+ . unstable_features ( )
531+ . require ( Feature :: public_dependency ( ) )
532+ . is_err ( )
533+ {
534+ return Ok ( None ) ;
535+ }
536+
537+ let ( package_set, resolve) = resolve_ws ( ws, true ) ?;
538+
539+ let mut latest = None ;
540+
541+ for ( _, path, dep) in manifest. get_dependencies ( ws, ws. unstable_features ( ) ) {
542+ if path != * section {
543+ continue ;
544+ }
545+
546+ let Some ( mut dep) = dep. ok ( ) else {
547+ continue ;
548+ } ;
549+
550+ let dep = query_dependency ( ws, gctx, & mut dep) ?;
551+ let Some ( dep_pkgid) = package_set
552+ . package_ids ( )
553+ . filter ( |package_id| {
554+ package_id. name ( ) == dep. package_name ( )
555+ && dep. version_req ( ) . matches ( package_id. version ( ) )
556+ } )
557+ . max_by_key ( |x| x. version ( ) )
558+ else {
559+ continue ;
560+ } ;
561+
562+ let pkg_ids_and_reqs = resolve. deps ( dep_pkgid) . filter_map ( |( id, deps) | {
563+ deps. iter ( )
564+ . find ( |dep| {
565+ dep. is_public ( )
566+ && dep. kind ( ) == DepKind :: Normal
567+ && dep. package_name ( ) == dependency. name . as_str ( )
568+ } )
569+ . map ( |dep| ( id, dep. version_req ( ) . clone ( ) ) )
570+ } ) ;
571+
572+ for ( pkg_id, req) in pkg_ids_and_reqs {
573+ if let Some ( ( old_pkg_id, _) ) = & latest
574+ && * old_pkg_id >= pkg_id
575+ {
576+ continue ;
577+ }
578+ latest = Some ( ( pkg_id, req) )
579+ }
580+ }
581+
582+ let Some ( ( pkg_id, version_req) ) = latest else {
583+ return Ok ( None ) ;
584+ } ;
585+
586+ let source = pkg_id. source_id ( ) ;
587+ if source. is_git ( ) {
588+ Ok ( Some ( (
589+ Option :: < String > :: None ,
590+ Source :: Git ( GitSource :: new ( source. as_encoded_url ( ) . to_string ( ) ) ) ,
591+ ) ) )
592+ } else if let Some ( path) = source. local_path ( ) {
593+ Ok ( Some ( ( None , Source :: Path ( PathSource :: new ( path) ) ) ) )
594+ } else {
595+ let toml_source = match version_req {
596+ crate :: util:: OptVersionReq :: Any => Source :: Registry ( RegistrySource :: new ( format ! (
597+ "={}" ,
598+ pkg_id. version( ) . to_string( )
599+ ) ) ) ,
600+ crate :: util:: OptVersionReq :: Req ( version_req)
601+ | crate :: util:: OptVersionReq :: Locked ( _, version_req)
602+ | crate :: util:: OptVersionReq :: Precise ( _, version_req) => {
603+ Source :: Registry ( RegistrySource :: new ( version_req. to_string ( ) ) )
604+ }
605+ } ;
606+ Ok ( Some ( (
607+ source
608+ . alt_registry_key ( )
609+ . map ( |x| x. to_owned ( ) )
610+ . filter ( |_| !source. is_crates_io ( ) ) ,
611+ toml_source,
612+ ) ) )
613+ }
614+ }
615+
510616fn query_dependency (
511617 ws : & Workspace < ' _ > ,
512618 gctx : & GlobalContext ,
513619 dependency : & mut Dependency ,
514- ) -> Result < crate :: core:: Dependency , anyhow :: Error > {
620+ ) -> CargoResult < crate :: core:: Dependency > {
515621 let query = dependency. query ( gctx) ?;
516622 let query = match query {
517623 MaybeWorkspace :: Workspace ( _workspace) => {
0 commit comments