@@ -16,12 +16,12 @@ use crate::core::resolver::ResolveBehavior;
16
16
use crate :: core:: { Dependency , Edition , PackageId , PackageIdSpec } ;
17
17
use crate :: core:: { EitherManifest , Package , SourceId , VirtualManifest } ;
18
18
use crate :: ops;
19
- use crate :: sources:: PathSource ;
19
+ use crate :: sources:: { PathSource , CRATES_IO_INDEX , CRATES_IO_REGISTRY } ;
20
20
use crate :: util:: errors:: { CargoResult , CargoResultExt , ManifestError } ;
21
21
use crate :: util:: interning:: InternedString ;
22
22
use crate :: util:: paths;
23
- use crate :: util:: toml:: { read_manifest, TomlProfiles } ;
24
- use crate :: util:: { Config , Filesystem } ;
23
+ use crate :: util:: toml:: { read_manifest, TomlDependency , TomlProfiles } ;
24
+ use crate :: util:: { config :: ConfigRelativePath , Config , Filesystem , IntoUrl } ;
25
25
26
26
/// The core abstraction in Cargo for working with a workspace of crates.
27
27
///
@@ -362,31 +362,89 @@ impl<'cfg> Workspace<'cfg> {
362
362
}
363
363
}
364
364
365
+ fn config_patch ( & self ) -> CargoResult < HashMap < Url , Vec < Dependency > > > {
366
+ let config_patch: Option <
367
+ BTreeMap < String , BTreeMap < String , TomlDependency < ConfigRelativePath > > > ,
368
+ > = self . config . get ( "patch" ) ?;
369
+
370
+ if config_patch. is_some ( ) && !self . config . cli_unstable ( ) . patch_in_config {
371
+ self . config . shell ( ) . warn ( "`[patch]` in cargo config was ignored, the -Zpatch-in-config command-line flag is required" . to_owned ( ) ) ?;
372
+ return Ok ( HashMap :: new ( ) ) ;
373
+ }
374
+
375
+ let source = SourceId :: for_path ( self . root ( ) ) ?;
376
+
377
+ let mut warnings = Vec :: new ( ) ;
378
+ let mut nested_paths = Vec :: new ( ) ;
379
+
380
+ let mut patch = HashMap :: new ( ) ;
381
+ for ( url, deps) in config_patch. into_iter ( ) . flatten ( ) {
382
+ let url = match & url[ ..] {
383
+ CRATES_IO_REGISTRY => CRATES_IO_INDEX . parse ( ) . unwrap ( ) ,
384
+ url => self
385
+ . config
386
+ . get_registry_index ( url)
387
+ . or_else ( |_| url. into_url ( ) )
388
+ . chain_err ( || {
389
+ format ! ( "[patch] entry `{}` should be a URL or registry name" , url)
390
+ } ) ?,
391
+ } ;
392
+ patch. insert (
393
+ url,
394
+ deps. iter ( )
395
+ . map ( |( name, dep) | {
396
+ dep. to_dependency_split (
397
+ name,
398
+ /* pkg_id */ None ,
399
+ source,
400
+ & mut nested_paths,
401
+ self . config ,
402
+ & mut warnings,
403
+ /* platform */ None ,
404
+ // NOTE: Since we use ConfigRelativePath, this root isn't used as
405
+ // any relative paths are resolved before they'd be joined with root.
406
+ self . root ( ) ,
407
+ self . unstable_features ( ) ,
408
+ None ,
409
+ )
410
+ } )
411
+ . collect :: < CargoResult < Vec < _ > > > ( ) ?,
412
+ ) ;
413
+ }
414
+
415
+ for message in warnings {
416
+ self . config
417
+ . shell ( )
418
+ . warn ( format ! ( "[patch] in cargo config: {}" , message) ) ?
419
+ }
420
+
421
+ let _ = nested_paths;
422
+
423
+ Ok ( patch)
424
+ }
425
+
365
426
/// Returns the root `[patch]` section of this workspace.
366
427
///
367
428
/// This may be from a virtual crate or an actual crate.
368
- pub fn root_patch ( & self ) -> HashMap < Url , Vec < Dependency > > {
429
+ pub fn root_patch ( & self ) -> CargoResult < HashMap < Url , Vec < Dependency > > > {
369
430
let from_manifest = match self . root_maybe ( ) {
370
431
MaybePackage :: Package ( p) => p. manifest ( ) . patch ( ) ,
371
432
MaybePackage :: Virtual ( vm) => vm. patch ( ) ,
372
433
} ;
373
434
374
- let from_config = self
375
- . config
376
- . patch ( )
377
- . expect ( "config [patch] was never parsed" ) ;
435
+ let from_config = self . config_patch ( ) ?;
378
436
if from_config. is_empty ( ) {
379
- return from_manifest. clone ( ) ;
437
+ return Ok ( from_manifest. clone ( ) ) ;
380
438
}
381
439
if from_manifest. is_empty ( ) {
382
- return from_config. clone ( ) ;
440
+ return Ok ( from_config. clone ( ) ) ;
383
441
}
384
442
385
443
// We could just chain from_manifest and from_config,
386
444
// but that's not quite right as it won't deal with overlaps.
387
445
let mut combined = from_manifest. clone ( ) ;
388
446
for ( url, cdeps) in from_config {
389
- if let Some ( deps) = combined. get_mut ( url) {
447
+ if let Some ( deps) = combined. get_mut ( & url) {
390
448
// We want from_manifest to take precedence for each patched name.
391
449
// NOTE: This is inefficient if the number of patches is large!
392
450
let mut left = cdeps. clone ( ) ;
@@ -404,7 +462,7 @@ impl<'cfg> Workspace<'cfg> {
404
462
combined. insert ( url. clone ( ) , cdeps. clone ( ) ) ;
405
463
}
406
464
}
407
- combined
465
+ Ok ( combined)
408
466
}
409
467
410
468
/// Returns an iterator over all packages in this workspace
0 commit comments