@@ -20,7 +20,7 @@ use crate::core::{
2020} ;
2121use crate :: core:: { EitherManifest , Package , SourceId , VirtualManifest } ;
2222use crate :: ops;
23- use crate :: sources:: { PathSource , CRATES_IO_INDEX , CRATES_IO_REGISTRY } ;
23+ use crate :: sources:: { PathSource , SourceConfigMap , CRATES_IO_INDEX , CRATES_IO_REGISTRY } ;
2424use crate :: util:: edit_distance;
2525use crate :: util:: errors:: { CargoResult , ManifestError } ;
2626use crate :: util:: interning:: InternedString ;
@@ -109,6 +109,9 @@ pub struct Workspace<'gctx> {
109109
110110 /// Workspace-level custom metadata
111111 custom_metadata : Option < toml:: Value > ,
112+
113+ /// Local overlay configuration. See [`crate::sources::overlay`].
114+ local_overlays : HashMap < SourceId , PathBuf > ,
112115}
113116
114117// Separate structure for tracking loaded packages (to avoid loading anything
@@ -237,6 +240,7 @@ impl<'gctx> Workspace<'gctx> {
237240 resolve_behavior : ResolveBehavior :: V1 ,
238241 resolve_honors_rust_version : false ,
239242 custom_metadata : None ,
243+ local_overlays : HashMap :: new ( ) ,
240244 }
241245 }
242246
@@ -1674,6 +1678,44 @@ impl<'gctx> Workspace<'gctx> {
16741678 // Cargo to panic, see issue #10545.
16751679 self . is_member ( & unit. pkg ) && !( unit. target . for_host ( ) || unit. pkg . proc_macro ( ) )
16761680 }
1681+
1682+ /// Adds a local package registry overlaying a `SourceId`.
1683+ ///
1684+ /// See [`crate::sources::overlay::DependencyConfusionThreatOverlaySource`] for why you shouldn't use this.
1685+ pub fn add_local_overlay ( & mut self , id : SourceId , registry_path : PathBuf ) {
1686+ self . local_overlays . insert ( id, registry_path) ;
1687+ }
1688+
1689+ /// Builds a package registry that reflects this workspace configuration.
1690+ pub fn package_registry ( & self ) -> CargoResult < PackageRegistry < ' gctx > > {
1691+ let source_config =
1692+ SourceConfigMap :: new_with_overlays ( self . gctx ( ) , self . local_overlays ( ) ?) ?;
1693+ PackageRegistry :: new_with_source_config ( self . gctx ( ) , source_config)
1694+ }
1695+
1696+ /// Returns all the configured local overlays, including the ones from our secret environment variable.
1697+ fn local_overlays ( & self ) -> CargoResult < impl Iterator < Item = ( SourceId , SourceId ) > > {
1698+ let mut ret = self
1699+ . local_overlays
1700+ . iter ( )
1701+ . map ( |( id, path) | Ok ( ( * id, SourceId :: for_local_registry ( path) ?) ) )
1702+ . collect :: < CargoResult < Vec < _ > > > ( ) ?;
1703+
1704+ if let Ok ( overlay) = self
1705+ . gctx
1706+ . get_env ( "__CARGO_TEST_DEPENDENCY_CONFUSION_VULNERABILITY_DO_NOT_USE_THIS" )
1707+ {
1708+ let ( url, path) = overlay. split_once ( '=' ) . ok_or ( anyhow:: anyhow!(
1709+ "invalid overlay format. I won't tell you why; you shouldn't be using it anyway"
1710+ ) ) ?;
1711+ ret. push ( (
1712+ SourceId :: from_url ( url) ?,
1713+ SourceId :: for_local_registry ( path. as_ref ( ) ) ?,
1714+ ) ) ;
1715+ }
1716+
1717+ Ok ( ret. into_iter ( ) )
1718+ }
16771719}
16781720
16791721impl < ' gctx > Packages < ' gctx > {
0 commit comments