@@ -12,6 +12,7 @@ use std::str::FromStr;
12
12
use anyhow:: Context as _;
13
13
use cargo_util:: paths;
14
14
use cargo_util_schemas:: core:: PartialVersion ;
15
+ use cargo_util_schemas:: manifest:: PathBaseName ;
15
16
use cargo_util_schemas:: manifest:: RustVersion ;
16
17
use indexmap:: IndexSet ;
17
18
use itertools:: Itertools ;
@@ -20,6 +21,7 @@ use toml_edit::Item as TomlItem;
20
21
use crate :: core:: dependency:: DepKind ;
21
22
use crate :: core:: registry:: PackageRegistry ;
22
23
use crate :: core:: FeatureValue ;
24
+ use crate :: core:: Features ;
23
25
use crate :: core:: Package ;
24
26
use crate :: core:: Registry ;
25
27
use crate :: core:: Shell ;
@@ -28,6 +30,7 @@ use crate::core::Workspace;
28
30
use crate :: sources:: source:: QueryKind ;
29
31
use crate :: util:: cache_lock:: CacheLockMode ;
30
32
use crate :: util:: style;
33
+ use crate :: util:: toml:: lookup_path_base;
31
34
use crate :: util:: toml_mut:: dependency:: Dependency ;
32
35
use crate :: util:: toml_mut:: dependency:: GitSource ;
33
36
use crate :: util:: toml_mut:: dependency:: MaybeWorkspace ;
@@ -197,7 +200,13 @@ pub fn add(workspace: &Workspace<'_>, options: &AddOptions<'_>) -> CargoResult<(
197
200
198
201
print_dep_table_msg ( & mut options. gctx . shell ( ) , & dep) ?;
199
202
200
- manifest. insert_into_table ( & dep_table, & dep) ?;
203
+ manifest. insert_into_table (
204
+ & dep_table,
205
+ & dep,
206
+ workspace. gctx ( ) ,
207
+ workspace. root ( ) ,
208
+ options. spec . manifest ( ) . unstable_features ( ) ,
209
+ ) ?;
201
210
if dep. optional == Some ( true ) {
202
211
let is_namespaced_features_supported =
203
212
check_rust_version_for_optional_dependency ( options. spec . rust_version ( ) ) ?;
@@ -270,8 +279,11 @@ pub struct DepOp {
270
279
/// Registry for looking up dependency version
271
280
pub registry : Option < String > ,
272
281
273
- /// Git repo for dependency
282
+ /// File system path for dependency
274
283
pub path : Option < String > ,
284
+ /// Specify a named base for a path dependency
285
+ pub base : Option < String > ,
286
+
275
287
/// Git repo for dependency
276
288
pub git : Option < String > ,
277
289
/// Specify an alternative git branch
@@ -332,7 +344,19 @@ fn resolve_dependency(
332
344
selected
333
345
} else if let Some ( raw_path) = & arg. path {
334
346
let path = paths:: normalize_path ( & std:: env:: current_dir ( ) ?. join ( raw_path) ) ;
335
- let src = PathSource :: new ( & path) ;
347
+ let mut src = PathSource :: new ( path) ;
348
+ src. base = arg. base . clone ( ) ;
349
+
350
+ if let Some ( base) = & arg. base {
351
+ // Validate that the base is valid.
352
+ let workspace_root = || Ok ( ws. root_manifest ( ) . parent ( ) . unwrap ( ) ) ;
353
+ lookup_path_base (
354
+ & PathBaseName :: new ( base. clone ( ) ) ?,
355
+ & gctx,
356
+ & workspace_root,
357
+ spec. manifest ( ) . unstable_features ( ) ,
358
+ ) ?;
359
+ }
336
360
337
361
let selected = if let Some ( crate_spec) = & crate_spec {
338
362
if let Some ( v) = crate_spec. version_req ( ) {
@@ -349,9 +373,13 @@ fn resolve_dependency(
349
373
}
350
374
selected
351
375
} else {
352
- let mut source = crate :: sources:: PathSource :: new ( & path, src. source_id ( ) ?, gctx) ;
376
+ let mut source = crate :: sources:: PathSource :: new ( & src . path , src. source_id ( ) ?, gctx) ;
353
377
let package = source. root_package ( ) ?;
354
- Dependency :: from ( package. summary ( ) )
378
+ let mut selected = Dependency :: from ( package. summary ( ) ) ;
379
+ if let Some ( Source :: Path ( selected_src) ) = & mut selected. source {
380
+ selected_src. base = src. base ;
381
+ }
382
+ selected
355
383
} ;
356
384
selected
357
385
} else if let Some ( crate_spec) = & crate_spec {
@@ -361,9 +389,16 @@ fn resolve_dependency(
361
389
} ;
362
390
selected_dep = populate_dependency ( selected_dep, arg) ;
363
391
364
- let lookup = |dep_key : & _ | get_existing_dependency ( manifest, dep_key, section) ;
392
+ let lookup = |dep_key : & _ | {
393
+ get_existing_dependency (
394
+ ws,
395
+ spec. manifest ( ) . unstable_features ( ) ,
396
+ manifest,
397
+ dep_key,
398
+ section,
399
+ )
400
+ } ;
365
401
let old_dep = fuzzy_lookup ( & mut selected_dep, lookup, gctx) ?;
366
-
367
402
let mut dependency = if let Some ( mut old_dep) = old_dep. clone ( ) {
368
403
if old_dep. name != selected_dep. name {
369
404
// Assuming most existing keys are not relevant when the package changes
@@ -385,7 +420,9 @@ fn resolve_dependency(
385
420
if dependency. source ( ) . is_none ( ) {
386
421
// Checking for a workspace dependency happens first since a member could be specified
387
422
// in the workspace dependencies table as a dependency
388
- let lookup = |toml_key : & _ | Ok ( find_workspace_dep ( toml_key, ws. root_manifest ( ) ) . ok ( ) ) ;
423
+ let lookup = |toml_key : & _ | {
424
+ Ok ( find_workspace_dep ( toml_key, ws, ws. root_manifest ( ) , ws. unstable_features ( ) ) . ok ( ) )
425
+ } ;
389
426
if let Some ( _dep) = fuzzy_lookup ( & mut dependency, lookup, gctx) ? {
390
427
dependency = dependency. set_source ( WorkspaceSource :: new ( ) ) ;
391
428
} else if let Some ( package) = ws. members ( ) . find ( |p| p. name ( ) . as_str ( ) == dependency. name ) {
@@ -432,7 +469,12 @@ fn resolve_dependency(
432
469
let query = dependency. query ( gctx) ?;
433
470
let query = match query {
434
471
MaybeWorkspace :: Workspace ( _workspace) => {
435
- let dep = find_workspace_dep ( dependency. toml_key ( ) , ws. root_manifest ( ) ) ?;
472
+ let dep = find_workspace_dep (
473
+ dependency. toml_key ( ) ,
474
+ ws,
475
+ ws. root_manifest ( ) ,
476
+ ws. unstable_features ( ) ,
477
+ ) ?;
436
478
if let Some ( features) = dep. features . clone ( ) {
437
479
dependency = dependency. set_inherited_features ( features) ;
438
480
}
@@ -547,6 +589,8 @@ fn check_rust_version_for_optional_dependency(
547
589
/// If it doesn't exist but exists in another table, let's use that as most likely users
548
590
/// want to use the same version across all tables unless they are renaming.
549
591
fn get_existing_dependency (
592
+ ws : & Workspace < ' _ > ,
593
+ unstable_features : & Features ,
550
594
manifest : & LocalManifest ,
551
595
dep_key : & str ,
552
596
section : & DepTable ,
@@ -561,7 +605,7 @@ fn get_existing_dependency(
561
605
}
562
606
563
607
let mut possible: Vec < _ > = manifest
564
- . get_dependency_versions ( dep_key)
608
+ . get_dependency_versions ( dep_key, ws , unstable_features )
565
609
. map ( |( path, dep) | {
566
610
let key = if path == * section {
567
611
( Key :: Existing , true )
@@ -776,6 +820,11 @@ fn select_package(
776
820
if let Some ( reg_name) = dependency. registry . as_deref ( ) {
777
821
dep = dep. set_registry ( reg_name) ;
778
822
}
823
+ if let Some ( Source :: Path ( PathSource { base, .. } ) ) = dependency. source ( ) {
824
+ if let Some ( Source :: Path ( dep_src) ) = & mut dep. source {
825
+ dep_src. base = base. clone ( ) ;
826
+ }
827
+ }
779
828
Ok ( dep)
780
829
}
781
830
_ => {
@@ -1107,7 +1156,12 @@ fn format_features_version_suffix(dep: &DependencyUI) -> String {
1107
1156
}
1108
1157
}
1109
1158
1110
- fn find_workspace_dep ( toml_key : & str , root_manifest : & Path ) -> CargoResult < Dependency > {
1159
+ fn find_workspace_dep (
1160
+ toml_key : & str ,
1161
+ ws : & Workspace < ' _ > ,
1162
+ root_manifest : & Path ,
1163
+ unstable_features : & Features ,
1164
+ ) -> CargoResult < Dependency > {
1111
1165
let manifest = LocalManifest :: try_new ( root_manifest) ?;
1112
1166
let manifest = manifest
1113
1167
. data
@@ -1127,7 +1181,14 @@ fn find_workspace_dep(toml_key: &str, root_manifest: &Path) -> CargoResult<Depen
1127
1181
let dep_item = dependencies
1128
1182
. get ( toml_key)
1129
1183
. with_context ( || format ! ( "could not find {toml_key} in `workspace.dependencies`" ) ) ?;
1130
- Dependency :: from_toml ( root_manifest. parent ( ) . unwrap ( ) , toml_key, dep_item)
1184
+ Dependency :: from_toml (
1185
+ ws. gctx ( ) ,
1186
+ ws. root ( ) ,
1187
+ root_manifest. parent ( ) . unwrap ( ) ,
1188
+ unstable_features,
1189
+ toml_key,
1190
+ dep_item,
1191
+ )
1131
1192
}
1132
1193
1133
1194
/// Convert a `semver::VersionReq` into a rendered `semver::Version` if all fields are fully
0 commit comments