@@ -88,7 +88,10 @@ pub struct PackageRegistry<'cfg> {
8888
8989 locked : LockedMap ,
9090 source_config : SourceConfigMap < ' cfg > ,
91+
9192 patches : HashMap < Url , Vec < Summary > > ,
93+ patches_locked : bool ,
94+ patches_available : HashMap < Url , Vec < PackageId > > ,
9295}
9396
9497type LockedMap = HashMap < SourceId , HashMap < String , Vec < ( PackageId , Vec < PackageId > ) > > > ;
@@ -110,6 +113,8 @@ impl<'cfg> PackageRegistry<'cfg> {
110113 source_config : source_config,
111114 locked : HashMap :: new ( ) ,
112115 patches : HashMap :: new ( ) ,
116+ patches_locked : false ,
117+ patches_available : HashMap :: new ( ) ,
113118 } )
114119 }
115120
@@ -188,9 +193,50 @@ impl<'cfg> PackageRegistry<'cfg> {
188193 sub_vec. push ( ( id, deps) ) ;
189194 }
190195
196+ /// Insert a `[patch]` section into this registry.
197+ ///
198+ /// This method will insert a `[patch]` section for the `url` specified,
199+ /// with the given list of dependencies. The `url` specified is the URL of
200+ /// the source to patch (for example this is `crates-io` in the manifest).
201+ /// The `deps` is an array of all the entries in the `[patch]` section of
202+ /// the manifest.
203+ ///
204+ /// Here the `deps` will be resolved to a precise version and stored
205+ /// internally for future calls to `query` below. It's expected that `deps`
206+ /// have had `lock_to` call already, if applicable. (e.g. if a lock file was
207+ /// already present).
208+ ///
209+ /// Note that the patch list specified here *will not* be available to
210+ /// `query` until `lock_patches` is called below, which should be called
211+ /// once all patches have been added.
191212 pub fn patch ( & mut self , url : & Url , deps : & [ Dependency ] ) -> CargoResult < ( ) > {
192- let deps = deps. iter ( ) . map ( |dep| {
193- let mut summaries = self . query_vec ( dep) ?. into_iter ( ) ;
213+ // First up we need to actually resolve each `deps` specification to
214+ // precisely one summary. We're not using the `query` method below as it
215+ // internally uses maps we're building up as part of this method
216+ // (`patches_available` and `patches). Instead we're going straight to
217+ // the source to load information from it.
218+ //
219+ // Remember that each dependency listed in `[patch]` has to resolve to
220+ // precisely one package, so that's why we're just creating a flat list
221+ // of summaries which should be the same length as `deps` above.
222+ let unlocked_summaries = deps. iter ( ) . map ( |dep| {
223+ debug ! ( "registring a patch for `{}` with `{}`" ,
224+ url,
225+ dep. name( ) ) ;
226+
227+ // Go straight to the source for resolving `dep`. Load it as we
228+ // normally would and then ask it directly for the list of summaries
229+ // corresponding to this `dep`.
230+ self . ensure_loaded ( dep. source_id ( ) , Kind :: Normal ) . chain_err ( || {
231+ format_err ! ( "failed to load source for a dependency \
232+ on `{}`", dep. name( ) )
233+ } ) ?;
234+
235+ let mut summaries = self . sources . get_mut ( dep. source_id ( ) )
236+ . expect ( "loaded source not present" )
237+ . query_vec ( dep) ?
238+ . into_iter ( ) ;
239+
194240 let summary = match summaries. next ( ) {
195241 Some ( summary) => summary,
196242 None => {
@@ -214,11 +260,38 @@ impl<'cfg> PackageRegistry<'cfg> {
214260 format_err ! ( "failed to resolve patches for `{}`" , url)
215261 } ) ?;
216262
217- self . patches . insert ( url. clone ( ) , deps) ;
263+ // Note that we do not use `lock` here to lock summaries! That step
264+ // happens later once `lock_patches` is invoked. In the meantime though
265+ // we want to fill in the `patches_available` map (later used in the
266+ // `lock` method) and otherwise store the unlocked summaries in
267+ // `patches` to get locked in a future call to `lock_patches`.
268+ let ids = unlocked_summaries. iter ( )
269+ . map ( |s| s. package_id ( ) )
270+ . cloned ( )
271+ . collect ( ) ;
272+ self . patches_available . insert ( url. clone ( ) , ids) ;
273+ self . patches . insert ( url. clone ( ) , unlocked_summaries) ;
218274
219275 Ok ( ( ) )
220276 }
221277
278+ /// Lock all patch summaries added via `patch`, making them available to
279+ /// resolution via `query`.
280+ ///
281+ /// This function will internally `lock` each summary added via `patch`
282+ /// above now that the full set of `patch` packages are known. This'll allow
283+ /// us to correctly resolve overridden dependencies between patches
284+ /// hopefully!
285+ pub fn lock_patches ( & mut self ) {
286+ assert ! ( !self . patches_locked) ;
287+ for summaries in self . patches . values_mut ( ) {
288+ for summary in summaries {
289+ * summary = lock ( & self . locked , & self . patches_available , summary. clone ( ) ) ;
290+ }
291+ }
292+ self . patches_locked = true ;
293+ }
294+
222295 pub fn patches ( & self ) -> & HashMap < Url , Vec < Summary > > {
223296 & self . patches
224297 }
@@ -271,7 +344,8 @@ impl<'cfg> PackageRegistry<'cfg> {
271344 /// possible. If we're unable to map a dependency though, we just pass it on
272345 /// through.
273346 pub fn lock ( & self , summary : Summary ) -> Summary {
274- lock ( & self . locked , & self . patches , summary)
347+ assert ! ( self . patches_locked) ;
348+ lock ( & self . locked , & self . patches_available , summary)
275349 }
276350
277351 fn warn_bad_override ( & self ,
@@ -323,6 +397,7 @@ impl<'cfg> Registry for PackageRegistry<'cfg> {
323397 fn query ( & mut self ,
324398 dep : & Dependency ,
325399 f : & mut FnMut ( Summary ) ) -> CargoResult < ( ) > {
400+ assert ! ( self . patches_locked) ;
326401 let ( override_summary, n, to_warn) = {
327402 // Look for an override and get ready to query the real source.
328403 let override_summary = self . query_overrides ( dep) ?;
@@ -357,8 +432,12 @@ impl<'cfg> Registry for PackageRegistry<'cfg> {
357432 }
358433 } else {
359434 if !patches. is_empty ( ) {
360- debug ! ( "found {} patches with an unlocked dep, \
361- looking at sources", patches. len( ) ) ;
435+ debug ! ( "found {} patches with an unlocked dep on `{}` at {} \
436+ with `{}`, \
437+ looking at sources", patches. len( ) ,
438+ dep. name( ) ,
439+ dep. source_id( ) ,
440+ dep. version_req( ) ) ;
362441 }
363442
364443 // Ensure the requested source_id is loaded
@@ -387,7 +466,7 @@ impl<'cfg> Registry for PackageRegistry<'cfg> {
387466 // version as something in `patches` that we've
388467 // already selected, then we skip this `summary`.
389468 let locked = & self . locked ;
390- let all_patches = & self . patches ;
469+ let all_patches = & self . patches_available ;
391470 return source. query ( dep, & mut |summary| {
392471 for patch in patches. iter ( ) {
393472 let patch = patch. package_id ( ) . version ( ) ;
@@ -437,7 +516,7 @@ impl<'cfg> Registry for PackageRegistry<'cfg> {
437516}
438517
439518fn lock ( locked : & LockedMap ,
440- patches : & HashMap < Url , Vec < Summary > > ,
519+ patches : & HashMap < Url , Vec < PackageId > > ,
441520 summary : Summary ) -> Summary {
442521 let pair = locked. get ( summary. source_id ( ) ) . and_then ( |map| {
443522 map. get ( summary. name ( ) )
@@ -504,24 +583,24 @@ fn lock(locked: &LockedMap,
504583 // this dependency.
505584 let v = patches. get ( dep. source_id ( ) . url ( ) ) . map ( |vec| {
506585 let dep2 = dep. clone ( ) ;
507- let mut iter = vec. iter ( ) . filter ( move |s | {
508- dep2. name ( ) == s . package_id ( ) . name ( ) &&
509- dep2. version_req ( ) . matches ( s . package_id ( ) . version ( ) )
586+ let mut iter = vec. iter ( ) . filter ( move |p | {
587+ dep2. name ( ) == p . name ( ) &&
588+ dep2. version_req ( ) . matches ( p . version ( ) )
510589 } ) ;
511590 ( iter. next ( ) , iter)
512591 } ) ;
513- if let Some ( ( Some ( summary ) , mut remaining) ) = v {
592+ if let Some ( ( Some ( patch_id ) , mut remaining) ) = v {
514593 assert ! ( remaining. next( ) . is_none( ) ) ;
515- let patch_source = summary . package_id ( ) . source_id ( ) ;
594+ let patch_source = patch_id . source_id ( ) ;
516595 let patch_locked = locked. get ( patch_source) . and_then ( |m| {
517- m. get ( summary . package_id ( ) . name ( ) )
596+ m. get ( patch_id . name ( ) )
518597 } ) . map ( |list| {
519- list. iter ( ) . any ( |& ( ref id, _) | id == summary . package_id ( ) )
598+ list. iter ( ) . any ( |& ( ref id, _) | id == patch_id )
520599 } ) . unwrap_or ( false ) ;
521600
522601 if patch_locked {
523- trace ! ( "\t third hit on {}" , summary . package_id ( ) ) ;
524- let req = VersionReq :: exact ( summary . package_id ( ) . version ( ) ) ;
602+ trace ! ( "\t third hit on {}" , patch_id ) ;
603+ let req = VersionReq :: exact ( patch_id . version ( ) ) ;
525604 let mut dep = dep. clone ( ) ;
526605 dep. set_version_req ( req) ;
527606 return dep
0 commit comments