@@ -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 ) ]
@@ -495,9 +523,9 @@ enum SetSubcmd {
495
523
} ,
496
524
}
497
525
498
- impl Rustup {
526
+ impl RustupSubcmd {
499
527
fn dispatch ( self , cfg : & mut Cfg ) -> Result < utils:: ExitCode > {
500
- match self . subcmd {
528
+ match self {
501
529
RustupSubcmd :: DumpTestament => common:: dump_testament ( ) ,
502
530
RustupSubcmd :: Install { opts } => update ( cfg, opts) ,
503
531
RustupSubcmd :: Uninstall { opts } => toolchain_remove ( cfg, opts) ,
@@ -605,7 +633,7 @@ pub fn main() -> Result<utils::ExitCode> {
605
633
self_update:: cleanup_self_updater ( ) ?;
606
634
607
635
use clap:: error:: ErrorKind :: * ;
608
- let matches = match cli ( ) . try_get_matches_from ( process ( ) . args_os ( ) ) {
636
+ let matches = match Rustup :: try_parse_from ( process ( ) . args_os ( ) ) {
609
637
Ok ( matches) => Ok ( matches) ,
610
638
Err ( err) if err. kind ( ) == DisplayHelp => {
611
639
write ! ( process( ) . stdout( ) . lock( ) , "{err}" ) ?;
@@ -655,66 +683,23 @@ pub fn main() -> Result<utils::ExitCode> {
655
683
Err ( err)
656
684
}
657
685
} ?;
658
- let verbose = matches. get_flag ( "verbose" ) ;
659
- let quiet = matches. get_flag ( "quiet" ) ;
660
- let cfg = & mut common:: set_globals ( verbose, quiet) ?;
686
+ let cfg = & mut common:: set_globals ( matches. verbose , matches. quiet ) ?;
661
687
662
- if let Some ( t) = matches. get_one :: < ResolvableToolchainName > ( "+toolchain" ) {
688
+ if let Some ( t) = & matches. plus_toolchain {
663
689
cfg. set_toolchain_override ( t) ;
664
690
}
665
691
666
692
cfg. check_metadata_version ( ) ?;
667
693
668
- Ok ( match matches. subcommand ( ) {
669
- Some ( _ ) => Rustup :: from_arg_matches ( & matches ) ? . dispatch ( cfg) ?,
694
+ Ok ( match matches. subcmd {
695
+ Some ( subcmd ) => subcmd . dispatch ( cfg) ?,
670
696
None => {
671
- eprintln ! ( "{}" , cli ( ) . render_long_help( ) ) ;
697
+ eprintln ! ( "{}" , Rustup :: command ( ) . render_long_help( ) ) ;
672
698
utils:: ExitCode ( 1 )
673
699
}
674
700
} )
675
701
}
676
702
677
- pub ( crate ) fn cli ( ) -> Command {
678
- let app = Command :: new ( "rustup" )
679
- . version ( common:: version ( ) )
680
- . about ( "The Rust toolchain installer" )
681
- . before_help ( format ! ( "rustup {}" , common:: version( ) ) )
682
- . after_help ( RUSTUP_HELP )
683
- . subcommand_required ( false )
684
- . arg (
685
- verbose_arg ( "Enable verbose output" ) ,
686
- )
687
- . arg (
688
- Arg :: new ( "quiet" )
689
- . conflicts_with ( "verbose" )
690
- . help ( "Disable progress output" )
691
- . short ( 'q' )
692
- . long ( "quiet" )
693
- . action ( ArgAction :: SetTrue ) ,
694
- )
695
- . arg (
696
- Arg :: new ( "+toolchain" )
697
- . help ( "release channel (e.g. +stable) or custom toolchain to set override" )
698
- . value_parser ( |s : & str | {
699
- use clap:: { Error , error:: ErrorKind } ;
700
- if let Some ( stripped) = s. strip_prefix ( '+' ) {
701
- ResolvableToolchainName :: try_from ( stripped) . map_err ( |e| Error :: raw ( ErrorKind :: InvalidValue , e) )
702
- } else {
703
- 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}" ) ) )
704
- }
705
- } ) ,
706
- ) ;
707
- RustupSubcmd :: augment_subcommands ( app)
708
- }
709
-
710
- fn verbose_arg ( help : & ' static str ) -> Arg {
711
- Arg :: new ( "verbose" )
712
- . help ( help)
713
- . short ( 'v' )
714
- . long ( "verbose" )
715
- . action ( ArgAction :: SetTrue )
716
- }
717
-
718
703
fn upgrade_data ( cfg : & Cfg ) -> Result < utils:: ExitCode > {
719
704
cfg. upgrade_data ( ) ?;
720
705
Ok ( utils:: ExitCode ( 0 ) )
@@ -1588,7 +1573,12 @@ impl fmt::Display for CompletionCommand {
1588
1573
fn output_completion_script ( shell : Shell , command : CompletionCommand ) -> Result < utils:: ExitCode > {
1589
1574
match command {
1590
1575
CompletionCommand :: Rustup => {
1591
- clap_complete:: generate ( shell, & mut cli ( ) , "rustup" , & mut process ( ) . stdout ( ) . lock ( ) ) ;
1576
+ clap_complete:: generate (
1577
+ shell,
1578
+ & mut Rustup :: command ( ) ,
1579
+ "rustup" ,
1580
+ & mut process ( ) . stdout ( ) . lock ( ) ,
1581
+ ) ;
1592
1582
}
1593
1583
CompletionCommand :: Cargo => {
1594
1584
if let Shell :: Zsh = shell {
0 commit comments