@@ -20,16 +20,20 @@ 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 ;
27+ use crate :: core:: PackageId ;
2628use crate :: core:: Registry ;
2729use crate :: core:: Shell ;
2830use crate :: core:: Summary ;
2931use crate :: core:: Workspace ;
3032use crate :: core:: dependency:: DepKind ;
3133use crate :: core:: registry:: PackageRegistry ;
34+ use crate :: ops:: resolve_ws;
3235use crate :: sources:: source:: QueryKind ;
36+ use crate :: util:: OptVersionReq ;
3337use crate :: util:: cache_lock:: CacheLockMode ;
3438use crate :: util:: edit_distance;
3539use crate :: util:: style;
@@ -38,6 +42,7 @@ use crate::util::toml_mut::dependency::Dependency;
3842use crate :: util:: toml_mut:: dependency:: GitSource ;
3943use crate :: util:: toml_mut:: dependency:: MaybeWorkspace ;
4044use crate :: util:: toml_mut:: dependency:: PathSource ;
45+ use crate :: util:: toml_mut:: dependency:: RegistrySource ;
4146use crate :: util:: toml_mut:: dependency:: Source ;
4247use crate :: util:: toml_mut:: dependency:: WorkspaceSource ;
4348use crate :: util:: toml_mut:: manifest:: DepTable ;
@@ -471,6 +476,13 @@ fn resolve_dependency(
471476 src = src. set_version ( v) ;
472477 }
473478 dependency = dependency. set_source ( src) ;
479+ } else if let Some ( ( registry, public_source) ) =
480+ get_public_dependency ( spec, manifest, ws, section, gctx, & dependency) ?
481+ {
482+ if let Some ( registry) = registry {
483+ dependency = dependency. set_registry ( registry) ;
484+ }
485+ dependency = dependency. set_source ( public_source) ;
474486 } else {
475487 let latest =
476488 get_latest_dependency ( spec, & dependency, honor_rust_version, gctx, registry) ?;
@@ -507,11 +519,119 @@ fn resolve_dependency(
507519 Ok ( dependency)
508520}
509521
522+ fn get_public_dependency (
523+ spec : & Package ,
524+ manifest : & LocalManifest ,
525+ ws : & Workspace < ' _ > ,
526+ section : & DepTable ,
527+ gctx : & GlobalContext ,
528+ dependency : & Dependency ,
529+ ) -> CargoResult < Option < ( Option < String > , Source ) > > {
530+ if spec
531+ . manifest ( )
532+ . unstable_features ( )
533+ . require ( Feature :: public_dependency ( ) )
534+ . is_err ( )
535+ {
536+ return Ok ( None ) ;
537+ }
538+
539+ let ( package_set, resolve) = resolve_ws ( ws, true ) ?;
540+
541+ let mut latest: Option < ( PackageId , OptVersionReq ) > = None ;
542+
543+ for ( _, path, dep) in manifest. get_dependencies ( ws, ws. unstable_features ( ) ) {
544+ if path != * section {
545+ continue ;
546+ }
547+
548+ let Some ( mut dep) = dep. ok ( ) else {
549+ continue ;
550+ } ;
551+
552+ let dep = query_dependency ( ws, gctx, & mut dep) ?;
553+ let Some ( dep_pkgid) = package_set
554+ . package_ids ( )
555+ . filter ( |package_id| {
556+ package_id. name ( ) == dep. package_name ( )
557+ && dep. version_req ( ) . matches ( package_id. version ( ) )
558+ } )
559+ . max_by_key ( |x| x. version ( ) )
560+ else {
561+ continue ;
562+ } ;
563+
564+ let mut pkg_ids_and_reqs = Vec :: new ( ) ;
565+ let mut pkg_id_queue = VecDeque :: new ( ) ;
566+ let mut examined = BTreeSet :: new ( ) ;
567+ pkg_id_queue. push_back ( dep_pkgid) ;
568+
569+ while let Some ( dep_pkgid) = pkg_id_queue. pop_front ( ) {
570+ let got_deps = resolve. deps ( dep_pkgid) . filter_map ( |( id, deps) | {
571+ deps. iter ( )
572+ . find ( |dep| dep. is_public ( ) && dep. kind ( ) == DepKind :: Normal )
573+ . map ( |dep| ( id, dep) )
574+ } ) ;
575+
576+ for ( pkg_id, got_dep) in got_deps {
577+ if got_dep. package_name ( ) == dependency. name . as_str ( ) {
578+ pkg_ids_and_reqs. push ( ( pkg_id, got_dep. version_req ( ) . clone ( ) ) ) ;
579+ }
580+
581+ if examined. insert ( pkg_id. clone ( ) ) {
582+ pkg_id_queue. push_back ( pkg_id)
583+ }
584+ }
585+ }
586+
587+ for ( pkg_id, req) in pkg_ids_and_reqs {
588+ if let Some ( ( old_pkg_id, _) ) = & latest
589+ && old_pkg_id. version ( ) >= pkg_id. version ( )
590+ {
591+ continue ;
592+ }
593+ latest = Some ( ( pkg_id, req) )
594+ }
595+ }
596+
597+ let Some ( ( pkg_id, version_req) ) = latest else {
598+ return Ok ( None ) ;
599+ } ;
600+
601+ let source = pkg_id. source_id ( ) ;
602+ if source. is_git ( ) {
603+ Ok ( Some ( (
604+ Option :: < String > :: None ,
605+ Source :: Git ( GitSource :: new ( source. as_encoded_url ( ) . to_string ( ) ) ) ,
606+ ) ) )
607+ } else if let Some ( path) = source. local_path ( ) {
608+ Ok ( Some ( ( None , Source :: Path ( PathSource :: new ( path) ) ) ) )
609+ } else {
610+ let toml_source = match version_req {
611+ crate :: util:: OptVersionReq :: Any => {
612+ Source :: Registry ( RegistrySource :: new ( pkg_id. version ( ) . to_string ( ) ) )
613+ }
614+ crate :: util:: OptVersionReq :: Req ( version_req)
615+ | crate :: util:: OptVersionReq :: Locked ( _, version_req)
616+ | crate :: util:: OptVersionReq :: Precise ( _, version_req) => {
617+ Source :: Registry ( RegistrySource :: new ( version_req. to_string ( ) ) )
618+ }
619+ } ;
620+ Ok ( Some ( (
621+ source
622+ . alt_registry_key ( )
623+ . map ( |x| x. to_owned ( ) )
624+ . filter ( |_| !source. is_crates_io ( ) ) ,
625+ toml_source,
626+ ) ) )
627+ }
628+ }
629+
510630fn query_dependency (
511631 ws : & Workspace < ' _ > ,
512632 gctx : & GlobalContext ,
513633 dependency : & mut Dependency ,
514- ) -> Result < crate :: core:: Dependency , anyhow :: Error > {
634+ ) -> CargoResult < crate :: core:: Dependency > {
515635 let query = dependency. query ( gctx) ?;
516636 let query = match query {
517637 MaybeWorkspace :: Workspace ( _workspace) => {
0 commit comments