diff --git a/dfx/src/commands/build.rs b/dfx/src/commands/build.rs index 7c1ec8d050..99371bde8b 100644 --- a/dfx/src/commands/build.rs +++ b/dfx/src/commands/build.rs @@ -153,8 +153,12 @@ where .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; - // get_path() returns the full path of the config file. We need to get the dirname. - let project_root = config.get_path().parent().unwrap(); + // get_path() returns the full path of the config file. We need to + // get the directory name. + let project_root = config + .get_path() + .parent() + .ok_or_else(|| DfxError::InvalidArgument("project root path".to_string()))?; let build_root = project_root.join( config @@ -172,7 +176,10 @@ where let input_as_path = project_root.join(path); let path = path.strip_prefix("src/").unwrap_or(&path); let output_path = build_root.join(path).with_extension("wasm"); - std::fs::create_dir_all(output_path.parent().unwrap())?; + let parent_output_path = output_path.parent().ok_or_else(|| { + DfxError::Unknown("unable to retrieve root path parent".to_string()) + })?; + std::fs::create_dir_all(parent_output_path)?; build_file( env, diff --git a/dfx/src/commands/canister/call.rs b/dfx/src/commands/canister/call.rs index 302c3e91b6..d531086d1e 100644 --- a/dfx/src/commands/canister/call.rs +++ b/dfx/src/commands/canister/call.rs @@ -52,10 +52,12 @@ where // Read the config. let canister_id = args .value_of("deployment_id") - .unwrap() + .ok_or_else(|| DfxError::InvalidArgument("deployment id".to_string()))? .parse::() .map_err(|e| DfxError::InvalidArgument(format!("Invalid deployment ID: {}", e)))?; - let method_name = args.value_of("method_name").unwrap(); + let method_name = args.value_of("method name").ok_or_else(|| { + DfxError::InvalidArgument("method name argument provided invalid".to_string()) + })?; let arguments: Option<&str> = args.value_of("argument"); let arg_type: Option<&str> = args.value_of("type"); diff --git a/dfx/src/commands/canister/install.rs b/dfx/src/commands/canister/install.rs index c6238726e2..10d9be6402 100644 --- a/dfx/src/commands/canister/install.rs +++ b/dfx/src/commands/canister/install.rs @@ -41,14 +41,18 @@ where .get_config() .ok_or(DfxError::CommandMustBeRunInAProject)?; - let project_root = config.get_path().parent().unwrap(); - + let project_root = config + .get_path() + .parent() + .ok_or_else(|| DfxError::InvalidConfiguration("project root".to_string()))?; let canister_id = args .value_of("deployment_id") - .unwrap() + .ok_or_else(|| DfxError::InvalidArgument("canister id".to_string()))? .parse::() .map_err(|e| DfxError::InvalidArgument(format!("Invalid deployment ID: {}", e)))?; - let wasm_path = args.value_of("wasm").unwrap(); + let wasm_path = args + .value_of("wasm") + .ok_or_else(|| DfxError::InvalidConfiguration("wasm path".to_string()))?; let wasm_path = PathBuf::from(project_root).join(wasm_path); let wasm = std::fs::read(wasm_path)?; diff --git a/dfx/src/commands/canister/query.rs b/dfx/src/commands/canister/query.rs index 027425dd89..79b7cd8fe9 100644 --- a/dfx/src/commands/canister/query.rs +++ b/dfx/src/commands/canister/query.rs @@ -46,10 +46,12 @@ where // Read the config. let canister_id = args .value_of("deployment_id") - .unwrap() + .ok_or_else(|| DfxError::InvalidArgument("deployment id".to_string()))? .parse::() .map_err(|e| DfxError::InvalidArgument(format!("Invalid deployment ID: {}", e)))?; - let method_name = args.value_of("method_name").unwrap(); + let method_name = args + .value_of("method_name") + .ok_or_else(|| DfxError::InvalidArgument("method name".to_string()))?; let arguments: Option<&str> = args.value_of("argument"); let arg_type: Option<&str> = args.value_of("type"); diff --git a/dfx/src/commands/canister/request_status.rs b/dfx/src/commands/canister/request_status.rs index 7bdfe352db..3389890879 100644 --- a/dfx/src/commands/canister/request_status.rs +++ b/dfx/src/commands/canister/request_status.rs @@ -25,8 +25,12 @@ pub fn exec(env: &T, args: &ArgMatches<'_>) -> DfxResult where T: ClientEnv, { - let request_id = RequestId::from_str(&args.value_of("request_id").unwrap()[2..]) - .map_err(|e| DfxError::InvalidArgument(format!("Invalid request ID: {:?}", e)))?; // FIXME Default formatter for RequestIdFromStringError + let request_id = RequestId::from_str( + &args + .value_of("request_id") + .ok_or_else(|| DfxError::InvalidArgument("request id".to_string()))?[2..], + ) + .map_err(|e| DfxError::InvalidArgument(format!("Invalid request ID: {:?}", e)))?; // FIXME Default formatter for RequestIdFromStringError let request_status = request_status(env.get_client(), request_id); let mut runtime = Runtime::new().expect("Unable to create a runtime"); match runtime.block_on(request_status) { diff --git a/dfx/src/commands/config.rs b/dfx/src/commands/config.rs index 9be920ee76..6106279f7f 100644 --- a/dfx/src/commands/config.rs +++ b/dfx/src/commands/config.rs @@ -22,7 +22,9 @@ pub fn exec(env: &T, args: &ArgMatches<'_>) -> DfxResult { .ok_or(DfxError::CommandMustBeRunInAProject)? .clone(); - let config_path = args.value_of("config_path").unwrap(); + let config_path = args + .value_of("config_path") + .ok_or_else(|| DfxError::InvalidArgument("config path".to_string()))?; // 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 diff --git a/dfx/src/commands/new.rs b/dfx/src/commands/new.rs index 34e974878b..ffcf2c01d8 100644 --- a/dfx/src/commands/new.rs +++ b/dfx/src/commands/new.rs @@ -86,7 +86,10 @@ where T: BinaryCacheEnv + PlatformEnv + VersionEnv, { let dry_run = args.is_present(DRY_RUN); - let project_name = Path::new(args.value_of(PROJECT_NAME).unwrap()); + 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); if project_name.exists() { return Err(DfxError::ProjectExists); @@ -100,6 +103,10 @@ where } let mut new_project_files = assets::new_project_files()?; + let project_name_str = project_name + .to_str() + .ok_or_else(|| DfxError::InvalidArgument("project name".to_string()))?; + for file in new_project_files.entries()? { let mut file = file?; @@ -108,10 +115,11 @@ where } let mut s = String::new(); - file.read_to_string(&mut s).unwrap(); + file.read_to_string(&mut s) + .or_else(|e| Err(DfxError::IO(e)))?; // Perform replacements. - let s = s.replace("{project_name}", project_name.to_str().unwrap()); + let s = s.replace("{project_name}", project_name_str); let s = s.replace("{dfx_version}", dfx_version); // Perform path replacements. @@ -119,7 +127,9 @@ where project_name .join(file.header().path()?) .to_str() - .unwrap() + .ok_or_else(|| { + DfxError::InvalidArgument("project name path or file header".to_string()) + })? .replace("__dot__", ".") .as_str(), ); @@ -133,7 +143,15 @@ where .arg("init") .current_dir(&project_name) .status(); - if init_status.is_ok() && init_status.unwrap().success() { + let is_success = init_status + .or_else(|e| { + Err(DfxError::IO(std::io::Error::new( + e.kind(), + format!("Unable to execute git {}", e), + ))) + })? + .success(); + if is_success { eprintln!("Creating git repository..."); std::process::Command::new("git") .arg("add") @@ -156,7 +174,7 @@ where include_str!("../../assets/welcome.txt"), dfx_version, assets::color_logo(), - project_name.to_str().unwrap() + project_name_str ); Ok(()) diff --git a/dfx/src/config/dfinity.rs b/dfx/src/config/dfinity.rs index 01ca2d0cf8..38f12311e7 100644 --- a/dfx/src/config/dfinity.rs +++ b/dfx/src/config/dfinity.rs @@ -214,10 +214,13 @@ impl Config { } pub fn save(&self) -> DfxResult { - std::fs::write( - &self.path, - serde_json::to_string_pretty(&self.json).unwrap(), - )?; + let json_pretty = serde_json::to_string_pretty(&self.json).or_else(|e| { + Err(DfxError::InvalidData(format!( + "Failed to serialize -- {}", + e + ))) + })?; + std::fs::write(&self.path, json_pretty)?; Ok(()) } } diff --git a/dfx/src/lib/error.rs b/dfx/src/lib/error.rs index bf541627b2..21f15712c2 100644 --- a/dfx/src/lib/error.rs +++ b/dfx/src/lib/error.rs @@ -57,7 +57,7 @@ pub enum DfxError { /// An error happened during build. BuildError(BuildErrorKind), Clap(clap::Error), - Io(std::io::Error), + IO(std::io::Error), Reqwest(reqwest::Error), Url(reqwest::UrlError), @@ -82,6 +82,7 @@ pub enum DfxError { // Configuration path does not exist in the config file. ConfigPathDoesNotExist(String), InvalidArgument(String), + InvalidConfiguration(String), InvalidData(String), } @@ -102,6 +103,6 @@ impl From for DfxError { impl From for DfxError { fn from(err: std::io::Error) -> DfxError { - DfxError::Io(err) + DfxError::IO(err) } } diff --git a/lib/serde_idl/src/de.rs b/lib/serde_idl/src/de.rs index 3624cd316c..64bb1eff17 100644 --- a/lib/serde_idl/src/de.rs +++ b/lib/serde_idl/src/de.rs @@ -482,11 +482,14 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { let value = visitor.visit_enum(Compound::new(&mut self, Style::Enum { len, fs }))?; Ok(value) } - + /// Deserialize identifier. + /// # Panics + /// *Will Panic* when identifier name is None. fn deserialize_identifier(self, visitor: V) -> Result where V: Visitor<'de>, { + // N.B. Here we want to panic as it indicates a logical error. let label = self.field_name.as_ref().unwrap(); let v = match label { FieldLabel::Named(name) => visitor.visit_str(name),