From 272b66aac81f5cfe3865f0d791b724972ee93ba9 Mon Sep 17 00:00:00 2001 From: Sylvestre Ledru Date: Fri, 22 May 2020 17:27:03 +0200 Subject: [PATCH] refactor(hostname): use clap instead of getopts for consistency (#1516) * refactor(hostname): use clap instead of getopts for consistency * deps ~ uucore/wide is required Co-authored-by: Roy Ivy III --- Cargo.lock | 2 +- src/uu/hostname/Cargo.toml | 4 +- src/uu/hostname/src/hostname.rs | 83 ++++++++++++++++++--------------- 3 files changed, 49 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3f7e67856..a10cc4336 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -660,7 +660,7 @@ dependencies = [ name = "hostname" version = "0.0.1" dependencies = [ - "getopts 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "hostname 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "uucore 0.0.2 (git+https://github.com/uutils/uucore/?tag=0.0.2)", diff --git a/src/uu/hostname/Cargo.toml b/src/uu/hostname/Cargo.toml index bcbb0674d..19f67f678 100644 --- a/src/uu/hostname/Cargo.toml +++ b/src/uu/hostname/Cargo.toml @@ -10,9 +10,9 @@ name = "uu_hostname" path = "src/hostname.rs" [dependencies] -getopts = "0.2" +clap = "2.32" libc = "0.2.42" -uucore = "0.0.2" +uucore = { version = "0.0.2", features = [ "wide" ] } winapi = { version = "0.3", features = ["sysinfoapi", "winsock2"] } hostname = { version = "^0.3", features = ["set"] } diff --git a/src/uu/hostname/src/hostname.rs b/src/uu/hostname/src/hostname.rs index 53a7223b1..1b6bc06b9 100644 --- a/src/uu/hostname/src/hostname.rs +++ b/src/uu/hostname/src/hostname.rs @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -extern crate getopts; +extern crate clap; extern crate hostname; extern crate libc; #[cfg(windows)] @@ -18,9 +18,8 @@ extern crate winapi; #[macro_use] extern crate uucore; -use getopts::Matches; +use clap::{App, Arg, ArgMatches}; use std::collections::hash_set::HashSet; -use std::ffi::OsStr; use std::net::ToSocketAddrs; use std::str; @@ -29,9 +28,14 @@ use winapi::shared::minwindef::MAKEWORD; #[cfg(windows)] use winapi::um::winsock2::{WSACleanup, WSAStartup}; -const SYNTAX: &str = "[OPTION]... [HOSTNAME]"; -const SUMMARY: &str = "Print or set the system's host name."; -const LONG_HELP: &str = ""; +static ABOUT: &str = "Display or set the system's host name."; +static VERSION: &str = env!("CARGO_PKG_VERSION"); + +static OPT_DOMAIN: &str = "domain"; +static OPT_IP_ADDRESS: &str = "ip-address"; +static OPT_FQDN: &str = "fqdn"; +static OPT_SHORT: &str = "short"; +static OPT_HOST: &str = "host"; pub fn uumain(args: Vec) -> i32 { #![allow(clippy::let_and_return)] @@ -52,53 +56,58 @@ pub fn uumain(args: Vec) -> i32 { result } +fn get_usage() -> String { + format!("{0} [OPTION]... [HOSTNAME]", executable!()) +} fn execute(args: Vec) -> i32 { - let matches = new_coreopts!(SYNTAX, SUMMARY, LONG_HELP) - .optflag( - "d", - "domain", - "Display the name of the DNS domain if possible", + let usage = get_usage(); + let matches = App::new(executable!()) + .version(VERSION) + .about(ABOUT) + .usage(&usage[..]) + .arg( + Arg::with_name(OPT_DOMAIN) + .short("d") + .long("domain") + .help("Display the name of the DNS domain if possible"), ) - .optflag( - "i", - "ip-address", - "Display the network address(es) of the host", + .arg( + Arg::with_name(OPT_IP_ADDRESS) + .short("i") + .long("ip-address") + .help("Display the network address(es) of the host"), ) // TODO: support --long - .optflag( - "f", - "fqdn", - "Display the FQDN (Fully Qualified Domain Name) (default)", + .arg( + Arg::with_name(OPT_FQDN) + .short("f") + .long("fqdn") + .help("Display the FQDN (Fully Qualified Domain Name) (default)"), ) - .optflag( - "s", - "short", + .arg(Arg::with_name(OPT_SHORT).short("s").long("short").help( "Display the short hostname (the portion before the first dot) if \ - possible", - ) - .parse(args); + possible", + )) + .arg(Arg::with_name(OPT_HOST)) + .get_matches_from(&args); - match matches.free.len() { - 0 => display_hostname(matches), - 1 => { - if let Err(err) = hostname::set(OsStr::new(matches.free.last().unwrap())) { + match matches.value_of(OPT_HOST) { + None => display_hostname(&matches), + Some(host) => { + if let Err(err) = hostname::set(host) { show_error!("{}", err); 1 } else { 0 } } - _ => { - show_error!("{}", msg_wrong_number_of_arguments!(0, 1)); - 1 - } } } -fn display_hostname(matches: Matches) -> i32 { +fn display_hostname(matches: &ArgMatches) -> i32 { let hostname = hostname::get().unwrap().into_string().unwrap(); - if matches.opt_present("i") { + if matches.is_present(OPT_IP_ADDRESS) { // XXX: to_socket_addrs needs hostname:port so append a dummy port and remove it later. // This was originally supposed to use std::net::lookup_host, but that seems to be // deprecated. Perhaps we should use the dns-lookup crate? @@ -134,10 +143,10 @@ fn display_hostname(matches: Matches) -> i32 { } } } else { - if matches.opt_present("s") || matches.opt_present("d") { + if matches.is_present(OPT_SHORT) || matches.is_present(OPT_DOMAIN) { let mut it = hostname.char_indices().filter(|&ci| ci.1 == '.'); if let Some(ci) = it.next() { - if matches.opt_present("s") { + if matches.is_present(OPT_SHORT) { println!("{}", &hostname[0..ci.0]); } else { println!("{}", &hostname[ci.0 + 1..]);