@@ -6,7 +6,7 @@ use std::str::FromStr;
6
6
use anyhow:: { anyhow, Error , Result } ;
7
7
use clap:: {
8
8
builder:: { PossibleValue , PossibleValuesParser } ,
9
- Arg , ArgAction , Args , Command , FromArgMatches as _ , Parser , Subcommand , ValueEnum ,
9
+ Args , CommandFactory , Parser , Subcommand , ValueEnum ,
10
10
} ;
11
11
use clap_complete:: Shell ;
12
12
use itertools:: Itertools ;
@@ -64,15 +64,43 @@ fn handle_epipe(res: Result<utils::ExitCode>) -> Result<utils::ExitCode> {
64
64
}
65
65
}
66
66
67
+ /// The Rust toolchain installer
67
68
#[ derive( Debug , Parser ) ]
68
69
#[ command(
69
70
name = "rustup" ,
70
71
bin_name = "rustup[EXE]" ,
71
72
version = common:: version( ) ,
73
+ before_help = format!( "rustup {}" , common:: version( ) ) ,
74
+ after_help = RUSTUP_HELP ,
72
75
) ]
73
76
struct Rustup {
77
+ /// Enable verbose output
78
+ #[ arg( short, long) ]
79
+ verbose : bool ,
80
+
81
+ /// Disable progress output
82
+ #[ arg( short, long, conflicts_with = "verbose" ) ]
83
+ quiet : bool ,
84
+
85
+ /// Release channel (e.g. +stable) or custom toolchain to set override
86
+ #[ arg(
87
+ name = "+toolchain" ,
88
+ value_parser = plus_toolchain_value_parser,
89
+ ) ]
90
+ plus_toolchain : Option < ResolvableToolchainName > ,
91
+
74
92
#[ command( subcommand) ]
75
- subcmd : RustupSubcmd ,
93
+ subcmd : Option < RustupSubcmd > ,
94
+ }
95
+
96
+ fn plus_toolchain_value_parser ( s : & str ) -> clap:: error:: Result < ResolvableToolchainName > {
97
+ use clap:: { error:: ErrorKind , Error } ;
98
+ if let Some ( stripped) = s. strip_prefix ( '+' ) {
99
+ ResolvableToolchainName :: try_from ( stripped)
100
+ . map_err ( |e| Error :: raw ( ErrorKind :: InvalidValue , e) )
101
+ } else {
102
+ Err ( Error :: raw ( ErrorKind :: InvalidSubcommand , format ! ( "\" {s}\" is not a valid subcommand, so it was interpreted as a toolchain name, but it is also invalid. {TOOLCHAIN_OVERRIDE_ERROR}" ) ) )
103
+ }
76
104
}
77
105
78
106
#[ derive( Debug , Subcommand ) ]
@@ -496,9 +524,9 @@ enum SetSubcmd {
496
524
} ,
497
525
}
498
526
499
- impl Rustup {
527
+ impl RustupSubcmd {
500
528
fn dispatch ( self , cfg : & mut Cfg ) -> Result < utils:: ExitCode > {
501
- match self . subcmd {
529
+ match self {
502
530
RustupSubcmd :: DumpTestament => common:: dump_testament ( ) ,
503
531
RustupSubcmd :: Install { opts } => update ( cfg, opts) ,
504
532
RustupSubcmd :: Uninstall { opts } => toolchain_remove ( cfg, opts) ,
@@ -606,7 +634,7 @@ pub fn main() -> Result<utils::ExitCode> {
606
634
self_update:: cleanup_self_updater ( ) ?;
607
635
608
636
use clap:: error:: ErrorKind :: * ;
609
- let matches = match cli ( ) . try_get_matches_from ( process ( ) . args_os ( ) ) {
637
+ let matches = match Rustup :: try_parse_from ( process ( ) . args_os ( ) ) {
610
638
Ok ( matches) => Ok ( matches) ,
611
639
Err ( err) if err. kind ( ) == DisplayHelp => {
612
640
write ! ( process( ) . stdout( ) . lock( ) , "{err}" ) ?;
@@ -656,66 +684,23 @@ pub fn main() -> Result<utils::ExitCode> {
656
684
Err ( err)
657
685
}
658
686
} ?;
659
- let verbose = matches. get_flag ( "verbose" ) ;
660
- let quiet = matches. get_flag ( "quiet" ) ;
661
- let cfg = & mut common:: set_globals ( verbose, quiet) ?;
687
+ let cfg = & mut common:: set_globals ( matches. verbose , matches. quiet ) ?;
662
688
663
- if let Some ( t) = matches. get_one :: < ResolvableToolchainName > ( "+toolchain" ) {
689
+ if let Some ( t) = & matches. plus_toolchain {
664
690
cfg. set_toolchain_override ( t) ;
665
691
}
666
692
667
693
cfg. check_metadata_version ( ) ?;
668
694
669
- Ok ( match matches. subcommand ( ) {
670
- Some ( _ ) => Rustup :: from_arg_matches ( & matches ) ? . dispatch ( cfg) ?,
695
+ Ok ( match matches. subcmd {
696
+ Some ( subcmd ) => subcmd . dispatch ( cfg) ?,
671
697
None => {
672
- eprintln ! ( "{}" , cli ( ) . render_long_help( ) ) ;
698
+ eprintln ! ( "{}" , Rustup :: command ( ) . render_long_help( ) ) ;
673
699
utils:: ExitCode ( 1 )
674
700
}
675
701
} )
676
702
}
677
703
678
- pub ( crate ) fn cli ( ) -> Command {
679
- let app = Command :: new ( "rustup" )
680
- . version ( common:: version ( ) )
681
- . about ( "The Rust toolchain installer" )
682
- . before_help ( format ! ( "rustup {}" , common:: version( ) ) )
683
- . after_help ( RUSTUP_HELP )
684
- . subcommand_required ( false )
685
- . arg (
686
- verbose_arg ( "Enable verbose output" ) ,
687
- )
688
- . arg (
689
- Arg :: new ( "quiet" )
690
- . conflicts_with ( "verbose" )
691
- . help ( "Disable progress output" )
692
- . short ( 'q' )
693
- . long ( "quiet" )
694
- . action ( ArgAction :: SetTrue ) ,
695
- )
696
- . arg (
697
- Arg :: new ( "+toolchain" )
698
- . help ( "release channel (e.g. +stable) or custom toolchain to set override" )
699
- . value_parser ( |s : & str | {
700
- use clap:: { Error , error:: ErrorKind } ;
701
- if let Some ( stripped) = s. strip_prefix ( '+' ) {
702
- ResolvableToolchainName :: try_from ( stripped) . map_err ( |e| Error :: raw ( ErrorKind :: InvalidValue , e) )
703
- } else {
704
- Err ( Error :: raw ( ErrorKind :: InvalidSubcommand , format ! ( "\" {s}\" is not a valid subcommand, so it was interpreted as a toolchain name, but it is also invalid. {TOOLCHAIN_OVERRIDE_ERROR}" ) ) )
705
- }
706
- } ) ,
707
- ) ;
708
- RustupSubcmd :: augment_subcommands ( app)
709
- }
710
-
711
- fn verbose_arg ( help : & ' static str ) -> Arg {
712
- Arg :: new ( "verbose" )
713
- . help ( help)
714
- . short ( 'v' )
715
- . long ( "verbose" )
716
- . action ( ArgAction :: SetTrue )
717
- }
718
-
719
704
fn upgrade_data ( cfg : & Cfg ) -> Result < utils:: ExitCode > {
720
705
cfg. upgrade_data ( ) ?;
721
706
Ok ( utils:: ExitCode ( 0 ) )
@@ -1589,7 +1574,12 @@ impl fmt::Display for CompletionCommand {
1589
1574
fn output_completion_script ( shell : Shell , command : CompletionCommand ) -> Result < utils:: ExitCode > {
1590
1575
match command {
1591
1576
CompletionCommand :: Rustup => {
1592
- clap_complete:: generate ( shell, & mut cli ( ) , "rustup" , & mut process ( ) . stdout ( ) . lock ( ) ) ;
1577
+ clap_complete:: generate (
1578
+ shell,
1579
+ & mut Rustup :: command ( ) ,
1580
+ "rustup" ,
1581
+ & mut process ( ) . stdout ( ) . lock ( ) ,
1582
+ ) ;
1593
1583
}
1594
1584
CompletionCommand :: Cargo => {
1595
1585
if let Shell :: Zsh = shell {
0 commit comments