From 39f5357ddb647c66e81a6a2d0b1f86af92e859b1 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Tue, 27 Oct 2020 19:33:55 -0700 Subject: [PATCH 01/26] feat: update to clap 3.0.0-beta.2 --- Cargo.lock | 54 ++++++++++++------- src/dfx/Cargo.toml | 2 +- src/dfx/src/commands/bootstrap.rs | 34 ++++++------ src/dfx/src/commands/build.rs | 20 +++---- src/dfx/src/commands/cache/delete.rs | 6 +-- src/dfx/src/commands/cache/install.rs | 4 +- src/dfx/src/commands/cache/list.rs | 4 +- src/dfx/src/commands/cache/mod.rs | 4 +- src/dfx/src/commands/cache/show.rs | 4 +- src/dfx/src/commands/canister/call.rs | 36 ++++++------- src/dfx/src/commands/canister/create.rs | 12 ++--- src/dfx/src/commands/canister/delete.rs | 12 ++--- src/dfx/src/commands/canister/id.rs | 8 +-- src/dfx/src/commands/canister/install.rs | 40 +++++++------- src/dfx/src/commands/canister/mod.rs | 8 +-- .../src/commands/canister/request_status.rs | 8 +-- .../src/commands/canister/set_controller.rs | 12 ++--- src/dfx/src/commands/canister/start.rs | 12 ++--- src/dfx/src/commands/canister/status.rs | 12 ++--- src/dfx/src/commands/canister/stop.rs | 12 ++--- src/dfx/src/commands/config.rs | 14 ++--- src/dfx/src/commands/deploy.rs | 20 +++---- src/dfx/src/commands/identity/list.rs | 4 +- src/dfx/src/commands/identity/mod.rs | 4 +- src/dfx/src/commands/identity/new.rs | 8 +-- src/dfx/src/commands/identity/principal.rs | 4 +- src/dfx/src/commands/identity/remove.rs | 8 +-- src/dfx/src/commands/identity/rename.rs | 12 ++--- src/dfx/src/commands/identity/use.rs | 8 +-- src/dfx/src/commands/identity/whoami.rs | 4 +- src/dfx/src/commands/language_service.rs | 42 +++++++++------ src/dfx/src/commands/mod.rs | 10 ++-- src/dfx/src/commands/new.rs | 18 +++---- src/dfx/src/commands/ping.rs | 8 +-- src/dfx/src/commands/replica.rs | 24 ++++----- src/dfx/src/commands/start.rs | 18 +++---- src/dfx/src/commands/stop.rs | 4 +- src/dfx/src/commands/upgrade.rs | 12 ++--- src/dfx/src/lib/provider.rs | 6 +-- src/dfx/src/main.rs | 16 +++--- 40 files changed, 287 insertions(+), 261 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 40a8436792..f8f8ce9a68 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -374,15 +374,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "arc-swap" version = "0.4.7" @@ -710,19 +701,36 @@ dependencies = [ [[package]] name = "clap" -version = "2.33.3" +version = "3.0.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "4bd1061998a501ee7d4b6d449020df3266ca3124b941ec56cf2005c3779ca142" dependencies = [ - "ansi_term", "atty", "bitflags", - "strsim 0.8.0", + "clap_derive", + "indexmap", + "lazy_static", + "os_str_bytes", + "strsim 0.10.0", + "termcolor", "textwrap", "unicode-width", "vec_map", ] +[[package]] +name = "clap_derive" +version = "3.0.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "370f715b81112975b1b69db93e0b56ea4cd4e5002ac43b2da8474106a54096a1" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "clicolors-control" version = "1.0.1" @@ -1676,7 +1684,7 @@ dependencies = [ [[package]] name = "ic-types" version = "0.1.2" -source = "git+https://github.com/dfinity/agent-rs.git?branch=next#191dca1c38cf7eebfb177f242063592223c87976" +source = "git+https://github.com/dfinity/agent-rs.git?branch=next#c973ab2dd4f0a5f081be8f2d8d336ce991f4d58b" dependencies = [ "base32", "crc32fast", @@ -2267,6 +2275,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "os_str_bytes" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ac6fe3538f701e339953a3ebbe4f39941aababa8a3f6964635b24ab526daeac" + [[package]] name = "parking_lot" version = "0.11.0" @@ -3224,15 +3238,15 @@ dependencies = [ [[package]] name = "strsim" -version = "0.8.0" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" [[package]] name = "strsim" -version = "0.9.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" @@ -3341,9 +3355,9 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +checksum = "203008d98caf094106cfaba70acfed15e18ed3ddb7d94e49baec153a2b462789" dependencies = [ "unicode-width", ] diff --git a/src/dfx/Cargo.toml b/src/dfx/Cargo.toml index 7504943926..dd3f360c10 100644 --- a/src/dfx/Cargo.toml +++ b/src/dfx/Cargo.toml @@ -23,7 +23,7 @@ atty = "0.2.13" base64 = "0.11.0" candid = "0.6.7" chrono = "0.4.9" -clap = "2.33.0" +clap = "3.0.0-beta.2" console = "0.7.7" crossbeam = "0.7.3" ctrlc = { version = "3.1.6", features = [ "termination" ] } diff --git a/src/dfx/src/commands/bootstrap.rs b/src/dfx/src/commands/bootstrap.rs index 3c969a4735..c4a5a32bc6 100644 --- a/src/dfx/src/commands/bootstrap.rs +++ b/src/dfx/src/commands/bootstrap.rs @@ -18,43 +18,43 @@ use std::time::Duration; use url::Url; /// Constructs a sub-command to run the bootstrap server. -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("bootstrap") .about(UserMessage::BootstrapCommand.to_str()) .arg( - Arg::with_name("ip") - .help(UserMessage::BootstrapIP.to_str()) + Arg::new("ip") + //.help(UserMessage::BootstrapIP.to_str()) .long("ip") .takes_value(true), ) .arg( - Arg::with_name("port") - .help(UserMessage::BootstrapPort.to_str()) + Arg::new("port") + //.help(UserMessage::BootstrapPort.to_str()) .long("port") .takes_value(true), ) .arg( - Arg::with_name("network") - .help(UserMessage::CanisterComputeNetwork.to_str()) + Arg::new("network") + //.help(UserMessage::CanisterComputeNetwork.to_str()) .long("network") .takes_value(true), ) .arg( - Arg::with_name("root") - .help(UserMessage::BootstrapRoot.to_str()) + Arg::new("root") + //.help(UserMessage::BootstrapRoot.to_str()) .long("root") .takes_value(true), ) .arg( - Arg::with_name("timeout") - .help(UserMessage::BootstrapTimeout.to_str()) + Arg::new("timeout") + //.help(UserMessage::BootstrapTimeout.to_str()) .long("timeout") .takes_value(true), ) } /// Runs the bootstrap server. -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let logger = env.get_logger(); let config = env .get_config() @@ -118,7 +118,7 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { fn apply_arguments( config: &ConfigDefaultsBootstrap, env: &dyn Environment, - args: &ArgMatches<'_>, + args: &ArgMatches, ) -> DfxResult { let ip = get_ip(&config, args)?; let port = get_port(&config, args)?; @@ -143,7 +143,7 @@ fn get_config_defaults_from_file(env: &dyn Environment) -> ConfigDefaults { /// Gets the IP address that the bootstrap server listens on. First checks if the IP address was /// specified on the command-line using --ip, otherwise checks if the IP address was specified in /// the dfx configuration file, otherise defaults to 127.0.0.1. -fn get_ip(config: &ConfigDefaultsBootstrap, args: &ArgMatches<'_>) -> DfxResult { +fn get_ip(config: &ConfigDefaultsBootstrap, args: &ArgMatches) -> DfxResult { args.value_of("ip") .map(|ip| ip.parse()) .unwrap_or_else(|| { @@ -156,7 +156,7 @@ fn get_ip(config: &ConfigDefaultsBootstrap, args: &ArgMatches<'_>) -> DfxResult< /// Gets the port number that the bootstrap server listens on. First checks if the port number was /// specified on the command-line using --port, otherwise checks if the port number was specified /// in the dfx configuration file, otherise defaults to 8081. -fn get_port(config: &ConfigDefaultsBootstrap, args: &ArgMatches<'_>) -> DfxResult { +fn get_port(config: &ConfigDefaultsBootstrap, args: &ArgMatches) -> DfxResult { args.value_of("port") .map(|port| port.parse()) .unwrap_or_else(|| { @@ -182,7 +182,7 @@ fn get_providers(network_descriptor: &NetworkDescriptor) -> DfxResult, + args: &ArgMatches, ) -> DfxResult { args.value_of("root") .map(|root| parse_dir(root)) @@ -205,7 +205,7 @@ fn get_root( /// requests to complete. First checks if the timeout was specified on the command-line using /// --timeout, otherwise checks if the timeout was specified in the dfx configuration file, /// otherise defaults to 30. -fn get_timeout(config: &ConfigDefaultsBootstrap, args: &ArgMatches<'_>) -> DfxResult { +fn get_timeout(config: &ConfigDefaultsBootstrap, args: &ArgMatches) -> DfxResult { args.value_of("timeout") .map(|timeout| timeout.parse()) .unwrap_or_else(|| { diff --git a/src/dfx/src/commands/build.rs b/src/dfx/src/commands/build.rs index 46874001c3..5981ea0dac 100644 --- a/src/dfx/src/commands/build.rs +++ b/src/dfx/src/commands/build.rs @@ -7,38 +7,38 @@ use crate::lib::models::canister_id_store::CanisterIdStore; use crate::lib::provider::create_agent_environment; use clap::{App, Arg, ArgMatches, SubCommand}; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("build") .about(UserMessage::BuildCanister.to_str()) .arg( - Arg::with_name("canister_name") + Arg::new("canister_name") .takes_value(true) .conflicts_with("all") - .help(UserMessage::BuildCanisterName.to_str()) + //.help(UserMessage::BuildCanisterName.to_str()) .required(false), ) .arg( - Arg::with_name("all") + Arg::new("all") .long("all") .conflicts_with("canister_name") - .help(UserMessage::BuildAll.to_str()) + //.help(UserMessage::BuildAll.to_str()) .takes_value(false), ) .arg( - Arg::with_name("check") + Arg::new("check") .long("check") .takes_value(false) - .help(UserMessage::BuildCheck.to_str()), + //.help(UserMessage::BuildCheck.to_str()), ) .arg( - Arg::with_name("network") - .help(UserMessage::CanisterComputeNetwork.to_str()) + Arg::new("network") + //.help(UserMessage::CanisterComputeNetwork.to_str()) .long("network") .takes_value(true), ) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let env = create_agent_environment(env, args)?; let logger = env.get_logger(); diff --git a/src/dfx/src/commands/cache/delete.rs b/src/dfx/src/commands/cache/delete.rs index cf25df6af8..89e5403b50 100644 --- a/src/dfx/src/commands/cache/delete.rs +++ b/src/dfx/src/commands/cache/delete.rs @@ -4,13 +4,13 @@ use crate::lib::error::DfxResult; use crate::lib::message::UserMessage; use clap::{App, Arg, ArgMatches, SubCommand}; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("delete") .about(UserMessage::CacheDelete.to_str()) - .arg(Arg::with_name("version").takes_value(true)) + .arg(Arg::new("version").takes_value(true)) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { match args.value_of("version") { Some(v) => delete_version(v).map(|_| {}), _ => env.get_cache().delete(), diff --git a/src/dfx/src/commands/cache/install.rs b/src/dfx/src/commands/cache/install.rs index 8d9b952ab4..b31ac5f170 100644 --- a/src/dfx/src/commands/cache/install.rs +++ b/src/dfx/src/commands/cache/install.rs @@ -3,10 +3,10 @@ use crate::lib::error::DfxResult; use crate::lib::message::UserMessage; use clap::{App, ArgMatches, SubCommand}; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("install").about(UserMessage::CacheUnpack.to_str()) } -pub fn exec(env: &dyn Environment, _args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { env.get_cache().force_install() } diff --git a/src/dfx/src/commands/cache/list.rs b/src/dfx/src/commands/cache/list.rs index 4e8344dc46..7da4c493ee 100644 --- a/src/dfx/src/commands/cache/list.rs +++ b/src/dfx/src/commands/cache/list.rs @@ -5,11 +5,11 @@ use crate::lib::message::UserMessage; use clap::{App, ArgMatches, SubCommand}; use std::io::Write; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("list").about(UserMessage::CacheList.to_str()) } -pub fn exec(env: &dyn Environment, _args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { let mut current_printed = false; let current_version = env.get_version(); let mut all_versions = cache::list_versions()?; diff --git a/src/dfx/src/commands/cache/mod.rs b/src/dfx/src/commands/cache/mod.rs index ae692f25de..e8f2d06920 100644 --- a/src/dfx/src/commands/cache/mod.rs +++ b/src/dfx/src/commands/cache/mod.rs @@ -18,13 +18,13 @@ fn builtins() -> Vec { ] } -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("cache") .about(UserMessage::ManageCache.to_str()) .subcommands(builtins().into_iter().map(|x| x.get_subcommand().clone())) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let subcommand = args.subcommand(); if let (name, Some(subcommand_args)) = subcommand { diff --git a/src/dfx/src/commands/cache/show.rs b/src/dfx/src/commands/cache/show.rs index 9132b20e02..56636bbab6 100644 --- a/src/dfx/src/commands/cache/show.rs +++ b/src/dfx/src/commands/cache/show.rs @@ -4,11 +4,11 @@ use crate::lib::error::DfxResult; use crate::lib::message::UserMessage; use clap::{App, ArgMatches, SubCommand}; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("show").about(UserMessage::CacheShow.to_str()) } -pub fn exec(env: &dyn Environment, _args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { let v = format!("{}", env.get_version()); println!("{}", cache::get_bin_cache(&v)?.as_path().display()); Ok(()) diff --git a/src/dfx/src/commands/canister/call.rs b/src/dfx/src/commands/canister/call.rs index 0bcc0995c4..dbc615fa57 100644 --- a/src/dfx/src/commands/canister/call.rs +++ b/src/dfx/src/commands/canister/call.rs @@ -10,66 +10,66 @@ use ic_types::principal::Principal as CanisterId; use std::option::Option; use tokio::runtime::Runtime; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("call") .about(UserMessage::CallCanister.to_str()) .arg( - Arg::with_name("canister_name") + Arg::new("canister_name") .takes_value(true) - .help(UserMessage::CanisterName.to_str()) + //.help(UserMessage::CanisterName.to_str()) .required(true), ) .arg( - Arg::with_name("method_name") - .help(UserMessage::MethodName.to_str()) + Arg::new("method_name") + //.help(UserMessage::MethodName.to_str()) .required(true), ) .arg( - Arg::with_name("async") - .help(UserMessage::AsyncResult.to_str()) + Arg::new("async") + //.help(UserMessage::AsyncResult.to_str()) .long("async") .takes_value(false), ) .arg( - Arg::with_name("query") - .help(UserMessage::QueryCanister.to_str()) + Arg::new("query") + //.help(UserMessage::QueryCanister.to_str()) .long("query") .conflicts_with("async") .conflicts_with("update") .takes_value(false), ) .arg( - Arg::with_name("update") - .help(UserMessage::UpdateCanisterArg.to_str()) + Arg::new("update") + //.help(UserMessage::UpdateCanisterArg.to_str()) .long("update") .conflicts_with("async") .conflicts_with("query") .takes_value(false), ) .arg( - Arg::with_name("type") - .help(UserMessage::ArgumentType.to_str()) + Arg::new("type") + //.help(UserMessage::ArgumentType.to_str()) .long("type") .takes_value(true) .requires("argument") .possible_values(&["idl", "raw"]), ) .arg( - Arg::with_name("output") - .help(UserMessage::OutputType.to_str()) + Arg::new("output") + //.help(UserMessage::OutputType.to_str()) .long("output") .takes_value(true) .conflicts_with("async") .possible_values(&["idl", "raw", "pp"]), ) .arg( - Arg::with_name("argument") - .help(UserMessage::ArgumentValue.to_str()) + Arg::new("argument") + //.help(UserMessage::ArgumentValue.to_str()) .takes_value(true), ) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; diff --git a/src/dfx/src/commands/canister/create.rs b/src/dfx/src/commands/canister/create.rs index 98bcc0d81b..d7432bf594 100644 --- a/src/dfx/src/commands/canister/create.rs +++ b/src/dfx/src/commands/canister/create.rs @@ -6,26 +6,26 @@ use crate::util::expiry_duration; use clap::{App, Arg, ArgMatches, SubCommand}; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("create") .about(UserMessage::CreateCanister.to_str()) .arg( - Arg::with_name("canister_name") + Arg::new("canister_name") .takes_value(true) .required_unless("all") - .help(UserMessage::CreateCanisterName.to_str()) + //.help(UserMessage::CreateCanisterName.to_str()) .required(false), ) .arg( - Arg::with_name("all") + Arg::new("all") .long("all") .required_unless("canister_name") - .help(UserMessage::CreateAll.to_str()) + //.help(UserMessage::CreateAll.to_str()) .takes_value(false), ) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; diff --git a/src/dfx/src/commands/canister/delete.rs b/src/dfx/src/commands/canister/delete.rs index 750f24a8a2..ec68f05c17 100644 --- a/src/dfx/src/commands/canister/delete.rs +++ b/src/dfx/src/commands/canister/delete.rs @@ -13,21 +13,21 @@ use slog::info; use std::time::Duration; use tokio::runtime::Runtime; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("delete") .about(UserMessage::DeleteCanister.to_str()) .arg( - Arg::with_name("canister_name") + Arg::new("canister_name") .takes_value(true) .required_unless("all") - .help(UserMessage::DeleteCanisterName.to_str()) + //.help(UserMessage::DeleteCanisterName.to_str()) .required(false), ) .arg( - Arg::with_name("all") + Arg::new("all") .long("all") .required_unless("canister_name") - .help(UserMessage::DeleteAll.to_str()) + //.help(UserMessage::DeleteAll.to_str()) .takes_value(false), ) } @@ -58,7 +58,7 @@ async fn delete_canister( Ok(()) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; diff --git a/src/dfx/src/commands/canister/id.rs b/src/dfx/src/commands/canister/id.rs index e4b7ea41d8..456fc2ae69 100644 --- a/src/dfx/src/commands/canister/id.rs +++ b/src/dfx/src/commands/canister/id.rs @@ -5,18 +5,18 @@ use crate::lib::models::canister_id_store::CanisterIdStore; use clap::{App, Arg, ArgMatches, SubCommand}; use ic_types::principal::Principal as CanisterId; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("id") .about(UserMessage::IdCanister.to_str()) .arg( - Arg::with_name("canister_name") + Arg::new("canister_name") .takes_value(true) - .help(UserMessage::CanisterName.to_str()) + //.help(UserMessage::CanisterName.to_str()) .required(true), ) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { env.get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; let canister_name = args.value_of("canister_name").unwrap(); diff --git a/src/dfx/src/commands/canister/install.rs b/src/dfx/src/commands/canister/install.rs index fde7a91237..6b87f01e7b 100644 --- a/src/dfx/src/commands/canister/install.rs +++ b/src/dfx/src/commands/canister/install.rs @@ -15,32 +15,32 @@ use std::convert::TryFrom; use std::str::FromStr; use tokio::runtime::Runtime; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("install") .about(UserMessage::InstallCanister.to_str()) .arg( - Arg::with_name("canister_name") + Arg::new("canister_name") .takes_value(true) .required_unless("all") - .help(UserMessage::InstallCanisterName.to_str()) + //.help(UserMessage::InstallCanisterName.to_str()) .required(false), ) .arg( - Arg::with_name("all") + Arg::new("all") .long("all") .required_unless("canister_name") - .help(UserMessage::InstallAll.to_str()) + //.help(UserMessage::InstallAll.to_str()) .takes_value(false), ) .arg( - Arg::with_name("async") - .help(UserMessage::AsyncResult.to_str()) + Arg::new("async") + //.help(UserMessage::AsyncResult.to_str()) .long("async") .takes_value(false), ) .arg( - Arg::with_name("mode") - .help(UserMessage::InstallMode.to_str()) + Arg::new("mode") + //.help(UserMessage::InstallMode.to_str()) .long("mode") .short("m") .possible_values(&["install", "reinstall", "upgrade"]) @@ -48,29 +48,29 @@ pub fn construct() -> App<'static, 'static> { .takes_value(true), ) .arg( - Arg::with_name("argument") - .help(UserMessage::ArgumentValue.to_str()) + Arg::new("argument") + //.help(UserMessage::ArgumentValue.to_str()) .takes_value(true), ) .arg( - Arg::with_name("type") - .help(UserMessage::ArgumentType.to_str()) + Arg::new("type") + //.help(UserMessage::ArgumentType.to_str()) .long("type") .takes_value(true) .requires("argument") .possible_values(&["idl", "raw"]), ) .arg( - Arg::with_name("compute-allocation") - .help(UserMessage::InstallComputeAllocation.to_str()) + Arg::new("compute-allocation") + //.help(UserMessage::InstallComputeAllocation.to_str()) .long("compute-allocation") .short("c") .takes_value(true) .validator(compute_allocation_validator), ) .arg( - Arg::with_name("memory-allocation") - .help(UserMessage::InstallMemoryAllocation.to_str()) + Arg::new("memory-allocation") + //.help(UserMessage::InstallMemoryAllocation.to_str()) .long("memory-allocation") .takes_value(true) .validator(memory_allocation_validator), @@ -97,7 +97,7 @@ fn memory_allocation_validator(memory_allocation: String) -> Result<(), String> } fn get_compute_allocation( - args: &ArgMatches<'_>, + args: &ArgMatches, config_interface: &ConfigInterface, canister_name: &str, ) -> DfxResult> { @@ -112,7 +112,7 @@ fn get_compute_allocation( } fn get_memory_allocation( - args: &ArgMatches<'_>, + args: &ArgMatches, config_interface: &ConfigInterface, canister_name: &str, ) -> DfxResult> { @@ -126,7 +126,7 @@ fn get_memory_allocation( })) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; diff --git a/src/dfx/src/commands/canister/mod.rs b/src/dfx/src/commands/canister/mod.rs index 5ae18e87d0..6ca74c1e8f 100644 --- a/src/dfx/src/commands/canister/mod.rs +++ b/src/dfx/src/commands/canister/mod.rs @@ -31,19 +31,19 @@ fn builtins() -> Vec { ] } -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("canister") .about(UserMessage::ManageCanister.to_str()) .arg( - Arg::with_name("network") - .help(UserMessage::CanisterComputeNetwork.to_str()) + Arg::new("network") + //.help(UserMessage::CanisterComputeNetwork.to_str()) .long("network") .takes_value(true), ) .subcommands(builtins().into_iter().map(|x| x.get_subcommand().clone())) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let subcommand = args.subcommand(); let agent_env = create_agent_environment(env, args)?; diff --git a/src/dfx/src/commands/canister/request_status.rs b/src/dfx/src/commands/canister/request_status.rs index b137a53cce..7b71efee56 100644 --- a/src/dfx/src/commands/canister/request_status.rs +++ b/src/dfx/src/commands/canister/request_status.rs @@ -11,19 +11,19 @@ use ic_agent::{AgentError, RequestId}; use std::str::FromStr; use tokio::runtime::Runtime; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("request-status") .about(UserMessage::RequestCallStatus.to_str()) .arg( - Arg::with_name("request_id") + Arg::new("request_id") .takes_value(true) - .help(UserMessage::RequestId.to_str()) + //.help(UserMessage::RequestId.to_str()) .required(true) .validator(validators::is_request_id), ) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let request_id = RequestId::from_str( &args .value_of("request_id") diff --git a/src/dfx/src/commands/canister/set_controller.rs b/src/dfx/src/commands/canister/set_controller.rs index 35b4f65edc..c81d3d6c84 100644 --- a/src/dfx/src/commands/canister/set_controller.rs +++ b/src/dfx/src/commands/canister/set_controller.rs @@ -12,24 +12,24 @@ use ic_utils::call::AsyncCall; use ic_utils::interfaces::ManagementCanister; use tokio::runtime::Runtime; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("set-controller") .about(UserMessage::SetController.to_str()) .arg( - Arg::with_name("canister") + Arg::new("canister") .takes_value(true) - .help(UserMessage::SetControllerCanister.to_str()) + //.help(UserMessage::SetControllerCanister.to_str()) .required(true), ) .arg( - Arg::with_name("new-controller") + Arg::new("new-controller") .takes_value(true) - .help(UserMessage::NewController.to_str()) + //.help(UserMessage::NewController.to_str()) .required(true), ) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let canister = args.value_of("canister").unwrap(); let canister_id = match CanisterId::from_text(canister) { Ok(id) => id, diff --git a/src/dfx/src/commands/canister/start.rs b/src/dfx/src/commands/canister/start.rs index 76e6048c5e..7e6c7e80c2 100644 --- a/src/dfx/src/commands/canister/start.rs +++ b/src/dfx/src/commands/canister/start.rs @@ -13,21 +13,21 @@ use slog::info; use std::time::Duration; use tokio::runtime::Runtime; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("start") .about(UserMessage::StartCanister.to_str()) .arg( - Arg::with_name("canister_name") + Arg::new("canister_name") .takes_value(true) .required_unless("all") - .help(UserMessage::StartCanisterName.to_str()) + //.help(UserMessage::StartCanisterName.to_str()) .required(false), ) .arg( - Arg::with_name("all") + Arg::new("all") .long("all") .required_unless("canister_name") - .help(UserMessage::StartAll.to_str()) + //.help(UserMessage::StartAll.to_str()) .takes_value(false), ) } @@ -58,7 +58,7 @@ async fn start_canister( Ok(()) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; diff --git a/src/dfx/src/commands/canister/status.rs b/src/dfx/src/commands/canister/status.rs index 129d680d8c..7e464e2e57 100644 --- a/src/dfx/src/commands/canister/status.rs +++ b/src/dfx/src/commands/canister/status.rs @@ -13,21 +13,21 @@ use slog::info; use std::time::Duration; use tokio::runtime::Runtime; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("status") .about(UserMessage::CanisterStatus.to_str()) .arg( - Arg::with_name("canister_name") + Arg::new("canister_name") .takes_value(true) .required_unless("all") - .help(UserMessage::StatusCanisterName.to_str()) + //.help(UserMessage::StatusCanisterName.to_str()) .required(false), ) .arg( - Arg::with_name("all") + Arg::new("all") .long("all") .required_unless("canister_name") - .help(UserMessage::StatusAll.to_str()) + //.help(UserMessage::StatusAll.to_str()) .takes_value(false), ) } @@ -52,7 +52,7 @@ async fn canister_status( Ok(()) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; diff --git a/src/dfx/src/commands/canister/stop.rs b/src/dfx/src/commands/canister/stop.rs index 46b8d677d6..0548026cca 100644 --- a/src/dfx/src/commands/canister/stop.rs +++ b/src/dfx/src/commands/canister/stop.rs @@ -13,21 +13,21 @@ use slog::info; use std::time::Duration; use tokio::runtime::Runtime; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("stop") .about(UserMessage::StopCanister.to_str()) .arg( - Arg::with_name("canister_name") + Arg::new("canister_name") .takes_value(true) .required_unless("all") - .help(UserMessage::StopCanisterName.to_str()) + //.help(UserMessage::StopCanisterName.to_str()) .required(false), ) .arg( - Arg::with_name("all") + Arg::new("all") .long("all") .required_unless("canister_name") - .help(UserMessage::StopAll.to_str()) + //.help(UserMessage::StopAll.to_str()) .takes_value(false), ) } @@ -57,7 +57,7 @@ async fn stop_canister( Ok(()) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; diff --git a/src/dfx/src/commands/config.rs b/src/dfx/src/commands/config.rs index 8de258deff..bf9319f968 100644 --- a/src/dfx/src/commands/config.rs +++ b/src/dfx/src/commands/config.rs @@ -5,14 +5,16 @@ use crate::lib::message::UserMessage; use clap::{App, Arg, ArgMatches, SubCommand}; use serde_json::value::Value; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("config") .about(UserMessage::ConfigureOptions.to_str()) - .arg(Arg::with_name("config_path").help(UserMessage::OptionName.to_str())) - .arg(Arg::with_name("value").help(UserMessage::OptionValue.to_str())) + .arg(Arg::new("config_path")) + //.help(UserMessage::OptionName.to_str())) + .arg(Arg::new("value")) + //.help(UserMessage::OptionValue.to_str())) .arg( - Arg::with_name("format") - .help(UserMessage::OptionFormat.to_str()) + Arg::new("format") + //.help(UserMessage::OptionFormat.to_str()) .long("format") .takes_value(true) .default_value("json") @@ -20,7 +22,7 @@ pub fn construct() -> App<'static, 'static> { ) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { // Cannot use the `env` variable as we need a mutable copy. let mut config: Config = env .get_config() diff --git a/src/dfx/src/commands/deploy.rs b/src/dfx/src/commands/deploy.rs index faadeb81fc..2365a43c99 100644 --- a/src/dfx/src/commands/deploy.rs +++ b/src/dfx/src/commands/deploy.rs @@ -6,30 +6,30 @@ use crate::lib::provider::create_agent_environment; use crate::util::expiry_duration; use clap::{App, Arg, ArgMatches, SubCommand}; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("deploy") .about(UserMessage::DeployCanister.to_str()) .arg( - Arg::with_name("canister_name") + Arg::new("canister_name") .takes_value(true) - .help(UserMessage::DeployCanisterName.to_str()) + //.help(UserMessage::DeployCanisterName.to_str()) .required(false), ) .arg( - Arg::with_name("network") - .help(UserMessage::CanisterComputeNetwork.to_str()) + Arg::new("network") + //.help(UserMessage::CanisterComputeNetwork.to_str()) .long("network") .takes_value(true), ) .arg( - Arg::with_name("argument") - .help(UserMessage::ArgumentValue.to_str()) + Arg::new("argument") + //.help(UserMessage::ArgumentValue.to_str()) .long("argument") .takes_value(true), ) .arg( - Arg::with_name("type") - .help(UserMessage::ArgumentType.to_str()) + Arg::new("type") + //.help(UserMessage::ArgumentType.to_str()) .long("type") .takes_value(true) .requires("argument") @@ -37,7 +37,7 @@ pub fn construct() -> App<'static, 'static> { ) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let env = create_agent_environment(env, args)?; let timeout = expiry_duration(); diff --git a/src/dfx/src/commands/identity/list.rs b/src/dfx/src/commands/identity/list.rs index 680280bd3a..6eda8f475e 100644 --- a/src/dfx/src/commands/identity/list.rs +++ b/src/dfx/src/commands/identity/list.rs @@ -5,11 +5,11 @@ use crate::lib::message::UserMessage; use clap::{App, ArgMatches, SubCommand}; use std::io::Write; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("list").about(UserMessage::ListIdentities.to_str()) } -pub fn exec(env: &dyn Environment, _args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { let mgr = IdentityManager::new(env)?; let identities = mgr.get_identity_names()?; let current_identity = mgr.get_selected_identity_name(); diff --git a/src/dfx/src/commands/identity/mod.rs b/src/dfx/src/commands/identity/mod.rs index 49ec291922..63f32c088b 100644 --- a/src/dfx/src/commands/identity/mod.rs +++ b/src/dfx/src/commands/identity/mod.rs @@ -24,13 +24,13 @@ fn builtins() -> Vec { ] } -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("identity") .about(UserMessage::ManageIdentity.to_str()) .subcommands(builtins().into_iter().map(|x| x.get_subcommand().clone())) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let subcommand = args.subcommand(); if let (name, Some(subcommand_args)) = subcommand { diff --git a/src/dfx/src/commands/identity/new.rs b/src/dfx/src/commands/identity/new.rs index e76225d15b..2cbcf36a3f 100644 --- a/src/dfx/src/commands/identity/new.rs +++ b/src/dfx/src/commands/identity/new.rs @@ -5,18 +5,18 @@ use crate::lib::message::UserMessage; use clap::{App, Arg, ArgMatches, SubCommand}; use slog::info; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("new") .about(UserMessage::NewIdentity.to_str()) .arg( - Arg::with_name("identity") - .help("The identity to create.") + Arg::new("identity") + //.help("The identity to create.") .required(true) .takes_value(true), ) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let name = args.value_of("identity").unwrap(); let log = env.get_logger(); diff --git a/src/dfx/src/commands/identity/principal.rs b/src/dfx/src/commands/identity/principal.rs index 80dd3fed09..3b6ae48d25 100644 --- a/src/dfx/src/commands/identity/principal.rs +++ b/src/dfx/src/commands/identity/principal.rs @@ -5,11 +5,11 @@ use crate::lib::message::UserMessage; use clap::{App, ArgMatches, SubCommand}; use ic_agent::Identity; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("get-principal").about(UserMessage::GetPrincipalId.to_str()) } -pub fn exec(env: &dyn Environment, _args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { let identity = IdentityManager::new(env)?.instantiate_selected_identity()?; let principal_id = identity.as_ref().sender()?; println!("{}", principal_id.to_text()); diff --git a/src/dfx/src/commands/identity/remove.rs b/src/dfx/src/commands/identity/remove.rs index e6856c287e..790c8bcc1d 100644 --- a/src/dfx/src/commands/identity/remove.rs +++ b/src/dfx/src/commands/identity/remove.rs @@ -5,18 +5,18 @@ use crate::lib::message::UserMessage; use clap::{App, Arg, ArgMatches, SubCommand}; use slog::info; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("remove") .about(UserMessage::RemoveIdentity.to_str()) .arg( - Arg::with_name("identity") - .help("The identity to remove.") + Arg::new("identity") + //.help("The identity to remove.") .required(true) .takes_value(true), ) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let name = args.value_of("identity").unwrap(); let log = env.get_logger(); diff --git a/src/dfx/src/commands/identity/rename.rs b/src/dfx/src/commands/identity/rename.rs index 23d6638fbc..6f6e4003b1 100644 --- a/src/dfx/src/commands/identity/rename.rs +++ b/src/dfx/src/commands/identity/rename.rs @@ -5,24 +5,24 @@ use crate::lib::message::UserMessage; use clap::{App, Arg, ArgMatches, SubCommand}; use slog::info; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("rename") .about(UserMessage::RenameIdentity.to_str()) .arg( - Arg::with_name("from") - .help("The current name of the identity.") + Arg::new("from") + //.help("The current name of the identity.") .required(true) .takes_value(true), ) .arg( - Arg::with_name("to") - .help("The new name of the identity.") + Arg::new("to") + //.help("The new name of the identity.") .required(true) .takes_value(true), ) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let from = args.value_of("from").unwrap(); let to = args.value_of("to").unwrap(); diff --git a/src/dfx/src/commands/identity/use.rs b/src/dfx/src/commands/identity/use.rs index db3023d98b..21ddbea3dc 100644 --- a/src/dfx/src/commands/identity/use.rs +++ b/src/dfx/src/commands/identity/use.rs @@ -5,18 +5,18 @@ use crate::lib::message::UserMessage; use clap::{App, Arg, ArgMatches, SubCommand}; use slog::info; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("use") .about(UserMessage::UseIdentity.to_str()) .arg( - Arg::with_name("identity") - .help("The identity to use.") + Arg::new("identity") + //.help("The identity to use.") .required(true) .takes_value(true), ) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let identity = args.value_of("identity").unwrap(); let log = env.get_logger(); diff --git a/src/dfx/src/commands/identity/whoami.rs b/src/dfx/src/commands/identity/whoami.rs index d88e72276f..38e469c1e1 100644 --- a/src/dfx/src/commands/identity/whoami.rs +++ b/src/dfx/src/commands/identity/whoami.rs @@ -4,11 +4,11 @@ use crate::lib::identity::identity_manager::IdentityManager; use crate::lib::message::UserMessage; use clap::{App, ArgMatches, SubCommand}; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("whoami").about(UserMessage::ShowIdentity.to_str()) } -pub fn exec(env: &dyn Environment, _args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { let mgr = IdentityManager::new(env)?; let identity = mgr.get_selected_identity_name(); println!("{}", identity); diff --git a/src/dfx/src/commands/language_service.rs b/src/dfx/src/commands/language_service.rs index 1a5276c01a..a432844dd4 100644 --- a/src/dfx/src/commands/language_service.rs +++ b/src/dfx/src/commands/language_service.rs @@ -3,34 +3,41 @@ use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; use crate::lib::message::UserMessage; use crate::lib::package_arguments::{self, PackageArguments}; -use clap::{App, AppSettings, Arg, ArgMatches, SubCommand}; +use clap::{App, AppSettings, Arg, ArgMatches, FromArgMatches, IntoApp}; use std::process::Stdio; const CANISTER_ARG: &str = "canister"; const FORCE_TTY: &str = "force-tty"; -pub fn construct() -> App<'static, 'static> { - SubCommand::with_name("_language-service") +/// Starts the Motoko IDE Language Server. This is meant to be run by editor plugins not the +/// end-user. +#[derive(Clap)] +pub struct LanguageServiceOpts { + /// Specifies the canister name. If you don't specify this argument, all canisters are + /// processed. + canister: Option, + + /// Forces the language server to start even when run from a terminal. + #[clap(long)] + force_tty: bool, +} + +pub fn construct() -> App<'static> { + IntoApp::::into_app() + .name("_language-service") .setting(AppSettings::Hidden) // Hide it from help menus as it shouldn't be used by users. - .about(UserMessage::StartLanguageService.to_str()) - .arg(Arg::with_name(CANISTER_ARG).help(UserMessage::CanisterName.to_str())) - .arg( - Arg::with_name(FORCE_TTY) - .help(UserMessage::ForceTTY.to_str()) - .long(FORCE_TTY) - .takes_value(false), - ) } // Don't read anything from stdin or output anything to stdout while this function is being // executed or LSP will become very unhappy -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { - let force_tty = args.is_present(FORCE_TTY); +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: LanguageServiceOpts = LanguageServiceOpts::from_arg_matches(args); + let force_tty = opts.force_tty; // Are we being run from a terminal? That's most likely not what we want if atty::is(atty::Stream::Stdout) && !force_tty { Err(DfxError::LanguageServerFromATerminal) } else if let Some(config) = env.get_config() { - let main_path = get_main_path(config.get_config(), args)?; + let main_path = get_main_path(config.get_config(), opts.canister)?; let packtool = &config .get_config() .get_defaults() @@ -43,11 +50,14 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { } } -fn get_main_path(config: &ConfigInterface, args: &ArgMatches<'_>) -> Result { +fn get_main_path( + config: &ConfigInterface, + canister_name: Option, +) -> Result { // TODO try and point at the actual dfx.json path let dfx_json = CONFIG_FILE_NAME; - let canister_name: Option<&str> = args.value_of(CANISTER_ARG); + // let canister_name: Option<&str> = args.value_of(CANISTER_ARG); let (canister_name, canister): (String, ConfigCanistersCanister) = match (config.canisters.as_ref(), canister_name) { diff --git a/src/dfx/src/commands/mod.rs b/src/dfx/src/commands/mod.rs index 199bd0eac8..fb6c88d254 100644 --- a/src/dfx/src/commands/mod.rs +++ b/src/dfx/src/commands/mod.rs @@ -17,26 +17,26 @@ mod start; mod stop; mod upgrade; -pub type CliExecFn = fn(&dyn Environment, &ArgMatches<'_>) -> DfxResult; +pub type CliExecFn = fn(&dyn Environment, &ArgMatches) -> DfxResult; pub struct CliCommand { - subcommand: clap::App<'static, 'static>, + subcommand: clap::App<'static>, executor: CliExecFn, } impl CliCommand { - pub fn new(subcommand: clap::App<'static, 'static>, executor: CliExecFn) -> CliCommand { + pub fn new(subcommand: clap::App<'static>, executor: CliExecFn) -> CliCommand { CliCommand { subcommand, executor, } } - pub fn get_subcommand(&self) -> &clap::App<'static, 'static> { + pub fn get_subcommand(&self) -> &clap::App<'static> { &self.subcommand } pub fn get_name(&self) -> &str { self.subcommand.get_name() } - pub fn execute(self: &CliCommand, env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { + pub fn execute(self: &CliCommand, env: &dyn Environment, args: &ArgMatches) -> DfxResult { (self.executor)(env, args) } } diff --git a/src/dfx/src/commands/new.rs b/src/dfx/src/commands/new.rs index e24083aad4..653761ef0d 100644 --- a/src/dfx/src/commands/new.rs +++ b/src/dfx/src/commands/new.rs @@ -63,30 +63,30 @@ pub fn project_name_validator(name: String) -> Result<(), String> { } } -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("new") .about(UserMessage::CreateProject.to_str()) .arg( - Arg::with_name(PROJECT_NAME) - .help(UserMessage::ProjectName.to_str()) + Arg::new(PROJECT_NAME) + //.help(UserMessage::ProjectName.to_str()) .validator(project_name_validator) .required(true), ) .arg( - Arg::with_name(DRY_RUN) - .help(UserMessage::DryRun.to_str()) + Arg::new(DRY_RUN) + //.help(UserMessage::DryRun.to_str()) .long("dry-run") .takes_value(false), ) .arg( - Arg::with_name("frontend") + Arg::new("frontend") .long("--frontend") - .help(UserMessage::NewFrontend.to_str()) + //.help(UserMessage::NewFrontend.to_str()) .takes_value(false) .conflicts_with("no-frontend"), ) .arg( - Arg::with_name("no-frontend") + Arg::new("no-frontend") .long("--no-frontend") .hidden(true) .takes_value(false) @@ -323,7 +323,7 @@ fn scaffold_frontend_code( Ok(()) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let log = env.get_logger(); let dry_run = args.is_present(DRY_RUN); let project_name_path = args diff --git a/src/dfx/src/commands/ping.rs b/src/dfx/src/commands/ping.rs index d76f38cee8..5e120a8eb4 100644 --- a/src/dfx/src/commands/ping.rs +++ b/src/dfx/src/commands/ping.rs @@ -8,17 +8,17 @@ use crate::util::expiry_duration; use clap::{App, Arg, ArgMatches, SubCommand}; use tokio::runtime::Runtime; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("ping") .about(UserMessage::Ping.to_str()) .arg( - Arg::with_name("network") - .help("The provider to use.") + Arg::new("network") + //.help("The provider to use.") .takes_value(true), ) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { env.get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; diff --git a/src/dfx/src/commands/replica.rs b/src/dfx/src/commands/replica.rs index 909a5d7d0a..4f49723303 100644 --- a/src/dfx/src/commands/replica.rs +++ b/src/dfx/src/commands/replica.rs @@ -12,25 +12,25 @@ use clap::{App, Arg, ArgMatches, SubCommand}; use std::default::Default; /// Constructs a sub-command to run the Internet Computer replica. -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("replica") .about(UserMessage::Replica.to_str()) .arg( - Arg::with_name("message-gas-limit") - .help(UserMessage::ReplicaMessageGasLimit.to_str()) + Arg::new("message-gas-limit") + //.help(UserMessage::ReplicaMessageGasLimit.to_str()) .hidden(true) .long("message-gas-limit") .takes_value(true), ) .arg( - Arg::with_name("port") - .help(UserMessage::ReplicaPort.to_str()) + Arg::new("port") + //.help(UserMessage::ReplicaPort.to_str()) .long("port") .takes_value(true), ) .arg( - Arg::with_name("round-gas-limit") - .help(UserMessage::ReplicaRoundGasLimit.to_str()) + Arg::new("round-gas-limit") + //.help(UserMessage::ReplicaRoundGasLimit.to_str()) .hidden(true) .long("round-gas-limit") .takes_value(true), @@ -38,7 +38,7 @@ pub fn construct() -> App<'static, 'static> { } /// Gets the configuration options for the Internet Computer replica. -fn get_config(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +fn get_config(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let config = get_config_from_file(env); let port = get_port(&config, args)?; let mut http_handler: HttpHandlerConfig = Default::default(); @@ -79,7 +79,7 @@ fn get_config_from_file(env: &dyn Environment) -> ConfigDefaultsReplica { /// Gets the port number that the Internet Computer replica listens on. First checks if the port /// number was specified on the command-line using --port, otherwise checks if the port number was /// specified in the dfx configuration file, otherise defaults to 8080. -fn get_port(config: &ConfigDefaultsReplica, args: &ArgMatches<'_>) -> DfxResult { +fn get_port(config: &ConfigDefaultsReplica, args: &ArgMatches) -> DfxResult { args.value_of("port") .map(|port| port.parse()) .unwrap_or_else(|| { @@ -92,7 +92,7 @@ fn get_port(config: &ConfigDefaultsReplica, args: &ArgMatches<'_>) -> DfxResult< /// Gets the maximum amount of gas a single message can consume. First checks if the gas limit was /// specified on the command-line using --message-gas-limit, otherwise checks if the gas limit was /// specified in the dfx configuration file, otherise defaults to 5368709120. -fn get_message_gas_limit(config: &ConfigDefaultsReplica, args: &ArgMatches<'_>) -> DfxResult { +fn get_message_gas_limit(config: &ConfigDefaultsReplica, args: &ArgMatches) -> DfxResult { args.value_of("message-gas-limit") .map(|limit| limit.parse()) .unwrap_or_else(|| { @@ -105,7 +105,7 @@ fn get_message_gas_limit(config: &ConfigDefaultsReplica, args: &ArgMatches<'_>) /// Gets the maximum amount of gas a single round can consume. First checks if the gas limit was /// specified on the command-line using --round-gas-limit, otherwise checks if the gas limit was /// specified in the dfx configuration file, otherise defaults to 26843545600. -fn get_round_gas_limit(config: &ConfigDefaultsReplica, args: &ArgMatches<'_>) -> DfxResult { +fn get_round_gas_limit(config: &ConfigDefaultsReplica, args: &ArgMatches) -> DfxResult { args.value_of("round-gas-limit") .map(|limit| limit.parse()) .unwrap_or_else(|| { @@ -118,7 +118,7 @@ fn get_round_gas_limit(config: &ConfigDefaultsReplica, args: &ArgMatches<'_>) -> /// Start the Internet Computer locally. Spawns a proxy to forward and /// manage browser requests. Responsible for running the network (one /// replica at the moment) and the proxy. -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let replica_pathbuf = env.get_cache().get_binary_command_path("replica")?; let ic_starter_pathbuf = env.get_cache().get_binary_command_path("ic-starter")?; diff --git a/src/dfx/src/commands/start.rs b/src/dfx/src/commands/start.rs index dc620ed82c..85a734e1b1 100644 --- a/src/dfx/src/commands/start.rs +++ b/src/dfx/src/commands/start.rs @@ -26,24 +26,24 @@ use tokio::runtime::Runtime; /// Provide necessary arguments to start the Internet Computer /// locally. See `exec` for further information. -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("start") .about(UserMessage::StartNode.to_str()) .arg( - Arg::with_name("host") - .help(UserMessage::NodeAddress.to_str()) + Arg::new("host") + //.help(UserMessage::NodeAddress.to_str()) .long("host") .takes_value(true), ) .arg( - Arg::with_name("background") - .help(UserMessage::StartBackground.to_str()) + Arg::new("background") + //.help(UserMessage::StartBackground.to_str()) .long("background") .takes_value(false), ) .arg( - Arg::with_name("clean") - .help(UserMessage::CleanState.to_str()) + Arg::new("clean") + //.help(UserMessage::CleanState.to_str()) .long("clean") .takes_value(false), ) @@ -112,7 +112,7 @@ fn fg_ping_and_wait(webserver_port_path: PathBuf, frontend_url: String) -> DfxRe /// Start the Internet Computer locally. Spawns a proxy to forward and /// manage browser requests. Responsible for running the network (one /// replica at the moment) and the proxy. -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; @@ -257,7 +257,7 @@ fn send_background() -> DfxResult<()> { Ok(()) } -fn frontend_address(args: &ArgMatches<'_>, config: &Config) -> DfxResult<(String, SocketAddr)> { +fn frontend_address(args: &ArgMatches, config: &Config) -> DfxResult<(String, SocketAddr)> { let mut address_and_port = args .value_of("host") .and_then(|host| Option::from(host.parse())) diff --git a/src/dfx/src/commands/stop.rs b/src/dfx/src/commands/stop.rs index a9f3c3f48c..20b0f6dd9e 100644 --- a/src/dfx/src/commands/stop.rs +++ b/src/dfx/src/commands/stop.rs @@ -4,7 +4,7 @@ use crate::lib::message::UserMessage; use clap::{App, ArgMatches, SubCommand}; use sysinfo::{Pid, Process, ProcessExt, Signal, System, SystemExt}; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("stop").about(UserMessage::StopNode.to_str()) } @@ -35,7 +35,7 @@ fn kill_all(pid: Pid) -> DfxResult { Ok(()) } -pub fn exec(env: &dyn Environment, _args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { let pid_file_path = env.get_temp_dir().join("pid"); if pid_file_path.exists() { // Read and verify it's not running. If it is just return. diff --git a/src/dfx/src/commands/upgrade.rs b/src/dfx/src/commands/upgrade.rs index 5774d7699f..5e85305e0d 100644 --- a/src/dfx/src/commands/upgrade.rs +++ b/src/dfx/src/commands/upgrade.rs @@ -8,25 +8,25 @@ use serde::{Deserialize, Deserializer}; use std::{collections::BTreeMap, env, fs, os::unix::fs::PermissionsExt}; use tar::Archive; -pub fn construct() -> App<'static, 'static> { +pub fn construct() -> App<'static> { SubCommand::with_name("upgrade") .about("Upgrade DFX.") .arg( - Arg::with_name("current-version") + Arg::new("current-version") .hidden(true) .long("current-version") .takes_value(true), ) .arg( - Arg::with_name("release-root") + Arg::new("release-root") .default_value("https://sdk.dfinity.org") .hidden(true) .long("release-root") .takes_value(true), ) .arg( - Arg::with_name("verbose") - .help("Verbose output.") + Arg::new("verbose") + //.help("Verbose output.") .long("verbose"), ) } @@ -154,7 +154,7 @@ fn get_latest_release(release_root: &str, version: &Version, arch: &str) -> DfxR Ok(()) } -pub fn exec(env: &dyn Environment, args: &ArgMatches<'_>) -> DfxResult { +pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { // Find OS architecture. let os_arch = match std::env::consts::OS { "linux" => "x86_64-linux", diff --git a/src/dfx/src/lib/provider.rs b/src/dfx/src/lib/provider.rs index 9e59a322e9..987415bb58 100644 --- a/src/dfx/src/lib/provider.rs +++ b/src/dfx/src/lib/provider.rs @@ -12,7 +12,7 @@ lazy_static! { static ref NETWORK_CONTEXT: Arc>> = Arc::new(RwLock::new(None)); } -fn set_network_context(args: &ArgMatches<'_>) { +fn set_network_context(args: &ArgMatches) { let name = args.value_of("network").unwrap_or("local").to_string(); let mut n = NETWORK_CONTEXT.write().unwrap(); @@ -30,7 +30,7 @@ pub fn get_network_context() -> DfxResult { // always returns at least one url pub fn get_network_descriptor<'a>( env: &'a (dyn Environment + 'a), - args: &ArgMatches<'_>, + args: &ArgMatches, ) -> DfxResult { set_network_context(args); let config = env @@ -78,7 +78,7 @@ pub fn get_network_descriptor<'a>( pub fn create_agent_environment<'a>( env: &'a (dyn Environment + 'a), - args: &ArgMatches<'_>, + args: &ArgMatches, ) -> DfxResult> { let network_descriptor = get_network_descriptor(env, args)?; let timeout = expiry_duration(); diff --git a/src/dfx/src/main.rs b/src/dfx/src/main.rs index 7ba703f1a0..41340af40d 100644 --- a/src/dfx/src/main.rs +++ b/src/dfx/src/main.rs @@ -12,38 +12,38 @@ mod config; mod lib; mod util; -fn cli(_: &impl Environment) -> App<'_, '_> { +fn cli(_: &impl Environment) -> App<'_> { App::new("dfx") .about("The DFINITY Executor.") .version(dfx_version_str()) .global_setting(AppSettings::ColoredHelp) .arg( - Arg::with_name("verbose") + Arg::new("verbose") .long("verbose") .short("v") .multiple(true), ) .arg( - Arg::with_name("quiet") + Arg::new("quiet") .long("quiet") .short("q") .multiple(true), ) .arg( - Arg::with_name("logmode") + Arg::new("logmode") .long("log") .takes_value(true) .possible_values(&["stderr", "tee", "file"]) .default_value("stderr"), ) .arg( - Arg::with_name("logfile") + Arg::new("logfile") .long("log-file") .long("logfile") .takes_value(true), ) .arg( - Arg::with_name("identity") + Arg::new("identity") .long("identity") .takes_value(true), ) @@ -54,7 +54,7 @@ fn cli(_: &impl Environment) -> App<'_, '_> { ) } -fn exec(env: &impl Environment, args: &clap::ArgMatches<'_>, cli: &App<'_, '_>) -> DfxResult { +fn exec(env: &impl Environment, args: &clap::ArgMatches, cli: &App<'_>) -> DfxResult { let (name, subcommand_args) = match args.subcommand() { (name, Some(args)) => (name, args), _ => { @@ -129,7 +129,7 @@ fn maybe_redirect_dfx(env: &impl Environment) -> Option<()> { /// Setup a logger with the proper configuration, based on arguments. /// Returns a topple of whether or not to have a progress bar, and a logger. -fn setup_logging(matches: &ArgMatches<'_>) -> (bool, slog::Logger) { +fn setup_logging(matches: &ArgMatches) -> (bool, slog::Logger) { // Create a logger with our argument matches. let level = matches.occurrences_of("verbose") as i64 - matches.occurrences_of("quiet") as i64; From 01226294859dc0e0e5131ff15beb9674fcd19293 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Thu, 29 Oct 2020 10:53:50 -0700 Subject: [PATCH 02/26] lang service fixes --- src/dfx/src/commands/language_service.rs | 55 ++++++++++++------------ 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/src/dfx/src/commands/language_service.rs b/src/dfx/src/commands/language_service.rs index a432844dd4..a09e05547b 100644 --- a/src/dfx/src/commands/language_service.rs +++ b/src/dfx/src/commands/language_service.rs @@ -1,9 +1,8 @@ use crate::config::dfinity::{ConfigCanistersCanister, ConfigInterface, CONFIG_FILE_NAME}; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use crate::lib::package_arguments::{self, PackageArguments}; -use clap::{App, AppSettings, Arg, ArgMatches, FromArgMatches, IntoApp}; +use clap::{App, AppSettings, ArgMatches, Clap, FromArgMatches, IntoApp}; use std::process::Stdio; const CANISTER_ARG: &str = "canister"; @@ -23,7 +22,7 @@ pub struct LanguageServiceOpts { } pub fn construct() -> App<'static> { - IntoApp::::into_app() + LanguageServiceOpts::into_app() .name("_language-service") .setting(AppSettings::Hidden) // Hide it from help menus as it shouldn't be used by users. } @@ -57,36 +56,36 @@ fn get_main_path( // TODO try and point at the actual dfx.json path let dfx_json = CONFIG_FILE_NAME; - // let canister_name: Option<&str> = args.value_of(CANISTER_ARG); + let (canister_name, canister): (String, ConfigCanistersCanister) = match ( + config.canisters.as_ref(), + canister_name.and_then(|v| Some(v.as_str())), + ) { + (None, _) => Err(DfxError::InvalidData(format!( + "Missing field 'canisters' in {0}", + dfx_json + ))), - let (canister_name, canister): (String, ConfigCanistersCanister) = - match (config.canisters.as_ref(), canister_name) { - (None, _) => Err(DfxError::InvalidData(format!( - "Missing field 'canisters' in {0}", - dfx_json - ))), - - (Some(canisters), Some(cn)) => { - let c = canisters.get(cn).ok_or_else(|| { - DfxError::InvalidArgument(format!( - "Canister {0} cannot not be found in {1}", - cn, dfx_json - )) - })?; - Ok((cn.to_string(), c.clone())) - } - (Some(canisters), None) => { - if canisters.len() == 1 { - let (n, c) = canisters.iter().next().unwrap(); - Ok((n.to_string(), c.clone())) - } else { - Err(DfxError::InvalidData(format!( + (Some(canisters), Some(cn)) => { + let c = canisters.get(cn).ok_or_else(|| { + DfxError::InvalidArgument(format!( + "Canister {0} cannot not be found in {1}", + cn, dfx_json + )) + })?; + Ok((cn.to_string(), c.clone())) + } + (Some(canisters), None) => { + if canisters.len() == 1 { + let (n, c) = canisters.iter().next().unwrap(); + Ok((n.to_string(), c.clone())) + } else { + Err(DfxError::InvalidData(format!( "There are multiple canisters in {0}, please select one using the {1} argument", dfx_json, CANISTER_ARG ))) - } } - }?; + } + }?; canister .extras From 2fdf267138ee148a9755aa8b66bb7de6516eabd0 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Thu, 29 Oct 2020 11:02:10 -0700 Subject: [PATCH 03/26] ping --- src/dfx/src/commands/ping.rs | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/dfx/src/commands/ping.rs b/src/dfx/src/commands/ping.rs index 5e120a8eb4..5fbaa8cf83 100644 --- a/src/dfx/src/commands/ping.rs +++ b/src/dfx/src/commands/ping.rs @@ -1,23 +1,35 @@ use crate::config::dfinity::NetworkType; use crate::lib::environment::{AgentEnvironment, Environment}; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use crate::lib::network::network_descriptor::NetworkDescriptor; use crate::lib::provider::{command_line_provider_to_url, get_network_descriptor}; use crate::util::expiry_duration; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, AppSettings, Arg, ArgMatches, Clap, FromArgMatches, IntoApp}; use tokio::runtime::Runtime; + +/// Pings an Internet Computer network and returns its status. +#[derive(Clap)] +pub struct PingOpts { + /// The provider to use. + network: Option, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("ping") - .about(UserMessage::Ping.to_str()) - .arg( - Arg::new("network") - //.help("The provider to use.") - .takes_value(true), - ) + PingOpts::into_app() + .name("ping") } +// pub fn construct() -> App<'static> { +// SubCommand::with_name("ping") +// .about(UserMessage::Ping.to_str()) +// .arg( +// Arg::new("network") +// //.help("The provider to use.") +// .takes_value(true), +// ) +// } + pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { env.get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; From eb49632aa629f842af5f2c2eec567384906e07ea Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Thu, 29 Oct 2020 11:02:26 -0700 Subject: [PATCH 04/26] ping --- src/dfx/src/lib/message.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/dfx/src/lib/message.rs b/src/dfx/src/lib/message.rs index 30f976b4fe..c2222bdcde 100644 --- a/src/dfx/src/lib/message.rs +++ b/src/dfx/src/lib/message.rs @@ -140,9 +140,6 @@ user_message!( DryRun => "Provides a preview the directories and files to be created without adding them to the file system.", NewFrontend => "Installs the frontend code example for the default canister. This defaults to true if Node is installed, or false if it isn't.", - // dfx ping - Ping => "Pings an Internet Computer network and returns its status.", - // dfx replica Replica => "Starts a local Internet Computer replica.", ReplicaMessageGasLimit => "Specifies the maximum number of cycles a single message can consume.", From 283277fd53379943c3d119416c9c69c4297cab48 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Thu, 29 Oct 2020 12:31:19 -0700 Subject: [PATCH 05/26] ping upgrade provider --- src/dfx/src/commands/ping.rs | 15 +++-------- src/dfx/src/commands/upgrade.rs | 45 ++++++++++++++++----------------- src/dfx/src/lib/provider.rs | 11 ++++---- 3 files changed, 31 insertions(+), 40 deletions(-) diff --git a/src/dfx/src/commands/ping.rs b/src/dfx/src/commands/ping.rs index 5fbaa8cf83..3ee012a68c 100644 --- a/src/dfx/src/commands/ping.rs +++ b/src/dfx/src/commands/ping.rs @@ -4,7 +4,7 @@ use crate::lib::error::{DfxError, DfxResult}; use crate::lib::network::network_descriptor::NetworkDescriptor; use crate::lib::provider::{command_line_provider_to_url, get_network_descriptor}; use crate::util::expiry_duration; -use clap::{App, AppSettings, Arg, ArgMatches, Clap, FromArgMatches, IntoApp}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use tokio::runtime::Runtime; @@ -20,24 +20,15 @@ pub fn construct() -> App<'static> { .name("ping") } -// pub fn construct() -> App<'static> { -// SubCommand::with_name("ping") -// .about(UserMessage::Ping.to_str()) -// .arg( -// Arg::new("network") -// //.help("The provider to use.") -// .takes_value(true), -// ) -// } - pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: PingOpts = PingOpts::from_arg_matches(args); env.get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; // For ping, "provider" could either be a URL or a network name. // If not passed, we default to the "local" network. let network_descriptor = - get_network_descriptor(env, args).or_else::(|err| match err { + get_network_descriptor(env, opts.network).or_else::(|err| match err { DfxError::ComputeNetworkNotFound(network_name) => { let url = command_line_provider_to_url(&network_name)?; let network_descriptor = NetworkDescriptor { diff --git a/src/dfx/src/commands/upgrade.rs b/src/dfx/src/commands/upgrade.rs index 5e85305e0d..d41fa9ace9 100644 --- a/src/dfx/src/commands/upgrade.rs +++ b/src/dfx/src/commands/upgrade.rs @@ -1,6 +1,6 @@ use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, AppSettings, Arg, ArgMatches, Clap, FromArgMatches, IntoApp}; use indicatif::{ProgressBar, ProgressDrawTarget}; use libflate::gzip::Decoder; use semver::Version; @@ -8,27 +8,25 @@ use serde::{Deserialize, Deserializer}; use std::{collections::BTreeMap, env, fs, os::unix::fs::PermissionsExt}; use tar::Archive; +/// Upgrade DFX. +#[derive(Clap)] +pub struct UpgradeOpts { + /// Current Version. + #[clap(long)] + current_version: Option, + + // hidden + #[clap(long, default_value = "https://sdk.dfinity.org")] + release_root: String, + + /// Verbose output. + #[clap(long)] + verbose: bool, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("upgrade") - .about("Upgrade DFX.") - .arg( - Arg::new("current-version") - .hidden(true) - .long("current-version") - .takes_value(true), - ) - .arg( - Arg::new("release-root") - .default_value("https://sdk.dfinity.org") - .hidden(true) - .long("release-root") - .takes_value(true), - ) - .arg( - Arg::new("verbose") - //.help("Verbose output.") - .long("verbose"), - ) + UpgradeOpts::into_app() + .name("upgrade") } fn parse_semver<'de, D>(version: &str) -> Result @@ -155,20 +153,21 @@ fn get_latest_release(release_root: &str, version: &Version, arch: &str) -> DfxR } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: UpgradeOpts = UpgradeOpts::from_arg_matches(args); // Find OS architecture. let os_arch = match std::env::consts::OS { "linux" => "x86_64-linux", "macos" => "x86_64-darwin", _ => panic!("Not supported architecture"), }; - let current_version = if let Some(version) = args.value_of("current-version") { + let current_version = if let Some(version) = opts.current_version.and_then(|v| Some(v.as_str())) { Version::parse(version)? } else { env.get_version().clone() }; println!("Current version: {}", current_version); - let release_root = args.value_of("release-root").unwrap(); + let release_root = opts.release_root.as_str(); let latest_version = get_latest_version(release_root, None)?; if latest_version > current_version { diff --git a/src/dfx/src/lib/provider.rs b/src/dfx/src/lib/provider.rs index 987415bb58..66c60a8aee 100644 --- a/src/dfx/src/lib/provider.rs +++ b/src/dfx/src/lib/provider.rs @@ -12,8 +12,8 @@ lazy_static! { static ref NETWORK_CONTEXT: Arc>> = Arc::new(RwLock::new(None)); } -fn set_network_context(args: &ArgMatches) { - let name = args.value_of("network").unwrap_or("local").to_string(); +fn set_network_context(network: Option) { + let name = network.unwrap_or("local".to_string()).to_string(); let mut n = NETWORK_CONTEXT.write().unwrap(); *n = Some(name); @@ -30,9 +30,9 @@ pub fn get_network_context() -> DfxResult { // always returns at least one url pub fn get_network_descriptor<'a>( env: &'a (dyn Environment + 'a), - args: &ArgMatches, + network: Option, ) -> DfxResult { - set_network_context(args); + set_network_context(network); let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; @@ -80,7 +80,8 @@ pub fn create_agent_environment<'a>( env: &'a (dyn Environment + 'a), args: &ArgMatches, ) -> DfxResult> { - let network_descriptor = get_network_descriptor(env, args)?; + let network = args.value_of("network").and_then(|v| Some(v.to_string())); + let network_descriptor = get_network_descriptor(env, network)?; let timeout = expiry_duration(); AgentEnvironment::new(env, network_descriptor, timeout) } From 13df6b951b88de240d4264965c3be262c227884c Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Thu, 29 Oct 2020 12:37:55 -0700 Subject: [PATCH 06/26] stop --- src/dfx/src/commands/stop.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/dfx/src/commands/stop.rs b/src/dfx/src/commands/stop.rs index 20b0f6dd9e..346884ffeb 100644 --- a/src/dfx/src/commands/stop.rs +++ b/src/dfx/src/commands/stop.rs @@ -1,11 +1,16 @@ use crate::lib::environment::Environment; use crate::lib::error::DfxResult; -use crate::lib::message::UserMessage; -use clap::{App, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, IntoApp}; use sysinfo::{Pid, Process, ProcessExt, Signal, System, SystemExt}; +/// Stops the local network replica. +#[derive(Clap)] +pub struct StopOpts { +} + pub fn construct() -> App<'static> { - SubCommand::with_name("stop").about(UserMessage::StopNode.to_str()) + StopOpts::into_app() + .name("stop") } fn list_all_descendants(pid: Pid) -> Vec { From 19f6578b2098a4bf19f700618c5537003dcadbef Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Thu, 29 Oct 2020 13:15:39 -0700 Subject: [PATCH 07/26] command start --- src/dfx/src/commands/start.rs | 58 ++++++++++++++++------------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/src/dfx/src/commands/start.rs b/src/dfx/src/commands/start.rs index 85a734e1b1..573c3e2456 100644 --- a/src/dfx/src/commands/start.rs +++ b/src/dfx/src/commands/start.rs @@ -6,14 +6,13 @@ use crate::actors::shutdown_controller::ShutdownController; use crate::config::dfinity::Config; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use crate::lib::network::network_descriptor::NetworkDescriptor; use crate::lib::provider::get_network_descriptor; use crate::lib::replica_config::ReplicaConfig; use crate::util::get_reusable_socket_addr; use actix::{Actor, Addr}; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use delay::{Delay, Waiter}; use ic_agent::Agent; use std::fs; @@ -24,29 +23,25 @@ use std::process::Command; use sysinfo::{System, SystemExt}; use tokio::runtime::Runtime; -/// Provide necessary arguments to start the Internet Computer -/// locally. See `exec` for further information. +/// Starts the local replica and a web server for the current project. +#[derive(Clap)] +pub struct StartOpts { + /// Specifies the host name and port number to bind the frontend to. + #[clap(long)] + host: Option, + + /// Exits the dfx leaving the replica running. Will wait until the replica replies before exiting. + #[clap(long)] + background: bool, + + /// Cleans the state of the current project. + #[clap(long)] + clean: bool, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("start") - .about(UserMessage::StartNode.to_str()) - .arg( - Arg::new("host") - //.help(UserMessage::NodeAddress.to_str()) - .long("host") - .takes_value(true), - ) - .arg( - Arg::new("background") - //.help(UserMessage::StartBackground.to_str()) - .long("background") - .takes_value(false), - ) - .arg( - Arg::new("clean") - //.help(UserMessage::CleanState.to_str()) - .long("clean") - .takes_value(false), - ) + StartOpts::into_app() + .name("start") } fn ping_and_wait(frontend_url: &str) -> DfxResult { @@ -113,11 +108,12 @@ fn fg_ping_and_wait(webserver_port_path: PathBuf, frontend_url: String) -> DfxRe /// manage browser requests. Responsible for running the network (one /// replica at the moment) and the proxy. pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: StartOpts = StartOpts::from_arg_matches(args); let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; - let network_descriptor = get_network_descriptor(env, args)?; + let network_descriptor = get_network_descriptor(env, None)?; let temp_dir = env.get_temp_dir(); let build_output_root = temp_dir.join(&network_descriptor.name).join("canisters"); @@ -136,9 +132,10 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { std::fs::write(&pid_file_path, "")?; // make sure we can write to this file std::fs::write(&webserver_port_path, "")?; - let (frontend_url, address_and_port) = frontend_address(args, &config)?; + let background = opts.background; + let (frontend_url, address_and_port) = frontend_address(opts.host, &config, background)?; - if args.is_present("background") { + if background { send_background()?; return fg_ping_and_wait(webserver_port_path, frontend_url); } @@ -257,9 +254,8 @@ fn send_background() -> DfxResult<()> { Ok(()) } -fn frontend_address(args: &ArgMatches, config: &Config) -> DfxResult<(String, SocketAddr)> { - let mut address_and_port = args - .value_of("host") +fn frontend_address(host: Option, config: &Config, background: bool) -> DfxResult<(String, SocketAddr)> { + let mut address_and_port = host .and_then(|host| Option::from(host.parse())) .unwrap_or_else(|| { Ok(config @@ -269,7 +265,7 @@ fn frontend_address(args: &ArgMatches, config: &Config) -> DfxResult<(String, So }) .map_err(|e| DfxError::InvalidArgument(format!("Invalid host: {}", e)))?; - if !args.is_present("background") { + if !background { // Since the user may have provided port "0", we need to grab a dynamically // allocated port and construct a resuable SocketAddr which the actix // HttpServer will bind to From 928c935d6d6381b614b5d6a2a43ef3efc09b9e7c Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Thu, 29 Oct 2020 13:16:59 -0700 Subject: [PATCH 08/26] command start --- src/dfx/src/commands/start.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dfx/src/commands/start.rs b/src/dfx/src/commands/start.rs index 573c3e2456..2c45ea612d 100644 --- a/src/dfx/src/commands/start.rs +++ b/src/dfx/src/commands/start.rs @@ -125,7 +125,7 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { // As we know no start process is running in this project, we can // clean up the state if it is necessary. - if args.is_present("clean") { + if opts.clean { clean_state(temp_dir, &state_root)?; } From 7c2b465cd173207e82c828251b7be19415b84ce7 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Thu, 29 Oct 2020 16:51:47 -0700 Subject: [PATCH 09/26] replica --- src/dfx/src/commands/replica.rs | 80 ++++++++++++++++----------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/dfx/src/commands/replica.rs b/src/dfx/src/commands/replica.rs index 4f49723303..0c6957daa0 100644 --- a/src/dfx/src/commands/replica.rs +++ b/src/dfx/src/commands/replica.rs @@ -1,46 +1,40 @@ use crate::actors; +use crate::actors::shutdown_controller; +use crate::actors::shutdown_controller::ShutdownController; use crate::config::dfinity::ConfigDefaultsReplica; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use crate::lib::replica_config::{HttpHandlerConfig, ReplicaConfig, SchedulerConfig}; - -use crate::actors::shutdown_controller; -use crate::actors::shutdown_controller::ShutdownController; use actix::Actor; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use std::default::Default; -/// Constructs a sub-command to run the Internet Computer replica. +/// Starts a local Internet Computer replica. +#[derive(Clap)] +pub struct ReplicaOpts { + /// Specifies the maximum number of cycles a single message can consume. + // hidden + #[clap(long)] + message_gas_limit: Option, + + /// Specifies the port the local replica should listen to. + #[clap(long)] + port: Option, + + /// Specifies the maximum number of cycles a single round can consume. + // hidden + #[clap(long)] + round_gas_limit: Option, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("replica") - .about(UserMessage::Replica.to_str()) - .arg( - Arg::new("message-gas-limit") - //.help(UserMessage::ReplicaMessageGasLimit.to_str()) - .hidden(true) - .long("message-gas-limit") - .takes_value(true), - ) - .arg( - Arg::new("port") - //.help(UserMessage::ReplicaPort.to_str()) - .long("port") - .takes_value(true), - ) - .arg( - Arg::new("round-gas-limit") - //.help(UserMessage::ReplicaRoundGasLimit.to_str()) - .hidden(true) - .long("round-gas-limit") - .takes_value(true), - ) + ReplicaOpts::into_app().name("replica") } /// Gets the configuration options for the Internet Computer replica. -fn get_config(env: &dyn Environment, args: &ArgMatches) -> DfxResult { +fn get_config(env: &dyn Environment, opts: ReplicaOpts) -> DfxResult { let config = get_config_from_file(env); - let port = get_port(&config, args)?; + let port = get_port(&config, opts.port)?; let mut http_handler: HttpHandlerConfig = Default::default(); if port == 0 { let config_dir = env.get_temp_dir().join("config"); @@ -50,8 +44,8 @@ fn get_config(env: &dyn Environment, args: &ArgMatches) -> DfxResult ConfigDefaultsReplica { /// Gets the port number that the Internet Computer replica listens on. First checks if the port /// number was specified on the command-line using --port, otherwise checks if the port number was /// specified in the dfx configuration file, otherise defaults to 8080. -fn get_port(config: &ConfigDefaultsReplica, args: &ArgMatches) -> DfxResult { - args.value_of("port") - .map(|port| port.parse()) +fn get_port(config: &ConfigDefaultsReplica, port: Option) -> DfxResult { + port.map(|port| port.parse()) .unwrap_or_else(|| { let default = 8080; Ok(config.port.unwrap_or(default)) @@ -92,8 +85,11 @@ fn get_port(config: &ConfigDefaultsReplica, args: &ArgMatches) -> DfxResult /// Gets the maximum amount of gas a single message can consume. First checks if the gas limit was /// specified on the command-line using --message-gas-limit, otherwise checks if the gas limit was /// specified in the dfx configuration file, otherise defaults to 5368709120. -fn get_message_gas_limit(config: &ConfigDefaultsReplica, args: &ArgMatches) -> DfxResult { - args.value_of("message-gas-limit") +fn get_message_gas_limit( + config: &ConfigDefaultsReplica, + message_gas_limit: Option, +) -> DfxResult { + message_gas_limit .map(|limit| limit.parse()) .unwrap_or_else(|| { let default = 5_368_709_120; @@ -105,8 +101,11 @@ fn get_message_gas_limit(config: &ConfigDefaultsReplica, args: &ArgMatches) -> D /// Gets the maximum amount of gas a single round can consume. First checks if the gas limit was /// specified on the command-line using --round-gas-limit, otherwise checks if the gas limit was /// specified in the dfx configuration file, otherise defaults to 26843545600. -fn get_round_gas_limit(config: &ConfigDefaultsReplica, args: &ArgMatches) -> DfxResult { - args.value_of("round-gas-limit") +fn get_round_gas_limit( + config: &ConfigDefaultsReplica, + round_gas_limit: Option, +) -> DfxResult { + round_gas_limit .map(|limit| limit.parse()) .unwrap_or_else(|| { let default = 26_843_545_600; @@ -119,11 +118,12 @@ fn get_round_gas_limit(config: &ConfigDefaultsReplica, args: &ArgMatches) -> Dfx /// manage browser requests. Responsible for running the network (one /// replica at the moment) and the proxy. pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: ReplicaOpts = ReplicaOpts::from_arg_matches(args); let replica_pathbuf = env.get_cache().get_binary_command_path("replica")?; let ic_starter_pathbuf = env.get_cache().get_binary_command_path("ic-starter")?; let system = actix::System::new("dfx-replica"); - let config = get_config(env, args)?; + let config = get_config(env, opts)?; let shutdown_controller = ShutdownController::new(shutdown_controller::Config { logger: Some(env.get_logger().clone()), From 812d127743dc0aa1889bfe261213aae5a08e8dd4 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Thu, 29 Oct 2020 20:26:15 -0700 Subject: [PATCH 10/26] new ping start stop upgrade --- src/dfx/src/commands/new.rs | 104 +++++++++++++++----------------- src/dfx/src/commands/ping.rs | 4 +- src/dfx/src/commands/start.rs | 9 ++- src/dfx/src/commands/stop.rs | 6 +- src/dfx/src/commands/upgrade.rs | 6 +- src/dfx/src/lib/message.rs | 11 ---- 6 files changed, 59 insertions(+), 81 deletions(-) diff --git a/src/dfx/src/commands/new.rs b/src/dfx/src/commands/new.rs index 653761ef0d..b309261a1c 100644 --- a/src/dfx/src/commands/new.rs +++ b/src/dfx/src/commands/new.rs @@ -3,9 +3,8 @@ use crate::config::dfinity::CONFIG_FILE_NAME; use crate::config::dfx_version_str; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use crate::util::assets; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use console::{style, Style}; use indicatif::HumanBytes; use lazy_static::lazy_static; @@ -34,7 +33,7 @@ lazy_static! { /// Validate a String can be a valid project name. /// A project name is valid if it starts with a letter, and is alphanumeric (with hyphens). /// It cannot end with a dash. -pub fn project_name_validator(name: String) -> Result<(), String> { +pub fn project_name_validator(name: &str) -> Result<(), String> { let mut chars = name.chars(); // Check first character first. If there's no first character it's empty. if let Some(first) = chars.next() { @@ -63,35 +62,28 @@ pub fn project_name_validator(name: String) -> Result<(), String> { } } +/// Creates a new project. +#[derive(Clap)] +pub struct NewOpts { + /// Specifies the name of the project to create. + #[clap(long, validator(project_name_validator))] + project_name: String, + + /// Provides a preview the directories and files to be created without adding them to the file system. + #[clap(long)] + dry_run: bool, + + /// Installs the frontend code example for the default canister. This defaults to true if Node is installed, or false if it isn't. + #[clap(long, conflicts_with("no_frontend"))] + frontend: bool, + + #[clap(long, conflicts_with("frontend"))] + no_frontend: bool, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("new") - .about(UserMessage::CreateProject.to_str()) - .arg( - Arg::new(PROJECT_NAME) - //.help(UserMessage::ProjectName.to_str()) - .validator(project_name_validator) - .required(true), - ) - .arg( - Arg::new(DRY_RUN) - //.help(UserMessage::DryRun.to_str()) - .long("dry-run") - .takes_value(false), - ) - .arg( - Arg::new("frontend") - .long("--frontend") - //.help(UserMessage::NewFrontend.to_str()) - .takes_value(false) - .conflicts_with("no-frontend"), - ) - .arg( - Arg::new("no-frontend") - .long("--no-frontend") - .hidden(true) - .takes_value(false) - .conflicts_with("frontend"), - ) + NewOpts::into_app() + .name("new") } enum Status<'a> { @@ -324,12 +316,10 @@ fn scaffold_frontend_code( } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: NewOpts = NewOpts::from_arg_matches(args); let log = env.get_logger(); - let dry_run = args.is_present(DRY_RUN); - let project_name_path = args - .value_of(PROJECT_NAME) - .ok_or_else(|| DfxError::InvalidArgument("project_path".to_string()))?; - let project_name = Path::new(project_name_path); + let dry_run = opts.dry_run; + let project_name = Path::new(opts.project_name.as_str()); if project_name.exists() { return Err(DfxError::ProjectExists); @@ -410,8 +400,8 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { env, dry_run, project_name, - args.is_present("no-frontend"), - args.is_present("frontend"), + opts.no_frontend, + opts.frontend, &variables, )?; @@ -490,28 +480,28 @@ mod tests { #[test] fn project_name_is_valid() { - assert!(project_name_validator("a".to_owned()).is_ok()); - assert!(project_name_validator("a_".to_owned()).is_ok()); - assert!(project_name_validator("a_1".to_owned()).is_ok()); - assert!(project_name_validator("A".to_owned()).is_ok()); - assert!(project_name_validator("A1".to_owned()).is_ok()); - assert!(project_name_validator("a_good_name_".to_owned()).is_ok()); - assert!(project_name_validator("a_good_name".to_owned()).is_ok()); + assert!(project_name_validator("a").is_ok()); + assert!(project_name_validator("a_").is_ok()); + assert!(project_name_validator("a_1").is_ok()); + assert!(project_name_validator("A").is_ok()); + assert!(project_name_validator("A1").is_ok()); + assert!(project_name_validator("a_good_name_").is_ok()); + assert!(project_name_validator("a_good_name").is_ok()); } #[test] fn project_name_is_invalid() { - assert!(project_name_validator("_a_good_name_".to_owned()).is_err()); - assert!(project_name_validator("__also_good".to_owned()).is_err()); - assert!(project_name_validator("_1".to_owned()).is_err()); - assert!(project_name_validator("_a".to_owned()).is_err()); - assert!(project_name_validator("1".to_owned()).is_err()); - assert!(project_name_validator("1_".to_owned()).is_err()); - assert!(project_name_validator("-".to_owned()).is_err()); - assert!(project_name_validator("_".to_owned()).is_err()); - assert!(project_name_validator("a-b-c".to_owned()).is_err()); - assert!(project_name_validator("🕹".to_owned()).is_err()); - assert!(project_name_validator("不好".to_owned()).is_err()); - assert!(project_name_validator("a:b".to_owned()).is_err()); + assert!(project_name_validator("_a_good_name_").is_err()); + assert!(project_name_validator("__also_good").is_err()); + assert!(project_name_validator("_1").is_err()); + assert!(project_name_validator("_a").is_err()); + assert!(project_name_validator("1").is_err()); + assert!(project_name_validator("1_").is_err()); + assert!(project_name_validator("-").is_err()); + assert!(project_name_validator("_").is_err()); + assert!(project_name_validator("a-b-c").is_err()); + assert!(project_name_validator("🕹").is_err()); + assert!(project_name_validator("不好").is_err()); + assert!(project_name_validator("a:b").is_err()); } } diff --git a/src/dfx/src/commands/ping.rs b/src/dfx/src/commands/ping.rs index 3ee012a68c..b7cdd49fb6 100644 --- a/src/dfx/src/commands/ping.rs +++ b/src/dfx/src/commands/ping.rs @@ -7,7 +7,6 @@ use crate::util::expiry_duration; use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use tokio::runtime::Runtime; - /// Pings an Internet Computer network and returns its status. #[derive(Clap)] pub struct PingOpts { @@ -16,8 +15,7 @@ pub struct PingOpts { } pub fn construct() -> App<'static> { - PingOpts::into_app() - .name("ping") + PingOpts::into_app().name("ping") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/start.rs b/src/dfx/src/commands/start.rs index 2c45ea612d..cbdcf2bd99 100644 --- a/src/dfx/src/commands/start.rs +++ b/src/dfx/src/commands/start.rs @@ -40,8 +40,7 @@ pub struct StartOpts { } pub fn construct() -> App<'static> { - StartOpts::into_app() - .name("start") + StartOpts::into_app().name("start") } fn ping_and_wait(frontend_url: &str) -> DfxResult { @@ -254,7 +253,11 @@ fn send_background() -> DfxResult<()> { Ok(()) } -fn frontend_address(host: Option, config: &Config, background: bool) -> DfxResult<(String, SocketAddr)> { +fn frontend_address( + host: Option, + config: &Config, + background: bool, +) -> DfxResult<(String, SocketAddr)> { let mut address_and_port = host .and_then(|host| Option::from(host.parse())) .unwrap_or_else(|| { diff --git a/src/dfx/src/commands/stop.rs b/src/dfx/src/commands/stop.rs index 346884ffeb..614c65c4eb 100644 --- a/src/dfx/src/commands/stop.rs +++ b/src/dfx/src/commands/stop.rs @@ -5,12 +5,10 @@ use sysinfo::{Pid, Process, ProcessExt, Signal, System, SystemExt}; /// Stops the local network replica. #[derive(Clap)] -pub struct StopOpts { -} +pub struct StopOpts {} pub fn construct() -> App<'static> { - StopOpts::into_app() - .name("stop") + StopOpts::into_app().name("stop") } fn list_all_descendants(pid: Pid) -> Vec { diff --git a/src/dfx/src/commands/upgrade.rs b/src/dfx/src/commands/upgrade.rs index d41fa9ace9..4819523f9e 100644 --- a/src/dfx/src/commands/upgrade.rs +++ b/src/dfx/src/commands/upgrade.rs @@ -25,8 +25,7 @@ pub struct UpgradeOpts { } pub fn construct() -> App<'static> { - UpgradeOpts::into_app() - .name("upgrade") + UpgradeOpts::into_app().name("upgrade") } fn parse_semver<'de, D>(version: &str) -> Result @@ -160,7 +159,8 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { "macos" => "x86_64-darwin", _ => panic!("Not supported architecture"), }; - let current_version = if let Some(version) = opts.current_version.and_then(|v| Some(v.as_str())) { + let current_version = if let Some(version) = opts.current_version.and_then(|v| Some(v.as_str())) + { Version::parse(version)? } else { env.get_version().clone() diff --git a/src/dfx/src/lib/message.rs b/src/dfx/src/lib/message.rs index c2222bdcde..d0d04ebaa3 100644 --- a/src/dfx/src/lib/message.rs +++ b/src/dfx/src/lib/message.rs @@ -141,22 +141,11 @@ user_message!( NewFrontend => "Installs the frontend code example for the default canister. This defaults to true if Node is installed, or false if it isn't.", // dfx replica - Replica => "Starts a local Internet Computer replica.", - ReplicaMessageGasLimit => "Specifies the maximum number of cycles a single message can consume.", - ReplicaPort => "Specifies the port the local replica should listen to.", ReplicaRoundGasLimit => "Specifies the maximum number of cycles a single round can consume.", - // dfx start - CleanState => "Cleans the state of the current project.", - StartNode => "Starts the local replica and a web server for the current project.", - NodeAddress => "Specifies the host name and port number to bind the frontend to.", - StartBackground => "Exits the dfx leaving the replica running. Will wait until the replica replies before exiting.", - // misc CanisterName => "Specifies the canister name. If you don't specify this argument, all canisters are processed.", - // dfx stop - StopNode => "Stops the local network replica.", // dfx ide StartLanguageService => "Starts the Motoko IDE Language Server. This is meant to be run by editor plugins not the end-user.", ForceTTY => "Forces the language server to start even when run from a terminal.", From bbc14a9723fff0f40b890a7bae5dfae4d2a52403 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Thu, 29 Oct 2020 20:43:49 -0700 Subject: [PATCH 11/26] rename use --- src/dfx/src/commands/identity/rename.rs | 35 ++++++++++++------------- src/dfx/src/commands/identity/use.rs | 23 ++++++++-------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/dfx/src/commands/identity/rename.rs b/src/dfx/src/commands/identity/rename.rs index 6f6e4003b1..fae449370d 100644 --- a/src/dfx/src/commands/identity/rename.rs +++ b/src/dfx/src/commands/identity/rename.rs @@ -1,30 +1,29 @@ use crate::lib::environment::Environment; use crate::lib::error::DfxResult; use crate::lib::identity::identity_manager::IdentityManager; -use crate::lib::message::UserMessage; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use slog::info; +/// Renames an existing identity. +#[derive(Clap)] +pub struct RenameOpts { + /// The current name of the identity. + #[clap(long)] + from: String, + + /// The new name of the identity. + #[clap(long)] + to: String, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("rename") - .about(UserMessage::RenameIdentity.to_str()) - .arg( - Arg::new("from") - //.help("The current name of the identity.") - .required(true) - .takes_value(true), - ) - .arg( - Arg::new("to") - //.help("The new name of the identity.") - .required(true) - .takes_value(true), - ) + RenameOpts::into_app().name("rename") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { - let from = args.value_of("from").unwrap(); - let to = args.value_of("to").unwrap(); + let opts: RenameOpts = RenameOpts::from_arg_matches(args); + let from = opts.from.as_str(); + let to = opts.to.as_str(); let log = env.get_logger(); info!(log, r#"Renaming identity "{}" to "{}"."#, from, to); diff --git a/src/dfx/src/commands/identity/use.rs b/src/dfx/src/commands/identity/use.rs index 21ddbea3dc..796a9f1ca1 100644 --- a/src/dfx/src/commands/identity/use.rs +++ b/src/dfx/src/commands/identity/use.rs @@ -1,23 +1,24 @@ use crate::lib::environment::Environment; use crate::lib::error::DfxResult; use crate::lib::identity::identity_manager::IdentityManager; -use crate::lib::message::UserMessage; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use slog::info; +/// Specifies the identity to use. +#[derive(Clap)] +pub struct UseOpts { + /// The identity to use. + #[clap(long)] + identity: String, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("use") - .about(UserMessage::UseIdentity.to_str()) - .arg( - Arg::new("identity") - //.help("The identity to use.") - .required(true) - .takes_value(true), - ) + UseOpts::into_app().name("use") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { - let identity = args.value_of("identity").unwrap(); + let opts: UseOpts = UseOpts::from_arg_matches(args); + let identity = opts.identity.as_str(); let log = env.get_logger(); info!(log, r#"Using identity: "{}"."#, identity); From b33ec5d30206b06b9d1940859dabc6980bec01db Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Thu, 29 Oct 2020 20:47:52 -0700 Subject: [PATCH 12/26] remove --- src/dfx/src/commands/identity/remove.rs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/dfx/src/commands/identity/remove.rs b/src/dfx/src/commands/identity/remove.rs index 790c8bcc1d..2a230cfb76 100644 --- a/src/dfx/src/commands/identity/remove.rs +++ b/src/dfx/src/commands/identity/remove.rs @@ -1,23 +1,24 @@ use crate::lib::environment::Environment; use crate::lib::error::DfxResult; use crate::lib::identity::identity_manager::IdentityManager; -use crate::lib::message::UserMessage; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use slog::info; +/// Removes an existing identity. +#[derive(Clap)] +pub struct RemoveOpts { + /// The identity to remove. + #[clap(long)] + identity: String, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("remove") - .about(UserMessage::RemoveIdentity.to_str()) - .arg( - Arg::new("identity") - //.help("The identity to remove.") - .required(true) - .takes_value(true), - ) + RemoveOpts::into_app().name("rename") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { - let name = args.value_of("identity").unwrap(); + let opts: RemoveOpts = RemoveOpts::from_arg_matches(args); + let name = opts.identity.as_str(); let log = env.get_logger(); info!(log, r#"Removing identity "{}"."#, name); From 4d90942c55789ef8df6419b642a75ad5dee0dac8 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Fri, 30 Oct 2020 00:14:49 -0700 Subject: [PATCH 13/26] updates --- src/dfx/src/commands/bootstrap.rs | 97 ++++++------ src/dfx/src/commands/build.rs | 60 ++++---- src/dfx/src/commands/cache/delete.rs | 17 ++- src/dfx/src/commands/canister/call.rs | 120 +++++++-------- src/dfx/src/commands/canister/create.rs | 37 +++-- src/dfx/src/commands/canister/delete.rs | 39 +++-- src/dfx/src/commands/canister/id.rs | 24 +-- src/dfx/src/commands/canister/install.rs | 143 ++++++++---------- src/dfx/src/commands/canister/mod.rs | 2 +- .../src/commands/canister/request_status.rs | 31 ++-- .../src/commands/canister/set_controller.rs | 36 ++--- src/dfx/src/commands/canister/start.rs | 38 +++-- src/dfx/src/commands/canister/status.rs | 39 +++-- src/dfx/src/commands/canister/stop.rs | 39 +++-- src/dfx/src/commands/config.rs | 44 +++--- src/dfx/src/commands/deploy.rs | 60 ++++---- src/dfx/src/commands/identity/new.rs | 23 +-- src/dfx/src/commands/new.rs | 3 +- src/dfx/src/lib/message.rs | 91 ----------- src/dfx/src/main.rs | 15 +- src/dfx/src/util/clap/validators.rs | 4 +- 21 files changed, 399 insertions(+), 563 deletions(-) diff --git a/src/dfx/src/commands/bootstrap.rs b/src/dfx/src/commands/bootstrap.rs index c4a5a32bc6..a43f93a014 100644 --- a/src/dfx/src/commands/bootstrap.rs +++ b/src/dfx/src/commands/bootstrap.rs @@ -1,12 +1,11 @@ use crate::config::dfinity::{ConfigDefaults, ConfigDefaultsBootstrap}; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use crate::lib::network::network_descriptor::NetworkDescriptor; use crate::lib::provider::get_network_descriptor; use crate::lib::webserver::webserver; use crate::util::get_reusable_socket_addr; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use slog::info; use std::default::Default; use std::fs; @@ -17,53 +16,48 @@ use std::str::FromStr; use std::time::Duration; use url::Url; -/// Constructs a sub-command to run the bootstrap server. +/// Starts the bootstrap server. +#[derive(Clap)] +pub struct BootstrapOpts { + /// Specifies the IP address that the bootstrap server listens on. Defaults to 127.0.0.1. + #[clap(long)] + ip: Option, + + /// Specifies the port number that the bootstrap server listens on. Defaults to 8081. + #[clap(long)] + port: Option, + + /// Override the compute network to connect to. By default, the local network is used. + #[clap(long)] + network: Option, + + /// Specifies the directory containing static assets served by the bootstrap server. + /// Defaults to $HOME/.cache/dfinity/versions/$DFX_VERSION/js-user-library/dist/bootstrap.", + #[clap(long)] + root: Option, + + /// Specifies the maximum number of seconds that the bootstrap server + /// will wait for upstream requests to complete. Defaults to 30.", + #[clap(long)] + timeout: Option, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("bootstrap") - .about(UserMessage::BootstrapCommand.to_str()) - .arg( - Arg::new("ip") - //.help(UserMessage::BootstrapIP.to_str()) - .long("ip") - .takes_value(true), - ) - .arg( - Arg::new("port") - //.help(UserMessage::BootstrapPort.to_str()) - .long("port") - .takes_value(true), - ) - .arg( - Arg::new("network") - //.help(UserMessage::CanisterComputeNetwork.to_str()) - .long("network") - .takes_value(true), - ) - .arg( - Arg::new("root") - //.help(UserMessage::BootstrapRoot.to_str()) - .long("root") - .takes_value(true), - ) - .arg( - Arg::new("timeout") - //.help(UserMessage::BootstrapTimeout.to_str()) - .long("timeout") - .takes_value(true), - ) + BootstrapOpts::into_app().name("bootstrap") } /// Runs the bootstrap server. pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: BootstrapOpts = BootstrapOpts::from_arg_matches(args); let logger = env.get_logger(); let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; let config_defaults = get_config_defaults_from_file(env); let base_config_bootstrap = config_defaults.get_bootstrap().to_owned(); - let config_bootstrap = apply_arguments(&base_config_bootstrap, env, args)?; + let config_bootstrap = apply_arguments(&base_config_bootstrap, env, opts)?; - let network_descriptor = get_network_descriptor(env, args)?; + let network_descriptor = get_network_descriptor(env, opts.network)?; let build_output_root = config.get_temp_path().join(network_descriptor.name.clone()); let build_output_root = build_output_root.join("canisters"); @@ -118,12 +112,12 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { fn apply_arguments( config: &ConfigDefaultsBootstrap, env: &dyn Environment, - args: &ArgMatches, + opts: BootstrapOpts, ) -> DfxResult { - let ip = get_ip(&config, args)?; - let port = get_port(&config, args)?; - let root = get_root(&config, env, args)?; - let timeout = get_timeout(&config, args)?; + let ip = get_ip(&config, opts.ip)?; + let port = get_port(&config, opts.port)?; + let root = get_root(&config, env, opts.root.and_then(|v| Some(v.as_str())))?; + let timeout = get_timeout(&config, opts.timeout)?; Ok(ConfigDefaultsBootstrap { ip: Some(ip), port: Some(port), @@ -143,9 +137,8 @@ fn get_config_defaults_from_file(env: &dyn Environment) -> ConfigDefaults { /// Gets the IP address that the bootstrap server listens on. First checks if the IP address was /// specified on the command-line using --ip, otherwise checks if the IP address was specified in /// the dfx configuration file, otherise defaults to 127.0.0.1. -fn get_ip(config: &ConfigDefaultsBootstrap, args: &ArgMatches) -> DfxResult { - args.value_of("ip") - .map(|ip| ip.parse()) +fn get_ip(config: &ConfigDefaultsBootstrap, ip: Option) -> DfxResult { + ip.map(|ip| ip.parse()) .unwrap_or_else(|| { let default = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); Ok(config.ip.unwrap_or(default)) @@ -156,9 +149,8 @@ fn get_ip(config: &ConfigDefaultsBootstrap, args: &ArgMatches) -> DfxResult DfxResult { - args.value_of("port") - .map(|port| port.parse()) +fn get_port(config: &ConfigDefaultsBootstrap, port: Option) -> DfxResult { + port.map(|port| port.parse()) .unwrap_or_else(|| { let default = 8081; Ok(config.port.unwrap_or(default)) @@ -182,10 +174,9 @@ fn get_providers(network_descriptor: &NetworkDescriptor) -> DfxResult, ) -> DfxResult { - args.value_of("root") - .map(|root| parse_dir(root)) + root.map(|root| parse_dir(root)) .unwrap_or_else(|| { config .root @@ -205,8 +196,8 @@ fn get_root( /// requests to complete. First checks if the timeout was specified on the command-line using /// --timeout, otherwise checks if the timeout was specified in the dfx configuration file, /// otherise defaults to 30. -fn get_timeout(config: &ConfigDefaultsBootstrap, args: &ArgMatches) -> DfxResult { - args.value_of("timeout") +fn get_timeout(config: &ConfigDefaultsBootstrap, timeout: Option) -> DfxResult { + timeout .map(|timeout| timeout.parse()) .unwrap_or_else(|| { let default = 30; diff --git a/src/dfx/src/commands/build.rs b/src/dfx/src/commands/build.rs index 5981ea0dac..3e2f1d84e3 100644 --- a/src/dfx/src/commands/build.rs +++ b/src/dfx/src/commands/build.rs @@ -1,44 +1,38 @@ use crate::lib::builders::BuildConfig; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use crate::lib::models::canister::CanisterPool; use crate::lib::models::canister_id_store::CanisterIdStore; use crate::lib::provider::create_agent_environment; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; + +/// Builds all or specific canisters from the code in your project. By default, all canisters are built. +#[derive(Clap)] +pub struct CanisterBuildOpts { + /// Specifies the name of the canister to build. + /// You must specify either a canister name or the --all option.", + #[clap(long, required_unless_present("all"))] + canister_name: String, + + /// Builds all canisters configured in the dfx.json file. + #[clap(long, required_unless_present("canister_name"))] + all: bool, + + /// Build canisters without creating them. This can be used to check that canisters build ok. + #[clap(long)] + check: bool, + + /// Override the compute network to connect to. By default, the local network is used. + #[clap(long)] + network: Option, +} pub fn construct() -> App<'static> { - SubCommand::with_name("build") - .about(UserMessage::BuildCanister.to_str()) - .arg( - Arg::new("canister_name") - .takes_value(true) - .conflicts_with("all") - //.help(UserMessage::BuildCanisterName.to_str()) - .required(false), - ) - .arg( - Arg::new("all") - .long("all") - .conflicts_with("canister_name") - //.help(UserMessage::BuildAll.to_str()) - .takes_value(false), - ) - .arg( - Arg::new("check") - .long("check") - .takes_value(false) - //.help(UserMessage::BuildCheck.to_str()), - ) - .arg( - Arg::new("network") - //.help(UserMessage::CanisterComputeNetwork.to_str()) - .long("network") - .takes_value(true), - ) + CanisterBuildOpts::into_app().name("build") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: CanisterBuildOpts = CanisterBuildOpts::from_arg_matches(args); let env = create_agent_environment(env, args)?; let logger = env.get_logger(); @@ -52,10 +46,10 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { // already. env.get_cache().install()?; - let build_mode_check = args.is_present("check"); + let build_mode_check = opts.check; // Option can be None in which case --all was specified - let some_canister = args.value_of("canister_name"); + let some_canister = Some(opts.canister_name.as_str()); let canister_names = config .get_config() .get_canister_names_with_dependencies(some_canister)?; @@ -64,7 +58,7 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let canister_pool = CanisterPool::load(&env, build_mode_check, &canister_names)?; // Create canisters on the replica and associate canister ids locally. - if args.is_present("check") { + if build_mode_check { slog::warn!( env.get_logger(), "Building canisters to check they build ok. Canister IDs might be hard coded." diff --git a/src/dfx/src/commands/cache/delete.rs b/src/dfx/src/commands/cache/delete.rs index 89e5403b50..e77f783bd3 100644 --- a/src/dfx/src/commands/cache/delete.rs +++ b/src/dfx/src/commands/cache/delete.rs @@ -1,17 +1,22 @@ use crate::config::cache::delete_version; use crate::lib::environment::Environment; use crate::lib::error::DfxResult; -use crate::lib::message::UserMessage; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; + +/// Deletes a specific versioned cache of dfx. +#[derive(Clap)] +pub struct CacheDeleteOpts { + #[clap(long)] + version: Option, +} pub fn construct() -> App<'static> { - SubCommand::with_name("delete") - .about(UserMessage::CacheDelete.to_str()) - .arg(Arg::new("version").takes_value(true)) + CacheDeleteOpts::into_app().name("delete") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { - match args.value_of("version") { + let opts: CacheDeleteOpts = CacheDeleteOpts::from_arg_matches(args); + match opts.version { Some(v) => delete_version(v).map(|_| {}), _ => env.get_cache().delete(), } diff --git a/src/dfx/src/commands/canister/call.rs b/src/dfx/src/commands/canister/call.rs index dbc615fa57..04ebe1f54f 100644 --- a/src/dfx/src/commands/canister/call.rs +++ b/src/dfx/src/commands/canister/call.rs @@ -1,82 +1,64 @@ use crate::lib::canister_info::CanisterInfo; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use crate::lib::models::canister_id_store::CanisterIdStore; use crate::lib::waiter::waiter_with_timeout; use crate::util::{blob_from_arguments, expiry_duration, get_candid_type, print_idl_blob}; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use ic_types::principal::Principal as CanisterId; use std::option::Option; use tokio::runtime::Runtime; +/// Deletes a canister on the Internet Computer network. +#[derive(Clap)] +pub struct CanisterCallOpts { + /// Specifies the name of the canister to build. + /// You must specify either a canister name or the --all option. + #[clap(long)] + canister_name: String, + + /// Specifies the method name to call on the canister. + #[clap(long)] + method_name: String, + + /// Specifies not to wait for the result of the call to be returned by polling the replica. + /// Instead return a response ID. + #[clap(long)] + async_call: bool, + + /// Sends a query request to a canister. + #[clap(long, conflicts_with("async"), conflicts_with("update"))] + query: bool, + + /// Sends an update request to a canister. This is the default if the method is not a query method. + #[clap(long, conflicts_with("async"), conflicts_with("query"))] + update: bool, + + /// Specifies the argument to pass to the method. + #[clap(long)] + argument: Option, + + /// Specifies the data type for the argument when making the call using an argument. + #[clap(long, requires("argument"), possible_values(&["idl", "raw"]))] + argument_type: Option, + + /// Specifies the format for displaying the method's return result. + #[clap(long, requires("argument"), conflicts_with("async"), + possible_values(&["idl", "raw", "pp"]))] + output: Option, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("call") - .about(UserMessage::CallCanister.to_str()) - .arg( - Arg::new("canister_name") - .takes_value(true) - //.help(UserMessage::CanisterName.to_str()) - .required(true), - ) - .arg( - Arg::new("method_name") - //.help(UserMessage::MethodName.to_str()) - .required(true), - ) - .arg( - Arg::new("async") - //.help(UserMessage::AsyncResult.to_str()) - .long("async") - .takes_value(false), - ) - .arg( - Arg::new("query") - //.help(UserMessage::QueryCanister.to_str()) - .long("query") - .conflicts_with("async") - .conflicts_with("update") - .takes_value(false), - ) - .arg( - Arg::new("update") - //.help(UserMessage::UpdateCanisterArg.to_str()) - .long("update") - .conflicts_with("async") - .conflicts_with("query") - .takes_value(false), - ) - .arg( - Arg::new("type") - //.help(UserMessage::ArgumentType.to_str()) - .long("type") - .takes_value(true) - .requires("argument") - .possible_values(&["idl", "raw"]), - ) - .arg( - Arg::new("output") - //.help(UserMessage::OutputType.to_str()) - .long("output") - .takes_value(true) - .conflicts_with("async") - .possible_values(&["idl", "raw", "pp"]), - ) - .arg( - Arg::new("argument") - //.help(UserMessage::ArgumentValue.to_str()) - .takes_value(true), - ) + CanisterCallOpts::into_app().name("call") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: CanisterCallOpts = CanisterCallOpts::from_arg_matches(args); let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; - let canister_name = args.value_of("canister_name").unwrap(); - let method_name = args - .value_of("method_name") - .ok_or_else(|| DfxError::InvalidArgument("method_name".to_string()))?; + let canister_name = opts.canister_name.as_str(); + let method_name = opts.method_name.as_str(); let (canister_id, maybe_candid_path) = match CanisterId::from_text(canister_name) { Ok(id) => { @@ -100,16 +82,16 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { None => None, }; - let arguments: Option<&str> = args.value_of("argument"); - let arg_type: Option<&str> = args.value_of("type"); - let output_type: Option<&str> = args.value_of("output"); - let is_query = if args.is_present("async") { + let arguments: Option<&str> = opts.argument.and_then(|v| Some(v.as_str())); + let arg_type: Option<&str> = opts.argument_type.and_then(|v| Some(v.as_str())); + let output_type: Option<&str> = opts.output.and_then(|v| Some(v.as_str())); + let is_query = if opts.async_call { false } else { match is_query_method { - Some(true) => !args.is_present("update"), + Some(true) => !opts.update, Some(false) => { - if args.is_present("query") { + if opts.query { return Err(DfxError::InvalidMethodCall(format!( "{} is not a query method", method_name @@ -118,7 +100,7 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { false } } - None => args.is_present("query"), + None => opts.query, } }; diff --git a/src/dfx/src/commands/canister/create.rs b/src/dfx/src/commands/canister/create.rs index d7432bf594..2c446c5c99 100644 --- a/src/dfx/src/commands/canister/create.rs +++ b/src/dfx/src/commands/canister/create.rs @@ -1,41 +1,38 @@ use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use crate::lib::operations::canister::create_canister; use crate::util::expiry_duration; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; -use clap::{App, Arg, ArgMatches, SubCommand}; +/// Creates an empty canister on the Internet Computer and +/// associates the Internet Computer assigned Canister ID to the canister name. +#[derive(Clap)] +pub struct CanisterCreateOpts { + /// Specifies the canister name. Either this or the --all flag are required. + #[clap(long, required_unless_present("all"))] + canister_name: String, + + /// Creates all canisters configured in dfx.json. + #[clap(long, required_unless_present("canister_name"))] + all: bool, +} pub fn construct() -> App<'static> { - SubCommand::with_name("create") - .about(UserMessage::CreateCanister.to_str()) - .arg( - Arg::new("canister_name") - .takes_value(true) - .required_unless("all") - //.help(UserMessage::CreateCanisterName.to_str()) - .required(false), - ) - .arg( - Arg::new("all") - .long("all") - .required_unless("canister_name") - //.help(UserMessage::CreateAll.to_str()) - .takes_value(false), - ) + CanisterCreateOpts::into_app().name("create") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: CanisterCreateOpts = CanisterCreateOpts::from_arg_matches(args); let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; let timeout = expiry_duration(); - if let Some(canister_name) = args.value_of("canister_name") { + if let Some(canister_name) = Some(opts.canister_name.as_str()) { create_canister(env, canister_name, timeout)?; Ok(()) - } else if args.is_present("all") { + } else if opts.all { // Create all canisters. if let Some(canisters) = &config.get_config().canisters { for canister_name in canisters.keys() { diff --git a/src/dfx/src/commands/canister/delete.rs b/src/dfx/src/commands/canister/delete.rs index ec68f05c17..8965aa6ffe 100644 --- a/src/dfx/src/commands/canister/delete.rs +++ b/src/dfx/src/commands/canister/delete.rs @@ -1,11 +1,9 @@ use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use crate::lib::models::canister_id_store::CanisterIdStore; use crate::lib::waiter::waiter_with_timeout; use crate::util::expiry_duration; - -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use ic_agent::Agent; use ic_utils::call::AsyncCall; use ic_utils::interfaces::ManagementCanister; @@ -13,23 +11,21 @@ use slog::info; use std::time::Duration; use tokio::runtime::Runtime; +/// Deletes a canister on the Internet Computer network. +#[derive(Clap)] +pub struct CanisterDeleteOpts { + /// Specifies the name of the canister to delete. + /// You must specify either a canister name or the --all flag. + #[clap(long, required_unless_present("all"))] + canister_name: String, + + /// Deletes all of the canisters configured in the dfx.json file. + #[clap(long, required_unless_present("canister_name"))] + all: bool, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("delete") - .about(UserMessage::DeleteCanister.to_str()) - .arg( - Arg::new("canister_name") - .takes_value(true) - .required_unless("all") - //.help(UserMessage::DeleteCanisterName.to_str()) - .required(false), - ) - .arg( - Arg::new("all") - .long("all") - .required_unless("canister_name") - //.help(UserMessage::DeleteAll.to_str()) - .takes_value(false), - ) + CanisterDeleteOpts::into_app().name("delete") } async fn delete_canister( @@ -59,6 +55,7 @@ async fn delete_canister( } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: CanisterDeleteOpts = CanisterDeleteOpts::from_arg_matches(args); let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; @@ -70,10 +67,10 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let mut runtime = Runtime::new().expect("Unable to create a runtime"); - if let Some(canister_name) = args.value_of("canister_name") { + if let Some(canister_name) = Some(opts.canister_name.as_str()) { runtime.block_on(delete_canister(env, &agent, &canister_name, timeout))?; Ok(()) - } else if args.is_present("all") { + } else if opts.all { if let Some(canisters) = &config.get_config().canisters { for canister_name in canisters.keys() { runtime.block_on(delete_canister(env, &agent, &canister_name, timeout))?; diff --git a/src/dfx/src/commands/canister/id.rs b/src/dfx/src/commands/canister/id.rs index 456fc2ae69..9460293899 100644 --- a/src/dfx/src/commands/canister/id.rs +++ b/src/dfx/src/commands/canister/id.rs @@ -1,25 +1,27 @@ use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use crate::lib::models::canister_id_store::CanisterIdStore; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use ic_types::principal::Principal as CanisterId; +/// Prints the identifier of a canister. +#[derive(Clap)] +pub struct CanisterIdOpts { + /// Specifies the name of the canister to stop. + /// You must specify either a canister name or the --all option. + #[clap(long)] + canister_name: String, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("id") - .about(UserMessage::IdCanister.to_str()) - .arg( - Arg::new("canister_name") - .takes_value(true) - //.help(UserMessage::CanisterName.to_str()) - .required(true), - ) + CanisterIdOpts::into_app().name("id") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts = CanisterIdOpts::from_arg_matches(args); env.get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; - let canister_name = args.value_of("canister_name").unwrap(); + let canister_name = opts.canister_name.as_str(); let canister_id = CanisterIdStore::for_env(env)?.get(canister_name)?; println!("{}", CanisterId::to_text(&canister_id)); diff --git a/src/dfx/src/commands/canister/install.rs b/src/dfx/src/commands/canister/install.rs index 6b87f01e7b..4c81b1620f 100644 --- a/src/dfx/src/commands/canister/install.rs +++ b/src/dfx/src/commands/canister/install.rs @@ -2,82 +2,59 @@ use crate::config::dfinity::ConfigInterface; use crate::lib::canister_info::CanisterInfo; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use crate::lib::models::canister_id_store::CanisterIdStore; use crate::lib::operations::canister::install_canister; use crate::util::{blob_from_arguments, expiry_duration, get_candid_init_type}; - -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use humanize_rs::bytes::{Bytes, Unit}; - use ic_utils::interfaces::management_canister::{ComputeAllocation, InstallMode, MemoryAllocation}; use std::convert::TryFrom; use std::str::FromStr; use tokio::runtime::Runtime; +/// Deploys compiled code as a canister on the Internet Computer. +#[derive(Clap)] +pub struct CanisterInstallOpts { + /// Specifies the canister name to deploy. You must specify either canister name or the --all option. + #[clap(long, required_unless_present("all"))] + canister_name: String, + + /// Deploys all canisters configured in the project dfx.json files. + #[clap(long, required_unless_present("canister_name"))] + all: bool, + + /// Specifies not to wait for the result of the call to be returned by polling the replica. Instead return a response ID. + #[clap(long)] + async_call: bool, + + /// Specifies the type of deployment. You can set the canister deployment modes to install, reinstall, or upgrade. + #[clap(long, short('m'), default_value("install"), + possible_values(&["install", "reinstall", "upgrade"]))] + mode: String, + + /// Specifies the argument to pass to the method. + #[clap(long)] + argument: Option, + + /// Specifies the data type for the argument when making the call using an argument. + #[clap(long, requires("argument"), possible_values(&["idl", "raw"]))] + argument_type: Option, + + /// Specifies the canister's compute allocation. This should be a percent in the range [0..100] + #[clap(long, short('c'), validator(compute_allocation_validator))] + compute_allocation: Option, + + /// Specifies how much memory the canister is allowed to use in total. + /// This should be a value in the range [0..256 TB] + #[clap(long, validator(memory_allocation_validator))] + memory_allocation: Option, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("install") - .about(UserMessage::InstallCanister.to_str()) - .arg( - Arg::new("canister_name") - .takes_value(true) - .required_unless("all") - //.help(UserMessage::InstallCanisterName.to_str()) - .required(false), - ) - .arg( - Arg::new("all") - .long("all") - .required_unless("canister_name") - //.help(UserMessage::InstallAll.to_str()) - .takes_value(false), - ) - .arg( - Arg::new("async") - //.help(UserMessage::AsyncResult.to_str()) - .long("async") - .takes_value(false), - ) - .arg( - Arg::new("mode") - //.help(UserMessage::InstallMode.to_str()) - .long("mode") - .short("m") - .possible_values(&["install", "reinstall", "upgrade"]) - .default_value("install") - .takes_value(true), - ) - .arg( - Arg::new("argument") - //.help(UserMessage::ArgumentValue.to_str()) - .takes_value(true), - ) - .arg( - Arg::new("type") - //.help(UserMessage::ArgumentType.to_str()) - .long("type") - .takes_value(true) - .requires("argument") - .possible_values(&["idl", "raw"]), - ) - .arg( - Arg::new("compute-allocation") - //.help(UserMessage::InstallComputeAllocation.to_str()) - .long("compute-allocation") - .short("c") - .takes_value(true) - .validator(compute_allocation_validator), - ) - .arg( - Arg::new("memory-allocation") - //.help(UserMessage::InstallMemoryAllocation.to_str()) - .long("memory-allocation") - .takes_value(true) - .validator(memory_allocation_validator), - ) + CanisterInstallOpts::into_app().name("install") } -fn compute_allocation_validator(compute_allocation: String) -> Result<(), String> { +fn compute_allocation_validator(compute_allocation: &str) -> Result<(), String> { if let Ok(num) = compute_allocation.parse::() { if num <= 100 { return Ok(()); @@ -86,7 +63,7 @@ fn compute_allocation_validator(compute_allocation: String) -> Result<(), String Err("Must be a percent between 0 and 100".to_string()) } -fn memory_allocation_validator(memory_allocation: String) -> Result<(), String> { +fn memory_allocation_validator(memory_allocation: &str) -> Result<(), String> { let limit = Bytes::new(256, Unit::TByte).map_err(|_| "Parse Overflow.")?; if let Ok(bytes) = memory_allocation.parse::() { if bytes.size() <= limit.size() { @@ -97,12 +74,11 @@ fn memory_allocation_validator(memory_allocation: String) -> Result<(), String> } fn get_compute_allocation( - args: &ArgMatches, + compute_allocation: Option, config_interface: &ConfigInterface, canister_name: &str, ) -> DfxResult> { - Ok(args - .value_of("compute-allocation") + Ok(compute_allocation .map(|v| v.to_string()) .or(config_interface.get_compute_allocation(canister_name)?) .map(|arg| { @@ -112,12 +88,11 @@ fn get_compute_allocation( } fn get_memory_allocation( - args: &ArgMatches, + memory_allocation: Option, config_interface: &ConfigInterface, canister_name: &str, ) -> DfxResult> { - Ok(args - .value_of("memory-allocation") + Ok(memory_allocation .map(|v| v.to_string()) .or(config_interface.get_memory_allocation(canister_name)?) .map(|arg| { @@ -127,6 +102,7 @@ fn get_memory_allocation( } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: CanisterInstallOpts = CanisterInstallOpts::from_arg_matches(args); let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; @@ -139,24 +115,26 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let config_interface = config.get_config(); - let mode = InstallMode::from_str(args.value_of("mode").unwrap())?; + let mode = InstallMode::from_str(opts.mode.as_str())?; let mut runtime = Runtime::new().expect("Unable to create a runtime"); let canister_id_store = CanisterIdStore::for_env(env)?; - if let Some(canister_name) = args.value_of("canister_name") { + if let Some(canister_name) = Some(opts.canister_name.as_str()) { let canister_id = canister_id_store.get(canister_name)?; let canister_info = CanisterInfo::load(&config, canister_name, Some(canister_id))?; let maybe_path = canister_info.get_output_idl_path(); let init_type = maybe_path.and_then(|path| get_candid_init_type(&path)); - let arguments: Option<&str> = args.value_of("argument"); - let arg_type: Option<&str> = args.value_of("type"); + let arguments: Option<&str> = opts.argument.and_then(|v| Some(v.as_str())); + let arg_type: Option<&str> = opts.argument_type.and_then(|v| Some(v.as_str())); let install_args = blob_from_arguments(arguments, arg_type, &init_type)?; - let compute_allocation = get_compute_allocation(args, config_interface, canister_name)?; - let memory_allocation = get_memory_allocation(args, config_interface, canister_name)?; + let compute_allocation = + get_compute_allocation(opts.compute_allocation, config_interface, canister_name)?; + let memory_allocation = + get_memory_allocation(opts.memory_allocation, config_interface, canister_name)?; runtime.block_on(install_canister( env, @@ -169,7 +147,7 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { timeout, ))?; Ok(()) - } else if args.is_present("all") { + } else if opts.all { // Install all canisters. if let Some(canisters) = &config.get_config().canisters { for canister_name in canisters.keys() { @@ -178,10 +156,13 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let install_args = []; - let compute_allocation = - get_compute_allocation(args, config_interface, canister_name)?; + let compute_allocation = get_compute_allocation( + opts.compute_allocation, + config_interface, + canister_name, + )?; let memory_allocation = - get_memory_allocation(args, config_interface, canister_name)?; + get_memory_allocation(opts.memory_allocation, config_interface, canister_name)?; runtime.block_on(install_canister( env, diff --git a/src/dfx/src/commands/canister/mod.rs b/src/dfx/src/commands/canister/mod.rs index 6ca74c1e8f..6ad4a37c9a 100644 --- a/src/dfx/src/commands/canister/mod.rs +++ b/src/dfx/src/commands/canister/mod.rs @@ -3,7 +3,7 @@ use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; use crate::lib::message::UserMessage; use crate::lib::provider::create_agent_environment; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, AppSettings, Arg, ArgMatches, FromArgMatches, IntoApp}; mod call; mod create; diff --git a/src/dfx/src/commands/canister/request_status.rs b/src/dfx/src/commands/canister/request_status.rs index 7b71efee56..129e161231 100644 --- a/src/dfx/src/commands/canister/request_status.rs +++ b/src/dfx/src/commands/canister/request_status.rs @@ -1,35 +1,32 @@ use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use crate::lib::waiter::waiter_with_timeout; use crate::util::clap::validators; use crate::util::{expiry_duration, print_idl_blob}; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use delay::Waiter; use ic_agent::agent::{Replied, RequestStatusResponse}; use ic_agent::{AgentError, RequestId}; use std::str::FromStr; use tokio::runtime::Runtime; +/// Requests the status of a specified call from a canister. +#[derive(Clap)] +pub struct RequestStatusOpts { + /// Specifies the request identifier. + /// The request identifier is an hexadecimal string starting with 0x. + #[clap(long, validator(validators::is_request_id))] + request_id: String, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("request-status") - .about(UserMessage::RequestCallStatus.to_str()) - .arg( - Arg::new("request_id") - .takes_value(true) - //.help(UserMessage::RequestId.to_str()) - .required(true) - .validator(validators::is_request_id), - ) + RequestStatusOpts::into_app().name("request-status") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { - let request_id = RequestId::from_str( - &args - .value_of("request_id") - .ok_or_else(|| DfxError::InvalidArgument("request_id".to_string()))?[2..], - ) - .map_err(|_| DfxError::InvalidArgument("request_id".to_owned()))?; + let opts = RequestStatusOpts::from_arg_matches(args); + let request_id = RequestId::from_str(&opts.request_id[2..]) + .map_err(|_| DfxError::InvalidArgument("request_id".to_owned()))?; let agent = env .get_agent() diff --git a/src/dfx/src/commands/canister/set_controller.rs b/src/dfx/src/commands/canister/set_controller.rs index c81d3d6c84..d9e70649e9 100644 --- a/src/dfx/src/commands/canister/set_controller.rs +++ b/src/dfx/src/commands/canister/set_controller.rs @@ -1,42 +1,42 @@ use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; use crate::lib::identity::identity_manager::IdentityManager; -use crate::lib::message::UserMessage; use crate::lib::models::canister_id_store::CanisterIdStore; use crate::lib::waiter::waiter_with_timeout; use crate::util::expiry_duration; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use ic_agent::Identity; use ic_types::principal::Principal as CanisterId; use ic_utils::call::AsyncCall; use ic_utils::interfaces::ManagementCanister; use tokio::runtime::Runtime; +/// Sets the provided identity's name or its principal as the +/// new controller of a canister on the Internet Computer network. +#[derive(Clap)] +pub struct SetControllerOpts { + /// Specifies the canister name or the canister identifier for the canister to be controlled. + #[clap(long)] + canister: String, + + /// Specifies the identity name or the principal of the new controller." + #[clap(long)] + new_controller: String, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("set-controller") - .about(UserMessage::SetController.to_str()) - .arg( - Arg::new("canister") - .takes_value(true) - //.help(UserMessage::SetControllerCanister.to_str()) - .required(true), - ) - .arg( - Arg::new("new-controller") - .takes_value(true) - //.help(UserMessage::NewController.to_str()) - .required(true), - ) + SetControllerOpts::into_app().name("set-controller") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { - let canister = args.value_of("canister").unwrap(); + let opts: SetControllerOpts = SetControllerOpts::from_arg_matches(args); + let canister = opts.canister.as_str(); let canister_id = match CanisterId::from_text(canister) { Ok(id) => id, Err(_) => CanisterIdStore::for_env(env)?.get(canister)?, }; - let new_controller = args.value_of("new-controller").unwrap(); + let new_controller = opts.new_controller.as_str(); let controller_principal = match CanisterId::from_text(new_controller) { Ok(principal) => principal, Err(_) => IdentityManager::new(env)? diff --git a/src/dfx/src/commands/canister/start.rs b/src/dfx/src/commands/canister/start.rs index 7e6c7e80c2..15521f093a 100644 --- a/src/dfx/src/commands/canister/start.rs +++ b/src/dfx/src/commands/canister/start.rs @@ -1,11 +1,9 @@ use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use crate::lib::models::canister_id_store::CanisterIdStore; use crate::lib::waiter::waiter_with_timeout; use crate::util::expiry_duration; - -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use ic_agent::Agent; use ic_utils::call::AsyncCall; use ic_utils::interfaces::ManagementCanister; @@ -13,23 +11,20 @@ use slog::info; use std::time::Duration; use tokio::runtime::Runtime; +/// Starts a canister on the Internet Computer network. +#[derive(Clap)] +pub struct CanisterStartOpts { + /// Specifies the name of the canister to start. You must specify either a canister name or the --all flag. + #[clap(long, required_unless_present("all"))] + canister_name: String, + + /// Starts all of the canisters configured in the dfx.json file. + #[clap(long, required_unless_present("canister_name"))] + all: bool, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("start") - .about(UserMessage::StartCanister.to_str()) - .arg( - Arg::new("canister_name") - .takes_value(true) - .required_unless("all") - //.help(UserMessage::StartCanisterName.to_str()) - .required(false), - ) - .arg( - Arg::new("all") - .long("all") - .required_unless("canister_name") - //.help(UserMessage::StartAll.to_str()) - .takes_value(false), - ) + CanisterStartOpts::into_app().name("start") } async fn start_canister( @@ -59,6 +54,7 @@ async fn start_canister( } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: CanisterStartOpts = CanisterStartOpts::from_arg_matches(args); let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; @@ -70,10 +66,10 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let timeout = expiry_duration(); - if let Some(canister_name) = args.value_of("canister_name") { + if let Some(canister_name) = Some(opts.canister_name.as_str()) { runtime.block_on(start_canister(env, &agent, &canister_name, timeout))?; Ok(()) - } else if args.is_present("all") { + } else if opts.all { if let Some(canisters) = &config.get_config().canisters { for canister_name in canisters.keys() { runtime.block_on(start_canister(env, &agent, &canister_name, timeout))?; diff --git a/src/dfx/src/commands/canister/status.rs b/src/dfx/src/commands/canister/status.rs index 7e464e2e57..df122b60ed 100644 --- a/src/dfx/src/commands/canister/status.rs +++ b/src/dfx/src/commands/canister/status.rs @@ -1,11 +1,9 @@ use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use crate::lib::models::canister_id_store::CanisterIdStore; use crate::lib::waiter::waiter_with_timeout; use crate::util::expiry_duration; - -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use ic_agent::Agent; use ic_utils::call::AsyncCall; use ic_utils::interfaces::ManagementCanister; @@ -13,23 +11,21 @@ use slog::info; use std::time::Duration; use tokio::runtime::Runtime; +/// Returns the current status of the canister on the Internet Computer network: Running, Stopping, or Stopped. +#[derive(Clap)] +pub struct CanisterStatusOpts { + /// Specifies the name of the canister to return information for. + /// You must specify either a canister name or the --all flag. + #[clap(long, required_unless_present("all"))] + canister_name: String, + + /// Returns status information for all of the canisters configured in the dfx.json file. + #[clap(long, required_unless_present("canister_name"))] + all: bool, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("status") - .about(UserMessage::CanisterStatus.to_str()) - .arg( - Arg::new("canister_name") - .takes_value(true) - .required_unless("all") - //.help(UserMessage::StatusCanisterName.to_str()) - .required(false), - ) - .arg( - Arg::new("all") - .long("all") - .required_unless("canister_name") - //.help(UserMessage::StatusAll.to_str()) - .takes_value(false), - ) + CanisterStatusOpts::into_app().name("status") } async fn canister_status( @@ -53,6 +49,7 @@ async fn canister_status( } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: CanisterStatusOpts = CanisterStatusOpts::from_arg_matches(args); let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; @@ -64,10 +61,10 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let timeout = expiry_duration(); - if let Some(canister_name) = args.value_of("canister_name") { + if let Some(canister_name) = Some(opts.canister_name.as_str()) { runtime.block_on(canister_status(env, &agent, &canister_name, timeout))?; Ok(()) - } else if args.is_present("all") { + } else if opts.all { if let Some(canisters) = &config.get_config().canisters { for canister_name in canisters.keys() { runtime.block_on(canister_status(env, &agent, &canister_name, timeout))?; diff --git a/src/dfx/src/commands/canister/stop.rs b/src/dfx/src/commands/canister/stop.rs index 0548026cca..49e1e09f87 100644 --- a/src/dfx/src/commands/canister/stop.rs +++ b/src/dfx/src/commands/canister/stop.rs @@ -1,11 +1,9 @@ use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use crate::lib::models::canister_id_store::CanisterIdStore; use crate::lib::waiter::waiter_with_timeout; use crate::util::expiry_duration; - -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use ic_agent::Agent; use ic_utils::call::AsyncCall; use ic_utils::interfaces::ManagementCanister; @@ -13,23 +11,21 @@ use slog::info; use std::time::Duration; use tokio::runtime::Runtime; +/// Stops a canister that is currently running on the Internet Computer network. +#[derive(Clap)] +pub struct CanisterStopOpts { + /// Specifies the name of the canister to stop. + /// You must specify either a canister name or the --all option. + #[clap(long, required_unless_present("all"))] + canister_name: String, + + /// Stops all of the canisters configured in the dfx.json file. + #[clap(long, required_unless_present("canister_name"))] + all: bool, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("stop") - .about(UserMessage::StopCanister.to_str()) - .arg( - Arg::new("canister_name") - .takes_value(true) - .required_unless("all") - //.help(UserMessage::StopCanisterName.to_str()) - .required(false), - ) - .arg( - Arg::new("all") - .long("all") - .required_unless("canister_name") - //.help(UserMessage::StopAll.to_str()) - .takes_value(false), - ) + CanisterStopOpts::into_app().name("stop") } async fn stop_canister( @@ -58,6 +54,7 @@ async fn stop_canister( } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: CanisterStopOpts = CanisterStopOpts::from_arg_matches(args); let config = env .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; @@ -68,10 +65,10 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let mut runtime = Runtime::new().expect("Unable to create a runtime"); let timeout = expiry_duration(); - if let Some(canister_name) = args.value_of("canister_name") { + if let Some(canister_name) = Some(opts.canister_name.as_str()) { runtime.block_on(stop_canister(env, &agent, &canister_name, timeout))?; Ok(()) - } else if args.is_present("all") { + } else if opts.all { if let Some(canisters) = &config.get_config().canisters { for canister_name in canisters.keys() { runtime.block_on(stop_canister(env, &agent, &canister_name, timeout))?; diff --git a/src/dfx/src/commands/config.rs b/src/dfx/src/commands/config.rs index bf9319f968..d4704dccf6 100644 --- a/src/dfx/src/commands/config.rs +++ b/src/dfx/src/commands/config.rs @@ -1,28 +1,34 @@ use crate::config::dfinity::Config; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use serde_json::value::Value; +/// Configures project options for your currently-selected project. +#[derive(Clap)] +pub struct ConfigOpts { + /// Specifies the name of the configuration option to set or read. + /// Use the period delineated path to specify the option to set or read. + /// If this is not mentioned, outputs the whole configuration. + #[clap(long)] + config_path: String, + + /// Specifies the new value to set. + /// If you don't specify a value, the command displays the current value of the option from the configuration file. + #[clap(long)] + value: String, + + /// Specifies the format of the output. By default, the output format is JSON. + #[clap(long, default_value("json"), possible_values(&["json", "text"]))] + format: String, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("config") - .about(UserMessage::ConfigureOptions.to_str()) - .arg(Arg::new("config_path")) - //.help(UserMessage::OptionName.to_str())) - .arg(Arg::new("value")) - //.help(UserMessage::OptionValue.to_str())) - .arg( - Arg::new("format") - //.help(UserMessage::OptionFormat.to_str()) - .long("format") - .takes_value(true) - .default_value("json") - .possible_values(&["json", "text"]), - ) + ConfigOpts::into_app().name("rename") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: ConfigOpts = ConfigOpts::from_arg_matches(args); // Cannot use the `env` variable as we need a mutable copy. let mut config: Config = env .get_config() @@ -30,8 +36,8 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { .as_ref() .clone(); - let config_path = args.value_of("config_path").unwrap_or(""); - let format = args.value_of("format").unwrap_or("json"); + let config_path = opts.config_path.as_str(); + let format = opts.format.as_str(); // We replace `.` with `/` so the user can use `path.value.field` instead of forcing him // to use `path/value/field`. Since none of our keys have slashes or tildes in them it @@ -47,7 +53,7 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { config_path.clear() } - if let Some(arg_value) = args.value_of("value") { + if let Some(arg_value) = Some(opts.value).and_then(|v| Some(v.as_str())) { // Try to parse the type of the value (which is a string from the arguments) as // JSON. By default we will just assume the type is string (if all parsing fails). let value = serde_json::from_str::(arg_value) diff --git a/src/dfx/src/commands/deploy.rs b/src/dfx/src/commands/deploy.rs index 2365a43c99..1afee7f2b7 100644 --- a/src/dfx/src/commands/deploy.rs +++ b/src/dfx/src/commands/deploy.rs @@ -1,50 +1,44 @@ use crate::lib::environment::Environment; use crate::lib::error::DfxResult; -use crate::lib::message::UserMessage; use crate::lib::operations::canister::deploy_canisters; use crate::lib::provider::create_agent_environment; use crate::util::expiry_duration; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; + +/// Deploys all or a specific canister from the code in your project. By default, all canisters are deployed. +#[derive(Clap)] +pub struct DeployOpts { + /// Specifies the name of the canister you want to deploy. + /// If you don’t specify a canister name, all canisters defined in the dfx.json file are deployed. + #[clap(long)] + canister_name: Option, + + /// Override the compute network to connect to. By default, the local network is used. + #[clap(long)] + network: Option, + + /// Specifies the argument to pass to the method. + #[clap(long)] + argument: Option, + + /// Specifies the data type for the argument when making the call using an argument. + #[clap(long, requires("argument"), possible_values(&["idl", "raw"]))] + argument_type: Option, +} pub fn construct() -> App<'static> { - SubCommand::with_name("deploy") - .about(UserMessage::DeployCanister.to_str()) - .arg( - Arg::new("canister_name") - .takes_value(true) - //.help(UserMessage::DeployCanisterName.to_str()) - .required(false), - ) - .arg( - Arg::new("network") - //.help(UserMessage::CanisterComputeNetwork.to_str()) - .long("network") - .takes_value(true), - ) - .arg( - Arg::new("argument") - //.help(UserMessage::ArgumentValue.to_str()) - .long("argument") - .takes_value(true), - ) - .arg( - Arg::new("type") - //.help(UserMessage::ArgumentType.to_str()) - .long("type") - .takes_value(true) - .requires("argument") - .possible_values(&["idl", "raw"]), - ) + DeployOpts::into_app().name("rename") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: DeployOpts = DeployOpts::from_arg_matches(args); let env = create_agent_environment(env, args)?; let timeout = expiry_duration(); - let canister = args.value_of("canister_name"); + let canister = opts.canister_name.and_then(|v| Some(v.as_str())); - let argument = args.value_of("argument"); - let argument_type = args.value_of("type"); + let argument = opts.argument.and_then(|v| Some(v.as_str())); + let argument_type = opts.argument_type.and_then(|v| Some(v.as_str())); deploy_canisters(&env, canister, argument, argument_type, timeout) } diff --git a/src/dfx/src/commands/identity/new.rs b/src/dfx/src/commands/identity/new.rs index 2cbcf36a3f..2d1e5a734a 100644 --- a/src/dfx/src/commands/identity/new.rs +++ b/src/dfx/src/commands/identity/new.rs @@ -1,23 +1,24 @@ use crate::lib::environment::Environment; use crate::lib::error::DfxResult; use crate::lib::identity::identity_manager::IdentityManager; -use crate::lib::message::UserMessage; -use clap::{App, Arg, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use slog::info; +/// Creates a new identity. +#[derive(Clap)] +pub struct NewIdentityOpts { + /// The identity to create. + #[clap(long)] + identity: String, +} + pub fn construct() -> App<'static> { - SubCommand::with_name("new") - .about(UserMessage::NewIdentity.to_str()) - .arg( - Arg::new("identity") - //.help("The identity to create.") - .required(true) - .takes_value(true), - ) + NewIdentityOpts::into_app().name("rename") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { - let name = args.value_of("identity").unwrap(); + let opts: NewIdentityOpts = NewIdentityOpts::from_arg_matches(args); + let name = opts.identity.as_str(); let log = env.get_logger(); info!(log, r#"Creating identity: "{}"."#, name); diff --git a/src/dfx/src/commands/new.rs b/src/dfx/src/commands/new.rs index b309261a1c..319d79897c 100644 --- a/src/dfx/src/commands/new.rs +++ b/src/dfx/src/commands/new.rs @@ -82,8 +82,7 @@ pub struct NewOpts { } pub fn construct() -> App<'static> { - NewOpts::into_app() - .name("new") + NewOpts::into_app().name("new") } enum Status<'a> { diff --git a/src/dfx/src/lib/message.rs b/src/dfx/src/lib/message.rs index d0d04ebaa3..0b407d1e03 100644 --- a/src/dfx/src/lib/message.rs +++ b/src/dfx/src/lib/message.rs @@ -18,128 +18,37 @@ macro_rules! user_message { } user_message!( - // dfx bootstrap - BootstrapCommand => "Starts the bootstrap server.", - BootstrapIP => "Specifies the IP address that the bootstrap server listens on. Defaults to 127.0.0.1.", - BootstrapPort => "Specifies the port number that the bootstrap server listens on. Defaults to 8081.", - BootstrapRoot => "Specifies the directory containing static assets served by the bootstrap server. Defaults to $HOME/.cache/dfinity/versions/$DFX_VERSION/js-user-library/dist/bootstrap.", - BootstrapTimeout => "Specifies the maximum number of seconds that the bootstrap server will wait for upstream requests to complete. Defaults to 30.", - // dfx cache ManageCache => "Manages the dfx version cache.", - CacheDelete => "Deletes a specific versioned cache of dfx.", CacheUnpack => "Forces unpacking the cache from this dfx version.", CacheList => "Lists installed and used version.", CacheShow => "Shows the path of the cache used by this version.", - // dfx canister id - IdCanister => "Prints the identifier of a canister.", - // dfx canister call CallCanister => "Calls a method on a deployed canister.", - MethodName => "Specifies the method name to call on the canister.", AsyncResult => "Specifies not to wait for the result of the call to be returned by polling the replica. Instead return a response ID.", ArgumentType => "Specifies the data type for the argument when making the call using an argument.", OutputType => "Specifies the format for displaying the method's return result.", ArgumentValue => "Specifies the argument to pass to the method.", - - // dfx canister create - CreateCanister => "Creates an empty canister on the Internet Computer and associates the Internet Computer assigned Canister ID to the canister name.", - CreateCanisterName => "Specifies the canister name. Either this or the --all flag are required.", - CreateAll => "Creates all canisters configured in dfx.json.", - - // dfx canister install - InstallCanister => "Deploys compiled code as a canister on the Internet Computer.", - InstallAll => "Deploys all canisters configured in the project dfx.json files.", - InstallCanisterName => "Specifies the canister name to deploy. You must specify either canister name or the --all option.", - InstallComputeAllocation => "Specifies the canister's compute allocation. This should be a percent in the range [0..100]", - InstallMemoryAllocation => "Specifies how much memory the canister is allowed to use in total. This should be a value in the range [0..256 TB]", - InstallMode => "Specifies the type of deployment. You can set the canister deployment modes to install, reinstall, or upgrade.", - // dfx canister mod ManageCanister => "Manages canisters deployed on a network replica.", - // dfx canister delete - DeleteCanister => "Deletes a canister on the Internet Computer network.", - DeleteCanisterName => "Specifies the name of the canister to delete. You must specify either a canister name or the --all flag.", - DeleteAll => "Deletes all of the canisters configured in the dfx.json file.", - - // dfx canister set-controller - SetController => "Sets the provided identity's name or its principal as the new controller of a canister on the Internet Computer network.", - SetControllerCanister => "Specifies the canister name or the canister identifier for the canister to be controlled.", - NewController => "Specifies the identity name or the principal of the new controller.", - - // dfx canister status - CanisterStatus => "Returns the current status of the canister on the Internet Computer network: Running, Stopping, or Stopped.", - StatusCanisterName => "Specifies the name of the canister to return information for. You must specify either a canister name or the --all flag.", - StatusAll => "Returns status information for all of the canisters configured in the dfx.json file.", - - // dfx canister start - StartCanister => "Starts a canister on the Internet Computer network.", - StartCanisterName => "Specifies the name of the canister to start. You must specify either a canister name or the --all flag.", - StartAll => "Starts all of the canisters configured in the dfx.json file.", - - // dfx canister stop - StopCanister => "Stops a canister that is currently running on the Internet Computer network.", - StopCanisterName => "Specifies the name of the canister to stop. You must specify either a canister name or the --all option.", - StopAll => "Stops all of the canisters configured in the dfx.json file.", - - // dfx canister query - QueryCanister => "Sends a query request to a canister.", - UpdateCanisterArg => "Sends an update request to a canister. This is the default if the method is not a query method.", - - // dfx canister request_status - RequestCallStatus => "Requests the status of a specified call from a canister.", - RequestId => "Specifies the request identifier. The request identifier is an hexadecimal string starting with 0x.", - // dfx build - BuildAll => "Builds all canisters configured in the dfx.json file.", - BuildCanisterName => "Specifies the name of the canister to build. You must specify either a canister name or the --all option.", - BuildCanister => "Builds all or specific canisters from the code in your project. By default, all canisters are built.", - BuildCheck => "Build canisters without creating them. This can be used to check that canisters build ok.", CanisterComputeNetwork => "Override the compute network to connect to. By default, the local network is used.", - // dfx config - ConfigureOptions => "Configures project options for your currently-selected project.", - OptionName => "Specifies the name of the configuration option to set or read. Use the period delineated path to specify the option to set or read. If this is not mentioned, outputs the whole configuration.", - OptionValue => "Specifies the new value to set. If you don't specify a value, the command displays the current value of the option from the configuration file.", - OptionFormat => "Specifies the format of the output. By default, the output format is JSON.", - - // dfx deploy - DeployCanister => "Deploys all or a specific canister from the code in your project. By default, all canisters are deployed.", - DeployCanisterName => "Specifies the name of the canister you want to deploy. If you don’t specify a canister name, all canisters defined in the dfx.json file are deployed.", - // dfx identity mod ManageIdentity => "Manages identities used to communicate with the Internet Computer network. Setting an identity enables you to test user-based access controls.", - // dfx identity new - NewIdentity => "Creates a new identity.", - // dfx identity list ListIdentities => "Lists existing identities.", - // dfx identity remove - RemoveIdentity => "Removes an existing identity.", - - // dfx identity rename - RenameIdentity => "Renames an existing identity.", - - // dfx identity use - UseIdentity => "Specifies the identity to use.", - // dfx identity whoami ShowIdentity => "Shows the name of the current identity.", // dfx identity get-principal GetPrincipalId => "Shows the textual representation of the Principal associated with the current identity.", - // dfx new - CreateProject => "Creates a new project.", - ProjectName => "Specifies the name of the project to create.", - DryRun => "Provides a preview the directories and files to be created without adding them to the file system.", - NewFrontend => "Installs the frontend code example for the default canister. This defaults to true if Node is installed, or false if it isn't.", - // dfx replica ReplicaRoundGasLimit => "Specifies the maximum number of cycles a single round can consume.", diff --git a/src/dfx/src/main.rs b/src/dfx/src/main.rs index 41340af40d..8bf57ebde2 100644 --- a/src/dfx/src/main.rs +++ b/src/dfx/src/main.rs @@ -20,15 +20,10 @@ fn cli(_: &impl Environment) -> App<'_> { .arg( Arg::new("verbose") .long("verbose") - .short("v") - .multiple(true), - ) - .arg( - Arg::new("quiet") - .long("quiet") - .short("q") + .short('v') .multiple(true), ) + .arg(Arg::new("quiet").long("quiet").short('q').multiple(true)) .arg( Arg::new("logmode") .long("log") @@ -42,11 +37,7 @@ fn cli(_: &impl Environment) -> App<'_> { .long("logfile") .takes_value(true), ) - .arg( - Arg::new("identity") - .long("identity") - .takes_value(true), - ) + .arg(Arg::new("identity").long("identity").takes_value(true)) .subcommands( commands::builtin() .into_iter() diff --git a/src/dfx/src/util/clap/validators.rs b/src/dfx/src/util/clap/validators.rs index 713cd3a91d..5f7b5b9c36 100644 --- a/src/dfx/src/util/clap/validators.rs +++ b/src/dfx/src/util/clap/validators.rs @@ -1,4 +1,4 @@ -pub fn is_request_id(v: String) -> Result<(), String> { +pub fn is_request_id(v: &str) -> Result<(), String> { // A valid Request Id starts with `0x` and is a series of 64 hexadecimals. if !v.starts_with("0x") { Err(String::from("A Request ID needs to start with 0x.")) @@ -6,7 +6,7 @@ pub fn is_request_id(v: String) -> Result<(), String> { Err(String::from( "A Request ID is 64 hexadecimal prefixed with 0x.", )) - } else if v.as_str()[2..].contains(|c: char| !c.is_ascii_hexdigit()) { + } else if v[2..].contains(|c: char| !c.is_ascii_hexdigit()) { Err(String::from( "A Request ID is 64 hexadecimal prefixed with 0x. An invalid character was found.", )) From c60cd8b34e10e2d6ee59f668e22c32a4022e68f8 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Fri, 30 Oct 2020 09:56:42 -0700 Subject: [PATCH 14/26] cache and identity commands --- src/dfx/src/commands/cache/delete.rs | 2 +- src/dfx/src/commands/cache/install.rs | 9 ++++++--- src/dfx/src/commands/cache/list.rs | 9 ++++++--- src/dfx/src/commands/cache/show.rs | 9 ++++++--- src/dfx/src/commands/identity/list.rs | 9 ++++++--- src/dfx/src/commands/identity/principal.rs | 9 ++++++--- src/dfx/src/commands/identity/whoami.rs | 9 ++++++--- src/dfx/src/commands/upgrade.rs | 2 +- src/dfx/src/lib/message.rs | 12 ------------ 9 files changed, 38 insertions(+), 32 deletions(-) diff --git a/src/dfx/src/commands/cache/delete.rs b/src/dfx/src/commands/cache/delete.rs index e77f783bd3..5a15231152 100644 --- a/src/dfx/src/commands/cache/delete.rs +++ b/src/dfx/src/commands/cache/delete.rs @@ -17,7 +17,7 @@ pub fn construct() -> App<'static> { pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let opts: CacheDeleteOpts = CacheDeleteOpts::from_arg_matches(args); match opts.version { - Some(v) => delete_version(v).map(|_| {}), + Some(v) => delete_version(v.as_str()).map(|_| {}), _ => env.get_cache().delete(), } } diff --git a/src/dfx/src/commands/cache/install.rs b/src/dfx/src/commands/cache/install.rs index b31ac5f170..cbdae8e5e3 100644 --- a/src/dfx/src/commands/cache/install.rs +++ b/src/dfx/src/commands/cache/install.rs @@ -1,10 +1,13 @@ use crate::lib::environment::Environment; use crate::lib::error::DfxResult; -use crate::lib::message::UserMessage; -use clap::{App, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, IntoApp}; + +/// Forces unpacking the cache from this dfx version. +#[derive(Clap)] +pub struct CacheInstall {} pub fn construct() -> App<'static> { - SubCommand::with_name("install").about(UserMessage::CacheUnpack.to_str()) + CacheInstall::into_app().name("install") } pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/cache/list.rs b/src/dfx/src/commands/cache/list.rs index 7da4c493ee..47aaa0128c 100644 --- a/src/dfx/src/commands/cache/list.rs +++ b/src/dfx/src/commands/cache/list.rs @@ -1,12 +1,15 @@ use crate::config::{cache, dfx_version}; use crate::lib::environment::Environment; use crate::lib::error::DfxResult; -use crate::lib::message::UserMessage; -use clap::{App, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, IntoApp}; use std::io::Write; +/// Lists installed and used version. +#[derive(Clap)] +pub struct CacheListOpts {} + pub fn construct() -> App<'static> { - SubCommand::with_name("list").about(UserMessage::CacheList.to_str()) + CacheListOpts::into_app().name("list") } pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/cache/show.rs b/src/dfx/src/commands/cache/show.rs index 56636bbab6..6fcefd841f 100644 --- a/src/dfx/src/commands/cache/show.rs +++ b/src/dfx/src/commands/cache/show.rs @@ -1,11 +1,14 @@ use crate::config::cache; use crate::lib::environment::Environment; use crate::lib::error::DfxResult; -use crate::lib::message::UserMessage; -use clap::{App, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, IntoApp}; + +/// Shows the path of the cache used by this version. +#[derive(Clap)] +pub struct CacheShowOpts {} pub fn construct() -> App<'static> { - SubCommand::with_name("show").about(UserMessage::CacheShow.to_str()) + CacheShowOpts::into_app().name("show") } pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/identity/list.rs b/src/dfx/src/commands/identity/list.rs index 6eda8f475e..6096eee398 100644 --- a/src/dfx/src/commands/identity/list.rs +++ b/src/dfx/src/commands/identity/list.rs @@ -1,12 +1,15 @@ use crate::lib::environment::Environment; use crate::lib::error::DfxResult; use crate::lib::identity::identity_manager::IdentityManager; -use crate::lib::message::UserMessage; -use clap::{App, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, IntoApp}; use std::io::Write; +/// Lists existing identities. +#[derive(Clap)] +pub struct ListOpts {} + pub fn construct() -> App<'static> { - SubCommand::with_name("list").about(UserMessage::ListIdentities.to_str()) + ListOpts::into_app().name("list") } pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/identity/principal.rs b/src/dfx/src/commands/identity/principal.rs index 3b6ae48d25..85147a41c6 100644 --- a/src/dfx/src/commands/identity/principal.rs +++ b/src/dfx/src/commands/identity/principal.rs @@ -1,12 +1,15 @@ use crate::lib::environment::Environment; use crate::lib::error::DfxResult; use crate::lib::identity::identity_manager::IdentityManager; -use crate::lib::message::UserMessage; -use clap::{App, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, IntoApp}; use ic_agent::Identity; +/// Shows the textual representation of the Principal associated with the current identity. +#[derive(Clap)] +pub struct GetPrincipalOpts {} + pub fn construct() -> App<'static> { - SubCommand::with_name("get-principal").about(UserMessage::GetPrincipalId.to_str()) + GetPrincipalOpts::into_app().name("get-principal") } pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/identity/whoami.rs b/src/dfx/src/commands/identity/whoami.rs index 38e469c1e1..3e411289ae 100644 --- a/src/dfx/src/commands/identity/whoami.rs +++ b/src/dfx/src/commands/identity/whoami.rs @@ -1,11 +1,14 @@ use crate::lib::environment::Environment; use crate::lib::error::DfxResult; use crate::lib::identity::identity_manager::IdentityManager; -use crate::lib::message::UserMessage; -use clap::{App, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, IntoApp}; + +/// Shows the name of the current identity. +#[derive(Clap)] +pub struct WhoAmIOpts {} pub fn construct() -> App<'static> { - SubCommand::with_name("whoami").about(UserMessage::ShowIdentity.to_str()) + WhoAmIOpts::into_app().name("whoami") } pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/upgrade.rs b/src/dfx/src/commands/upgrade.rs index 4819523f9e..d93602504d 100644 --- a/src/dfx/src/commands/upgrade.rs +++ b/src/dfx/src/commands/upgrade.rs @@ -1,6 +1,6 @@ use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use clap::{App, AppSettings, Arg, ArgMatches, Clap, FromArgMatches, IntoApp}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use indicatif::{ProgressBar, ProgressDrawTarget}; use libflate::gzip::Decoder; use semver::Version; diff --git a/src/dfx/src/lib/message.rs b/src/dfx/src/lib/message.rs index 0b407d1e03..ac40268a71 100644 --- a/src/dfx/src/lib/message.rs +++ b/src/dfx/src/lib/message.rs @@ -20,9 +20,6 @@ macro_rules! user_message { user_message!( // dfx cache ManageCache => "Manages the dfx version cache.", - CacheUnpack => "Forces unpacking the cache from this dfx version.", - CacheList => "Lists installed and used version.", - CacheShow => "Shows the path of the cache used by this version.", // dfx canister call CallCanister => "Calls a method on a deployed canister.", @@ -40,15 +37,6 @@ user_message!( // dfx identity mod ManageIdentity => "Manages identities used to communicate with the Internet Computer network. Setting an identity enables you to test user-based access controls.", - // dfx identity list - ListIdentities => "Lists existing identities.", - - // dfx identity whoami - ShowIdentity => "Shows the name of the current identity.", - - // dfx identity get-principal - GetPrincipalId => "Shows the textual representation of the Principal associated with the current identity.", - // dfx replica ReplicaRoundGasLimit => "Specifies the maximum number of cycles a single round can consume.", From b6ab536380dc6069da8ee41a590b88386207aa74 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Sat, 31 Oct 2020 17:22:48 -0700 Subject: [PATCH 15/26] fix compilation errors --- src/dfx/src/commands/bootstrap.rs | 10 ++-- src/dfx/src/commands/cache/mod.rs | 6 +-- src/dfx/src/commands/canister/call.rs | 6 +-- src/dfx/src/commands/canister/install.rs | 15 +++--- src/dfx/src/commands/canister/mod.rs | 4 +- src/dfx/src/commands/config.rs | 2 +- src/dfx/src/commands/deploy.rs | 8 ++-- src/dfx/src/commands/identity/mod.rs | 6 +-- src/dfx/src/commands/language_service.rs | 48 +++++++++---------- src/dfx/src/commands/upgrade.rs | 4 +- .../operations/canister/deploy_canisters.rs | 11 +++-- src/dfx/src/main.rs | 8 ++-- src/dfx/src/util/mod.rs | 16 ++++--- 13 files changed, 75 insertions(+), 69 deletions(-) diff --git a/src/dfx/src/commands/bootstrap.rs b/src/dfx/src/commands/bootstrap.rs index a43f93a014..b6c860c960 100644 --- a/src/dfx/src/commands/bootstrap.rs +++ b/src/dfx/src/commands/bootstrap.rs @@ -17,7 +17,7 @@ use std::time::Duration; use url::Url; /// Starts the bootstrap server. -#[derive(Clap)] +#[derive(Clap, Clone)] pub struct BootstrapOpts { /// Specifies the IP address that the bootstrap server listens on. Defaults to 127.0.0.1. #[clap(long)] @@ -55,7 +55,7 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { .ok_or(DfxError::CommandMustBeRunInAProject)?; let config_defaults = get_config_defaults_from_file(env); let base_config_bootstrap = config_defaults.get_bootstrap().to_owned(); - let config_bootstrap = apply_arguments(&base_config_bootstrap, env, opts)?; + let config_bootstrap = apply_arguments(&base_config_bootstrap, env, opts.clone())?; let network_descriptor = get_network_descriptor(env, opts.network)?; let build_output_root = config.get_temp_path().join(network_descriptor.name.clone()); @@ -116,7 +116,7 @@ fn apply_arguments( ) -> DfxResult { let ip = get_ip(&config, opts.ip)?; let port = get_port(&config, opts.port)?; - let root = get_root(&config, env, opts.root.and_then(|v| Some(v.as_str())))?; + let root = get_root(&config, env, opts.root)?; let timeout = get_timeout(&config, opts.timeout)?; Ok(ConfigDefaultsBootstrap { ip: Some(ip), @@ -174,9 +174,9 @@ fn get_providers(network_descriptor: &NetworkDescriptor) -> DfxResult, + root: Option, ) -> DfxResult { - root.map(|root| parse_dir(root)) + root.map(|root| parse_dir(root.as_str())) .unwrap_or_else(|| { config .root diff --git a/src/dfx/src/commands/cache/mod.rs b/src/dfx/src/commands/cache/mod.rs index e8f2d06920..5bea009f0f 100644 --- a/src/dfx/src/commands/cache/mod.rs +++ b/src/dfx/src/commands/cache/mod.rs @@ -2,7 +2,7 @@ use crate::commands::CliCommand; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; use crate::lib::message::UserMessage; -use clap::{App, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; mod delete; mod install; @@ -19,7 +19,7 @@ fn builtins() -> Vec { } pub fn construct() -> App<'static> { - SubCommand::with_name("cache") + App::new("cache") .about(UserMessage::ManageCache.to_str()) .subcommands(builtins().into_iter().map(|x| x.get_subcommand().clone())) } @@ -27,7 +27,7 @@ pub fn construct() -> App<'static> { pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let subcommand = args.subcommand(); - if let (name, Some(subcommand_args)) = subcommand { + if let Some((name, subcommand_args)) = subcommand { match builtins().into_iter().find(|x| name == x.get_name()) { Some(cmd) => cmd.execute(env, subcommand_args), None => Err(DfxError::UnknownCommand(format!( diff --git a/src/dfx/src/commands/canister/call.rs b/src/dfx/src/commands/canister/call.rs index 04ebe1f54f..19a8e479ed 100644 --- a/src/dfx/src/commands/canister/call.rs +++ b/src/dfx/src/commands/canister/call.rs @@ -82,9 +82,9 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { None => None, }; - let arguments: Option<&str> = opts.argument.and_then(|v| Some(v.as_str())); - let arg_type: Option<&str> = opts.argument_type.and_then(|v| Some(v.as_str())); - let output_type: Option<&str> = opts.output.and_then(|v| Some(v.as_str())); + let arguments: Option = opts.argument; + let arg_type: Option = opts.argument_type; + let output_type: Option = opts.output; let is_query = if opts.async_call { false } else { diff --git a/src/dfx/src/commands/canister/install.rs b/src/dfx/src/commands/canister/install.rs index 4c81b1620f..f0935a1f68 100644 --- a/src/dfx/src/commands/canister/install.rs +++ b/src/dfx/src/commands/canister/install.rs @@ -13,7 +13,7 @@ use std::str::FromStr; use tokio::runtime::Runtime; /// Deploys compiled code as a canister on the Internet Computer. -#[derive(Clap)] +#[derive(Clap, Clone)] pub struct CanisterInstallOpts { /// Specifies the canister name to deploy. You must specify either canister name or the --all option. #[clap(long, required_unless_present("all"))] @@ -127,8 +127,8 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let maybe_path = canister_info.get_output_idl_path(); let init_type = maybe_path.and_then(|path| get_candid_init_type(&path)); - let arguments: Option<&str> = opts.argument.and_then(|v| Some(v.as_str())); - let arg_type: Option<&str> = opts.argument_type.and_then(|v| Some(v.as_str())); + let arguments: Option = opts.argument; + let arg_type: Option = opts.argument_type; let install_args = blob_from_arguments(arguments, arg_type, &init_type)?; let compute_allocation = @@ -157,12 +157,15 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let install_args = []; let compute_allocation = get_compute_allocation( - opts.compute_allocation, + opts.compute_allocation.clone(), + config_interface, + canister_name, + )?; + let memory_allocation = get_memory_allocation( + opts.memory_allocation.clone(), config_interface, canister_name, )?; - let memory_allocation = - get_memory_allocation(opts.memory_allocation, config_interface, canister_name)?; runtime.block_on(install_canister( env, diff --git a/src/dfx/src/commands/canister/mod.rs b/src/dfx/src/commands/canister/mod.rs index 6ad4a37c9a..d09c4cc33a 100644 --- a/src/dfx/src/commands/canister/mod.rs +++ b/src/dfx/src/commands/canister/mod.rs @@ -32,7 +32,7 @@ fn builtins() -> Vec { } pub fn construct() -> App<'static> { - SubCommand::with_name("canister") + App::new("canister") .about(UserMessage::ManageCanister.to_str()) .arg( Arg::new("network") @@ -47,7 +47,7 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let subcommand = args.subcommand(); let agent_env = create_agent_environment(env, args)?; - if let (name, Some(subcommand_args)) = subcommand { + if let Some((name, subcommand_args)) = subcommand { match builtins().into_iter().find(|x| name == x.get_name()) { Some(cmd) => cmd.execute(&agent_env, subcommand_args), None => Err(DfxError::UnknownCommand(format!( diff --git a/src/dfx/src/commands/config.rs b/src/dfx/src/commands/config.rs index d4704dccf6..0b099cc3e7 100644 --- a/src/dfx/src/commands/config.rs +++ b/src/dfx/src/commands/config.rs @@ -53,7 +53,7 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { config_path.clear() } - if let Some(arg_value) = Some(opts.value).and_then(|v| Some(v.as_str())) { + if let Some(arg_value) = Some(opts.value.as_str()) { // Try to parse the type of the value (which is a string from the arguments) as // JSON. By default we will just assume the type is string (if all parsing fails). let value = serde_json::from_str::(arg_value) diff --git a/src/dfx/src/commands/deploy.rs b/src/dfx/src/commands/deploy.rs index 1afee7f2b7..7953a79712 100644 --- a/src/dfx/src/commands/deploy.rs +++ b/src/dfx/src/commands/deploy.rs @@ -35,10 +35,12 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let env = create_agent_environment(env, args)?; let timeout = expiry_duration(); - let canister = opts.canister_name.and_then(|v| Some(v.as_str())); + // let canister = opts.canister_name.and_then(|v| Some(v.as_str())); + let canister_name = opts.canister_name.unwrap(); + let canister = Some(canister_name.as_str()); - let argument = opts.argument.and_then(|v| Some(v.as_str())); - let argument_type = opts.argument_type.and_then(|v| Some(v.as_str())); + let argument = opts.argument; + let argument_type = opts.argument_type; deploy_canisters(&env, canister, argument, argument_type, timeout) } diff --git a/src/dfx/src/commands/identity/mod.rs b/src/dfx/src/commands/identity/mod.rs index 63f32c088b..40b97a5f2a 100644 --- a/src/dfx/src/commands/identity/mod.rs +++ b/src/dfx/src/commands/identity/mod.rs @@ -2,7 +2,7 @@ use crate::commands::CliCommand; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; use crate::lib::message::UserMessage; -use clap::{App, ArgMatches, SubCommand}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; mod list; mod new; @@ -25,7 +25,7 @@ fn builtins() -> Vec { } pub fn construct() -> App<'static> { - SubCommand::with_name("identity") + App::new("identity") .about(UserMessage::ManageIdentity.to_str()) .subcommands(builtins().into_iter().map(|x| x.get_subcommand().clone())) } @@ -33,7 +33,7 @@ pub fn construct() -> App<'static> { pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let subcommand = args.subcommand(); - if let (name, Some(subcommand_args)) = subcommand { + if let Some((name, subcommand_args)) = subcommand { match builtins().into_iter().find(|x| name == x.get_name()) { Some(cmd) => cmd.execute(env, subcommand_args), None => Err(DfxError::UnknownCommand(format!( diff --git a/src/dfx/src/commands/language_service.rs b/src/dfx/src/commands/language_service.rs index a09e05547b..6825b90185 100644 --- a/src/dfx/src/commands/language_service.rs +++ b/src/dfx/src/commands/language_service.rs @@ -56,36 +56,34 @@ fn get_main_path( // TODO try and point at the actual dfx.json path let dfx_json = CONFIG_FILE_NAME; - let (canister_name, canister): (String, ConfigCanistersCanister) = match ( - config.canisters.as_ref(), - canister_name.and_then(|v| Some(v.as_str())), - ) { - (None, _) => Err(DfxError::InvalidData(format!( - "Missing field 'canisters' in {0}", - dfx_json - ))), + let (canister_name, canister): (String, ConfigCanistersCanister) = + match (config.canisters.as_ref(), canister_name) { + (None, _) => Err(DfxError::InvalidData(format!( + "Missing field 'canisters' in {0}", + dfx_json + ))), - (Some(canisters), Some(cn)) => { - let c = canisters.get(cn).ok_or_else(|| { - DfxError::InvalidArgument(format!( - "Canister {0} cannot not be found in {1}", - cn, dfx_json - )) - })?; - Ok((cn.to_string(), c.clone())) - } - (Some(canisters), None) => { - if canisters.len() == 1 { - let (n, c) = canisters.iter().next().unwrap(); - Ok((n.to_string(), c.clone())) - } else { - Err(DfxError::InvalidData(format!( + (Some(canisters), Some(cn)) => { + let c = canisters.get(cn.as_str()).ok_or_else(|| { + DfxError::InvalidArgument(format!( + "Canister {0} cannot not be found in {1}", + cn, dfx_json + )) + })?; + Ok((cn.to_string(), c.clone())) + } + (Some(canisters), None) => { + if canisters.len() == 1 { + let (n, c) = canisters.iter().next().unwrap(); + Ok((n.to_string(), c.clone())) + } else { + Err(DfxError::InvalidData(format!( "There are multiple canisters in {0}, please select one using the {1} argument", dfx_json, CANISTER_ARG ))) + } } - } - }?; + }?; canister .extras diff --git a/src/dfx/src/commands/upgrade.rs b/src/dfx/src/commands/upgrade.rs index d93602504d..25fb9a19ef 100644 --- a/src/dfx/src/commands/upgrade.rs +++ b/src/dfx/src/commands/upgrade.rs @@ -159,8 +159,8 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { "macos" => "x86_64-darwin", _ => panic!("Not supported architecture"), }; - let current_version = if let Some(version) = opts.current_version.and_then(|v| Some(v.as_str())) - { + let curr_ver_str = opts.current_version.unwrap(); + let current_version = if let Some(version) = Some(curr_ver_str.as_str()) { Version::parse(version)? } else { env.get_version().clone() diff --git a/src/dfx/src/lib/operations/canister/deploy_canisters.rs b/src/dfx/src/lib/operations/canister/deploy_canisters.rs index 375804cd61..0dca6f9b5a 100644 --- a/src/dfx/src/lib/operations/canister/deploy_canisters.rs +++ b/src/dfx/src/lib/operations/canister/deploy_canisters.rs @@ -19,8 +19,8 @@ use tokio::runtime::Runtime; pub fn deploy_canisters( env: &dyn Environment, some_canister: Option<&str>, - argument: Option<&str>, - argument_type: Option<&str>, + argument: Option, + argument_type: Option, timeout: Duration, ) -> DfxResult { let log = env.get_logger(); @@ -99,8 +99,8 @@ fn install_canisters( canister_names: &[String], initial_canister_id_store: &CanisterIdStore, config: &Config, - argument: Option<&str>, - argument_type: Option<&str>, + argument: Option, + argument_type: Option, timeout: Duration, ) -> DfxResult { info!(env.get_logger(), "Installing canisters..."); @@ -124,7 +124,8 @@ fn install_canisters( let maybe_path = canister_info.get_output_idl_path(); let init_type = maybe_path.and_then(|path| get_candid_init_type(&path)); - let install_args = blob_from_arguments(argument, argument_type, &init_type)?; + let install_args = + blob_from_arguments(argument.clone(), argument_type.clone(), &init_type)?; let config_interface = config.get_config(); let compute_allocation = diff --git a/src/dfx/src/main.rs b/src/dfx/src/main.rs index 8bf57ebde2..45b8240015 100644 --- a/src/dfx/src/main.rs +++ b/src/dfx/src/main.rs @@ -12,7 +12,7 @@ mod config; mod lib; mod util; -fn cli(_: &impl Environment) -> App<'_> { +fn cli(_: &impl Environment) -> App<'static> { App::new("dfx") .about("The DFINITY Executor.") .version(dfx_version_str()) @@ -45,9 +45,9 @@ fn cli(_: &impl Environment) -> App<'_> { ) } -fn exec(env: &impl Environment, args: &clap::ArgMatches, cli: &App<'_>) -> DfxResult { +fn exec(env: &impl Environment, args: &clap::ArgMatches, cli: &mut App<'static>) -> DfxResult { let (name, subcommand_args) = match args.subcommand() { - (name, Some(args)) => (name, args), + Some((name, args)) => (name, args), _ => { cli.write_help(&mut std::io::stderr())?; eprintln!(); @@ -163,7 +163,7 @@ fn main() { env.get_logger(), "Trace mode enabled. Lots of logs coming up." ); - exec(&env, &matches, &(cli(&env))) + exec(&env, &matches, &mut (cli(&env))) } Err(e) => Err(e), } diff --git a/src/dfx/src/util/mod.rs b/src/dfx/src/util/mod.rs index 7f8e0c2629..b941abf79f 100644 --- a/src/dfx/src/util/mod.rs +++ b/src/dfx/src/util/mod.rs @@ -35,10 +35,11 @@ pub fn expiry_duration() -> Duration { /// Deserialize and print return values from canister method. pub fn print_idl_blob( blob: &[u8], - output_type: Option<&str>, + output_type: Option, method_type: &Option<(TypeEnv, Function)>, ) -> DfxResult<()> { - let output_type = output_type.unwrap_or("pp"); + let output_type_str = output_type.unwrap_or("pp".to_string()); + let output_type = output_type_str.as_str(); match output_type { "raw" => { let hex_string = hex::encode(blob); @@ -104,20 +105,21 @@ pub fn check_candid_file(idl_path: &std::path::Path) -> DfxResult<(TypeEnv, Opti } pub fn blob_from_arguments( - arguments: Option<&str>, - arg_type: Option<&str>, + arguments: Option, + arg_type: Option, method_type: &Option<(TypeEnv, Function)>, ) -> DfxResult> { - let arg_type = arg_type.unwrap_or("idl"); + let arg_type_str = arg_type.unwrap_or("idl".to_string()); + let arg_type = arg_type_str.as_str(); match arg_type { "raw" => { - let bytes = hex::decode(&arguments.unwrap_or("")).map_err(|e| { + let bytes = hex::decode(&arguments.unwrap_or("".to_string())).map_err(|e| { DfxError::InvalidArgument(format!("Argument is not a valid hex string: {}", e)) })?; Ok(bytes) } "idl" => { - let arguments = arguments.unwrap_or("()"); + let arguments = arguments.unwrap_or("()".to_string()); let typed_args = match method_type { None => candid::pretty_parse::("Candid argument", &arguments) .map_err(|e| { From e61f07c748c092aedd47ce1227687c443dff6859 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Sat, 31 Oct 2020 18:58:29 -0700 Subject: [PATCH 16/26] patches --- src/dfx/src/commands/build.rs | 18 +++++++----------- src/dfx/src/commands/cache/mod.rs | 2 +- src/dfx/src/commands/canister/mod.rs | 2 +- src/dfx/src/commands/deploy.rs | 7 +++---- src/dfx/src/commands/identity/mod.rs | 2 +- src/dfx/src/commands/language_service.rs | 2 +- src/dfx/src/commands/new.rs | 10 +++++----- src/dfx/src/commands/upgrade.rs | 7 +++---- src/dfx/src/lib/message.rs | 20 ++++++++++---------- src/dfx/src/lib/provider.rs | 4 ++-- src/dfx/src/util/mod.rs | 8 ++++---- 11 files changed, 38 insertions(+), 44 deletions(-) diff --git a/src/dfx/src/commands/build.rs b/src/dfx/src/commands/build.rs index 3e2f1d84e3..bc059fb81c 100644 --- a/src/dfx/src/commands/build.rs +++ b/src/dfx/src/commands/build.rs @@ -11,20 +11,15 @@ use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; pub struct CanisterBuildOpts { /// Specifies the name of the canister to build. /// You must specify either a canister name or the --all option.", - #[clap(long, required_unless_present("all"))] - canister_name: String, - - /// Builds all canisters configured in the dfx.json file. - #[clap(long, required_unless_present("canister_name"))] - all: bool, + #[clap(long)] + canister_name: Option, /// Build canisters without creating them. This can be used to check that canisters build ok. #[clap(long)] check: bool, - - /// Override the compute network to connect to. By default, the local network is used. - #[clap(long)] - network: Option, + // Override the compute network to connect to. By default, the local network is used. + // #[clap(long)] + // network: Option, } pub fn construct() -> App<'static> { @@ -49,7 +44,8 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let build_mode_check = opts.check; // Option can be None in which case --all was specified - let some_canister = Some(opts.canister_name.as_str()); + let canister_name = opts.canister_name.unwrap(); + let some_canister = Some(canister_name.as_str()); let canister_names = config .get_config() .get_canister_names_with_dependencies(some_canister)?; diff --git a/src/dfx/src/commands/cache/mod.rs b/src/dfx/src/commands/cache/mod.rs index 5bea009f0f..151a77b160 100644 --- a/src/dfx/src/commands/cache/mod.rs +++ b/src/dfx/src/commands/cache/mod.rs @@ -2,7 +2,7 @@ use crate::commands::CliCommand; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; use crate::lib::message::UserMessage; -use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; +use clap::{App, ArgMatches}; mod delete; mod install; diff --git a/src/dfx/src/commands/canister/mod.rs b/src/dfx/src/commands/canister/mod.rs index d09c4cc33a..9c2e20469f 100644 --- a/src/dfx/src/commands/canister/mod.rs +++ b/src/dfx/src/commands/canister/mod.rs @@ -3,7 +3,7 @@ use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; use crate::lib::message::UserMessage; use crate::lib::provider::create_agent_environment; -use clap::{App, AppSettings, Arg, ArgMatches, FromArgMatches, IntoApp}; +use clap::{App, Arg, ArgMatches}; mod call; mod create; diff --git a/src/dfx/src/commands/deploy.rs b/src/dfx/src/commands/deploy.rs index 7953a79712..fc93eeb33f 100644 --- a/src/dfx/src/commands/deploy.rs +++ b/src/dfx/src/commands/deploy.rs @@ -13,10 +13,9 @@ pub struct DeployOpts { #[clap(long)] canister_name: Option, - /// Override the compute network to connect to. By default, the local network is used. - #[clap(long)] - network: Option, - + // Override the compute network to connect to. By default, the local network is used. + // #[clap(long)] + // network: Option, /// Specifies the argument to pass to the method. #[clap(long)] argument: Option, diff --git a/src/dfx/src/commands/identity/mod.rs b/src/dfx/src/commands/identity/mod.rs index 40b97a5f2a..7b828b9fcb 100644 --- a/src/dfx/src/commands/identity/mod.rs +++ b/src/dfx/src/commands/identity/mod.rs @@ -2,7 +2,7 @@ use crate::commands::CliCommand; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; use crate::lib::message::UserMessage; -use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; +use clap::{App, ArgMatches}; mod list; mod new; diff --git a/src/dfx/src/commands/language_service.rs b/src/dfx/src/commands/language_service.rs index 6825b90185..16b8c11495 100644 --- a/src/dfx/src/commands/language_service.rs +++ b/src/dfx/src/commands/language_service.rs @@ -6,7 +6,7 @@ use clap::{App, AppSettings, ArgMatches, Clap, FromArgMatches, IntoApp}; use std::process::Stdio; const CANISTER_ARG: &str = "canister"; -const FORCE_TTY: &str = "force-tty"; +// const FORCE_TTY: &str = "force-tty"; /// Starts the Motoko IDE Language Server. This is meant to be run by editor plugins not the /// end-user. diff --git a/src/dfx/src/commands/new.rs b/src/dfx/src/commands/new.rs index 319d79897c..ea568ee19c 100644 --- a/src/dfx/src/commands/new.rs +++ b/src/dfx/src/commands/new.rs @@ -18,8 +18,8 @@ use std::process::Stdio; use std::time::Duration; use tar::Archive; -const DRY_RUN: &str = "dry_run"; -const PROJECT_NAME: &str = "project_name"; +// const DRY_RUN: &str = "dry_run"; +// const PROJECT_NAME: &str = "project_name"; const RELEASE_ROOT: &str = "https://sdk.dfinity.org"; lazy_static! { // Tested on a phone tethering connection. This should be fine with @@ -66,7 +66,7 @@ pub fn project_name_validator(name: &str) -> Result<(), String> { #[derive(Clap)] pub struct NewOpts { /// Specifies the name of the project to create. - #[clap(long, validator(project_name_validator))] + #[clap(validator(project_name_validator))] project_name: String, /// Provides a preview the directories and files to be created without adding them to the file system. @@ -74,10 +74,10 @@ pub struct NewOpts { dry_run: bool, /// Installs the frontend code example for the default canister. This defaults to true if Node is installed, or false if it isn't. - #[clap(long, conflicts_with("no_frontend"))] + #[clap(long)] frontend: bool, - #[clap(long, conflicts_with("frontend"))] + #[clap(long, conflicts_with = "frontend")] no_frontend: bool, } diff --git a/src/dfx/src/commands/upgrade.rs b/src/dfx/src/commands/upgrade.rs index 25fb9a19ef..985e3bc2fa 100644 --- a/src/dfx/src/commands/upgrade.rs +++ b/src/dfx/src/commands/upgrade.rs @@ -18,10 +18,9 @@ pub struct UpgradeOpts { // hidden #[clap(long, default_value = "https://sdk.dfinity.org")] release_root: String, - - /// Verbose output. - #[clap(long)] - verbose: bool, + // Verbose output. + // #[clap(long)] + // verbose: bool, } pub fn construct() -> App<'static> { diff --git a/src/dfx/src/lib/message.rs b/src/dfx/src/lib/message.rs index ac40268a71..00d0e50849 100644 --- a/src/dfx/src/lib/message.rs +++ b/src/dfx/src/lib/message.rs @@ -22,30 +22,30 @@ user_message!( ManageCache => "Manages the dfx version cache.", // dfx canister call - CallCanister => "Calls a method on a deployed canister.", - AsyncResult => "Specifies not to wait for the result of the call to be returned by polling the replica. Instead return a response ID.", - ArgumentType => "Specifies the data type for the argument when making the call using an argument.", - OutputType => "Specifies the format for displaying the method's return result.", - ArgumentValue => "Specifies the argument to pass to the method.", + // CallCanister => "Calls a method on a deployed canister.", + // AsyncResult => "Specifies not to wait for the result of the call to be returned by polling the replica. Instead return a response ID.", + // ArgumentType => "Specifies the data type for the argument when making the call using an argument.", + // OutputType => "Specifies the format for displaying the method's return result.", + // ArgumentValue => "Specifies the argument to pass to the method.", // dfx canister mod ManageCanister => "Manages canisters deployed on a network replica.", // dfx build - CanisterComputeNetwork => "Override the compute network to connect to. By default, the local network is used.", + // CanisterComputeNetwork => "Override the compute network to connect to. By default, the local network is used.", // dfx identity mod ManageIdentity => "Manages identities used to communicate with the Internet Computer network. Setting an identity enables you to test user-based access controls.", // dfx replica - ReplicaRoundGasLimit => "Specifies the maximum number of cycles a single round can consume.", + // ReplicaRoundGasLimit => "Specifies the maximum number of cycles a single round can consume.", // misc - CanisterName => "Specifies the canister name. If you don't specify this argument, all canisters are processed.", + // CanisterName => "Specifies the canister name. If you don't specify this argument, all canisters are processed.", // dfx ide - StartLanguageService => "Starts the Motoko IDE Language Server. This is meant to be run by editor plugins not the end-user.", - ForceTTY => "Forces the language server to start even when run from a terminal.", + // StartLanguageService => "Starts the Motoko IDE Language Server. This is meant to be run by editor plugins not the end-user.", + // ForceTTY => "Forces the language server to start even when run from a terminal.", ); impl fmt::Display for UserMessage { diff --git a/src/dfx/src/lib/provider.rs b/src/dfx/src/lib/provider.rs index 66c60a8aee..be7e79cdfd 100644 --- a/src/dfx/src/lib/provider.rs +++ b/src/dfx/src/lib/provider.rs @@ -13,7 +13,7 @@ lazy_static! { } fn set_network_context(network: Option) { - let name = network.unwrap_or("local".to_string()).to_string(); + let name = network.unwrap_or_else(|| "local".to_string()); let mut n = NETWORK_CONTEXT.write().unwrap(); *n = Some(name); @@ -80,7 +80,7 @@ pub fn create_agent_environment<'a>( env: &'a (dyn Environment + 'a), args: &ArgMatches, ) -> DfxResult> { - let network = args.value_of("network").and_then(|v| Some(v.to_string())); + let network = args.value_of("network").map(|v| v.to_string()); let network_descriptor = get_network_descriptor(env, network)?; let timeout = expiry_duration(); AgentEnvironment::new(env, network_descriptor, timeout) diff --git a/src/dfx/src/util/mod.rs b/src/dfx/src/util/mod.rs index b941abf79f..31c6876b6f 100644 --- a/src/dfx/src/util/mod.rs +++ b/src/dfx/src/util/mod.rs @@ -38,7 +38,7 @@ pub fn print_idl_blob( output_type: Option, method_type: &Option<(TypeEnv, Function)>, ) -> DfxResult<()> { - let output_type_str = output_type.unwrap_or("pp".to_string()); + let output_type_str = output_type.unwrap_or_else(|| "pp".to_string()); let output_type = output_type_str.as_str(); match output_type { "raw" => { @@ -109,17 +109,17 @@ pub fn blob_from_arguments( arg_type: Option, method_type: &Option<(TypeEnv, Function)>, ) -> DfxResult> { - let arg_type_str = arg_type.unwrap_or("idl".to_string()); + let arg_type_str = arg_type.unwrap_or_else(|| "idl".to_string()); let arg_type = arg_type_str.as_str(); match arg_type { "raw" => { - let bytes = hex::decode(&arguments.unwrap_or("".to_string())).map_err(|e| { + let bytes = hex::decode(&arguments.unwrap_or_else(|| "".to_string())).map_err(|e| { DfxError::InvalidArgument(format!("Argument is not a valid hex string: {}", e)) })?; Ok(bytes) } "idl" => { - let arguments = arguments.unwrap_or("()".to_string()); + let arguments = arguments.unwrap_or_else(|| "()".to_string()); let typed_args = match method_type { None => candid::pretty_parse::("Candid argument", &arguments) .map_err(|e| { From 222f730b9390ae23a9e50173e526bc54ba596ef3 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Sun, 1 Nov 2020 13:14:04 -0800 Subject: [PATCH 17/26] use deref and some more patches --- src/dfx/src/commands/build.rs | 5 +-- src/dfx/src/commands/canister/call.rs | 14 ++++---- src/dfx/src/commands/canister/create.rs | 10 +++--- src/dfx/src/commands/canister/install.rs | 14 ++++---- src/dfx/src/commands/deploy.rs | 11 +++--- src/dfx/src/commands/new.rs | 34 +++++++++---------- .../operations/canister/deploy_canisters.rs | 11 +++--- src/dfx/src/util/mod.rs | 16 ++++----- 8 files changed, 51 insertions(+), 64 deletions(-) diff --git a/src/dfx/src/commands/build.rs b/src/dfx/src/commands/build.rs index bc059fb81c..995775f88f 100644 --- a/src/dfx/src/commands/build.rs +++ b/src/dfx/src/commands/build.rs @@ -11,7 +11,6 @@ use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; pub struct CanisterBuildOpts { /// Specifies the name of the canister to build. /// You must specify either a canister name or the --all option.", - #[clap(long)] canister_name: Option, /// Build canisters without creating them. This can be used to check that canisters build ok. @@ -44,11 +43,9 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let build_mode_check = opts.check; // Option can be None in which case --all was specified - let canister_name = opts.canister_name.unwrap(); - let some_canister = Some(canister_name.as_str()); let canister_names = config .get_config() - .get_canister_names_with_dependencies(some_canister)?; + .get_canister_names_with_dependencies(opts.canister_name.as_deref())?; // Get pool of canisters to build let canister_pool = CanisterPool::load(&env, build_mode_check, &canister_names)?; diff --git a/src/dfx/src/commands/canister/call.rs b/src/dfx/src/commands/canister/call.rs index 19a8e479ed..d594907b6a 100644 --- a/src/dfx/src/commands/canister/call.rs +++ b/src/dfx/src/commands/canister/call.rs @@ -14,11 +14,9 @@ use tokio::runtime::Runtime; pub struct CanisterCallOpts { /// Specifies the name of the canister to build. /// You must specify either a canister name or the --all option. - #[clap(long)] canister_name: String, /// Specifies the method name to call on the canister. - #[clap(long)] method_name: String, /// Specifies not to wait for the result of the call to be returned by polling the replica. @@ -27,11 +25,11 @@ pub struct CanisterCallOpts { async_call: bool, /// Sends a query request to a canister. - #[clap(long, conflicts_with("async"), conflicts_with("update"))] + #[clap(long, conflicts_with("async-call"))] query: bool, /// Sends an update request to a canister. This is the default if the method is not a query method. - #[clap(long, conflicts_with("async"), conflicts_with("query"))] + #[clap(long, conflicts_with("async-call"), conflicts_with("query"))] update: bool, /// Specifies the argument to pass to the method. @@ -43,7 +41,7 @@ pub struct CanisterCallOpts { argument_type: Option, /// Specifies the format for displaying the method's return result. - #[clap(long, requires("argument"), conflicts_with("async"), + #[clap(long, requires("argument"), conflicts_with("async-call"), possible_values(&["idl", "raw", "pp"]))] output: Option, } @@ -82,9 +80,9 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { None => None, }; - let arguments: Option = opts.argument; - let arg_type: Option = opts.argument_type; - let output_type: Option = opts.output; + let arguments = opts.argument.as_deref(); + let arg_type = opts.argument_type.as_deref(); + let output_type = opts.output.as_deref(); let is_query = if opts.async_call { false } else { diff --git a/src/dfx/src/commands/canister/create.rs b/src/dfx/src/commands/canister/create.rs index 2c446c5c99..04d76d9bb5 100644 --- a/src/dfx/src/commands/canister/create.rs +++ b/src/dfx/src/commands/canister/create.rs @@ -9,11 +9,11 @@ use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; #[derive(Clap)] pub struct CanisterCreateOpts { /// Specifies the canister name. Either this or the --all flag are required. - #[clap(long, required_unless_present("all"))] - canister_name: String, + #[clap(required_unless_present = "all")] + canister_name: Option, /// Creates all canisters configured in dfx.json. - #[clap(long, required_unless_present("canister_name"))] + #[clap(long, required_unless_present = "canister-name")] all: bool, } @@ -29,8 +29,8 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let timeout = expiry_duration(); - if let Some(canister_name) = Some(opts.canister_name.as_str()) { - create_canister(env, canister_name, timeout)?; + if let Some(canister_name) = opts.canister_name { + create_canister(env, canister_name.as_str(), timeout)?; Ok(()) } else if opts.all { // Create all canisters. diff --git a/src/dfx/src/commands/canister/install.rs b/src/dfx/src/commands/canister/install.rs index f0935a1f68..a41e0094ca 100644 --- a/src/dfx/src/commands/canister/install.rs +++ b/src/dfx/src/commands/canister/install.rs @@ -16,11 +16,11 @@ use tokio::runtime::Runtime; #[derive(Clap, Clone)] pub struct CanisterInstallOpts { /// Specifies the canister name to deploy. You must specify either canister name or the --all option. - #[clap(long, required_unless_present("all"))] - canister_name: String, + #[clap(required_unless_present("all"))] + canister_name: Option, /// Deploys all canisters configured in the project dfx.json files. - #[clap(long, required_unless_present("canister_name"))] + #[clap(long, required_unless_present("canister-name"))] all: bool, /// Specifies not to wait for the result of the call to be returned by polling the replica. Instead return a response ID. @@ -79,7 +79,6 @@ fn get_compute_allocation( canister_name: &str, ) -> DfxResult> { Ok(compute_allocation - .map(|v| v.to_string()) .or(config_interface.get_compute_allocation(canister_name)?) .map(|arg| { ComputeAllocation::try_from(arg.parse::().unwrap()) @@ -93,7 +92,6 @@ fn get_memory_allocation( canister_name: &str, ) -> DfxResult> { Ok(memory_allocation - .map(|v| v.to_string()) .or(config_interface.get_memory_allocation(canister_name)?) .map(|arg| { MemoryAllocation::try_from(u64::try_from(arg.parse::().unwrap().size()).unwrap()) @@ -121,14 +119,14 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let canister_id_store = CanisterIdStore::for_env(env)?; - if let Some(canister_name) = Some(opts.canister_name.as_str()) { + if let Some(canister_name) = opts.canister_name.as_deref() { let canister_id = canister_id_store.get(canister_name)?; let canister_info = CanisterInfo::load(&config, canister_name, Some(canister_id))?; let maybe_path = canister_info.get_output_idl_path(); let init_type = maybe_path.and_then(|path| get_candid_init_type(&path)); - let arguments: Option = opts.argument; - let arg_type: Option = opts.argument_type; + let arguments = opts.argument.as_deref(); + let arg_type = opts.argument_type.as_deref(); let install_args = blob_from_arguments(arguments, arg_type, &init_type)?; let compute_allocation = diff --git a/src/dfx/src/commands/deploy.rs b/src/dfx/src/commands/deploy.rs index fc93eeb33f..dc46e2d504 100644 --- a/src/dfx/src/commands/deploy.rs +++ b/src/dfx/src/commands/deploy.rs @@ -34,12 +34,9 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let env = create_agent_environment(env, args)?; let timeout = expiry_duration(); - // let canister = opts.canister_name.and_then(|v| Some(v.as_str())); - let canister_name = opts.canister_name.unwrap(); - let canister = Some(canister_name.as_str()); + let canister_name = opts.canister_name.as_deref(); + let argument = opts.argument.as_deref(); + let argument_type = opts.argument_type.as_deref(); - let argument = opts.argument; - let argument_type = opts.argument_type; - - deploy_canisters(&env, canister, argument, argument_type, timeout) + deploy_canisters(&env, canister_name, argument, argument_type, timeout) } diff --git a/src/dfx/src/commands/new.rs b/src/dfx/src/commands/new.rs index ea568ee19c..ea63ec922c 100644 --- a/src/dfx/src/commands/new.rs +++ b/src/dfx/src/commands/new.rs @@ -358,23 +358,23 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { // Any version that contains a `-` is a local build. // TODO: when adding alpha/beta, take that into account. // TODO: move this to a Version type. - let is_dirty = dfx_version_str().contains('-'); - - let js_agent_version = if is_dirty { - // file!() returns a path like `src/dfx/src/commands/new.rs`, but since we are - // running from a directory outside the source tree, this does not help. - let agent_path = std::env::current_exe()? - .parent() - .unwrap() - .join("../../src/agent/javascript"); - agent_path - .canonicalize() - .map_err(|e| DfxError::IoWithPath(e, agent_path))? - .to_string_lossy() - .to_string() - } else { - dfx_version_str().to_owned() - }; + let _is_dirty = dfx_version_str().contains('-'); + + let js_agent_version = dfx_version_str().to_owned(); // if is_dirty { + // // file!() returns a path like `src/dfx/src/commands/new.rs`, but since we are + // // running from a directory outside the source tree, this does not help. + // let agent_path = std::env::current_exe()? + // .parent() + // .unwrap() + // .join("../../src/agent/javascript"); + // agent_path + // .canonicalize() + // .map_err(|e| DfxError::IoWithPath(e, agent_path))? + // .to_string_lossy() + // .to_string() + // } else { + // dfx_version_str().to_owned() + // }; let variables: BTreeMap = [ ("project_name".to_string(), project_name_str.to_string()), diff --git a/src/dfx/src/lib/operations/canister/deploy_canisters.rs b/src/dfx/src/lib/operations/canister/deploy_canisters.rs index 0dca6f9b5a..375804cd61 100644 --- a/src/dfx/src/lib/operations/canister/deploy_canisters.rs +++ b/src/dfx/src/lib/operations/canister/deploy_canisters.rs @@ -19,8 +19,8 @@ use tokio::runtime::Runtime; pub fn deploy_canisters( env: &dyn Environment, some_canister: Option<&str>, - argument: Option, - argument_type: Option, + argument: Option<&str>, + argument_type: Option<&str>, timeout: Duration, ) -> DfxResult { let log = env.get_logger(); @@ -99,8 +99,8 @@ fn install_canisters( canister_names: &[String], initial_canister_id_store: &CanisterIdStore, config: &Config, - argument: Option, - argument_type: Option, + argument: Option<&str>, + argument_type: Option<&str>, timeout: Duration, ) -> DfxResult { info!(env.get_logger(), "Installing canisters..."); @@ -124,8 +124,7 @@ fn install_canisters( let maybe_path = canister_info.get_output_idl_path(); let init_type = maybe_path.and_then(|path| get_candid_init_type(&path)); - let install_args = - blob_from_arguments(argument.clone(), argument_type.clone(), &init_type)?; + let install_args = blob_from_arguments(argument, argument_type, &init_type)?; let config_interface = config.get_config(); let compute_allocation = diff --git a/src/dfx/src/util/mod.rs b/src/dfx/src/util/mod.rs index 31c6876b6f..7f8e0c2629 100644 --- a/src/dfx/src/util/mod.rs +++ b/src/dfx/src/util/mod.rs @@ -35,11 +35,10 @@ pub fn expiry_duration() -> Duration { /// Deserialize and print return values from canister method. pub fn print_idl_blob( blob: &[u8], - output_type: Option, + output_type: Option<&str>, method_type: &Option<(TypeEnv, Function)>, ) -> DfxResult<()> { - let output_type_str = output_type.unwrap_or_else(|| "pp".to_string()); - let output_type = output_type_str.as_str(); + let output_type = output_type.unwrap_or("pp"); match output_type { "raw" => { let hex_string = hex::encode(blob); @@ -105,21 +104,20 @@ pub fn check_candid_file(idl_path: &std::path::Path) -> DfxResult<(TypeEnv, Opti } pub fn blob_from_arguments( - arguments: Option, - arg_type: Option, + arguments: Option<&str>, + arg_type: Option<&str>, method_type: &Option<(TypeEnv, Function)>, ) -> DfxResult> { - let arg_type_str = arg_type.unwrap_or_else(|| "idl".to_string()); - let arg_type = arg_type_str.as_str(); + let arg_type = arg_type.unwrap_or("idl"); match arg_type { "raw" => { - let bytes = hex::decode(&arguments.unwrap_or_else(|| "".to_string())).map_err(|e| { + let bytes = hex::decode(&arguments.unwrap_or("")).map_err(|e| { DfxError::InvalidArgument(format!("Argument is not a valid hex string: {}", e)) })?; Ok(bytes) } "idl" => { - let arguments = arguments.unwrap_or_else(|| "()".to_string()); + let arguments = arguments.unwrap_or("()"); let typed_args = match method_type { None => candid::pretty_parse::("Candid argument", &arguments) .map_err(|e| { From a57971b7967fe59931f1edbe3f8a113df3b8592c Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Sun, 1 Nov 2020 18:46:34 -0800 Subject: [PATCH 18/26] fixes --- src/dfx/src/commands/build.rs | 9 +++---- src/dfx/src/commands/canister/call.rs | 15 ++++++------ src/dfx/src/commands/canister/id.rs | 1 - src/dfx/src/commands/canister/mod.rs | 24 ++++++++++--------- .../src/commands/canister/request_status.rs | 2 +- src/dfx/src/commands/config.rs | 12 ++++------ src/dfx/src/commands/deploy.rs | 8 +++++-- src/dfx/src/commands/identity/new.rs | 2 +- src/dfx/src/commands/identity/remove.rs | 2 +- src/dfx/src/lib/message.rs | 3 --- src/dfx/src/lib/provider.rs | 4 +--- 11 files changed, 40 insertions(+), 42 deletions(-) diff --git a/src/dfx/src/commands/build.rs b/src/dfx/src/commands/build.rs index 995775f88f..a96850d810 100644 --- a/src/dfx/src/commands/build.rs +++ b/src/dfx/src/commands/build.rs @@ -16,9 +16,10 @@ pub struct CanisterBuildOpts { /// Build canisters without creating them. This can be used to check that canisters build ok. #[clap(long)] check: bool, - // Override the compute network to connect to. By default, the local network is used. - // #[clap(long)] - // network: Option, + + /// Override the compute network to connect to. By default, the local network is used. + #[clap(long)] + network: Option, } pub fn construct() -> App<'static> { @@ -27,7 +28,7 @@ pub fn construct() -> App<'static> { pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let opts: CanisterBuildOpts = CanisterBuildOpts::from_arg_matches(args); - let env = create_agent_environment(env, args)?; + let env = create_agent_environment(env, opts.network)?; let logger = env.get_logger(); diff --git a/src/dfx/src/commands/canister/call.rs b/src/dfx/src/commands/canister/call.rs index d594907b6a..20d2169eac 100644 --- a/src/dfx/src/commands/canister/call.rs +++ b/src/dfx/src/commands/canister/call.rs @@ -22,26 +22,25 @@ pub struct CanisterCallOpts { /// Specifies not to wait for the result of the call to be returned by polling the replica. /// Instead return a response ID. #[clap(long)] - async_call: bool, + r#async: bool, /// Sends a query request to a canister. - #[clap(long, conflicts_with("async-call"))] + #[clap(long, conflicts_with("async"))] query: bool, /// Sends an update request to a canister. This is the default if the method is not a query method. - #[clap(long, conflicts_with("async-call"), conflicts_with("query"))] + #[clap(long, conflicts_with("async"), conflicts_with("query"))] update: bool, /// Specifies the argument to pass to the method. - #[clap(long)] argument: Option, /// Specifies the data type for the argument when making the call using an argument. #[clap(long, requires("argument"), possible_values(&["idl", "raw"]))] - argument_type: Option, + r#type: Option, /// Specifies the format for displaying the method's return result. - #[clap(long, requires("argument"), conflicts_with("async-call"), + #[clap(long, conflicts_with("async"), possible_values(&["idl", "raw", "pp"]))] output: Option, } @@ -81,9 +80,9 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { }; let arguments = opts.argument.as_deref(); - let arg_type = opts.argument_type.as_deref(); + let arg_type = opts.r#type.as_deref(); let output_type = opts.output.as_deref(); - let is_query = if opts.async_call { + let is_query = if opts.r#async { false } else { match is_query_method { diff --git a/src/dfx/src/commands/canister/id.rs b/src/dfx/src/commands/canister/id.rs index 9460293899..d629b321eb 100644 --- a/src/dfx/src/commands/canister/id.rs +++ b/src/dfx/src/commands/canister/id.rs @@ -9,7 +9,6 @@ use ic_types::principal::Principal as CanisterId; pub struct CanisterIdOpts { /// Specifies the name of the canister to stop. /// You must specify either a canister name or the --all option. - #[clap(long)] canister_name: String, } diff --git a/src/dfx/src/commands/canister/mod.rs b/src/dfx/src/commands/canister/mod.rs index 9c2e20469f..10eea2b7a3 100644 --- a/src/dfx/src/commands/canister/mod.rs +++ b/src/dfx/src/commands/canister/mod.rs @@ -1,9 +1,8 @@ use crate::commands::CliCommand; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use crate::lib::provider::create_agent_environment; -use clap::{App, Arg, ArgMatches}; +use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; mod call; mod create; @@ -31,21 +30,24 @@ fn builtins() -> Vec { ] } +/// Manages canisters deployed on a network replica. +#[derive(Clap)] +pub struct CanisterOpts { + // Override the compute network to connect to. By default, the local network is used. + #[clap(long)] + network: Option, +} + pub fn construct() -> App<'static> { - App::new("canister") - .about(UserMessage::ManageCanister.to_str()) - .arg( - Arg::new("network") - //.help(UserMessage::CanisterComputeNetwork.to_str()) - .long("network") - .takes_value(true), - ) + CanisterOpts::into_app() + .name("canister") .subcommands(builtins().into_iter().map(|x| x.get_subcommand().clone())) } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { + let opts: CanisterOpts = CanisterOpts::from_arg_matches(args); let subcommand = args.subcommand(); - let agent_env = create_agent_environment(env, args)?; + let agent_env = create_agent_environment(env, opts.network)?; if let Some((name, subcommand_args)) = subcommand { match builtins().into_iter().find(|x| name == x.get_name()) { diff --git a/src/dfx/src/commands/canister/request_status.rs b/src/dfx/src/commands/canister/request_status.rs index 129e161231..c3564ad071 100644 --- a/src/dfx/src/commands/canister/request_status.rs +++ b/src/dfx/src/commands/canister/request_status.rs @@ -15,7 +15,7 @@ use tokio::runtime::Runtime; pub struct RequestStatusOpts { /// Specifies the request identifier. /// The request identifier is an hexadecimal string starting with 0x. - #[clap(long, validator(validators::is_request_id))] + #[clap(validator(validators::is_request_id))] request_id: String, } diff --git a/src/dfx/src/commands/config.rs b/src/dfx/src/commands/config.rs index 0b099cc3e7..04e1276c4a 100644 --- a/src/dfx/src/commands/config.rs +++ b/src/dfx/src/commands/config.rs @@ -10,13 +10,11 @@ pub struct ConfigOpts { /// Specifies the name of the configuration option to set or read. /// Use the period delineated path to specify the option to set or read. /// If this is not mentioned, outputs the whole configuration. - #[clap(long)] config_path: String, /// Specifies the new value to set. /// If you don't specify a value, the command displays the current value of the option from the configuration file. - #[clap(long)] - value: String, + value: Option, /// Specifies the format of the output. By default, the output format is JSON. #[clap(long, default_value("json"), possible_values(&["json", "text"]))] @@ -24,7 +22,7 @@ pub struct ConfigOpts { } pub fn construct() -> App<'static> { - ConfigOpts::into_app().name("rename") + ConfigOpts::into_app().name("config") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { @@ -53,11 +51,11 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { config_path.clear() } - if let Some(arg_value) = Some(opts.value.as_str()) { + if let Some(arg_value) = opts.value { // Try to parse the type of the value (which is a string from the arguments) as // JSON. By default we will just assume the type is string (if all parsing fails). - let value = serde_json::from_str::(arg_value) - .unwrap_or_else(|_| Value::String(arg_value.to_owned())); + let value = + serde_json::from_str::(&arg_value).unwrap_or_else(|_| Value::String(arg_value)); *config .get_mut_json() .pointer_mut(config_path.as_str()) diff --git a/src/dfx/src/commands/deploy.rs b/src/dfx/src/commands/deploy.rs index dc46e2d504..ea752a62f5 100644 --- a/src/dfx/src/commands/deploy.rs +++ b/src/dfx/src/commands/deploy.rs @@ -23,15 +23,19 @@ pub struct DeployOpts { /// Specifies the data type for the argument when making the call using an argument. #[clap(long, requires("argument"), possible_values(&["idl", "raw"]))] argument_type: Option, + + /// Override the compute network to connect to. By default, the local network is used. + #[clap(long)] + network: Option, } pub fn construct() -> App<'static> { - DeployOpts::into_app().name("rename") + DeployOpts::into_app().name("deploy") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let opts: DeployOpts = DeployOpts::from_arg_matches(args); - let env = create_agent_environment(env, args)?; + let env = create_agent_environment(env, opts.network)?; let timeout = expiry_duration(); let canister_name = opts.canister_name.as_deref(); diff --git a/src/dfx/src/commands/identity/new.rs b/src/dfx/src/commands/identity/new.rs index 2d1e5a734a..7acc2dc544 100644 --- a/src/dfx/src/commands/identity/new.rs +++ b/src/dfx/src/commands/identity/new.rs @@ -13,7 +13,7 @@ pub struct NewIdentityOpts { } pub fn construct() -> App<'static> { - NewIdentityOpts::into_app().name("rename") + NewIdentityOpts::into_app().name("new") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/identity/remove.rs b/src/dfx/src/commands/identity/remove.rs index 2a230cfb76..2ebe3bc206 100644 --- a/src/dfx/src/commands/identity/remove.rs +++ b/src/dfx/src/commands/identity/remove.rs @@ -13,7 +13,7 @@ pub struct RemoveOpts { } pub fn construct() -> App<'static> { - RemoveOpts::into_app().name("rename") + RemoveOpts::into_app().name("remove") } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/lib/message.rs b/src/dfx/src/lib/message.rs index 00d0e50849..da18db72fe 100644 --- a/src/dfx/src/lib/message.rs +++ b/src/dfx/src/lib/message.rs @@ -28,9 +28,6 @@ user_message!( // OutputType => "Specifies the format for displaying the method's return result.", // ArgumentValue => "Specifies the argument to pass to the method.", - // dfx canister mod - ManageCanister => "Manages canisters deployed on a network replica.", - // dfx build // CanisterComputeNetwork => "Override the compute network to connect to. By default, the local network is used.", diff --git a/src/dfx/src/lib/provider.rs b/src/dfx/src/lib/provider.rs index be7e79cdfd..609071c518 100644 --- a/src/dfx/src/lib/provider.rs +++ b/src/dfx/src/lib/provider.rs @@ -3,7 +3,6 @@ use crate::lib::environment::{AgentEnvironment, Environment}; use crate::lib::error::{DfxError, DfxResult}; use crate::lib::network::network_descriptor::NetworkDescriptor; use crate::util::expiry_duration; -use clap::ArgMatches; use lazy_static::lazy_static; use std::sync::{Arc, RwLock}; use url::Url; @@ -78,9 +77,8 @@ pub fn get_network_descriptor<'a>( pub fn create_agent_environment<'a>( env: &'a (dyn Environment + 'a), - args: &ArgMatches, + network: Option, ) -> DfxResult> { - let network = args.value_of("network").map(|v| v.to_string()); let network_descriptor = get_network_descriptor(env, network)?; let timeout = expiry_duration(); AgentEnvironment::new(env, network_descriptor, timeout) From a3cc0faa065c0b7ade81ffdc4f2654c3bcefc1c5 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Sun, 1 Nov 2020 19:24:18 -0800 Subject: [PATCH 19/26] fixes --- src/dfx/src/commands/build.rs | 5 +++++ src/dfx/src/commands/canister/create.rs | 1 - src/dfx/src/commands/canister/delete.rs | 9 ++++----- src/dfx/src/commands/canister/install.rs | 1 - src/dfx/src/commands/canister/set_controller.rs | 17 ++++++++--------- src/dfx/src/commands/canister/start.rs | 7 +++---- src/dfx/src/commands/canister/status.rs | 5 ++--- src/dfx/src/commands/canister/stop.rs | 7 +++---- src/dfx/src/commands/deploy.rs | 1 - src/dfx/src/commands/identity/new.rs | 1 - src/dfx/src/commands/identity/remove.rs | 1 - src/dfx/src/commands/identity/rename.rs | 2 -- src/dfx/src/commands/identity/use.rs | 1 - 13 files changed, 25 insertions(+), 33 deletions(-) diff --git a/src/dfx/src/commands/build.rs b/src/dfx/src/commands/build.rs index a96850d810..e9846cc24d 100644 --- a/src/dfx/src/commands/build.rs +++ b/src/dfx/src/commands/build.rs @@ -13,6 +13,10 @@ pub struct CanisterBuildOpts { /// You must specify either a canister name or the --all option.", canister_name: Option, + /// Builds all canisters configured in the dfx.json file. + #[clap(long, conflicts_with("canister-name"))] + all: bool, + /// Build canisters without creating them. This can be used to check that canisters build ok. #[clap(long)] check: bool, @@ -42,6 +46,7 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { env.get_cache().install()?; let build_mode_check = opts.check; + let _all = opts.all; // Option can be None in which case --all was specified let canister_names = config diff --git a/src/dfx/src/commands/canister/create.rs b/src/dfx/src/commands/canister/create.rs index 04d76d9bb5..e83d0b926d 100644 --- a/src/dfx/src/commands/canister/create.rs +++ b/src/dfx/src/commands/canister/create.rs @@ -9,7 +9,6 @@ use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; #[derive(Clap)] pub struct CanisterCreateOpts { /// Specifies the canister name. Either this or the --all flag are required. - #[clap(required_unless_present = "all")] canister_name: Option, /// Creates all canisters configured in dfx.json. diff --git a/src/dfx/src/commands/canister/delete.rs b/src/dfx/src/commands/canister/delete.rs index 8965aa6ffe..895923397e 100644 --- a/src/dfx/src/commands/canister/delete.rs +++ b/src/dfx/src/commands/canister/delete.rs @@ -16,11 +16,10 @@ use tokio::runtime::Runtime; pub struct CanisterDeleteOpts { /// Specifies the name of the canister to delete. /// You must specify either a canister name or the --all flag. - #[clap(long, required_unless_present("all"))] - canister_name: String, + canister_name: Option, /// Deletes all of the canisters configured in the dfx.json file. - #[clap(long, required_unless_present("canister_name"))] + #[clap(long, required_unless_present("canister-name"))] all: bool, } @@ -67,8 +66,8 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let mut runtime = Runtime::new().expect("Unable to create a runtime"); - if let Some(canister_name) = Some(opts.canister_name.as_str()) { - runtime.block_on(delete_canister(env, &agent, &canister_name, timeout))?; + if let Some(canister_name) = opts.canister_name.as_deref() { + runtime.block_on(delete_canister(env, &agent, canister_name, timeout))?; Ok(()) } else if opts.all { if let Some(canisters) = &config.get_config().canisters { diff --git a/src/dfx/src/commands/canister/install.rs b/src/dfx/src/commands/canister/install.rs index a41e0094ca..07657ce231 100644 --- a/src/dfx/src/commands/canister/install.rs +++ b/src/dfx/src/commands/canister/install.rs @@ -16,7 +16,6 @@ use tokio::runtime::Runtime; #[derive(Clap, Clone)] pub struct CanisterInstallOpts { /// Specifies the canister name to deploy. You must specify either canister name or the --all option. - #[clap(required_unless_present("all"))] canister_name: Option, /// Deploys all canisters configured in the project dfx.json files. diff --git a/src/dfx/src/commands/canister/set_controller.rs b/src/dfx/src/commands/canister/set_controller.rs index d9e70649e9..730bdf7ad7 100644 --- a/src/dfx/src/commands/canister/set_controller.rs +++ b/src/dfx/src/commands/canister/set_controller.rs @@ -16,11 +16,9 @@ use tokio::runtime::Runtime; #[derive(Clap)] pub struct SetControllerOpts { /// Specifies the canister name or the canister identifier for the canister to be controlled. - #[clap(long)] canister: String, /// Specifies the identity name or the principal of the new controller." - #[clap(long)] new_controller: String, } @@ -30,17 +28,15 @@ pub fn construct() -> App<'static> { pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let opts: SetControllerOpts = SetControllerOpts::from_arg_matches(args); - let canister = opts.canister.as_str(); - let canister_id = match CanisterId::from_text(canister) { + let canister_id = match CanisterId::from_text(&opts.canister) { Ok(id) => id, - Err(_) => CanisterIdStore::for_env(env)?.get(canister)?, + Err(_) => CanisterIdStore::for_env(env)?.get(&opts.canister)?, }; - let new_controller = opts.new_controller.as_str(); - let controller_principal = match CanisterId::from_text(new_controller) { + let controller_principal = match CanisterId::from_text(&opts.new_controller) { Ok(principal) => principal, Err(_) => IdentityManager::new(env)? - .instantiate_identity_from_name(new_controller)? + .instantiate_identity_from_name(&opts.new_controller)? .sender()?, }; @@ -57,6 +53,9 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { .call_and_wait(waiter_with_timeout(timeout)), )?; - println!("Set {:?} as controller of {:?}.", new_controller, canister); + println!( + "Set {:?} as controller of {:?}.", + opts.new_controller, opts.canister + ); Ok(()) } diff --git a/src/dfx/src/commands/canister/start.rs b/src/dfx/src/commands/canister/start.rs index 15521f093a..729d7e7f7e 100644 --- a/src/dfx/src/commands/canister/start.rs +++ b/src/dfx/src/commands/canister/start.rs @@ -15,11 +15,10 @@ use tokio::runtime::Runtime; #[derive(Clap)] pub struct CanisterStartOpts { /// Specifies the name of the canister to start. You must specify either a canister name or the --all flag. - #[clap(long, required_unless_present("all"))] - canister_name: String, + canister_name: Option, /// Starts all of the canisters configured in the dfx.json file. - #[clap(long, required_unless_present("canister_name"))] + #[clap(long, required_unless_present("canister-name"))] all: bool, } @@ -66,7 +65,7 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let timeout = expiry_duration(); - if let Some(canister_name) = Some(opts.canister_name.as_str()) { + if let Some(canister_name) = opts.canister_name.as_deref() { runtime.block_on(start_canister(env, &agent, &canister_name, timeout))?; Ok(()) } else if opts.all { diff --git a/src/dfx/src/commands/canister/status.rs b/src/dfx/src/commands/canister/status.rs index df122b60ed..7f5777af76 100644 --- a/src/dfx/src/commands/canister/status.rs +++ b/src/dfx/src/commands/canister/status.rs @@ -16,8 +16,7 @@ use tokio::runtime::Runtime; pub struct CanisterStatusOpts { /// Specifies the name of the canister to return information for. /// You must specify either a canister name or the --all flag. - #[clap(long, required_unless_present("all"))] - canister_name: String, + canister_name: Option, /// Returns status information for all of the canisters configured in the dfx.json file. #[clap(long, required_unless_present("canister_name"))] @@ -61,7 +60,7 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let timeout = expiry_duration(); - if let Some(canister_name) = Some(opts.canister_name.as_str()) { + if let Some(canister_name) = opts.canister_name.as_deref() { runtime.block_on(canister_status(env, &agent, &canister_name, timeout))?; Ok(()) } else if opts.all { diff --git a/src/dfx/src/commands/canister/stop.rs b/src/dfx/src/commands/canister/stop.rs index 49e1e09f87..300f9e9df6 100644 --- a/src/dfx/src/commands/canister/stop.rs +++ b/src/dfx/src/commands/canister/stop.rs @@ -16,11 +16,10 @@ use tokio::runtime::Runtime; pub struct CanisterStopOpts { /// Specifies the name of the canister to stop. /// You must specify either a canister name or the --all option. - #[clap(long, required_unless_present("all"))] - canister_name: String, + canister_name: Option, /// Stops all of the canisters configured in the dfx.json file. - #[clap(long, required_unless_present("canister_name"))] + #[clap(long, required_unless_present("canister-name"))] all: bool, } @@ -65,7 +64,7 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let mut runtime = Runtime::new().expect("Unable to create a runtime"); let timeout = expiry_duration(); - if let Some(canister_name) = Some(opts.canister_name.as_str()) { + if let Some(canister_name) = opts.canister_name.as_deref() { runtime.block_on(stop_canister(env, &agent, &canister_name, timeout))?; Ok(()) } else if opts.all { diff --git a/src/dfx/src/commands/deploy.rs b/src/dfx/src/commands/deploy.rs index ea752a62f5..078317cbff 100644 --- a/src/dfx/src/commands/deploy.rs +++ b/src/dfx/src/commands/deploy.rs @@ -10,7 +10,6 @@ use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; pub struct DeployOpts { /// Specifies the name of the canister you want to deploy. /// If you don’t specify a canister name, all canisters defined in the dfx.json file are deployed. - #[clap(long)] canister_name: Option, // Override the compute network to connect to. By default, the local network is used. diff --git a/src/dfx/src/commands/identity/new.rs b/src/dfx/src/commands/identity/new.rs index 7acc2dc544..51d0391365 100644 --- a/src/dfx/src/commands/identity/new.rs +++ b/src/dfx/src/commands/identity/new.rs @@ -8,7 +8,6 @@ use slog::info; #[derive(Clap)] pub struct NewIdentityOpts { /// The identity to create. - #[clap(long)] identity: String, } diff --git a/src/dfx/src/commands/identity/remove.rs b/src/dfx/src/commands/identity/remove.rs index 2ebe3bc206..ad3c2f9f6a 100644 --- a/src/dfx/src/commands/identity/remove.rs +++ b/src/dfx/src/commands/identity/remove.rs @@ -8,7 +8,6 @@ use slog::info; #[derive(Clap)] pub struct RemoveOpts { /// The identity to remove. - #[clap(long)] identity: String, } diff --git a/src/dfx/src/commands/identity/rename.rs b/src/dfx/src/commands/identity/rename.rs index fae449370d..cc3eed0153 100644 --- a/src/dfx/src/commands/identity/rename.rs +++ b/src/dfx/src/commands/identity/rename.rs @@ -8,11 +8,9 @@ use slog::info; #[derive(Clap)] pub struct RenameOpts { /// The current name of the identity. - #[clap(long)] from: String, /// The new name of the identity. - #[clap(long)] to: String, } diff --git a/src/dfx/src/commands/identity/use.rs b/src/dfx/src/commands/identity/use.rs index 796a9f1ca1..f5e60050cd 100644 --- a/src/dfx/src/commands/identity/use.rs +++ b/src/dfx/src/commands/identity/use.rs @@ -8,7 +8,6 @@ use slog::info; #[derive(Clap)] pub struct UseOpts { /// The identity to use. - #[clap(long)] identity: String, } From 35e845d675d83bdbf4a434c4ec99bd354e2b7897 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Sun, 1 Nov 2020 19:30:14 -0800 Subject: [PATCH 20/26] change required unless to conflicts with --- src/dfx/src/commands/canister/create.rs | 2 +- src/dfx/src/commands/canister/delete.rs | 2 +- src/dfx/src/commands/canister/install.rs | 2 +- src/dfx/src/commands/canister/start.rs | 2 +- src/dfx/src/commands/canister/status.rs | 2 +- src/dfx/src/commands/canister/stop.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dfx/src/commands/canister/create.rs b/src/dfx/src/commands/canister/create.rs index e83d0b926d..2476f6a3e9 100644 --- a/src/dfx/src/commands/canister/create.rs +++ b/src/dfx/src/commands/canister/create.rs @@ -12,7 +12,7 @@ pub struct CanisterCreateOpts { canister_name: Option, /// Creates all canisters configured in dfx.json. - #[clap(long, required_unless_present = "canister-name")] + #[clap(long, conflicts_with("canister-name"))] all: bool, } diff --git a/src/dfx/src/commands/canister/delete.rs b/src/dfx/src/commands/canister/delete.rs index 895923397e..05dc36039d 100644 --- a/src/dfx/src/commands/canister/delete.rs +++ b/src/dfx/src/commands/canister/delete.rs @@ -19,7 +19,7 @@ pub struct CanisterDeleteOpts { canister_name: Option, /// Deletes all of the canisters configured in the dfx.json file. - #[clap(long, required_unless_present("canister-name"))] + #[clap(long, conflicts_with("canister-name"))] all: bool, } diff --git a/src/dfx/src/commands/canister/install.rs b/src/dfx/src/commands/canister/install.rs index 07657ce231..2c4d7759a2 100644 --- a/src/dfx/src/commands/canister/install.rs +++ b/src/dfx/src/commands/canister/install.rs @@ -19,7 +19,7 @@ pub struct CanisterInstallOpts { canister_name: Option, /// Deploys all canisters configured in the project dfx.json files. - #[clap(long, required_unless_present("canister-name"))] + #[clap(long, conflicts_with("canister-name"))] all: bool, /// Specifies not to wait for the result of the call to be returned by polling the replica. Instead return a response ID. diff --git a/src/dfx/src/commands/canister/start.rs b/src/dfx/src/commands/canister/start.rs index 729d7e7f7e..1e69b44e57 100644 --- a/src/dfx/src/commands/canister/start.rs +++ b/src/dfx/src/commands/canister/start.rs @@ -18,7 +18,7 @@ pub struct CanisterStartOpts { canister_name: Option, /// Starts all of the canisters configured in the dfx.json file. - #[clap(long, required_unless_present("canister-name"))] + #[clap(long, conflicts_with("canister-name"))] all: bool, } diff --git a/src/dfx/src/commands/canister/status.rs b/src/dfx/src/commands/canister/status.rs index 7f5777af76..5f5688d3a0 100644 --- a/src/dfx/src/commands/canister/status.rs +++ b/src/dfx/src/commands/canister/status.rs @@ -19,7 +19,7 @@ pub struct CanisterStatusOpts { canister_name: Option, /// Returns status information for all of the canisters configured in the dfx.json file. - #[clap(long, required_unless_present("canister_name"))] + #[clap(long, conflicts_with("canister_name"))] all: bool, } diff --git a/src/dfx/src/commands/canister/stop.rs b/src/dfx/src/commands/canister/stop.rs index 300f9e9df6..72ebca82ab 100644 --- a/src/dfx/src/commands/canister/stop.rs +++ b/src/dfx/src/commands/canister/stop.rs @@ -19,7 +19,7 @@ pub struct CanisterStopOpts { canister_name: Option, /// Stops all of the canisters configured in the dfx.json file. - #[clap(long, required_unless_present("canister-name"))] + #[clap(long, conflicts_with("canister-name"))] all: bool, } From 06a324c2dc00a08881c3d9773602f5672c194f18 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Sun, 1 Nov 2020 19:47:07 -0800 Subject: [PATCH 21/26] revert conflicts_with required_unless_present --- src/dfx/src/commands/canister/create.rs | 2 +- src/dfx/src/commands/canister/delete.rs | 2 +- src/dfx/src/commands/canister/install.rs | 2 +- src/dfx/src/commands/canister/start.rs | 2 +- src/dfx/src/commands/canister/status.rs | 2 +- src/dfx/src/commands/canister/stop.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dfx/src/commands/canister/create.rs b/src/dfx/src/commands/canister/create.rs index 2476f6a3e9..48c7dcd60d 100644 --- a/src/dfx/src/commands/canister/create.rs +++ b/src/dfx/src/commands/canister/create.rs @@ -12,7 +12,7 @@ pub struct CanisterCreateOpts { canister_name: Option, /// Creates all canisters configured in dfx.json. - #[clap(long, conflicts_with("canister-name"))] + #[clap(long, required_unless_present("canister-name"))] all: bool, } diff --git a/src/dfx/src/commands/canister/delete.rs b/src/dfx/src/commands/canister/delete.rs index 05dc36039d..895923397e 100644 --- a/src/dfx/src/commands/canister/delete.rs +++ b/src/dfx/src/commands/canister/delete.rs @@ -19,7 +19,7 @@ pub struct CanisterDeleteOpts { canister_name: Option, /// Deletes all of the canisters configured in the dfx.json file. - #[clap(long, conflicts_with("canister-name"))] + #[clap(long, required_unless_present("canister-name"))] all: bool, } diff --git a/src/dfx/src/commands/canister/install.rs b/src/dfx/src/commands/canister/install.rs index 2c4d7759a2..07657ce231 100644 --- a/src/dfx/src/commands/canister/install.rs +++ b/src/dfx/src/commands/canister/install.rs @@ -19,7 +19,7 @@ pub struct CanisterInstallOpts { canister_name: Option, /// Deploys all canisters configured in the project dfx.json files. - #[clap(long, conflicts_with("canister-name"))] + #[clap(long, required_unless_present("canister-name"))] all: bool, /// Specifies not to wait for the result of the call to be returned by polling the replica. Instead return a response ID. diff --git a/src/dfx/src/commands/canister/start.rs b/src/dfx/src/commands/canister/start.rs index 1e69b44e57..729d7e7f7e 100644 --- a/src/dfx/src/commands/canister/start.rs +++ b/src/dfx/src/commands/canister/start.rs @@ -18,7 +18,7 @@ pub struct CanisterStartOpts { canister_name: Option, /// Starts all of the canisters configured in the dfx.json file. - #[clap(long, conflicts_with("canister-name"))] + #[clap(long, required_unless_present("canister-name"))] all: bool, } diff --git a/src/dfx/src/commands/canister/status.rs b/src/dfx/src/commands/canister/status.rs index 5f5688d3a0..7f5777af76 100644 --- a/src/dfx/src/commands/canister/status.rs +++ b/src/dfx/src/commands/canister/status.rs @@ -19,7 +19,7 @@ pub struct CanisterStatusOpts { canister_name: Option, /// Returns status information for all of the canisters configured in the dfx.json file. - #[clap(long, conflicts_with("canister_name"))] + #[clap(long, required_unless_present("canister_name"))] all: bool, } diff --git a/src/dfx/src/commands/canister/stop.rs b/src/dfx/src/commands/canister/stop.rs index 72ebca82ab..300f9e9df6 100644 --- a/src/dfx/src/commands/canister/stop.rs +++ b/src/dfx/src/commands/canister/stop.rs @@ -19,7 +19,7 @@ pub struct CanisterStopOpts { canister_name: Option, /// Stops all of the canisters configured in the dfx.json file. - #[clap(long, conflicts_with("canister-name"))] + #[clap(long, required_unless_present("canister-name"))] all: bool, } From 49b9710885541f0f25052f654c2144002cafe956 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Sun, 1 Nov 2020 19:53:02 -0800 Subject: [PATCH 22/26] fix canister status --- src/dfx/src/commands/canister/status.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dfx/src/commands/canister/status.rs b/src/dfx/src/commands/canister/status.rs index 7f5777af76..db62eea6a1 100644 --- a/src/dfx/src/commands/canister/status.rs +++ b/src/dfx/src/commands/canister/status.rs @@ -19,7 +19,7 @@ pub struct CanisterStatusOpts { canister_name: Option, /// Returns status information for all of the canisters configured in the dfx.json file. - #[clap(long, required_unless_present("canister_name"))] + #[clap(long, required_unless_present("canister-name"))] all: bool, } From 120a893586a5fd5a1d4b39a06c30f2ce33d82c3b Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Thu, 5 Nov 2020 14:06:35 -0800 Subject: [PATCH 23/26] patches --- src/dfx/src/commands/bootstrap.rs | 22 ++++---- src/dfx/src/commands/build.rs | 2 +- src/dfx/src/commands/cache/mod.rs | 3 +- .../src/commands/canister/set_controller.rs | 2 +- src/dfx/src/commands/deploy.rs | 3 -- src/dfx/src/commands/identity/mod.rs | 3 +- src/dfx/src/commands/language_service.rs | 6 +-- src/dfx/src/commands/replica.rs | 6 +-- src/dfx/src/commands/upgrade.rs | 6 +-- src/dfx/src/lib/message.rs | 52 ------------------- src/dfx/src/lib/mod.rs | 1 - 11 files changed, 20 insertions(+), 86 deletions(-) delete mode 100644 src/dfx/src/lib/message.rs diff --git a/src/dfx/src/commands/bootstrap.rs b/src/dfx/src/commands/bootstrap.rs index b6c860c960..3d6a442187 100644 --- a/src/dfx/src/commands/bootstrap.rs +++ b/src/dfx/src/commands/bootstrap.rs @@ -32,12 +32,12 @@ pub struct BootstrapOpts { network: Option, /// Specifies the directory containing static assets served by the bootstrap server. - /// Defaults to $HOME/.cache/dfinity/versions/$DFX_VERSION/js-user-library/dist/bootstrap.", + /// Defaults to $HOME/.cache/dfinity/versions/$DFX_VERSION/js-user-library/dist/bootstrap. #[clap(long)] root: Option, /// Specifies the maximum number of seconds that the bootstrap server - /// will wait for upstream requests to complete. Defaults to 30.", + /// will wait for upstream requests to complete. Defaults to 30. #[clap(long)] timeout: Option, } @@ -114,10 +114,10 @@ fn apply_arguments( env: &dyn Environment, opts: BootstrapOpts, ) -> DfxResult { - let ip = get_ip(&config, opts.ip)?; - let port = get_port(&config, opts.port)?; - let root = get_root(&config, env, opts.root)?; - let timeout = get_timeout(&config, opts.timeout)?; + let ip = get_ip(&config, opts.ip.as_deref())?; + let port = get_port(&config, opts.port.as_deref())?; + let root = get_root(&config, env, opts.root.as_deref())?; + let timeout = get_timeout(&config, opts.timeout.as_deref())?; Ok(ConfigDefaultsBootstrap { ip: Some(ip), port: Some(port), @@ -137,7 +137,7 @@ fn get_config_defaults_from_file(env: &dyn Environment) -> ConfigDefaults { /// Gets the IP address that the bootstrap server listens on. First checks if the IP address was /// specified on the command-line using --ip, otherwise checks if the IP address was specified in /// the dfx configuration file, otherise defaults to 127.0.0.1. -fn get_ip(config: &ConfigDefaultsBootstrap, ip: Option) -> DfxResult { +fn get_ip(config: &ConfigDefaultsBootstrap, ip: Option<&str>) -> DfxResult { ip.map(|ip| ip.parse()) .unwrap_or_else(|| { let default = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)); @@ -149,7 +149,7 @@ fn get_ip(config: &ConfigDefaultsBootstrap, ip: Option) -> DfxResult) -> DfxResult { +fn get_port(config: &ConfigDefaultsBootstrap, port: Option<&str>) -> DfxResult { port.map(|port| port.parse()) .unwrap_or_else(|| { let default = 8081; @@ -174,9 +174,9 @@ fn get_providers(network_descriptor: &NetworkDescriptor) -> DfxResult, + root: Option<&str>, ) -> DfxResult { - root.map(|root| parse_dir(root.as_str())) + root.map(|root| parse_dir(root)) .unwrap_or_else(|| { config .root @@ -196,7 +196,7 @@ fn get_root( /// requests to complete. First checks if the timeout was specified on the command-line using /// --timeout, otherwise checks if the timeout was specified in the dfx configuration file, /// otherise defaults to 30. -fn get_timeout(config: &ConfigDefaultsBootstrap, timeout: Option) -> DfxResult { +fn get_timeout(config: &ConfigDefaultsBootstrap, timeout: Option<&str>) -> DfxResult { timeout .map(|timeout| timeout.parse()) .unwrap_or_else(|| { diff --git a/src/dfx/src/commands/build.rs b/src/dfx/src/commands/build.rs index e9846cc24d..ac3a32a71a 100644 --- a/src/dfx/src/commands/build.rs +++ b/src/dfx/src/commands/build.rs @@ -10,7 +10,7 @@ use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; #[derive(Clap)] pub struct CanisterBuildOpts { /// Specifies the name of the canister to build. - /// You must specify either a canister name or the --all option.", + /// You must specify either a canister name or the --all option. canister_name: Option, /// Builds all canisters configured in the dfx.json file. diff --git a/src/dfx/src/commands/cache/mod.rs b/src/dfx/src/commands/cache/mod.rs index 151a77b160..a7701eb419 100644 --- a/src/dfx/src/commands/cache/mod.rs +++ b/src/dfx/src/commands/cache/mod.rs @@ -1,7 +1,6 @@ use crate::commands::CliCommand; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use clap::{App, ArgMatches}; mod delete; @@ -20,7 +19,7 @@ fn builtins() -> Vec { pub fn construct() -> App<'static> { App::new("cache") - .about(UserMessage::ManageCache.to_str()) + .about("Manages the dfx version cache.") .subcommands(builtins().into_iter().map(|x| x.get_subcommand().clone())) } diff --git a/src/dfx/src/commands/canister/set_controller.rs b/src/dfx/src/commands/canister/set_controller.rs index 730bdf7ad7..c85365910b 100644 --- a/src/dfx/src/commands/canister/set_controller.rs +++ b/src/dfx/src/commands/canister/set_controller.rs @@ -18,7 +18,7 @@ pub struct SetControllerOpts { /// Specifies the canister name or the canister identifier for the canister to be controlled. canister: String, - /// Specifies the identity name or the principal of the new controller." + /// Specifies the identity name or the principal of the new controller. new_controller: String, } diff --git a/src/dfx/src/commands/deploy.rs b/src/dfx/src/commands/deploy.rs index 078317cbff..c2712ea0b3 100644 --- a/src/dfx/src/commands/deploy.rs +++ b/src/dfx/src/commands/deploy.rs @@ -12,9 +12,6 @@ pub struct DeployOpts { /// If you don’t specify a canister name, all canisters defined in the dfx.json file are deployed. canister_name: Option, - // Override the compute network to connect to. By default, the local network is used. - // #[clap(long)] - // network: Option, /// Specifies the argument to pass to the method. #[clap(long)] argument: Option, diff --git a/src/dfx/src/commands/identity/mod.rs b/src/dfx/src/commands/identity/mod.rs index 7b828b9fcb..2baa94d59c 100644 --- a/src/dfx/src/commands/identity/mod.rs +++ b/src/dfx/src/commands/identity/mod.rs @@ -1,7 +1,6 @@ use crate::commands::CliCommand; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use crate::lib::message::UserMessage; use clap::{App, ArgMatches}; mod list; @@ -26,7 +25,7 @@ fn builtins() -> Vec { pub fn construct() -> App<'static> { App::new("identity") - .about(UserMessage::ManageIdentity.to_str()) + .about("Manages identities used to communicate with the Internet Computer network. Setting an identity enables you to test user-based access controls.") .subcommands(builtins().into_iter().map(|x| x.get_subcommand().clone())) } diff --git a/src/dfx/src/commands/language_service.rs b/src/dfx/src/commands/language_service.rs index 16b8c11495..c6fc761843 100644 --- a/src/dfx/src/commands/language_service.rs +++ b/src/dfx/src/commands/language_service.rs @@ -6,11 +6,11 @@ use clap::{App, AppSettings, ArgMatches, Clap, FromArgMatches, IntoApp}; use std::process::Stdio; const CANISTER_ARG: &str = "canister"; -// const FORCE_TTY: &str = "force-tty"; /// Starts the Motoko IDE Language Server. This is meant to be run by editor plugins not the /// end-user. #[derive(Clap)] +#[clap(setting = AppSettings::Hidden)] pub struct LanguageServiceOpts { /// Specifies the canister name. If you don't specify this argument, all canisters are /// processed. @@ -22,9 +22,7 @@ pub struct LanguageServiceOpts { } pub fn construct() -> App<'static> { - LanguageServiceOpts::into_app() - .name("_language-service") - .setting(AppSettings::Hidden) // Hide it from help menus as it shouldn't be used by users. + LanguageServiceOpts::into_app().name("_language-service") } // Don't read anything from stdin or output anything to stdout while this function is being diff --git a/src/dfx/src/commands/replica.rs b/src/dfx/src/commands/replica.rs index 0c6957daa0..2c48720537 100644 --- a/src/dfx/src/commands/replica.rs +++ b/src/dfx/src/commands/replica.rs @@ -13,8 +13,7 @@ use std::default::Default; #[derive(Clap)] pub struct ReplicaOpts { /// Specifies the maximum number of cycles a single message can consume. - // hidden - #[clap(long)] + #[clap(long, hidden = true)] message_gas_limit: Option, /// Specifies the port the local replica should listen to. @@ -22,8 +21,7 @@ pub struct ReplicaOpts { port: Option, /// Specifies the maximum number of cycles a single round can consume. - // hidden - #[clap(long)] + #[clap(long, hidden = true)] round_gas_limit: Option, } diff --git a/src/dfx/src/commands/upgrade.rs b/src/dfx/src/commands/upgrade.rs index 985e3bc2fa..02ca1ec880 100644 --- a/src/dfx/src/commands/upgrade.rs +++ b/src/dfx/src/commands/upgrade.rs @@ -15,12 +15,8 @@ pub struct UpgradeOpts { #[clap(long)] current_version: Option, - // hidden - #[clap(long, default_value = "https://sdk.dfinity.org")] + #[clap(long, default_value = "https://sdk.dfinity.org", hidden = true)] release_root: String, - // Verbose output. - // #[clap(long)] - // verbose: bool, } pub fn construct() -> App<'static> { diff --git a/src/dfx/src/lib/message.rs b/src/dfx/src/lib/message.rs deleted file mode 100644 index da18db72fe..0000000000 --- a/src/dfx/src/lib/message.rs +++ /dev/null @@ -1,52 +0,0 @@ -use std::fmt; - -macro_rules! user_message { - ( $($name: ident => $msg: literal,)+ ) => { - #[derive(Debug, Copy, Clone)] - pub enum UserMessage { - $($name), + - } - - impl UserMessage { - pub fn to_str(&self) -> &str { - match &self { - $(UserMessage::$name => $msg,)+ - } - } - } - }; -} - -user_message!( - // dfx cache - ManageCache => "Manages the dfx version cache.", - - // dfx canister call - // CallCanister => "Calls a method on a deployed canister.", - // AsyncResult => "Specifies not to wait for the result of the call to be returned by polling the replica. Instead return a response ID.", - // ArgumentType => "Specifies the data type for the argument when making the call using an argument.", - // OutputType => "Specifies the format for displaying the method's return result.", - // ArgumentValue => "Specifies the argument to pass to the method.", - - // dfx build - // CanisterComputeNetwork => "Override the compute network to connect to. By default, the local network is used.", - - // dfx identity mod - ManageIdentity => "Manages identities used to communicate with the Internet Computer network. Setting an identity enables you to test user-based access controls.", - - // dfx replica - // ReplicaRoundGasLimit => "Specifies the maximum number of cycles a single round can consume.", - - // misc - // CanisterName => "Specifies the canister name. If you don't specify this argument, all canisters are processed.", - - // dfx ide - // StartLanguageService => "Starts the Motoko IDE Language Server. This is meant to be run by editor plugins not the end-user.", - // ForceTTY => "Forces the language server to start even when run from a terminal.", -); - -impl fmt::Display for UserMessage { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", &self.to_str()) - } -} diff --git a/src/dfx/src/lib/mod.rs b/src/dfx/src/lib/mod.rs index 6c663a9ea6..bfbe4ed842 100644 --- a/src/dfx/src/lib/mod.rs +++ b/src/dfx/src/lib/mod.rs @@ -7,7 +7,6 @@ pub mod identity; pub mod installers; pub mod locations; pub mod logger; -pub mod message; pub mod models; pub mod network; pub mod operations; From f0660d118cb6340cf02c6acc284798f20c3c2a5e Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Thu, 5 Nov 2020 19:06:51 -0800 Subject: [PATCH 24/26] patches --- src/dfx/src/commands/bootstrap.rs | 3 +- src/dfx/src/commands/build.rs | 3 +- src/dfx/src/commands/cache/delete.rs | 3 +- src/dfx/src/commands/cache/install.rs | 3 +- src/dfx/src/commands/cache/list.rs | 3 +- src/dfx/src/commands/cache/mod.rs | 11 ++- src/dfx/src/commands/cache/show.rs | 3 +- src/dfx/src/commands/canister/call.rs | 3 +- src/dfx/src/commands/canister/create.rs | 3 +- src/dfx/src/commands/canister/delete.rs | 3 +- src/dfx/src/commands/canister/id.rs | 3 +- src/dfx/src/commands/canister/install.rs | 25 +----- src/dfx/src/commands/canister/mod.rs | 5 +- .../src/commands/canister/request_status.rs | 3 +- .../src/commands/canister/set_controller.rs | 3 +- src/dfx/src/commands/canister/start.rs | 3 +- src/dfx/src/commands/canister/status.rs | 3 +- src/dfx/src/commands/canister/stop.rs | 3 +- src/dfx/src/commands/config.rs | 3 +- src/dfx/src/commands/deploy.rs | 3 +- src/dfx/src/commands/identity/list.rs | 3 +- src/dfx/src/commands/identity/mod.rs | 18 ++-- src/dfx/src/commands/identity/new.rs | 3 +- src/dfx/src/commands/identity/principal.rs | 3 +- src/dfx/src/commands/identity/remove.rs | 3 +- src/dfx/src/commands/identity/rename.rs | 3 +- src/dfx/src/commands/identity/use.rs | 3 +- src/dfx/src/commands/identity/whoami.rs | 3 +- src/dfx/src/commands/language_service.rs | 3 +- src/dfx/src/commands/new.rs | 36 +------- src/dfx/src/commands/ping.rs | 3 +- src/dfx/src/commands/replica.rs | 3 +- src/dfx/src/commands/start.rs | 3 +- src/dfx/src/commands/stop.rs | 3 +- src/dfx/src/commands/upgrade.rs | 3 +- src/dfx/src/main.rs | 84 ++++++++----------- src/dfx/src/util/clap/validators.rs | 53 ++++++++++++ 37 files changed, 177 insertions(+), 145 deletions(-) diff --git a/src/dfx/src/commands/bootstrap.rs b/src/dfx/src/commands/bootstrap.rs index 3d6a442187..139b4d0a0d 100644 --- a/src/dfx/src/commands/bootstrap.rs +++ b/src/dfx/src/commands/bootstrap.rs @@ -18,6 +18,7 @@ use url::Url; /// Starts the bootstrap server. #[derive(Clap, Clone)] +#[clap(name("bootstrap"))] pub struct BootstrapOpts { /// Specifies the IP address that the bootstrap server listens on. Defaults to 127.0.0.1. #[clap(long)] @@ -43,7 +44,7 @@ pub struct BootstrapOpts { } pub fn construct() -> App<'static> { - BootstrapOpts::into_app().name("bootstrap") + BootstrapOpts::into_app() } /// Runs the bootstrap server. diff --git a/src/dfx/src/commands/build.rs b/src/dfx/src/commands/build.rs index ac3a32a71a..ed6af01bfd 100644 --- a/src/dfx/src/commands/build.rs +++ b/src/dfx/src/commands/build.rs @@ -8,6 +8,7 @@ use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; /// Builds all or specific canisters from the code in your project. By default, all canisters are built. #[derive(Clap)] +#[clap(name("build"))] pub struct CanisterBuildOpts { /// Specifies the name of the canister to build. /// You must specify either a canister name or the --all option. @@ -27,7 +28,7 @@ pub struct CanisterBuildOpts { } pub fn construct() -> App<'static> { - CanisterBuildOpts::into_app().name("build") + CanisterBuildOpts::into_app() } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/cache/delete.rs b/src/dfx/src/commands/cache/delete.rs index 5a15231152..8669d9dcc4 100644 --- a/src/dfx/src/commands/cache/delete.rs +++ b/src/dfx/src/commands/cache/delete.rs @@ -5,13 +5,14 @@ use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; /// Deletes a specific versioned cache of dfx. #[derive(Clap)] +#[clap(name("delete"))] pub struct CacheDeleteOpts { #[clap(long)] version: Option, } pub fn construct() -> App<'static> { - CacheDeleteOpts::into_app().name("delete") + CacheDeleteOpts::into_app() } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/cache/install.rs b/src/dfx/src/commands/cache/install.rs index cbdae8e5e3..1b69df7905 100644 --- a/src/dfx/src/commands/cache/install.rs +++ b/src/dfx/src/commands/cache/install.rs @@ -4,10 +4,11 @@ use clap::{App, ArgMatches, Clap, IntoApp}; /// Forces unpacking the cache from this dfx version. #[derive(Clap)] +#[clap(name("install"))] pub struct CacheInstall {} pub fn construct() -> App<'static> { - CacheInstall::into_app().name("install") + CacheInstall::into_app() } pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/cache/list.rs b/src/dfx/src/commands/cache/list.rs index 47aaa0128c..cdeb9c070e 100644 --- a/src/dfx/src/commands/cache/list.rs +++ b/src/dfx/src/commands/cache/list.rs @@ -6,10 +6,11 @@ use std::io::Write; /// Lists installed and used version. #[derive(Clap)] +#[clap(name("list"))] pub struct CacheListOpts {} pub fn construct() -> App<'static> { - CacheListOpts::into_app().name("list") + CacheListOpts::into_app() } pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/cache/mod.rs b/src/dfx/src/commands/cache/mod.rs index a7701eb419..f415d2b5d8 100644 --- a/src/dfx/src/commands/cache/mod.rs +++ b/src/dfx/src/commands/cache/mod.rs @@ -1,7 +1,7 @@ use crate::commands::CliCommand; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use clap::{App, ArgMatches}; +use clap::{App, ArgMatches, Clap, IntoApp}; mod delete; mod install; @@ -17,10 +17,13 @@ fn builtins() -> Vec { ] } +/// Manages the dfx version cache. +#[derive(Clap)] +#[clap(name("cache"))] +pub struct CacheOpts {} + pub fn construct() -> App<'static> { - App::new("cache") - .about("Manages the dfx version cache.") - .subcommands(builtins().into_iter().map(|x| x.get_subcommand().clone())) + CacheOpts::into_app().subcommands(builtins().into_iter().map(|x| x.get_subcommand().clone())) } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/cache/show.rs b/src/dfx/src/commands/cache/show.rs index 6fcefd841f..25f99b11f4 100644 --- a/src/dfx/src/commands/cache/show.rs +++ b/src/dfx/src/commands/cache/show.rs @@ -5,10 +5,11 @@ use clap::{App, ArgMatches, Clap, IntoApp}; /// Shows the path of the cache used by this version. #[derive(Clap)] +#[clap(name("show"))] pub struct CacheShowOpts {} pub fn construct() -> App<'static> { - CacheShowOpts::into_app().name("show") + CacheShowOpts::into_app() } pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/canister/call.rs b/src/dfx/src/commands/canister/call.rs index 20d2169eac..b914eafd19 100644 --- a/src/dfx/src/commands/canister/call.rs +++ b/src/dfx/src/commands/canister/call.rs @@ -11,6 +11,7 @@ use tokio::runtime::Runtime; /// Deletes a canister on the Internet Computer network. #[derive(Clap)] +#[clap(name("call"))] pub struct CanisterCallOpts { /// Specifies the name of the canister to build. /// You must specify either a canister name or the --all option. @@ -46,7 +47,7 @@ pub struct CanisterCallOpts { } pub fn construct() -> App<'static> { - CanisterCallOpts::into_app().name("call") + CanisterCallOpts::into_app() } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/canister/create.rs b/src/dfx/src/commands/canister/create.rs index 48c7dcd60d..72cda8011b 100644 --- a/src/dfx/src/commands/canister/create.rs +++ b/src/dfx/src/commands/canister/create.rs @@ -7,6 +7,7 @@ use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; /// Creates an empty canister on the Internet Computer and /// associates the Internet Computer assigned Canister ID to the canister name. #[derive(Clap)] +#[clap(name("create"))] pub struct CanisterCreateOpts { /// Specifies the canister name. Either this or the --all flag are required. canister_name: Option, @@ -17,7 +18,7 @@ pub struct CanisterCreateOpts { } pub fn construct() -> App<'static> { - CanisterCreateOpts::into_app().name("create") + CanisterCreateOpts::into_app() } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/canister/delete.rs b/src/dfx/src/commands/canister/delete.rs index 895923397e..a88658bcf0 100644 --- a/src/dfx/src/commands/canister/delete.rs +++ b/src/dfx/src/commands/canister/delete.rs @@ -13,6 +13,7 @@ use tokio::runtime::Runtime; /// Deletes a canister on the Internet Computer network. #[derive(Clap)] +#[clap(name("delete"))] pub struct CanisterDeleteOpts { /// Specifies the name of the canister to delete. /// You must specify either a canister name or the --all flag. @@ -24,7 +25,7 @@ pub struct CanisterDeleteOpts { } pub fn construct() -> App<'static> { - CanisterDeleteOpts::into_app().name("delete") + CanisterDeleteOpts::into_app() } async fn delete_canister( diff --git a/src/dfx/src/commands/canister/id.rs b/src/dfx/src/commands/canister/id.rs index d629b321eb..349c8af679 100644 --- a/src/dfx/src/commands/canister/id.rs +++ b/src/dfx/src/commands/canister/id.rs @@ -6,6 +6,7 @@ use ic_types::principal::Principal as CanisterId; /// Prints the identifier of a canister. #[derive(Clap)] +#[clap(name("id"))] pub struct CanisterIdOpts { /// Specifies the name of the canister to stop. /// You must specify either a canister name or the --all option. @@ -13,7 +14,7 @@ pub struct CanisterIdOpts { } pub fn construct() -> App<'static> { - CanisterIdOpts::into_app().name("id") + CanisterIdOpts::into_app() } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/canister/install.rs b/src/dfx/src/commands/canister/install.rs index 07657ce231..057ab40f1b 100644 --- a/src/dfx/src/commands/canister/install.rs +++ b/src/dfx/src/commands/canister/install.rs @@ -4,9 +4,10 @@ use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; use crate::lib::models::canister_id_store::CanisterIdStore; use crate::lib::operations::canister::install_canister; +use crate::util::clap::validators::{compute_allocation_validator, memory_allocation_validator}; use crate::util::{blob_from_arguments, expiry_duration, get_candid_init_type}; use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; -use humanize_rs::bytes::{Bytes, Unit}; +use humanize_rs::bytes::Bytes; use ic_utils::interfaces::management_canister::{ComputeAllocation, InstallMode, MemoryAllocation}; use std::convert::TryFrom; use std::str::FromStr; @@ -14,6 +15,7 @@ use tokio::runtime::Runtime; /// Deploys compiled code as a canister on the Internet Computer. #[derive(Clap, Clone)] +#[clap(name("install"))] pub struct CanisterInstallOpts { /// Specifies the canister name to deploy. You must specify either canister name or the --all option. canister_name: Option, @@ -50,26 +52,7 @@ pub struct CanisterInstallOpts { } pub fn construct() -> App<'static> { - CanisterInstallOpts::into_app().name("install") -} - -fn compute_allocation_validator(compute_allocation: &str) -> Result<(), String> { - if let Ok(num) = compute_allocation.parse::() { - if num <= 100 { - return Ok(()); - } - } - Err("Must be a percent between 0 and 100".to_string()) -} - -fn memory_allocation_validator(memory_allocation: &str) -> Result<(), String> { - let limit = Bytes::new(256, Unit::TByte).map_err(|_| "Parse Overflow.")?; - if let Ok(bytes) = memory_allocation.parse::() { - if bytes.size() <= limit.size() { - return Ok(()); - } - } - Err("Must be a value between 0..256 TB inclusive.".to_string()) + CanisterInstallOpts::into_app() } fn get_compute_allocation( diff --git a/src/dfx/src/commands/canister/mod.rs b/src/dfx/src/commands/canister/mod.rs index 10eea2b7a3..9107d1d62b 100644 --- a/src/dfx/src/commands/canister/mod.rs +++ b/src/dfx/src/commands/canister/mod.rs @@ -32,6 +32,7 @@ fn builtins() -> Vec { /// Manages canisters deployed on a network replica. #[derive(Clap)] +#[clap(name("canister"))] pub struct CanisterOpts { // Override the compute network to connect to. By default, the local network is used. #[clap(long)] @@ -39,9 +40,7 @@ pub struct CanisterOpts { } pub fn construct() -> App<'static> { - CanisterOpts::into_app() - .name("canister") - .subcommands(builtins().into_iter().map(|x| x.get_subcommand().clone())) + CanisterOpts::into_app().subcommands(builtins().into_iter().map(|x| x.get_subcommand().clone())) } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/canister/request_status.rs b/src/dfx/src/commands/canister/request_status.rs index c3564ad071..04cedf601a 100644 --- a/src/dfx/src/commands/canister/request_status.rs +++ b/src/dfx/src/commands/canister/request_status.rs @@ -12,6 +12,7 @@ use tokio::runtime::Runtime; /// Requests the status of a specified call from a canister. #[derive(Clap)] +#[clap(name("request-status"))] pub struct RequestStatusOpts { /// Specifies the request identifier. /// The request identifier is an hexadecimal string starting with 0x. @@ -20,7 +21,7 @@ pub struct RequestStatusOpts { } pub fn construct() -> App<'static> { - RequestStatusOpts::into_app().name("request-status") + RequestStatusOpts::into_app() } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/canister/set_controller.rs b/src/dfx/src/commands/canister/set_controller.rs index c85365910b..73090c128a 100644 --- a/src/dfx/src/commands/canister/set_controller.rs +++ b/src/dfx/src/commands/canister/set_controller.rs @@ -14,6 +14,7 @@ use tokio::runtime::Runtime; /// Sets the provided identity's name or its principal as the /// new controller of a canister on the Internet Computer network. #[derive(Clap)] +#[clap(name("set-controller"))] pub struct SetControllerOpts { /// Specifies the canister name or the canister identifier for the canister to be controlled. canister: String, @@ -23,7 +24,7 @@ pub struct SetControllerOpts { } pub fn construct() -> App<'static> { - SetControllerOpts::into_app().name("set-controller") + SetControllerOpts::into_app() } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/canister/start.rs b/src/dfx/src/commands/canister/start.rs index 729d7e7f7e..8cf0a3d9b5 100644 --- a/src/dfx/src/commands/canister/start.rs +++ b/src/dfx/src/commands/canister/start.rs @@ -13,6 +13,7 @@ use tokio::runtime::Runtime; /// Starts a canister on the Internet Computer network. #[derive(Clap)] +#[clap(name("start"))] pub struct CanisterStartOpts { /// Specifies the name of the canister to start. You must specify either a canister name or the --all flag. canister_name: Option, @@ -23,7 +24,7 @@ pub struct CanisterStartOpts { } pub fn construct() -> App<'static> { - CanisterStartOpts::into_app().name("start") + CanisterStartOpts::into_app() } async fn start_canister( diff --git a/src/dfx/src/commands/canister/status.rs b/src/dfx/src/commands/canister/status.rs index db62eea6a1..e7fc63e4c5 100644 --- a/src/dfx/src/commands/canister/status.rs +++ b/src/dfx/src/commands/canister/status.rs @@ -13,6 +13,7 @@ use tokio::runtime::Runtime; /// Returns the current status of the canister on the Internet Computer network: Running, Stopping, or Stopped. #[derive(Clap)] +#[clap(name("status"))] pub struct CanisterStatusOpts { /// Specifies the name of the canister to return information for. /// You must specify either a canister name or the --all flag. @@ -24,7 +25,7 @@ pub struct CanisterStatusOpts { } pub fn construct() -> App<'static> { - CanisterStatusOpts::into_app().name("status") + CanisterStatusOpts::into_app() } async fn canister_status( diff --git a/src/dfx/src/commands/canister/stop.rs b/src/dfx/src/commands/canister/stop.rs index 300f9e9df6..cb78e48e35 100644 --- a/src/dfx/src/commands/canister/stop.rs +++ b/src/dfx/src/commands/canister/stop.rs @@ -13,6 +13,7 @@ use tokio::runtime::Runtime; /// Stops a canister that is currently running on the Internet Computer network. #[derive(Clap)] +#[clap(name("stop"))] pub struct CanisterStopOpts { /// Specifies the name of the canister to stop. /// You must specify either a canister name or the --all option. @@ -24,7 +25,7 @@ pub struct CanisterStopOpts { } pub fn construct() -> App<'static> { - CanisterStopOpts::into_app().name("stop") + CanisterStopOpts::into_app() } async fn stop_canister( diff --git a/src/dfx/src/commands/config.rs b/src/dfx/src/commands/config.rs index 04e1276c4a..1c97563614 100644 --- a/src/dfx/src/commands/config.rs +++ b/src/dfx/src/commands/config.rs @@ -6,6 +6,7 @@ use serde_json::value::Value; /// Configures project options for your currently-selected project. #[derive(Clap)] +#[clap(name("config"))] pub struct ConfigOpts { /// Specifies the name of the configuration option to set or read. /// Use the period delineated path to specify the option to set or read. @@ -22,7 +23,7 @@ pub struct ConfigOpts { } pub fn construct() -> App<'static> { - ConfigOpts::into_app().name("config") + ConfigOpts::into_app() } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/deploy.rs b/src/dfx/src/commands/deploy.rs index c2712ea0b3..77ea672735 100644 --- a/src/dfx/src/commands/deploy.rs +++ b/src/dfx/src/commands/deploy.rs @@ -7,6 +7,7 @@ use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; /// Deploys all or a specific canister from the code in your project. By default, all canisters are deployed. #[derive(Clap)] +#[clap(name("deploy"))] pub struct DeployOpts { /// Specifies the name of the canister you want to deploy. /// If you don’t specify a canister name, all canisters defined in the dfx.json file are deployed. @@ -26,7 +27,7 @@ pub struct DeployOpts { } pub fn construct() -> App<'static> { - DeployOpts::into_app().name("deploy") + DeployOpts::into_app() } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/identity/list.rs b/src/dfx/src/commands/identity/list.rs index 6096eee398..a066d4d754 100644 --- a/src/dfx/src/commands/identity/list.rs +++ b/src/dfx/src/commands/identity/list.rs @@ -6,10 +6,11 @@ use std::io::Write; /// Lists existing identities. #[derive(Clap)] +#[clap(name("list"))] pub struct ListOpts {} pub fn construct() -> App<'static> { - ListOpts::into_app().name("list") + ListOpts::into_app() } pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/identity/mod.rs b/src/dfx/src/commands/identity/mod.rs index 2baa94d59c..a9cba1c748 100644 --- a/src/dfx/src/commands/identity/mod.rs +++ b/src/dfx/src/commands/identity/mod.rs @@ -1,7 +1,7 @@ use crate::commands::CliCommand; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; -use clap::{App, ArgMatches}; +use clap::{App, ArgMatches, Clap, IntoApp}; mod list; mod new; @@ -11,6 +11,16 @@ mod rename; mod r#use; mod whoami; +/// Manages identities used to communicate with the Internet Computer network. +/// Setting an identity enables you to test user-based access controls. +#[derive(Clap)] +#[clap(name("identity"))] +pub struct IdentityOpt {} + +pub fn construct() -> App<'static> { + IdentityOpt::into_app().subcommands(builtins().into_iter().map(|x| x.get_subcommand().clone())) +} + fn builtins() -> Vec { vec![ CliCommand::new(list::construct(), list::exec), @@ -23,12 +33,6 @@ fn builtins() -> Vec { ] } -pub fn construct() -> App<'static> { - App::new("identity") - .about("Manages identities used to communicate with the Internet Computer network. Setting an identity enables you to test user-based access controls.") - .subcommands(builtins().into_iter().map(|x| x.get_subcommand().clone())) -} - pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { let subcommand = args.subcommand(); diff --git a/src/dfx/src/commands/identity/new.rs b/src/dfx/src/commands/identity/new.rs index 51d0391365..187f17ed05 100644 --- a/src/dfx/src/commands/identity/new.rs +++ b/src/dfx/src/commands/identity/new.rs @@ -6,13 +6,14 @@ use slog::info; /// Creates a new identity. #[derive(Clap)] +#[clap(name("new"))] pub struct NewIdentityOpts { /// The identity to create. identity: String, } pub fn construct() -> App<'static> { - NewIdentityOpts::into_app().name("new") + NewIdentityOpts::into_app() } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/identity/principal.rs b/src/dfx/src/commands/identity/principal.rs index 85147a41c6..8737953cab 100644 --- a/src/dfx/src/commands/identity/principal.rs +++ b/src/dfx/src/commands/identity/principal.rs @@ -6,10 +6,11 @@ use ic_agent::Identity; /// Shows the textual representation of the Principal associated with the current identity. #[derive(Clap)] +#[clap(name("get-principal"))] pub struct GetPrincipalOpts {} pub fn construct() -> App<'static> { - GetPrincipalOpts::into_app().name("get-principal") + GetPrincipalOpts::into_app() } pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/identity/remove.rs b/src/dfx/src/commands/identity/remove.rs index ad3c2f9f6a..95c209709d 100644 --- a/src/dfx/src/commands/identity/remove.rs +++ b/src/dfx/src/commands/identity/remove.rs @@ -6,13 +6,14 @@ use slog::info; /// Removes an existing identity. #[derive(Clap)] +#[clap(name("remove"))] pub struct RemoveOpts { /// The identity to remove. identity: String, } pub fn construct() -> App<'static> { - RemoveOpts::into_app().name("remove") + RemoveOpts::into_app() } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/identity/rename.rs b/src/dfx/src/commands/identity/rename.rs index cc3eed0153..a17c68b613 100644 --- a/src/dfx/src/commands/identity/rename.rs +++ b/src/dfx/src/commands/identity/rename.rs @@ -6,6 +6,7 @@ use slog::info; /// Renames an existing identity. #[derive(Clap)] +#[clap(name("rename"))] pub struct RenameOpts { /// The current name of the identity. from: String, @@ -15,7 +16,7 @@ pub struct RenameOpts { } pub fn construct() -> App<'static> { - RenameOpts::into_app().name("rename") + RenameOpts::into_app() } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/identity/use.rs b/src/dfx/src/commands/identity/use.rs index f5e60050cd..89f2368713 100644 --- a/src/dfx/src/commands/identity/use.rs +++ b/src/dfx/src/commands/identity/use.rs @@ -6,13 +6,14 @@ use slog::info; /// Specifies the identity to use. #[derive(Clap)] +#[clap(name("use"))] pub struct UseOpts { /// The identity to use. identity: String, } pub fn construct() -> App<'static> { - UseOpts::into_app().name("use") + UseOpts::into_app() } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/identity/whoami.rs b/src/dfx/src/commands/identity/whoami.rs index 3e411289ae..52638106a7 100644 --- a/src/dfx/src/commands/identity/whoami.rs +++ b/src/dfx/src/commands/identity/whoami.rs @@ -5,10 +5,11 @@ use clap::{App, ArgMatches, Clap, IntoApp}; /// Shows the name of the current identity. #[derive(Clap)] +#[clap(name("whoami"))] pub struct WhoAmIOpts {} pub fn construct() -> App<'static> { - WhoAmIOpts::into_app().name("whoami") + WhoAmIOpts::into_app() } pub fn exec(env: &dyn Environment, _args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/language_service.rs b/src/dfx/src/commands/language_service.rs index c6fc761843..31b2230797 100644 --- a/src/dfx/src/commands/language_service.rs +++ b/src/dfx/src/commands/language_service.rs @@ -10,6 +10,7 @@ const CANISTER_ARG: &str = "canister"; /// Starts the Motoko IDE Language Server. This is meant to be run by editor plugins not the /// end-user. #[derive(Clap)] +#[clap(name("_language-service"))] #[clap(setting = AppSettings::Hidden)] pub struct LanguageServiceOpts { /// Specifies the canister name. If you don't specify this argument, all canisters are @@ -22,7 +23,7 @@ pub struct LanguageServiceOpts { } pub fn construct() -> App<'static> { - LanguageServiceOpts::into_app().name("_language-service") + LanguageServiceOpts::into_app() } // Don't read anything from stdin or output anything to stdout while this function is being diff --git a/src/dfx/src/commands/new.rs b/src/dfx/src/commands/new.rs index ea63ec922c..40dc6dbf2f 100644 --- a/src/dfx/src/commands/new.rs +++ b/src/dfx/src/commands/new.rs @@ -4,6 +4,7 @@ use crate::config::dfx_version_str; use crate::lib::environment::Environment; use crate::lib::error::{DfxError, DfxResult}; use crate::util::assets; +use crate::util::clap::validators::project_name_validator; use clap::{App, ArgMatches, Clap, FromArgMatches, IntoApp}; use console::{style, Style}; use indicatif::HumanBytes; @@ -30,40 +31,9 @@ lazy_static! { static ref CHECK_VERSION_TIMEOUT: Duration = Duration::from_secs(2); } -/// Validate a String can be a valid project name. -/// A project name is valid if it starts with a letter, and is alphanumeric (with hyphens). -/// It cannot end with a dash. -pub fn project_name_validator(name: &str) -> Result<(), String> { - let mut chars = name.chars(); - // Check first character first. If there's no first character it's empty. - if let Some(first) = chars.next() { - if first.is_ascii_alphabetic() { - // Then check all other characters. - // Reverses the search here; if there is a character that is not compatible - // it is found and an error is returned. - let m: Vec<&str> = name - .matches(|x: char| !x.is_ascii_alphanumeric() && x != '_') - .collect(); - - if m.is_empty() { - Ok(()) - } else { - Err(format!( - r#"Invalid character(s): "{}""#, - m.iter() - .fold(String::new(), |acc, &num| acc + &num.to_string()) - )) - } - } else { - Err("Must start with a letter.".to_owned()) - } - } else { - Err("Cannot be empty.".to_owned()) - } -} - /// Creates a new project. #[derive(Clap)] +#[clap(name("new"))] pub struct NewOpts { /// Specifies the name of the project to create. #[clap(validator(project_name_validator))] @@ -82,7 +52,7 @@ pub struct NewOpts { } pub fn construct() -> App<'static> { - NewOpts::into_app().name("new") + NewOpts::into_app() } enum Status<'a> { diff --git a/src/dfx/src/commands/ping.rs b/src/dfx/src/commands/ping.rs index b7cdd49fb6..0cf3bcb99f 100644 --- a/src/dfx/src/commands/ping.rs +++ b/src/dfx/src/commands/ping.rs @@ -9,13 +9,14 @@ use tokio::runtime::Runtime; /// Pings an Internet Computer network and returns its status. #[derive(Clap)] +#[clap(name("ping"))] pub struct PingOpts { /// The provider to use. network: Option, } pub fn construct() -> App<'static> { - PingOpts::into_app().name("ping") + PingOpts::into_app() } pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { diff --git a/src/dfx/src/commands/replica.rs b/src/dfx/src/commands/replica.rs index 2c48720537..3dbbf94c6b 100644 --- a/src/dfx/src/commands/replica.rs +++ b/src/dfx/src/commands/replica.rs @@ -11,6 +11,7 @@ use std::default::Default; /// Starts a local Internet Computer replica. #[derive(Clap)] +#[clap(name("replica"))] pub struct ReplicaOpts { /// Specifies the maximum number of cycles a single message can consume. #[clap(long, hidden = true)] @@ -26,7 +27,7 @@ pub struct ReplicaOpts { } pub fn construct() -> App<'static> { - ReplicaOpts::into_app().name("replica") + ReplicaOpts::into_app() } /// Gets the configuration options for the Internet Computer replica. diff --git a/src/dfx/src/commands/start.rs b/src/dfx/src/commands/start.rs index cbdcf2bd99..aa2c31a7f5 100644 --- a/src/dfx/src/commands/start.rs +++ b/src/dfx/src/commands/start.rs @@ -25,6 +25,7 @@ use tokio::runtime::Runtime; /// Starts the local replica and a web server for the current project. #[derive(Clap)] +#[clap(name("start"))] pub struct StartOpts { /// Specifies the host name and port number to bind the frontend to. #[clap(long)] @@ -40,7 +41,7 @@ pub struct StartOpts { } pub fn construct() -> App<'static> { - StartOpts::into_app().name("start") + StartOpts::into_app() } fn ping_and_wait(frontend_url: &str) -> DfxResult { diff --git a/src/dfx/src/commands/stop.rs b/src/dfx/src/commands/stop.rs index 614c65c4eb..4a28e75c6a 100644 --- a/src/dfx/src/commands/stop.rs +++ b/src/dfx/src/commands/stop.rs @@ -5,10 +5,11 @@ use sysinfo::{Pid, Process, ProcessExt, Signal, System, SystemExt}; /// Stops the local network replica. #[derive(Clap)] +#[clap(name("stop"))] pub struct StopOpts {} pub fn construct() -> App<'static> { - StopOpts::into_app().name("stop") + StopOpts::into_app() } fn list_all_descendants(pid: Pid) -> Vec { diff --git a/src/dfx/src/commands/upgrade.rs b/src/dfx/src/commands/upgrade.rs index 02ca1ec880..a726c24386 100644 --- a/src/dfx/src/commands/upgrade.rs +++ b/src/dfx/src/commands/upgrade.rs @@ -10,6 +10,7 @@ use tar::Archive; /// Upgrade DFX. #[derive(Clap)] +#[clap(name("upgrade"))] pub struct UpgradeOpts { /// Current Version. #[clap(long)] @@ -20,7 +21,7 @@ pub struct UpgradeOpts { } pub fn construct() -> App<'static> { - UpgradeOpts::into_app().name("upgrade") + UpgradeOpts::into_app() } fn parse_semver<'de, D>(version: &str) -> Result diff --git a/src/dfx/src/main.rs b/src/dfx/src/main.rs index 45b8240015..79a0c384e4 100644 --- a/src/dfx/src/main.rs +++ b/src/dfx/src/main.rs @@ -1,9 +1,8 @@ -use crate::commands::CliCommand; use crate::config::{dfx_version, dfx_version_str}; use crate::lib::environment::{Environment, EnvironmentImpl}; use crate::lib::error::*; use crate::lib::logger::{create_root_logger, LoggingMode}; -use clap::{App, AppSettings, Arg, ArgMatches}; +use clap::{App, AppSettings, ArgMatches, Clap, FromArgMatches, IntoApp}; use std::path::PathBuf; mod actors; @@ -12,40 +11,36 @@ mod config; mod lib; mod util; +/// The DFINITY Executor. +#[derive(Clap)] +#[clap(name("dfx"))] +#[clap(version = dfx_version_str(), global_setting = AppSettings::ColoredHelp)] +pub struct CliOpts { + #[clap(long, short('v'), parse(from_occurrences))] + verbose: u64, + + #[clap(long, short('q'), parse(from_occurrences))] + quiet: u64, + + #[clap(long("log"), default_value("stderr"), possible_values(&["stderr", "tee", "file"]))] + logmode: String, + + #[clap(long)] + logfile: Option, + + #[clap(long)] + identity: Option, +} + fn cli(_: &impl Environment) -> App<'static> { - App::new("dfx") - .about("The DFINITY Executor.") - .version(dfx_version_str()) - .global_setting(AppSettings::ColoredHelp) - .arg( - Arg::new("verbose") - .long("verbose") - .short('v') - .multiple(true), - ) - .arg(Arg::new("quiet").long("quiet").short('q').multiple(true)) - .arg( - Arg::new("logmode") - .long("log") - .takes_value(true) - .possible_values(&["stderr", "tee", "file"]) - .default_value("stderr"), - ) - .arg( - Arg::new("logfile") - .long("log-file") - .long("logfile") - .takes_value(true), - ) - .arg(Arg::new("identity").long("identity").takes_value(true)) - .subcommands( - commands::builtin() - .into_iter() - .map(|x: CliCommand| x.get_subcommand().clone()), - ) + CliOpts::into_app().subcommands( + commands::builtin() + .into_iter() + .map(|x| x.get_subcommand().clone()), + ) } -fn exec(env: &impl Environment, args: &clap::ArgMatches, cli: &mut App<'static>) -> DfxResult { +fn exec(env: &impl Environment, args: &ArgMatches, cli: &mut App<'static>) -> DfxResult { let (name, subcommand_args) = match args.subcommand() { Some((name, args)) => (name, args), _ => { @@ -120,17 +115,13 @@ fn maybe_redirect_dfx(env: &impl Environment) -> Option<()> { /// Setup a logger with the proper configuration, based on arguments. /// Returns a topple of whether or not to have a progress bar, and a logger. -fn setup_logging(matches: &ArgMatches) -> (bool, slog::Logger) { +fn setup_logging(opts: &CliOpts) -> (bool, slog::Logger) { // Create a logger with our argument matches. - let level = matches.occurrences_of("verbose") as i64 - matches.occurrences_of("quiet") as i64; - - let mode = match matches.value_of("logmode") { - Some("tee") => LoggingMode::Tee(PathBuf::from( - matches.value_of("logfile").unwrap_or("log.txt"), - )), - Some("file") => LoggingMode::File(PathBuf::from( - matches.value_of("logfile").unwrap_or("log.txt"), - )), + let level = opts.verbose as i64 - opts.quiet as i64; + + let mode = match opts.logmode.as_str() { + "tee" => LoggingMode::Tee(PathBuf::from(opts.logfile.as_deref().unwrap_or("log.txt"))), + "file" => LoggingMode::File(PathBuf::from(opts.logfile.as_deref().unwrap_or("log.txt"))), _ => LoggingMode::Stderr, }; @@ -146,17 +137,16 @@ fn main() { } let matches = cli(&env).get_matches(); + let opts: CliOpts = CliOpts::from_arg_matches(&matches); - let (progress_bar, log) = setup_logging(&matches); - - let identity_name = matches.value_of("identity").map(String::from); + let (progress_bar, log) = setup_logging(&opts); // Need to recreate the environment because we use it to get matches. // TODO(hansl): resolve this double-create problem. match EnvironmentImpl::new().map(|x| { x.with_logger(log) .with_progress_bar(progress_bar) - .with_identity_override(identity_name) + .with_identity_override(opts.identity) }) { Ok(env) => { slog::trace!( diff --git a/src/dfx/src/util/clap/validators.rs b/src/dfx/src/util/clap/validators.rs index 5f7b5b9c36..163a9ff6d4 100644 --- a/src/dfx/src/util/clap/validators.rs +++ b/src/dfx/src/util/clap/validators.rs @@ -1,3 +1,5 @@ +use humanize_rs::bytes::{Bytes, Unit}; + pub fn is_request_id(v: &str) -> Result<(), String> { // A valid Request Id starts with `0x` and is a series of 64 hexadecimals. if !v.starts_with("0x") { @@ -14,3 +16,54 @@ pub fn is_request_id(v: &str) -> Result<(), String> { Ok(()) } } + +pub fn compute_allocation_validator(compute_allocation: &str) -> Result<(), String> { + if let Ok(num) = compute_allocation.parse::() { + if num <= 100 { + return Ok(()); + } + } + Err("Must be a percent between 0 and 100".to_string()) +} + +pub fn memory_allocation_validator(memory_allocation: &str) -> Result<(), String> { + let limit = Bytes::new(256, Unit::TByte).map_err(|_| "Parse Overflow.")?; + if let Ok(bytes) = memory_allocation.parse::() { + if bytes.size() <= limit.size() { + return Ok(()); + } + } + Err("Must be a value between 0..256 TB inclusive.".to_string()) +} + +/// Validate a String can be a valid project name. +/// A project name is valid if it starts with a letter, and is alphanumeric (with hyphens). +/// It cannot end with a dash. +pub fn project_name_validator(name: &str) -> Result<(), String> { + let mut chars = name.chars(); + // Check first character first. If there's no first character it's empty. + if let Some(first) = chars.next() { + if first.is_ascii_alphabetic() { + // Then check all other characters. + // Reverses the search here; if there is a character that is not compatible + // it is found and an error is returned. + let m: Vec<&str> = name + .matches(|x: char| !x.is_ascii_alphanumeric() && x != '_') + .collect(); + + if m.is_empty() { + Ok(()) + } else { + Err(format!( + r#"Invalid character(s): "{}""#, + m.iter() + .fold(String::new(), |acc, &num| acc + &num.to_string()) + )) + } + } else { + Err("Must start with a letter.".to_owned()) + } + } else { + Err("Cannot be empty.".to_owned()) + } +} From 680e63201f283a877c72a44137080a102e9ba0e6 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Thu, 5 Nov 2020 19:38:32 -0800 Subject: [PATCH 25/26] patch --- src/dfx/src/commands/new.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/dfx/src/commands/new.rs b/src/dfx/src/commands/new.rs index 40dc6dbf2f..58b8bcc305 100644 --- a/src/dfx/src/commands/new.rs +++ b/src/dfx/src/commands/new.rs @@ -328,23 +328,23 @@ pub fn exec(env: &dyn Environment, args: &ArgMatches) -> DfxResult { // Any version that contains a `-` is a local build. // TODO: when adding alpha/beta, take that into account. // TODO: move this to a Version type. - let _is_dirty = dfx_version_str().contains('-'); - - let js_agent_version = dfx_version_str().to_owned(); // if is_dirty { - // // file!() returns a path like `src/dfx/src/commands/new.rs`, but since we are - // // running from a directory outside the source tree, this does not help. - // let agent_path = std::env::current_exe()? - // .parent() - // .unwrap() - // .join("../../src/agent/javascript"); - // agent_path - // .canonicalize() - // .map_err(|e| DfxError::IoWithPath(e, agent_path))? - // .to_string_lossy() - // .to_string() - // } else { - // dfx_version_str().to_owned() - // }; + let is_dirty = dfx_version_str().contains('-'); + + let js_agent_version = if is_dirty { + // file!() returns a path like `src/dfx/src/commands/new.rs`, but since we are + // running from a directory outside the source tree, this does not help. + let agent_path = std::env::current_exe()? + .parent() + .unwrap() + .join("../../src/agent/javascript"); + agent_path + .canonicalize() + .map_err(|e| DfxError::IoWithPath(e, agent_path))? + .to_string_lossy() + .to_string() + } else { + dfx_version_str().to_owned() + }; let variables: BTreeMap = [ ("project_name".to_string(), project_name_str.to_string()), From 334f5b6a055e58c72959b97facf007b776980ee2 Mon Sep 17 00:00:00 2001 From: Prithvi Shahi Date: Thu, 12 Nov 2020 14:08:56 -0800 Subject: [PATCH 26/26] fix lock file --- Cargo.lock | 217 ++++++++++++++++++++++++++--------------------------- 1 file changed, 108 insertions(+), 109 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 208de44239..761bb18e81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -318,7 +318,7 @@ dependencies = [ "serde_urlencoded", "socket2", "time 0.2.22", - "tinyvec 1.0.1", + "tinyvec", "url", ] @@ -367,19 +367,13 @@ checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" [[package]] name = "aho-corasick" -version = "0.7.14" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b476ce7103678b0c6d3d395dbbae31d48ff910bd28be979ba5d48c6351131d0d" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" dependencies = [ "memchr", ] -[[package]] -name = "arc-swap" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034" - [[package]] name = "arrayref" version = "0.3.6" @@ -488,9 +482,9 @@ dependencies = [ [[package]] name = "base-x" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b20b618342cf9891c292c4f5ac2cde7287cc5c87e87e9c769d617793607dec1" +checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" [[package]] name = "base32" @@ -545,9 +539,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "blake2b_simd" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" dependencies = [ "arrayref", "arrayvec", @@ -648,9 +642,9 @@ dependencies = [ [[package]] name = "candid" -version = "0.6.7" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a72c51bb97c469cbb72afcc2372af1d7ce9f2126a89075dc1bf357c775c6f0db" +checksum = "74f44084374a7a6746e4c843ee24e70af99f4aed0919aac56ea36de0bd33c594" dependencies = [ "byteorder", "candid_derive", @@ -672,10 +666,11 @@ dependencies = [ [[package]] name = "candid_derive" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab31ccaf3ab1184bab4a139afb0d23c3aa54144d4a92ef0d0de7653cad4f679f" +checksum = "e04dba517a775d8e2937618658f5be4dc8fc845fafa57eb8e0e9e3ecc11889b3" dependencies = [ + "lazy_static", "proc-macro2", "quote", "syn", @@ -683,9 +678,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed67cbde08356238e75fc4656be4749481eeffb09e19f320a25237d5221c985d" +checksum = "f1770ced377336a88a67c473594ccc14eca6f4559217c34f64aac8f83d641b40" [[package]] name = "cfg-if" @@ -848,9 +843,9 @@ dependencies = [ [[package]] name = "const_fn" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce90df4c658c62f12d78f7508cf92f9173e5184a539c10bfe54a3107b3ffd0f2" +checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab" [[package]] name = "constant_time_eq" @@ -860,9 +855,9 @@ checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] name = "cookie" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1373a16a4937bc34efec7b391f9c1500c30b8478a701a4f44c9165cc0475a6e0" +checksum = "784ad0fbab4f3e9cef09f20e0aea6000ae08d2cb98ac4c0abc53df18803d702f" dependencies = [ "percent-encoding", "time 0.2.22", @@ -877,9 +872,9 @@ checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" [[package]] name = "core-foundation" -version = "0.7.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" dependencies = [ "core-foundation-sys", "libc", @@ -887,9 +882,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.7.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" +checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" [[package]] name = "cpuid-bool" @@ -1259,11 +1254,11 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.24" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a51b8cf747471cb9499b6d59e59b0444f4c90eba8968c4e44874e92b5b64ace2" +checksum = "801bbab217d7f79c0062f4f7205b5d4427c6d1a7bd7aafdd1475f7c59d62b283" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", ] [[package]] @@ -1320,11 +1315,11 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "filetime" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed85775dcc68644b5c950ac06a2b23768d3bc9390464151aaf27136998dcf9e" +checksum = "0c122a393ea57648015bf06fbd3d372378992e86b9ff5a7a497b076a28c79efe" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", "redox_syscall", "winapi 0.3.9", @@ -1338,11 +1333,11 @@ checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" [[package]] name = "flate2" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da80be589a72651dcda34d8b35bcdc9b7254ad06325611074d9cc0fbb19f60ee" +checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "crc32fast", "libc", "miniz_oxide", @@ -1378,6 +1373,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "form_urlencoded" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00" +dependencies = [ + "matches", + "percent-encoding", +] + [[package]] name = "fragile" version = "0.3.0" @@ -1408,9 +1413,9 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futures" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95314d38584ffbfda215621d723e0a3906f032e03ae5551e650058dac83d4797" +checksum = "9b3b0c040a1fe6529d30b3c5944b280c7f0dcb2930d2c3062bca967b602583d0" dependencies = [ "futures-channel", "futures-core", @@ -1423,9 +1428,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0448174b01148032eed37ac4aed28963aaaa8cfa93569a08e5b479bbc6c2c151" +checksum = "4b7109687aa4e177ef6fe84553af6280ef2778bdb7783ba44c9dc3399110fe64" dependencies = [ "futures-core", "futures-sink", @@ -1433,15 +1438,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18eaa56102984bed2c88ea39026cff3ce3b4c7f508ca970cedf2450ea10d4e46" +checksum = "847ce131b72ffb13b6109a221da9ad97a64cbe48feb1028356b836b47b8f1748" [[package]] name = "futures-executor" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5f8e0c9258abaea85e78ebdda17ef9666d390e987f006be6080dfe354b708cb" +checksum = "4caa2b2b68b880003057c1dd49f1ed937e38f22fcf6c212188a121f08cf40a65" dependencies = [ "futures-core", "futures-task", @@ -1450,15 +1455,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1798854a4727ff944a7b12aa999f58ce7aa81db80d2dfaaf2ba06f065ddd2b" +checksum = "611834ce18aaa1bd13c4b374f5d653e1027cf99b6b502584ff8c9a64413b30bb" [[package]] name = "futures-macro" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36fccf3fc58563b4a14d265027c627c3b665d7fed489427e88e7cc929559efe" +checksum = "77408a692f1f97bcc61dc001d752e00643408fbc922e4d634c655df50d595556" dependencies = [ "proc-macro-hack", "proc-macro2", @@ -1468,24 +1473,24 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e3ca3f17d6e8804ae5d3df7a7d35b2b3a6fe89dac84b31872720fc3060a0b11" +checksum = "f878195a49cee50e006b02b93cf7e0a95a38ac7b776b4c4d9cc1207cd20fcb3d" [[package]] name = "futures-task" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d502af37186c4fef99453df03e374683f8a1eec9dcc1e66b3b82dc8278ce3c" +checksum = "7c554eb5bf48b2426c4771ab68c6b14468b6e76cc90996f528c3338d761a4d0d" dependencies = [ "once_cell", ] [[package]] name = "futures-util" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abcb44342f62e6f3e8ac427b8aa815f724fd705dfad060b18ac7866c15bb8e34" +checksum = "d304cff4a7b99cfb7986f7d43fbe93d175e72e704a8860787cc95e9ffd85cbd2" dependencies = [ "futures-channel", "futures-core", @@ -1663,9 +1668,9 @@ dependencies = [ [[package]] name = "hyper" -version = "0.13.8" +version = "0.13.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f3afcfae8af5ad0576a31e768415edb627824129e8e5a29b8bfccb2f234e835" +checksum = "f6ad767baac13b44d4529fcf58ba2cd0995e36e7b435bc5b039de6f47e880dbf" dependencies = [ "bytes", "futures-channel", @@ -1677,7 +1682,7 @@ dependencies = [ "httparse", "httpdate", "itoa", - "pin-project 0.4.27", + "pin-project 1.0.1", "socket2", "tokio", "tower-service", @@ -1717,7 +1722,7 @@ dependencies = [ [[package]] name = "ic-agent" version = "0.1.0" -source = "git+https://github.com/dfinity/agent-rs.git?branch=next#191dca1c38cf7eebfb177f242063592223c87976" +source = "git+https://github.com/dfinity/agent-rs.git?branch=next#132d7995435aeaf8011ee02c0b4009c292c5c2cd" dependencies = [ "async-trait", "base32", @@ -1744,19 +1749,19 @@ dependencies = [ [[package]] name = "ic-types" version = "0.1.2" -source = "git+https://github.com/dfinity/agent-rs.git?branch=next#c973ab2dd4f0a5f081be8f2d8d336ce991f4d58b" +source = "git+https://github.com/dfinity/agent-rs.git?branch=next#132d7995435aeaf8011ee02c0b4009c292c5c2cd" dependencies = [ "base32", "crc32fast", "serde", - "sha2 0.9.1", + "sha2 0.9.2", "thiserror", ] [[package]] name = "ic-utils" version = "0.1.0" -source = "git+https://github.com/dfinity/agent-rs.git?branch=next#191dca1c38cf7eebfb177f242063592223c87976" +source = "git+https://github.com/dfinity/agent-rs.git?branch=next#132d7995435aeaf8011ee02c0b4009c292c5c2cd" dependencies = [ "async-trait", "candid", @@ -2148,9 +2153,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" +checksum = "6fcc7939b5edc4e4f86b1b4a04bb1498afaaf871b1a6691838ed06fcb48d3a3f" dependencies = [ "lazy_static", "libc", @@ -2211,9 +2216,9 @@ checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" [[package]] name = "num-bigint" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f3fc75e3697059fb1bc465e3d8cca6cf92f56854f201158b3f9c77d5a3cfa0" +checksum = "5e9a41747ae4633fce5adffb4d2e81ffc5e89593cb19917f8fb2cc5ff76507bf" dependencies = [ "autocfg 1.0.1", "num-integer", @@ -2285,9 +2290,9 @@ checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" [[package]] name = "once_cell" -version = "1.4.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad" +checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" [[package]] name = "opaque-debug" @@ -2336,9 +2341,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "2.3.2" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ac6fe3538f701e339953a3ebbe4f39941aababa8a3f6964635b24ab526daeac" +checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85" [[package]] name = "parking_lot" @@ -2368,9 +2373,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba7ae1a2180ed02ddfdb5ab70c70d596a26dd642e097bb6fe78b1bde8588ed97" +checksum = "7151b083b0664ed58ed669fcdd92f01c3d2fdbf10af4931a301474950b52bfa9" [[package]] name = "pem" @@ -2479,9 +2484,9 @@ checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" [[package]] name = "ppv-lite86" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "precomputed-hash" @@ -2817,9 +2822,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8963b85b8ce3074fecffde43b4b0dded83ce2f367dc8d363afc56679f3ee820b" +checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" dependencies = [ "aho-corasick", "memchr", @@ -2829,9 +2834,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.20" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cab7a364d15cde1e505267766a2d3c4e22a843e1a601f0fa7564c0f82ced11c" +checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" [[package]] name = "remove_dir_all" @@ -3008,9 +3013,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "0.4.4" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535" +checksum = "c1759c2e3c8580017a484a7ac56d3abc5a6c1feadf88db2f3633f12ae4268c69" dependencies = [ "bitflags", "core-foundation", @@ -3021,9 +3026,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "0.4.3" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405" +checksum = "f99b9d5e26d2a71633cc4f2ebae7cc9f874044e0c351a27e17892d76dce5678b" dependencies = [ "core-foundation-sys", "libc", @@ -3119,12 +3124,12 @@ dependencies = [ [[package]] name = "sha-1" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "170a36ea86c864a3f16dd2687712dd6646f7019f301e57537c7f4dc9f5916770" +checksum = "ce3cdf1b5e620a498ee6f2a171885ac7e22f0e12089ec4b3d22b84921792507c" dependencies = [ "block-buffer 0.9.0", - "cfg-if 0.1.10", + "cfg-if 1.0.0", "cpuid-bool", "digest 0.9.0", "opaque-debug 0.3.0", @@ -3150,12 +3155,12 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1" +checksum = "6e7aab86fe2149bad8c507606bdb3f4ef5e7b2380eb92350f56122cca72a42a8" dependencies = [ "block-buffer 0.9.0", - "cfg-if 0.1.10", + "cfg-if 1.0.0", "cpuid-bool", "digest 0.9.0", "opaque-debug 0.3.0", @@ -3169,11 +3174,10 @@ checksum = "b6fa3938c99da4914afedd13bf3d79bcb6c277d1b2c398d23257a304d9e1b074" [[package]] name = "signal-hook-registry" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e12110bc539e657a646068aaf5eb5b63af9d0c1f7b29c97113fad80e15f035" +checksum = "ce32ea0c6c56d5eacaeb814fbed9960547021d3edd010ded1425f180536b20ab" dependencies = [ - "arc-swap", "libc", ] @@ -3228,9 +3232,9 @@ checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252" [[package]] name = "socket2" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1fa70dc5c8104ec096f4fe7ede7a221d35ae13dcd19ba1ad9a81d2cab9a1c44" +checksum = "7fd8b795c389288baa5f355489c65e71fd48a02104600d15c4cfbc561e9e429d" dependencies = [ "cfg-if 0.1.10", "libc", @@ -3443,18 +3447,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "318234ffa22e0920fe9a40d7b8369b5f649d490980cf7aadcf1eb91594869b42" +checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cae2447b6282786c3493999f40a9be2a6ad20cb8bd268b0a0dbf5a065535c0ab" +checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56" dependencies = [ "proc-macro2", "quote", @@ -3528,12 +3532,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tinyvec" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" - [[package]] name = "tinyvec" version = "1.0.1" @@ -3551,9 +3549,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "0.2.22" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d34ca54d84bf2b5b4d7d31e901a8464f7b60ac145a284fba25ceb801f2ddccd" +checksum = "a6d7ad61edd59bfcc7e80dababf0f4aed2e6d5e0ba1659356ae889752dfc12ff" dependencies = [ "bytes", "fnv", @@ -3748,11 +3746,11 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977" +checksum = "b7f98e67a4d84f730d343392f9bfff7d21e3fca562b9cb7a43b768350beeddc6" dependencies = [ - "tinyvec 0.3.4", + "tinyvec", ] [[package]] @@ -3781,10 +3779,11 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" +checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e" dependencies = [ + "form_urlencoded", "idna", "matches", "percent-encoding",