rust/rhg/src/main.rs
changeset 49640 37bc3edef76f
parent 49569 5318ac25dfdc
child 49914 58074252db3c
equal deleted inserted replaced
49639:5844cd8e81ca 49640:37bc3edef76f
     1 extern crate log;
     1 extern crate log;
     2 use crate::error::CommandError;
     2 use crate::error::CommandError;
     3 use crate::ui::{local_to_utf8, Ui};
     3 use crate::ui::{local_to_utf8, Ui};
     4 use clap::App;
     4 use clap::{command, Arg, ArgMatches};
     5 use clap::AppSettings;
       
     6 use clap::Arg;
       
     7 use clap::ArgMatches;
       
     8 use format_bytes::{format_bytes, join};
     5 use format_bytes::{format_bytes, join};
     9 use hg::config::{Config, ConfigSource, PlainInfo};
     6 use hg::config::{Config, ConfigSource, PlainInfo};
    10 use hg::repo::{Repo, RepoError};
     7 use hg::repo::{Repo, RepoError};
    11 use hg::utils::files::{get_bytes_from_os_str, get_path_from_bytes};
     8 use hg::utils::files::{get_bytes_from_os_str, get_path_from_bytes};
    12 use hg::utils::SliceExt;
     9 use hg::utils::SliceExt;
    33     repo: Result<&Repo, &NoRepoInCwdError>,
    30     repo: Result<&Repo, &NoRepoInCwdError>,
    34     config: &Config,
    31     config: &Config,
    35 ) -> Result<(), CommandError> {
    32 ) -> Result<(), CommandError> {
    36     check_unsupported(config, repo)?;
    33     check_unsupported(config, repo)?;
    37 
    34 
    38     let app = App::new("rhg")
    35     let app = command!()
    39         .global_setting(AppSettings::AllowInvalidUtf8)
    36         .subcommand_required(true)
    40         .global_setting(AppSettings::DisableVersion)
       
    41         .setting(AppSettings::SubcommandRequired)
       
    42         .setting(AppSettings::VersionlessSubcommands)
       
    43         .arg(
    37         .arg(
    44             Arg::with_name("repository")
    38             Arg::new("repository")
    45                 .help("repository root directory")
    39                 .help("repository root directory")
    46                 .short("-R")
    40                 .short('R')
    47                 .long("--repository")
       
    48                 .value_name("REPO")
    41                 .value_name("REPO")
    49                 .takes_value(true)
       
    50                 // Both ok: `hg -R ./foo log` or `hg log -R ./foo`
    42                 // Both ok: `hg -R ./foo log` or `hg log -R ./foo`
    51                 .global(true),
    43                 .global(true),
    52         )
    44         )
    53         .arg(
    45         .arg(
    54             Arg::with_name("config")
    46             Arg::new("config")
    55                 .help("set/override config option (use 'section.name=value')")
    47                 .help("set/override config option (use 'section.name=value')")
    56                 .long("--config")
       
    57                 .value_name("CONFIG")
    48                 .value_name("CONFIG")
    58                 .takes_value(true)
       
    59                 .global(true)
    49                 .global(true)
       
    50                 .long("config")
    60                 // Ok: `--config section.key1=val --config section.key2=val2`
    51                 // Ok: `--config section.key1=val --config section.key2=val2`
    61                 .multiple(true)
       
    62                 // Not ok: `--config section.key1=val section.key2=val2`
    52                 // Not ok: `--config section.key1=val section.key2=val2`
    63                 .number_of_values(1),
    53                 .action(clap::ArgAction::Append),
    64         )
    54         )
    65         .arg(
    55         .arg(
    66             Arg::with_name("cwd")
    56             Arg::new("cwd")
    67                 .help("change working directory")
    57                 .help("change working directory")
    68                 .long("--cwd")
       
    69                 .value_name("DIR")
    58                 .value_name("DIR")
    70                 .takes_value(true)
    59                 .long("cwd")
    71                 .global(true),
    60                 .global(true),
    72         )
    61         )
    73         .arg(
    62         .arg(
    74             Arg::with_name("color")
    63             Arg::new("color")
    75                 .help("when to colorize (boolean, always, auto, never, or debug)")
    64                 .help("when to colorize (boolean, always, auto, never, or debug)")
    76                 .long("--color")
       
    77                 .value_name("TYPE")
    65                 .value_name("TYPE")
    78                 .takes_value(true)
    66                 .long("color")
    79                 .global(true),
    67                 .global(true),
    80         )
    68         )
    81         .version("0.0.1");
    69         .version("0.0.1");
    82     let app = add_subcommand_args(app);
    70     let app = add_subcommand_args(app);
    83 
    71 
    84     let matches = app.clone().get_matches_from_safe(argv.iter())?;
    72     let matches = app.clone().try_get_matches_from(argv.iter())?;
    85 
    73 
    86     let (subcommand_name, subcommand_matches) = matches.subcommand();
    74     let (subcommand_name, subcommand_args) =
       
    75         matches.subcommand().expect("subcommand required");
    87 
    76 
    88     // Mercurial allows users to define "defaults" for commands, fallback
    77     // Mercurial allows users to define "defaults" for commands, fallback
    89     // if a default is detected for the current command
    78     // if a default is detected for the current command
    90     let defaults = config.get_str(b"defaults", subcommand_name.as_bytes());
    79     let defaults = config.get_str(b"defaults", subcommand_name.as_bytes());
    91     if defaults?.is_some() {
    80     if defaults?.is_some() {
   102             let msg = format!("{}-{} hook defined", prefix, subcommand_name);
    91             let msg = format!("{}-{} hook defined", prefix, subcommand_name);
   103             return Err(CommandError::unsupported(msg));
    92             return Err(CommandError::unsupported(msg));
   104         }
    93         }
   105     }
    94     }
   106     let run = subcommand_run_fn(subcommand_name)
    95     let run = subcommand_run_fn(subcommand_name)
   107         .expect("unknown subcommand name from clap despite AppSettings::SubcommandRequired");
    96         .expect("unknown subcommand name from clap despite Command::subcommand_required");
   108     let subcommand_args = subcommand_matches
       
   109         .expect("no subcommand arguments from clap despite AppSettings::SubcommandRequired");
       
   110 
    97 
   111     let invocation = CliInvocation {
    98     let invocation = CliInvocation {
   112         ui,
    99         ui,
   113         subcommand_args,
   100         subcommand_args,
   114         config,
   101         config,
   533             $(
   520             $(
   534                 pub mod $command;
   521                 pub mod $command;
   535             )+
   522             )+
   536         }
   523         }
   537 
   524 
   538         fn add_subcommand_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
   525         fn add_subcommand_args(app: clap::Command) -> clap::Command {
   539             app
   526             app
   540             $(
   527             $(
   541                 .subcommand(commands::$command::args())
   528                 .subcommand(commands::$command::args())
   542             )+
   529             )+
   543         }
   530         }
   567     status
   554     status
   568 }
   555 }
   569 
   556 
   570 pub struct CliInvocation<'a> {
   557 pub struct CliInvocation<'a> {
   571     ui: &'a Ui,
   558     ui: &'a Ui,
   572     subcommand_args: &'a ArgMatches<'a>,
   559     subcommand_args: &'a ArgMatches,
   573     config: &'a Config,
   560     config: &'a Config,
   574     /// References inside `Result` is a bit peculiar but allow
   561     /// References inside `Result` is a bit peculiar but allow
   575     /// `invocation.repo?` to work out with `&CliInvocation` since this
   562     /// `invocation.repo?` to work out with `&CliInvocation` since this
   576     /// `Result` type is `Copy`.
   563     /// `Result` type is `Copy`.
   577     repo: Result<&'a Repo, &'a NoRepoInCwdError>,
   564     repo: Result<&'a Repo, &'a NoRepoInCwdError>,