D12001: rust: upgrade to Clap 3

martinvonz (Martin von Zweigbergk) phabricator at mercurial-scm.org
Fri Jan 14 22:23:02 UTC 2022


martinvonz created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  Clap 3 was released about a week ago. Let's stay up to date.
  
  Some changes worth mentioning:
  
  - `AppSettings::VersionlessSubcommands` is on by default and deleted
  - `AllowInvalidUtf8` moved from `AppSettings` to `ArgSettings`. I set it only on the global args (`-R`, `--config`, `--cwd`). The other commands don't actually support invalid UTF-8, despite the setting being on at the top level. I'll leave it to someone else to switch to `value[s]_of_os()` and enable `AllowInvalidUtf8` on remaining arguments (where appropriate).
  - `Arg::short()` now takes a single character (used to take a string). That makes the leading dashes we have on strings passed to `Arg::long()` stand out (to me at least). I'll leave it to someone else to drop them if they care.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D12001

AFFECTED FILES
  rust/Cargo.lock
  rust/hg-core/Cargo.toml
  rust/hg-core/examples/nodemap/main.rs
  rust/rhg/Cargo.toml
  rust/rhg/src/commands/cat.rs
  rust/rhg/src/commands/config.rs
  rust/rhg/src/commands/debugdata.rs
  rust/rhg/src/commands/debugignorerhg.rs
  rust/rhg/src/commands/debugrequirements.rs
  rust/rhg/src/commands/files.rs
  rust/rhg/src/commands/root.rs
  rust/rhg/src/commands/status.rs
  rust/rhg/src/main.rs

CHANGE DETAILS

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,10 @@
 extern crate log;
 use crate::error::CommandError;
 use crate::ui::Ui;
-use clap::App;
 use clap::AppSettings;
 use clap::Arg;
 use clap::ArgMatches;
+use clap::{App, ArgSettings};
 use format_bytes::{format_bytes, join};
 use hg::config::{Config, ConfigSource};
 use hg::exit_codes;
@@ -32,46 +32,47 @@
     check_unsupported(config, repo, ui)?;
 
     let app = App::new("rhg")
-        .global_setting(AppSettings::AllowInvalidUtf8)
-        .global_setting(AppSettings::DisableVersion)
+        .global_setting(AppSettings::DisableVersionFlag)
         .setting(AppSettings::SubcommandRequired)
-        .setting(AppSettings::VersionlessSubcommands)
         .arg(
-            Arg::with_name("repository")
+            Arg::new("repository")
                 .help("repository root directory")
-                .short("-R")
+                .short('R')
                 .long("--repository")
                 .value_name("REPO")
                 .takes_value(true)
+                .setting(ArgSettings::AllowInvalidUtf8)
                 // 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)
+                .setting(ArgSettings::AllowInvalidUtf8)
                 .global(true)
                 // Ok: `--config section.key1=val --config section.key2=val2`
-                .multiple(true)
+                .multiple_occurrences(true)
                 // Not ok: `--config section.key1=val section.key2=val2`
                 .number_of_values(1),
         )
         .arg(
-            Arg::with_name("cwd")
+            Arg::new("cwd")
                 .help("change working directory")
                 .long("--cwd")
                 .value_name("DIR")
                 .takes_value(true)
+                .setting(ArgSettings::AllowInvalidUtf8)
                 .global(true),
         )
         .version("0.0.1");
     let app = add_subcommand_args(app);
 
-    let matches = app.clone().get_matches_safe()?;
+    let matches = app.clone().try_get_matches()?;
 
-    let (subcommand_name, subcommand_matches) = matches.subcommand();
+    let (subcommand_name, subcommand_args) = matches.subcommand().expect("unknown subcommand name from clap despite AppSettings::SubcommandRequired");
 
     // Mercurial allows users to define "defaults" for commands, fallback
     // if a default is detected for the current command
@@ -93,8 +94,6 @@
     }
     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");
 
     let invocation = CliInvocation {
         ui,
@@ -462,7 +461,7 @@
             )+
         }
 
-        fn add_subcommand_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
+        fn add_subcommand_args(app: App<'static>) -> App<'static> {
             app
             $(
                 .subcommand(commands::$command::args())
@@ -495,7 +494,7 @@
 
 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/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;
 use hg::config::Config;
@@ -38,68 +38,68 @@
 Some options might be missing, check the list below.
 ";
 
-pub fn args() -> clap::App<'static, 'static> {
-    SubCommand::with_name("status")
+pub fn args() -> clap::App<'static> {
+    clap::App::new("status")
         .alias("st")
         .about(HELP_TEXT)
         .arg(
-            Arg::with_name("all")
+            Arg::new("all")
                 .help("show status of all files")
-                .short("-A")
+                .short('A')
                 .long("--all"),
         )
         .arg(
-            Arg::with_name("modified")
+            Arg::new("modified")
                 .help("show only modified files")
-                .short("-m")
+                .short('m')
                 .long("--modified"),
         )
         .arg(
-            Arg::with_name("added")
+            Arg::new("added")
                 .help("show only added files")
-                .short("-a")
+                .short('a')
                 .long("--added"),
         )
         .arg(
-            Arg::with_name("removed")
+            Arg::new("removed")
                 .help("show only removed files")
-                .short("-r")
+                .short('r')
                 .long("--removed"),
         )
         .arg(
-            Arg::with_name("clean")
+            Arg::new("clean")
                 .help("show only clean files")
-                .short("-c")
+                .short('c')
                 .long("--clean"),
         )
         .arg(
-            Arg::with_name("deleted")
+            Arg::new("deleted")
                 .help("show only deleted files")
-                .short("-d")
+                .short('d')
                 .long("--deleted"),
         )
         .arg(
-            Arg::with_name("unknown")
+            Arg::new("unknown")
                 .help("show only unknown (not tracked) files")
-                .short("-u")
+                .short('u')
                 .long("--unknown"),
         )
         .arg(
-            Arg::with_name("ignored")
+            Arg::new("ignored")
                 .help("show only ignored files")
-                .short("-i")
+                .short('i')
                 .long("--ignored"),
         )
         .arg(
-            Arg::with_name("copies")
+            Arg::new("copies")
                 .help("show source of copied files (DEFAULT: ui.statuscopies)")
-                .short("-C")
+                .short('C')
                 .long("--copies"),
         )
         .arg(
-            Arg::with_name("no-status")
+            Arg::new("no-status")
                 .help("hide status prefix")
-                .short("-n")
+                .short('n')
                 .long("--no-status"),
         )
 }
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 @@
 Returns 0 on success.
 ";
 
-pub fn args() -> clap::App<'static, 'static> {
-    clap::SubCommand::with_name("root").about(HELP_TEXT)
+pub fn args() -> clap::App<'static> {
+    clap::App::new("root").about(HELP_TEXT)
 }
 
 pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> {
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,12 +14,12 @@
 Returns 0 on success.
 ";
 
-pub fn args() -> clap::App<'static, 'static> {
-    clap::SubCommand::with_name("files")
+pub fn args() -> clap::App<'static> {
+    clap::App::new("files")
         .arg(
-            Arg::with_name("rev")
+            Arg::new("rev")
                 .help("search the repository as it is in REV")
-                .short("-r")
+                .short('r')
                 .long("--revision")
                 .value_name("REV")
                 .takes_value(true),
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 @@
 Print the current repo requirements.
 ";
 
-pub fn args() -> clap::App<'static, 'static> {
-    clap::SubCommand::with_name("debugrequirements").about(HELP_TEXT)
+pub fn args() -> clap::App<'static> {
+    clap::App::new("debugrequirements").about(HELP_TEXT)
 }
 
 pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> {
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 @@
 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::App<'static> {
+    clap::App::new("debugignorerhg").about(HELP_TEXT)
 }
 
 pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> {
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 @@
 Dump the contents of a data file revision
 ";
 
-pub fn args() -> clap::App<'static, 'static> {
-    clap::SubCommand::with_name("debugdata")
+pub fn args() -> clap::App<'static> {
+    clap::App::new("debugdata")
         .arg(
-            Arg::with_name("changelog")
+            Arg::new("changelog")
                 .help("open changelog")
-                .short("-c")
+                .short('c')
                 .long("--changelog"),
         )
         .arg(
-            Arg::with_name("manifest")
+            Arg::new("manifest")
                 .help("open manifest")
-                .short("-m")
+                .short('m')
                 .long("--manifest"),
         )
         .group(
-            ArgGroup::with_name("")
+            ArgGroup::new("")
                 .args(&["changelog", "manifest"])
                 .required(true),
         )
         .arg(
-            Arg::with_name("rev")
+            Arg::new("rev")
                 .help("revision")
                 .required(true)
                 .value_name("REV"),
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,10 +8,10 @@
 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::App<'static> {
+    clap::App::new("config")
         .arg(
-            Arg::with_name("name")
+            Arg::new("name")
                 .help("the section.name to print")
                 .value_name("NAME")
                 .required(true)
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
@@ -10,21 +10,21 @@
 Output the current or given revision of files
 ";
 
-pub fn args() -> clap::App<'static, 'static> {
-    clap::SubCommand::with_name("cat")
+pub fn args() -> clap::App<'static> {
+    clap::App::new("cat")
         .arg(
-            Arg::with_name("rev")
+            Arg::new("rev")
                 .help("search the repository as it is in REV")
-                .short("-r")
+                .short('r')
                 .long("--rev")
                 .value_name("REV")
                 .takes_value(true),
         )
         .arg(
-            clap::Arg::with_name("files")
+            clap::Arg::new("files")
                 .required(true)
-                .multiple(true)
-                .empty_values(false)
+                .multiple_occurrences(true)
+                .forbid_empty_values(true)
                 .value_name("FILE")
                 .help("Files to output"),
         )
diff --git a/rust/rhg/Cargo.toml b/rust/rhg/Cargo.toml
--- a/rust/rhg/Cargo.toml
+++ b/rust/rhg/Cargo.toml
@@ -10,7 +10,7 @@
 [dependencies]
 hg-core = { path = "../hg-core"}
 chrono = "0.4.19"
-clap = "2.33.1"
+clap = "3.0.7"
 derive_more = "0.99"
 home = "0.5.3"
 lazy_static = "1.4.0"
diff --git a/rust/hg-core/examples/nodemap/main.rs b/rust/hg-core/examples/nodemap/main.rs
--- a/rust/hg-core/examples/nodemap/main.rs
+++ b/rust/hg-core/examples/nodemap/main.rs
@@ -88,29 +88,29 @@
 fn main() {
     let matches = App::new("Nodemap pure Rust example")
         .arg(
-            Arg::with_name("REPOSITORY")
+            Arg::new("REPOSITORY")
                 .help("Path to the repository, always necessary for its index")
                 .required(true),
         )
         .arg(
-            Arg::with_name("NODEMAP_FILE")
+            Arg::new("NODEMAP_FILE")
                 .help("Path to the nodemap file, independent of REPOSITORY")
                 .required(true),
         )
         .subcommand(
-            SubCommand::with_name("create")
+            App::new("create")
                 .about("Create NODEMAP_FILE by scanning repository index"),
         )
         .subcommand(
-            SubCommand::with_name("query")
+            App::new("query")
                 .about("Query NODEMAP_FILE for PREFIX")
-                .arg(Arg::with_name("PREFIX").required(true)),
+                .arg(Arg::new("PREFIX").required(true)),
         )
         .subcommand(
-            SubCommand::with_name("bench")
+            App::new("bench")
                 .about(
                     "Perform #QUERIES random successful queries on NODEMAP_FILE")
-                .arg(Arg::with_name("QUERIES").required(true)),
+                .arg(Arg::new("QUERIES").required(true)),
         )
         .get_matches();
 
diff --git a/rust/hg-core/Cargo.toml b/rust/hg-core/Cargo.toml
--- a/rust/hg-core/Cargo.toml
+++ b/rust/hg-core/Cargo.toml
@@ -43,5 +43,5 @@
 default-features = false
 
 [dev-dependencies]
-clap = "*"
+clap = "3.0.7"
 pretty_assertions = "0.6.1"
diff --git a/rust/Cargo.lock b/rust/Cargo.lock
--- a/rust/Cargo.lock
+++ b/rust/Cargo.lock
@@ -129,17 +129,17 @@
 
 [[package]]
 name = "clap"
-version = "2.33.3"
+version = "3.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
+checksum = "12e8611f9ae4e068fa3e56931fded356ff745e70987ff76924a6e0ab1c8ef2e3"
 dependencies = [
- "ansi_term",
  "atty",
  "bitflags",
+ "indexmap",
+ "os_str_bytes",
  "strsim",
+ "termcolor",
  "textwrap",
- "unicode-width",
- "vec_map",
 ]
 
 [[package]]
@@ -373,6 +373,12 @@
 checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
 
 [[package]]
+name = "hashbrown"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+
+[[package]]
 name = "hermit-abi"
 version = "0.1.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -468,6 +474,16 @@
 ]
 
 [[package]]
+name = "indexmap"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
+dependencies = [
+ "autocfg",
+ "hashbrown",
+]
+
+[[package]]
 name = "itertools"
 version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -531,9 +547,9 @@
 
 [[package]]
 name = "memchr"
-version = "2.3.4"
+version = "2.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
+checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
 
 [[package]]
 name = "memmap2"
@@ -623,6 +639,15 @@
 checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
 
 [[package]]
+name = "os_str_bytes"
+version = "6.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
 name = "output_vt100"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -942,9 +967,9 @@
 
 [[package]]
 name = "strsim"
-version = "0.8.0"
+version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 
 [[package]]
 name = "syn"
@@ -982,12 +1007,9 @@
 
 [[package]]
 name = "textwrap"
-version = "0.11.0"
+version = "0.14.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
-dependencies = [
- "unicode-width",
-]
+checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
 
 [[package]]
 name = "thread_local"
@@ -1027,12 +1049,6 @@
 checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
 
 [[package]]
-name = "unicode-width"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
-
-[[package]]
 name = "unicode-xid"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1066,12 +1082,6 @@
 ]
 
 [[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.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"



To: martinvonz, #hg-reviewers
Cc: mercurial-patches, mercurial-devel


More information about the Mercurial-devel mailing list