@@ -78,6 +78,9 @@ pub(crate) struct Args {
78
78
pub ( crate ) depth : Option < usize > ,
79
79
/// --group-features <FEATURES>...
80
80
pub ( crate ) group_features : Vec < Feature > ,
81
+ /// --at-least-one-of <FEATURES>...
82
+ /// Implies --exclude-no-default-features. Can be specified multiple times.
83
+ pub ( crate ) at_least_one_of : Vec < Feature > ,
81
84
82
85
// options that will be propagated to cargo
83
86
/// --features <FEATURES>...
@@ -151,6 +154,7 @@ impl Args {
151
154
152
155
let mut optional_deps = None ;
153
156
let mut include_features = vec ! [ ] ;
157
+ let mut at_least_one_of = vec ! [ ] ;
154
158
let mut include_deps_features = false ;
155
159
156
160
let mut exclude_features = vec ! [ ] ;
@@ -277,6 +281,7 @@ impl Args {
277
281
Long ( "remove-dev-deps" ) => parse_flag ! ( remove_dev_deps) ,
278
282
Long ( "each-feature" ) => parse_flag ! ( each_feature) ,
279
283
Long ( "feature-powerset" ) => parse_flag ! ( feature_powerset) ,
284
+ Long ( "at-least-one-of" ) => at_least_one_of. push ( parser. value ( ) ?. parse ( ) ?) ,
280
285
Long ( "no-private" ) => parse_flag ! ( no_private) ,
281
286
Long ( "ignore-private" ) => parse_flag ! ( ignore_private) ,
282
287
Long ( "exclude-no-default-features" ) => parse_flag ! ( exclude_no_default_features) ,
@@ -391,8 +396,16 @@ impl Args {
391
396
requires ( "--include-features" , & [ "--each-feature" , "--feature-powerset" ] ) ?;
392
397
} else if include_deps_features {
393
398
requires ( "--include-deps-features" , & [ "--each-feature" , "--feature-powerset" ] ) ?;
399
+ } else if !at_least_one_of. is_empty ( ) {
400
+ requires ( "--at-least-one-of" , & [ "--feature-powerset" ] ) ?;
394
401
}
395
402
}
403
+
404
+ if !at_least_one_of. is_empty ( ) {
405
+ // there will always be a feature set
406
+ exclude_no_default_features = true ;
407
+ }
408
+
396
409
if !feature_powerset {
397
410
if depth. is_some ( ) {
398
411
requires ( "--depth" , & [ "--feature-powerset" ] ) ?;
@@ -410,21 +423,8 @@ impl Args {
410
423
}
411
424
412
425
let depth = depth. as_deref ( ) . map ( str:: parse :: < usize > ) . transpose ( ) ?;
413
- let group_features =
414
- group_features. iter ( ) . try_fold ( Vec :: with_capacity ( group_features. len ( ) ) , |mut v, g| {
415
- let g = if g. contains ( ',' ) {
416
- g. split ( ',' )
417
- } else if g. contains ( ' ' ) {
418
- g. split ( ' ' )
419
- } else {
420
- bail ! (
421
- "--group-features requires a list of two or more features separated by space \
422
- or comma"
423
- ) ;
424
- } ;
425
- v. push ( Feature :: group ( g) ) ;
426
- Ok ( v)
427
- } ) ?;
426
+ let group_features = parse_grouped_features ( group_features, "group-features" ) ?;
427
+ let at_least_one_of = parse_grouped_features ( at_least_one_of, "at-least-one-of" ) ?;
428
428
429
429
if let Some ( subcommand) = subcommand. as_deref ( ) {
430
430
match subcommand {
@@ -567,6 +567,7 @@ impl Args {
567
567
print_command_list,
568
568
no_manifest_path,
569
569
include_features : include_features. into_iter ( ) . map ( Into :: into) . collect ( ) ,
570
+ at_least_one_of,
570
571
include_deps_features,
571
572
version_range,
572
573
version_step,
@@ -586,6 +587,25 @@ impl Args {
586
587
}
587
588
}
588
589
590
+ fn parse_grouped_features ( group_features : Vec < String > , option_name : & str ) -> Result < Vec < Feature > , anyhow:: Error > {
591
+ let group_features =
592
+ group_features. iter ( ) . try_fold ( Vec :: with_capacity ( group_features. len ( ) ) , |mut v, g| {
593
+ let g = if g. contains ( ',' ) {
594
+ g. split ( ',' )
595
+ } else if g. contains ( ' ' ) {
596
+ g. split ( ' ' )
597
+ } else {
598
+ bail ! (
599
+ "--{option_name} requires a list of two or more features separated by space \
600
+ or comma"
601
+ ) ;
602
+ } ;
603
+ v. push ( Feature :: group ( g) ) ;
604
+ Ok ( v)
605
+ } ) ?;
606
+ Ok ( group_features)
607
+ }
608
+
589
609
fn has_z_flag ( args : & [ String ] , name : & str ) -> bool {
590
610
let mut iter = args. iter ( ) . map ( String :: as_str) ;
591
611
while let Some ( mut arg) = iter. next ( ) {
@@ -668,6 +688,12 @@ const HELP: &[HelpText<'_>] = &[
668
688
--group-features c,d`",
669
689
"This flag can only be used together with --feature-powerset flag." ,
670
690
] ) ,
691
+ ( "" , "--at-least-one-of" , "<FEATURES>..." , "Space or comma separated list of features. Skips sets of features that don't
692
+ enable any of the features listed." , & [
693
+ "To specify multiple groups, use this option multiple times: `--at-least-one-of a,b \
694
+ --at-least-one-of c,d`",
695
+ "This flag can only be used together with --feature-powerset flag." ,
696
+ ] ) ,
671
697
(
672
698
"" ,
673
699
"--include-features" ,
0 commit comments