@@ -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) ?;
@@ -501,6 +513,125 @@ fn resolve_dependency(
501513 dependency = dependency. clear_version ( ) ;
502514 }
503515
516+ let query = query_dependency ( ws, gctx, & mut dependency) ?;
517+ let dependency = populate_available_features ( dependency, & query, registry) ?;
518+
519+ Ok ( dependency)
520+ }
521+
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+
630+ fn query_dependency (
631+ ws : & Workspace < ' _ > ,
632+ gctx : & GlobalContext ,
633+ dependency : & mut Dependency ,
634+ ) -> CargoResult < crate :: core:: Dependency > {
504635 let query = dependency. query ( gctx) ?;
505636 let query = match query {
506637 MaybeWorkspace :: Workspace ( _workspace) => {
@@ -511,7 +642,7 @@ fn resolve_dependency(
511642 ws. unstable_features ( ) ,
512643 ) ?;
513644 if let Some ( features) = dep. features . clone ( ) {
514- dependency = dependency. set_inherited_features ( features) ;
645+ * dependency = dependency. clone ( ) . set_inherited_features ( features) ;
515646 }
516647 let query = dep. query ( gctx) ?;
517648 match query {
@@ -523,10 +654,7 @@ fn resolve_dependency(
523654 }
524655 MaybeWorkspace :: Other ( query) => query,
525656 } ;
526-
527- let dependency = populate_available_features ( dependency, & query, registry) ?;
528-
529- Ok ( dependency)
657+ Ok ( query)
530658}
531659
532660fn fuzzy_lookup (
@@ -640,8 +768,11 @@ fn get_existing_dependency(
640768 }
641769
642770 let mut possible: Vec < _ > = manifest
643- . get_dependency_versions ( dep_key, ws, unstable_features)
644- . map ( |( path, dep) | {
771+ . get_dependencies ( ws, unstable_features)
772+ . filter_map ( |( key, path, dep) | {
773+ if key. as_str ( ) != dep_key {
774+ return None ;
775+ }
645776 let key = if path == * section {
646777 ( Key :: Existing , true )
647778 } else if dep. is_err ( ) {
@@ -654,7 +785,7 @@ fn get_existing_dependency(
654785 } ;
655786 ( key, path. target ( ) . is_some ( ) )
656787 } ;
657- ( key, dep)
788+ Some ( ( key, dep) )
658789 } )
659790 . collect ( ) ;
660791 possible. sort_by_key ( |( key, _) | * key) ;
0 commit comments