@@ -7,6 +7,7 @@ use std::slice;
7
7
8
8
use anyhow:: { bail, Context as _} ;
9
9
use glob:: glob;
10
+ use itertools:: Itertools ;
10
11
use log:: debug;
11
12
use url:: Url ;
12
13
@@ -1071,7 +1072,7 @@ impl<'cfg> Workspace<'cfg> {
1071
1072
if self . allows_new_cli_feature_behavior ( ) {
1072
1073
self . members_with_features_new ( specs, cli_features)
1073
1074
} else {
1074
- Ok ( self . members_with_features_old ( specs, cli_features) )
1075
+ self . members_with_features_old ( specs, cli_features)
1075
1076
}
1076
1077
}
1077
1078
@@ -1196,7 +1197,7 @@ impl<'cfg> Workspace<'cfg> {
1196
1197
& self ,
1197
1198
specs : & [ PackageIdSpec ] ,
1198
1199
cli_features : & CliFeatures ,
1199
- ) -> Vec < ( & Package , CliFeatures ) > {
1200
+ ) -> CargoResult < Vec < ( & Package , CliFeatures ) > > {
1200
1201
// Split off any features with the syntax `member-name/feature-name` into a map
1201
1202
// so that those features can be applied directly to those workspace-members.
1202
1203
let mut member_specific_features: HashMap < InternedString , BTreeSet < FeatureValue > > =
@@ -1215,29 +1216,29 @@ impl<'cfg> Workspace<'cfg> {
1215
1216
} => panic ! ( "unexpected dep: syntax {}" , feature) ,
1216
1217
FeatureValue :: DepFeature {
1217
1218
dep_name,
1218
- dep_feature,
1219
+ dep_feature : _ ,
1219
1220
dep_prefix : _,
1220
1221
weak : _,
1221
1222
} => {
1222
- // I think weak can be ignored here.
1223
- // * With `--features member?/feat -p member`, the ? doesn't
1224
- // really mean anything (either the member is built or it isn't).
1225
- // * With `--features nonmember?/feat`, cwd_features will
1226
- // handle processing it correctly.
1223
+ // Check if `dep_name` is member of the workspace or package.
1224
+ // Weak can be ignored for this moment.
1227
1225
let is_member = self . members ( ) . any ( |member| member. name ( ) == * dep_name) ;
1228
1226
if is_member && specs. iter ( ) . any ( |spec| spec. name ( ) == * dep_name) {
1229
1227
member_specific_features
1230
1228
. entry ( * dep_name)
1231
1229
. or_default ( )
1232
- . insert ( FeatureValue :: Feature ( * dep_feature ) ) ;
1230
+ . insert ( feature . clone ( ) ) ;
1233
1231
} else {
1232
+ // With `--features nonmember?/feat`, cwd_features will
1233
+ // handle processing it correctly.
1234
1234
cwd_features. insert ( feature. clone ( ) ) ;
1235
1235
}
1236
1236
}
1237
1237
}
1238
1238
}
1239
1239
1240
- let ms = self . members ( ) . filter_map ( |member| {
1240
+ let mut result = Vec :: new ( ) ;
1241
+ for member in self . members ( ) {
1241
1242
let member_id = member. package_id ( ) ;
1242
1243
match self . current_opt ( ) {
1243
1244
// The features passed on the command-line only apply to
@@ -1248,13 +1249,29 @@ impl<'cfg> Workspace<'cfg> {
1248
1249
all_features : cli_features. all_features ,
1249
1250
uses_default_features : cli_features. uses_default_features ,
1250
1251
} ;
1251
- Some ( ( member, feats) )
1252
+
1253
+ // If any member specific features were passed to non-virtual package, it's error
1254
+ if !member_specific_features. is_empty ( ) {
1255
+ let invalid: Vec < _ > = member_specific_features
1256
+ . values ( )
1257
+ . map ( |set| set. iter ( ) )
1258
+ . flatten ( )
1259
+ . map ( |feature| feature. to_string ( ) )
1260
+ . sorted ( )
1261
+ . collect ( ) ;
1262
+
1263
+ bail ! (
1264
+ "Member specific features with `pkg/feat` syntax are dissalowed outside of workspace with `resolver = \" 1\" , remove: {}" ,
1265
+ invalid. join( ", " )
1266
+ ) ;
1267
+ }
1268
+
1269
+ result. push ( ( member, feats) )
1252
1270
}
1253
1271
_ => {
1254
1272
// Ignore members that are not enabled on the command-line.
1255
1273
if specs. iter ( ) . any ( |spec| spec. matches ( member_id) ) {
1256
- // -p for a workspace member that is not the "current"
1257
- // one.
1274
+ // -p for a workspace member that is not the "current" one.
1258
1275
//
1259
1276
// The odd behavior here is due to backwards
1260
1277
// compatibility. `--features` and
@@ -1266,20 +1283,36 @@ impl<'cfg> Workspace<'cfg> {
1266
1283
features : Rc :: new (
1267
1284
member_specific_features
1268
1285
. remove ( member. name ( ) . as_str ( ) )
1269
- . unwrap_or_default ( ) ,
1286
+ . unwrap_or_default ( )
1287
+ . into_iter ( )
1288
+ . map ( |feature| match feature {
1289
+ // I think weak can be ignored here.
1290
+ // With `--features member?/feat -p member`, the ? doesn't
1291
+ // really mean anything (either the member is built or it isn't).
1292
+ FeatureValue :: DepFeature {
1293
+ dep_name : _,
1294
+ dep_feature,
1295
+ dep_prefix : false ,
1296
+ weak : _,
1297
+ } => FeatureValue :: new ( dep_feature) ,
1298
+ // Member specific features by definition contain only `FeatureValue::DepFeature`
1299
+ _ => unreachable ! ( ) ,
1300
+ } )
1301
+ . collect ( ) ,
1270
1302
) ,
1271
1303
uses_default_features : true ,
1272
1304
all_features : cli_features. all_features ,
1273
1305
} ;
1274
- Some ( ( member, feats) )
1306
+
1307
+ result. push ( ( member, feats) )
1275
1308
} else {
1276
1309
// This member was not requested on the command-line, skip.
1277
- None
1278
1310
}
1279
1311
}
1280
1312
}
1281
- } ) ;
1282
- ms. collect ( )
1313
+ }
1314
+
1315
+ Ok ( result)
1283
1316
}
1284
1317
}
1285
1318
0 commit comments