diff --git a/src/bin/fullnode-config.rs b/src/bin/fullnode-config.rs index 24eea86e4f..e58c7c22bb 100644 --- a/src/bin/fullnode-config.rs +++ b/src/bin/fullnode-config.rs @@ -1,57 +1,52 @@ -extern crate getopts; +extern crate clap; extern crate serde_json; extern crate solana; -use getopts::Options; +use clap::{App, Arg}; use solana::crdt::{get_ip_addr, parse_port_or_addr, ReplicatedData}; use solana::nat::get_public_ip_addr; -use std::env; use std::io; use std::net::SocketAddr; -use std::process::exit; - -fn print_usage(program: &str, opts: Options) { - let mut brief = format!("Usage: {} [options]\n\n", program); - brief += " Create a solana fullnode config file\n"; - - print!("{}", opts.usage(&brief)); -} fn main() { - let mut opts = Options::new(); - opts.optopt("b", "", "bind", "bind to port or address"); - opts.optflag( - "p", - "", - "detect public network address using public servers", - ); - opts.optflag( - "l", - "", - "detect network address from local machine configuration", - ); - opts.optflag("h", "help", "print help"); - let args: Vec = env::args().collect(); - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(e) => { - eprintln!("{}", e); - exit(1); - } - }; - if matches.opt_present("h") { - let program = args[0].clone(); - print_usage(&program, opts); - return; - } + let matches = App::new("fullnode-config") + .arg( + Arg::with_name("local") + .short("l") + .long("local") + .takes_value(false) + .help("detect network address from local machine configuration"), + ) + .arg( + Arg::with_name("public") + .short("p") + .long("public") + .takes_value(false) + .help("detect public network address using public servers"), + ) + .arg( + Arg::with_name("bind") + .short("b") + .long("bind") + .value_name("PORT") + .takes_value(true) + .help("bind to port or address"), + ) + .get_matches(); let bind_addr: SocketAddr = { - let mut bind_addr = parse_port_or_addr(matches.opt_str("b")); - if matches.opt_present("l") { + let mut bind_addr = parse_port_or_addr({ + if let Some(b) = matches.value_of("bind") { + Some(b.to_string()) + } else { + None + } + }); + if matches.is_present("local") { let ip = get_ip_addr().unwrap(); bind_addr.set_ip(ip); } - if matches.opt_present("p") { + if matches.is_present("public") { let ip = get_public_ip_addr().unwrap(); bind_addr.set_ip(ip); } diff --git a/src/bin/fullnode.rs b/src/bin/fullnode.rs index facd1c2116..c1a265564e 100644 --- a/src/bin/fullnode.rs +++ b/src/bin/fullnode.rs @@ -1,4 +1,5 @@ extern crate atty; +extern crate clap; extern crate env_logger; extern crate getopts; extern crate log; @@ -6,11 +7,10 @@ extern crate serde_json; extern crate solana; use atty::{is, Stream}; -use getopts::Options; +use clap::{App, Arg}; use solana::crdt::{ReplicatedData, TestNode}; use solana::fullnode::{FullNode, InFile, OutFile}; use solana::service::Service; -use std::env; use std::fs::File; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::process::exit; @@ -18,46 +18,34 @@ use std::sync::atomic::AtomicBool; use std::sync::Arc; //use std::time::Duration; -fn print_usage(program: &str, opts: Options) { - let mut brief = format!("Usage: cat | {} [options]\n\n", program); - brief += " Run a Solana node to handle transactions and\n"; - brief += " write a new transaction log to stdout.\n"; - brief += " Takes existing transaction log from stdin."; - - print!("{}", opts.usage(&brief)); -} - fn main() -> () { env_logger::init(); - let mut opts = Options::new(); - opts.optflag("h", "help", "print help"); - opts.optopt("l", "", "run with the identity found in FILE", "FILE"); - opts.optopt( - "t", - "", - "testnet; connect to the network at this gossip entry point", - "HOST:PORT", - ); - opts.optopt( - "o", - "", - "output log to FILE, defaults to stdout (ignored by validators)", - "FILE", - ); - - let args: Vec = env::args().collect(); - let matches = match opts.parse(&args[1..]) { - Ok(m) => m, - Err(e) => { - eprintln!("{}", e); - exit(1); - } - }; - if matches.opt_present("h") { - let program = args[0].clone(); - print_usage(&program, opts); - return; - } + let matches = App::new("fullnode") + .arg( + Arg::with_name("identity") + .short("l") + .long("local") + .value_name("FILE") + .takes_value(true) + .help("run with the identity found in FILE"), + ) + .arg( + Arg::with_name("testnet") + .short("t") + .long("testnet") + .value_name("HOST:PORT") + .takes_value(true) + .help("testnet; connect to the network at this gossip entry point"), + ) + .arg( + Arg::with_name("output") + .short("o") + .long("output") + .value_name("FILE") + .takes_value(true) + .help("output log to FILE, defaults to stdout (ignored by validators)"), + ) + .get_matches(); if is(Stream::Stdin) { eprintln!("nothing found on stdin, expected a log file"); exit(1); @@ -65,8 +53,8 @@ fn main() -> () { let bind_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 8000); let mut repl_data = ReplicatedData::new_leader(&bind_addr); - if matches.opt_present("l") { - let path = matches.opt_str("l").unwrap(); + if let Some(l) = matches.value_of("identity") { + let path = l.to_string(); if let Ok(file) = File::open(path.clone()) { if let Ok(data) = serde_json::from_reader(file) { repl_data = data; @@ -81,15 +69,15 @@ fn main() -> () { } let mut node = TestNode::new_with_bind_addr(repl_data, bind_addr); let exit = Arc::new(AtomicBool::new(false)); - let fullnode = if matches.opt_present("t") { - let testnet_address_string = matches.opt_str("t").unwrap(); + let fullnode = if let Some(t) = matches.value_of("testnet") { + let testnet_address_string = t.to_string(); let testnet_addr = testnet_address_string.parse().unwrap(); FullNode::new(node, false, InFile::StdIn, Some(testnet_addr), None, exit) } else { node.data.current_leader_id = node.data.id.clone(); - let outfile = if let Some(f) = matches.opt_str("o") { - OutFile::Path(f) + let outfile = if let Some(o) = matches.value_of("output") { + OutFile::Path(o.to_string()) } else { OutFile::StdOut };