diff --git a/rust/Cargo.lock b/rust/Cargo.lock --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -50,15 +50,6 @@ dependencies = [ ] [[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - -[[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -172,21 +163,6 @@ dependencies = [ [[package]] name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim 0.8.0", - "textwrap", - "unicode-width", - "vec_map", -] - -[[package]] -name = "clap" version = "4.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60494cedb60cb47462c0ff7be53de32c0e42a6fc2c772184554fa12bd9489c03" @@ -196,7 +172,7 @@ dependencies = [ "clap_derive", "clap_lex", "once_cell", - "strsim 0.10.0", + "strsim", "termcolor", ] @@ -548,7 +524,7 @@ dependencies = [ "bitflags", "byteorder", "bytes-cast", - "clap 4.0.24", + "clap", "crossbeam-channel", "derive_more", "flate2", @@ -1110,7 +1086,7 @@ version = "0.1.0" dependencies = [ "atty", "chrono", - "clap 2.34.0", + "clap", "derive_more", "env_logger", "format-bytes", @@ -1209,12 +1185,6 @@ checksum = "a2eb9349b6444b326872e140eb1c [[package]] name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" @@ -1254,15 +1224,6 @@ dependencies = [ ] [[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] name = "thread_local" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1339,12 +1300,6 @@ dependencies = [ ] [[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/rust/rhg/Cargo.toml b/rust/rhg/Cargo.toml --- a/rust/rhg/Cargo.toml +++ b/rust/rhg/Cargo.toml @@ -11,7 +11,7 @@ edition = "2021" atty = "0.2.14" hg-core = { path = "../hg-core"} chrono = "0.4.19" -clap = "2.34.0" +clap = { version = "4.0.24", features = ["cargo"] } derive_more = "0.99.17" home = "0.5.3" lazy_static = "1.4.0" diff --git a/rust/rhg/src/commands/cat.rs b/rust/rhg/src/commands/cat.rs --- a/rust/rhg/src/commands/cat.rs +++ b/rust/rhg/src/commands/cat.rs @@ -4,27 +4,28 @@ use format_bytes::format_bytes; use hg::operations::cat; use hg::utils::hg_path::HgPathBuf; use micro_timer::timed; +use std::ffi::OsString; +use std::os::unix::prelude::OsStrExt; pub const HELP_TEXT: &str = " Output the current or given revision of files "; -pub fn args() -> clap::App<'static, 'static> { - clap::SubCommand::with_name("cat") +pub fn args() -> clap::Command { + clap::command!("cat") .arg( - Arg::with_name("rev") + Arg::new("rev") .help("search the repository as it is in REV") - .short("-r") - .long("--rev") - .value_name("REV") - .takes_value(true), + .short('r') + .long("rev") + .value_name("REV"), ) .arg( - clap::Arg::with_name("files") + clap::Arg::new("files") .required(true) - .multiple(true) - .empty_values(false) + .num_args(1..) .value_name("FILE") + .value_parser(clap::value_parser!(std::ffi::OsString)) .help("Files to output"), ) .about(HELP_TEXT) @@ -41,11 +42,15 @@ pub fn run(invocation: &crate::CliInvoca )); } - let rev = invocation.subcommand_args.value_of("rev"); - let file_args = match invocation.subcommand_args.values_of("files") { - Some(files) => files.collect(), - None => vec![], - }; + let rev = invocation.subcommand_args.get_one::("rev"); + let file_args = + match invocation.subcommand_args.get_many::("files") { + Some(files) => files + .filter(|s| !s.is_empty()) + .map(|s| s.as_os_str()) + .collect(), + None => vec![], + }; let repo = invocation.repo?; let cwd = hg::utils::current_dir()?; @@ -53,8 +58,8 @@ pub fn run(invocation: &crate::CliInvoca let working_directory = cwd.join(working_directory); // Make it absolute let mut files = vec![]; - for file in file_args.iter() { - if file.starts_with("set:") { + for file in file_args { + if file.as_bytes().starts_with(b"set:") { let message = "fileset"; return Err(CommandError::unsupported(message)); } @@ -62,7 +67,7 @@ pub fn run(invocation: &crate::CliInvoca let normalized = cwd.join(&file); // TODO: actually normalize `..` path segments etc? let dotted = normalized.components().any(|c| c.as_os_str() == ".."); - if file == &"." || dotted { + if file.as_bytes() == b"." || dotted { let message = "`..` or `.` path segment"; return Err(CommandError::unsupported(message)); } @@ -74,7 +79,7 @@ pub fn run(invocation: &crate::CliInvoca .map_err(|_| { CommandError::abort(format!( "abort: {} not under root '{}'\n(consider using '--cwd {}')", - file, + String::from_utf8_lossy(file.as_bytes()), working_directory.display(), relative_path.display(), )) diff --git a/rust/rhg/src/commands/config.rs b/rust/rhg/src/commands/config.rs --- a/rust/rhg/src/commands/config.rs +++ b/rust/rhg/src/commands/config.rs @@ -8,14 +8,13 @@ pub const HELP_TEXT: &str = " With one argument of the form section.name, print just the value of that config item. "; -pub fn args() -> clap::App<'static, 'static> { - clap::SubCommand::with_name("config") +pub fn args() -> clap::Command { + clap::command!("config") .arg( - Arg::with_name("name") + Arg::new("name") .help("the section.name to print") .value_name("NAME") - .required(true) - .takes_value(true), + .required(true), ) .about(HELP_TEXT) } @@ -23,7 +22,7 @@ pub fn args() -> clap::App<'static, 'sta pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> { let (section, name) = invocation .subcommand_args - .value_of("name") + .get_one::("name") .expect("missing required CLI argument") .as_bytes() .split_2(b'.') diff --git a/rust/rhg/src/commands/debugdata.rs b/rust/rhg/src/commands/debugdata.rs --- a/rust/rhg/src/commands/debugdata.rs +++ b/rust/rhg/src/commands/debugdata.rs @@ -8,27 +8,27 @@ pub const HELP_TEXT: &str = " Dump the contents of a data file revision "; -pub fn args() -> clap::App<'static, 'static> { - clap::SubCommand::with_name("debugdata") +pub fn args() -> clap::Command { + clap::command!("debugdata") .arg( - Arg::with_name("changelog") + Arg::new("changelog") .help("open changelog") - .short("-c") - .long("--changelog"), + .short('c') + .action(clap::ArgAction::SetTrue), ) .arg( - Arg::with_name("manifest") + Arg::new("manifest") .help("open manifest") - .short("-m") - .long("--manifest"), + .short('m') + .action(clap::ArgAction::SetTrue), ) .group( - ArgGroup::with_name("") + ArgGroup::new("revlog") .args(&["changelog", "manifest"]) .required(true), ) .arg( - Arg::with_name("rev") + Arg::new("rev") .help("revision") .required(true) .value_name("REV"), @@ -40,19 +40,21 @@ pub fn args() -> clap::App<'static, 'sta pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> { let args = invocation.subcommand_args; let rev = args - .value_of("rev") + .get_one::("rev") .expect("rev should be a required argument"); - let kind = - match (args.is_present("changelog"), args.is_present("manifest")) { - (true, false) => DebugDataKind::Changelog, - (false, true) => DebugDataKind::Manifest, - (true, true) => { - unreachable!("Should not happen since options are exclusive") - } - (false, false) => { - unreachable!("Should not happen since options are required") - } - }; + let kind = match ( + args.get_one::("changelog").unwrap(), + args.get_one::("manifest").unwrap(), + ) { + (true, false) => DebugDataKind::Changelog, + (false, true) => DebugDataKind::Manifest, + (true, true) => { + unreachable!("Should not happen since options are exclusive") + } + (false, false) => { + unreachable!("Should not happen since options are required") + } + }; let repo = invocation.repo?; if repo.has_narrow() { @@ -60,7 +62,7 @@ pub fn run(invocation: &crate::CliInvoca "support for ellipsis nodes is missing and repo has narrow enabled", )); } - let data = debug_data(repo, rev, kind).map_err(|e| (e, rev))?; + let data = debug_data(repo, rev, kind).map_err(|e| (e, rev.as_ref()))?; let mut stdout = invocation.ui.stdout_buffer(); stdout.write_all(&data)?; diff --git a/rust/rhg/src/commands/debugignorerhg.rs b/rust/rhg/src/commands/debugignorerhg.rs --- a/rust/rhg/src/commands/debugignorerhg.rs +++ b/rust/rhg/src/commands/debugignorerhg.rs @@ -1,5 +1,4 @@ use crate::error::CommandError; -use clap::SubCommand; use hg; use hg::matchers::get_ignore_matcher; use hg::StatusError; @@ -13,8 +12,8 @@ This is a pure Rust version of `hg debug Some options might be missing, check the list below. "; -pub fn args() -> clap::App<'static, 'static> { - SubCommand::with_name("debugignorerhg").about(HELP_TEXT) +pub fn args() -> clap::Command { + clap::command!("debugignorerhg").about(HELP_TEXT) } pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> { diff --git a/rust/rhg/src/commands/debugrequirements.rs b/rust/rhg/src/commands/debugrequirements.rs --- a/rust/rhg/src/commands/debugrequirements.rs +++ b/rust/rhg/src/commands/debugrequirements.rs @@ -4,8 +4,8 @@ pub const HELP_TEXT: &str = " Print the current repo requirements. "; -pub fn args() -> clap::App<'static, 'static> { - clap::SubCommand::with_name("debugrequirements").about(HELP_TEXT) +pub fn args() -> clap::Command { + clap::command!("debugrequirements").about(HELP_TEXT) } pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> { diff --git a/rust/rhg/src/commands/debugrhgsparse.rs b/rust/rhg/src/commands/debugrhgsparse.rs --- a/rust/rhg/src/commands/debugrhgsparse.rs +++ b/rust/rhg/src/commands/debugrhgsparse.rs @@ -1,19 +1,21 @@ -use std::os::unix::prelude::OsStrExt; +use std::{ + ffi::{OsStr, OsString}, + os::unix::prelude::OsStrExt, +}; use crate::error::CommandError; -use clap::SubCommand; use hg::{self, utils::hg_path::HgPath}; pub const HELP_TEXT: &str = ""; -pub fn args() -> clap::App<'static, 'static> { - SubCommand::with_name("debugrhgsparse") +pub fn args() -> clap::Command { + clap::command!("debugrhgsparse") .arg( - clap::Arg::with_name("files") + clap::Arg::new("files") + .value_name("FILES") .required(true) - .multiple(true) - .empty_values(false) - .value_name("FILES") + .num_args(1..) + .value_parser(clap::value_parser!(std::ffi::OsString)) .help("Files to check against sparse profile"), ) .about(HELP_TEXT) @@ -23,8 +25,12 @@ pub fn run(invocation: &crate::CliInvoca let repo = invocation.repo?; let (matcher, _warnings) = hg::sparse::matcher(&repo).unwrap(); - let files = invocation.subcommand_args.values_of_os("files"); + let files = invocation.subcommand_args.get_many::("files"); if let Some(files) = files { + let files: Vec<&OsStr> = files + .filter(|s| !s.is_empty()) + .map(|s| s.as_os_str()) + .collect(); for file in files { invocation.ui.write_stdout(b"matches: ")?; invocation.ui.write_stdout( diff --git a/rust/rhg/src/commands/files.rs b/rust/rhg/src/commands/files.rs --- a/rust/rhg/src/commands/files.rs +++ b/rust/rhg/src/commands/files.rs @@ -14,15 +14,14 @@ List tracked files. Returns 0 on success. "; -pub fn args() -> clap::App<'static, 'static> { - clap::SubCommand::with_name("files") +pub fn args() -> clap::Command { + clap::command!("files") .arg( - Arg::with_name("rev") + Arg::new("rev") .help("search the repository as it is in REV") - .short("-r") - .long("--revision") - .value_name("REV") - .takes_value(true), + .short('r') + .long("revision") + .value_name("REV"), ) .about(HELP_TEXT) } @@ -35,7 +34,7 @@ pub fn run(invocation: &crate::CliInvoca )); } - let rev = invocation.subcommand_args.value_of("rev"); + let rev = invocation.subcommand_args.get_one::("rev"); let repo = invocation.repo?; @@ -57,7 +56,8 @@ pub fn run(invocation: &crate::CliInvoca "rhg files -r is not supported in narrow clones", )); } - let files = list_rev_tracked_files(repo, rev).map_err(|e| (e, rev))?; + let files = list_rev_tracked_files(repo, rev) + .map_err(|e| (e, rev.as_ref()))?; display_files(invocation.ui, repo, files.iter()) } else { // The dirstate always reflects the sparse narrowspec, so if diff --git a/rust/rhg/src/commands/root.rs b/rust/rhg/src/commands/root.rs --- a/rust/rhg/src/commands/root.rs +++ b/rust/rhg/src/commands/root.rs @@ -9,8 +9,8 @@ Print the root directory of the current Returns 0 on success. "; -pub fn args() -> clap::App<'static, 'static> { - clap::SubCommand::with_name("root").about(HELP_TEXT) +pub fn args() -> clap::Command { + clap::command!("root").about(HELP_TEXT) } pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> { diff --git a/rust/rhg/src/commands/status.rs b/rust/rhg/src/commands/status.rs --- a/rust/rhg/src/commands/status.rs +++ b/rust/rhg/src/commands/status.rs @@ -8,7 +8,7 @@ use crate::error::CommandError; use crate::ui::Ui; use crate::utils::path_utils::RelativizePaths; -use clap::{Arg, SubCommand}; +use clap::Arg; use format_bytes::format_bytes; use hg::config::Config; use hg::dirstate::has_exec_bit; @@ -41,75 +41,86 @@ This is a pure Rust version of `hg statu Some options might be missing, check the list below. "; -pub fn args() -> clap::App<'static, 'static> { - SubCommand::with_name("status") +pub fn args() -> clap::Command { + clap::command!("status") .alias("st") .about(HELP_TEXT) .arg( - Arg::with_name("all") + Arg::new("all") .help("show status of all files") - .short("-A") - .long("--all"), + .short('A') + .action(clap::ArgAction::SetTrue) + .long("all"), ) .arg( - Arg::with_name("modified") + Arg::new("modified") .help("show only modified files") - .short("-m") - .long("--modified"), + .short('m') + .action(clap::ArgAction::SetTrue) + .long("modified"), ) .arg( - Arg::with_name("added") + Arg::new("added") .help("show only added files") - .short("-a") - .long("--added"), + .short('a') + .action(clap::ArgAction::SetTrue) + .long("added"), ) .arg( - Arg::with_name("removed") + Arg::new("removed") .help("show only removed files") - .short("-r") - .long("--removed"), + .short('r') + .action(clap::ArgAction::SetTrue) + .long("removed"), ) .arg( - Arg::with_name("clean") + Arg::new("clean") .help("show only clean files") - .short("-c") - .long("--clean"), + .short('c') + .action(clap::ArgAction::SetTrue) + .long("clean"), ) .arg( - Arg::with_name("deleted") + Arg::new("deleted") .help("show only deleted files") - .short("-d") - .long("--deleted"), + .short('d') + .action(clap::ArgAction::SetTrue) + .long("deleted"), ) .arg( - Arg::with_name("unknown") + Arg::new("unknown") .help("show only unknown (not tracked) files") - .short("-u") - .long("--unknown"), + .short('u') + .action(clap::ArgAction::SetTrue) + .long("unknown"), ) .arg( - Arg::with_name("ignored") + Arg::new("ignored") .help("show only ignored files") - .short("-i") - .long("--ignored"), + .short('i') + .action(clap::ArgAction::SetTrue) + .long("ignored"), ) .arg( - Arg::with_name("copies") + Arg::new("copies") .help("show source of copied files (DEFAULT: ui.statuscopies)") - .short("-C") - .long("--copies"), + .short('C') + .action(clap::ArgAction::SetTrue) + .long("copies"), ) .arg( - Arg::with_name("no-status") + Arg::new("no-status") .help("hide status prefix") - .short("-n") - .long("--no-status"), + .short('n') + .action(clap::ArgAction::SetTrue) + .long("no-status"), ) .arg( - Arg::with_name("verbose") + Arg::new("verbose") .help("enable additional output") - .short("-v") - .long("--verbose"), + .short('v') + .action(clap::ArgAction::SetTrue) + .long("verbose"), ) } @@ -200,25 +211,25 @@ pub fn run(invocation: &crate::CliInvoca let config = invocation.config; let args = invocation.subcommand_args; - let verbose = !args.is_present("print0") - && (args.is_present("verbose") - || config.get_bool(b"ui", b"verbose")? - || config.get_bool(b"commands", b"status.verbose")?); + // TODO add `!args.get_flag("print0") &&` when we support `print0` + let verbose = args.get_flag("verbose") + || config.get_bool(b"ui", b"verbose")? + || config.get_bool(b"commands", b"status.verbose")?; - let all = args.is_present("all"); + let all = args.get_flag("all"); let display_states = if all { // TODO when implementing `--quiet`: it excludes clean files // from `--all` ALL_DISPLAY_STATES } else { let requested = DisplayStates { - modified: args.is_present("modified"), - added: args.is_present("added"), - removed: args.is_present("removed"), - clean: args.is_present("clean"), - deleted: args.is_present("deleted"), - unknown: args.is_present("unknown"), - ignored: args.is_present("ignored"), + modified: args.get_flag("modified"), + added: args.get_flag("added"), + removed: args.get_flag("removed"), + clean: args.get_flag("clean"), + deleted: args.get_flag("deleted"), + unknown: args.get_flag("unknown"), + ignored: args.get_flag("ignored"), }; if requested.is_empty() { DEFAULT_DISPLAY_STATES @@ -226,9 +237,9 @@ pub fn run(invocation: &crate::CliInvoca requested } }; - let no_status = args.is_present("no-status"); + let no_status = args.get_flag("no-status"); let list_copies = all - || args.is_present("copies") + || args.get_flag("copies") || config.get_bool(b"ui", b"statuscopies")?; let repo = invocation.repo?; diff --git a/rust/rhg/src/main.rs b/rust/rhg/src/main.rs --- a/rust/rhg/src/main.rs +++ b/rust/rhg/src/main.rs @@ -1,10 +1,7 @@ extern crate log; use crate::error::CommandError; use crate::ui::{local_to_utf8, Ui}; -use clap::App; -use clap::AppSettings; -use clap::Arg; -use clap::ArgMatches; +use clap::{command, Arg, ArgMatches}; use format_bytes::{format_bytes, join}; use hg::config::{Config, ConfigSource, PlainInfo}; use hg::repo::{Repo, RepoError}; @@ -35,55 +32,47 @@ fn main_with_result( ) -> Result<(), CommandError> { check_unsupported(config, repo)?; - let app = App::new("rhg") - .global_setting(AppSettings::AllowInvalidUtf8) - .global_setting(AppSettings::DisableVersion) - .setting(AppSettings::SubcommandRequired) - .setting(AppSettings::VersionlessSubcommands) + let app = command!() + .subcommand_required(true) .arg( - Arg::with_name("repository") + Arg::new("repository") .help("repository root directory") - .short("-R") - .long("--repository") + .short('R') .value_name("REPO") - .takes_value(true) // Both ok: `hg -R ./foo log` or `hg log -R ./foo` .global(true), ) .arg( - Arg::with_name("config") + Arg::new("config") .help("set/override config option (use 'section.name=value')") - .long("--config") .value_name("CONFIG") - .takes_value(true) .global(true) + .long("config") // Ok: `--config section.key1=val --config section.key2=val2` - .multiple(true) // Not ok: `--config section.key1=val section.key2=val2` - .number_of_values(1), + .action(clap::ArgAction::Append), ) .arg( - Arg::with_name("cwd") + Arg::new("cwd") .help("change working directory") - .long("--cwd") .value_name("DIR") - .takes_value(true) + .long("cwd") .global(true), ) .arg( - Arg::with_name("color") + Arg::new("color") .help("when to colorize (boolean, always, auto, never, or debug)") - .long("--color") .value_name("TYPE") - .takes_value(true) + .long("color") .global(true), ) .version("0.0.1"); let app = add_subcommand_args(app); - let matches = app.clone().get_matches_from_safe(argv.iter())?; + let matches = app.clone().try_get_matches_from(argv.iter())?; - let (subcommand_name, subcommand_matches) = matches.subcommand(); + let (subcommand_name, subcommand_args) = + matches.subcommand().expect("subcommand required"); // Mercurial allows users to define "defaults" for commands, fallback // if a default is detected for the current command @@ -104,9 +93,7 @@ fn main_with_result( } } let run = subcommand_run_fn(subcommand_name) - .expect("unknown subcommand name from clap despite AppSettings::SubcommandRequired"); - let subcommand_args = subcommand_matches - .expect("no subcommand arguments from clap despite AppSettings::SubcommandRequired"); + .expect("unknown subcommand name from clap despite Command::subcommand_required"); let invocation = CliInvocation { ui, @@ -535,7 +522,7 @@ macro_rules! subcommands { )+ } - fn add_subcommand_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> { + fn add_subcommand_args(app: clap::Command) -> clap::Command { app $( .subcommand(commands::$command::args()) @@ -569,7 +556,7 @@ subcommands! { pub struct CliInvocation<'a> { ui: &'a Ui, - subcommand_args: &'a ArgMatches<'a>, + subcommand_args: &'a ArgMatches, config: &'a Config, /// References inside `Result` is a bit peculiar but allow /// `invocation.repo?` to work out with `&CliInvocation` since this diff --git a/tests/test-rhg.t b/tests/test-rhg.t --- a/tests/test-rhg.t +++ b/tests/test-rhg.t @@ -4,12 +4,11 @@ Unimplemented command $ $NO_FALLBACK rhg unimplemented-command - unsupported feature: error: Found argument 'unimplemented-command' which wasn't expected, or isn't valid in this context + unsupported feature: error: The subcommand 'unimplemented-command' wasn't recognized - USAGE: - rhg [OPTIONS] + Usage: rhg [OPTIONS] - For more information try --help + For more information try '--help' [252] $ rhg unimplemented-command --config rhg.on-unsupported=abort-silent @@ -159,10 +158,11 @@ Fallback to Python $ $NO_FALLBACK rhg cat original --exclude="*.rs" unsupported feature: error: Found argument '--exclude' which wasn't expected, or isn't valid in this context - USAGE: - rhg cat [OPTIONS] ... + If you tried to supply '--exclude' as a value rather than a flag, use '-- --exclude' - For more information try --help + Usage: rhg cat ... + + For more information try '--help' [252] $ rhg cat original --exclude="*.rs" @@ -190,10 +190,11 @@ Check that `fallback-immediately` overri Blocking recursive fallback. The 'rhg.fallback-executable = rhg' config points to `rhg` itself. unsupported feature: error: Found argument '--exclude' which wasn't expected, or isn't valid in this context - USAGE: - rhg cat [OPTIONS] ... + If you tried to supply '--exclude' as a value rather than a flag, use '-- --exclude' - For more information try --help + Usage: rhg cat ... + + For more information try '--help' [252]