diff --git a/rust/Cargo.Bazel.lock b/rust/Cargo.Bazel.lock index 58046d9a2e4db..35fe4dff4e6a7 100644 --- a/rust/Cargo.Bazel.lock +++ b/rust/Cargo.Bazel.lock @@ -1,5 +1,5 @@ { - "checksum": "495be0038fd3bd2826baeb0433f22c042c1b03eeeb117631135bc6339799addf", + "checksum": "4745128072794bf6ed7da8d621ea818d5d0e11d98386c45fd55852bd6ca41af8", "crates": { "addr2line 0.19.0": { "name": "addr2line", @@ -478,6 +478,71 @@ }, "license": "MIT OR Apache-2.0" }, + "anyhow 1.0.75": { + "name": "anyhow", + "version": "1.0.75", + "repository": { + "Http": { + "url": "https://crates.io/api/v1/crates/anyhow/1.0.75/download", + "sha256": "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" + } + }, + "targets": [ + { + "Library": { + "crate_name": "anyhow", + "crate_root": "src/lib.rs", + "srcs": [ + "**/*.rs" + ] + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": [ + "**/*.rs" + ] + } + } + ], + "library_target_name": "anyhow", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "backtrace", + "default", + "std" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "anyhow 1.0.75", + "target": "build_script_build" + }, + { + "id": "backtrace 0.3.67", + "target": "backtrace" + } + ], + "selects": {} + }, + "edition": "2018", + "version": "1.0.75" + }, + "build_script_attrs": { + "data_glob": [ + "**" + ] + }, + "license": "MIT OR Apache-2.0" + }, "assert_cmd 2.0.12": { "name": "assert_cmd", "version": "2.0.12", @@ -605,6 +670,13 @@ "compile_data_glob": [ "**" ], + "crate_features": { + "common": [ + "default", + "std" + ], + "selects": {} + }, "deps": { "common": [ { @@ -3718,6 +3790,13 @@ "compile_data_glob": [ "**" ], + "crate_features": { + "common": [ + "read", + "read-core" + ], + "selects": {} + }, "edition": "2018", "version": "0.27.3" }, @@ -5704,6 +5783,18 @@ "compile_data_glob": [ "**" ], + "crate_features": { + "common": [ + "archive", + "coff", + "elf", + "macho", + "pe", + "read_core", + "unaligned" + ], + "selects": {} + }, "deps": { "common": [ { @@ -7742,6 +7833,10 @@ ], "deps": { "common": [ + { + "id": "anyhow 1.0.75", + "target": "anyhow" + }, { "id": "bzip2 0.4.4", "target": "bzip2" diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 27bbb73d5360b..6a74c34b83c6c 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -98,6 +98,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "anyhow" +version = "1.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +dependencies = [ + "backtrace", +] + [[package]] name = "assert_cmd" version = "2.0.12" @@ -1442,6 +1451,7 @@ dependencies = [ name = "selenium-manager" version = "0.4.14" dependencies = [ + "anyhow", "assert_cmd", "bzip2", "clap", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index b6dcf3d853af7..5814bdf97763d 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -32,6 +32,7 @@ toml = "0.7.6" bzip2 = "0.4.4" sevenz-rust = "0.5.2" walkdir = "2.4.0" +anyhow = { version = "1.0.75", features = ["backtrace"] } [dev-dependencies] assert_cmd = "2.0.12" diff --git a/rust/src/chrome.rs b/rust/src/chrome.rs index 6a1fe5822ac9f..cc0daf8313589 100644 --- a/rust/src/chrome.rs +++ b/rust/src/chrome.rs @@ -19,7 +19,9 @@ use crate::config::ManagerConfig; use reqwest::Client; use serde::{Deserialize, Serialize}; use std::collections::HashMap; -use std::error::Error; + +use anyhow::anyhow; +use anyhow::Error; use std::option::Option; use std::path::PathBuf; @@ -62,7 +64,7 @@ pub struct ChromeManager { } impl ChromeManager { - pub fn new() -> Result, Box> { + pub fn new() -> Result, Error> { let browser_name = CHROME_NAME; let driver_name = CHROMEDRIVER_NAME; let config = ManagerConfig::default(browser_name, driver_name); @@ -96,10 +98,7 @@ impl ChromeManager { format!("{}{}", CFT_URL, endpoint) } - fn request_driver_version_from_latest( - &self, - driver_url: String, - ) -> Result> { + fn request_driver_version_from_latest(&self, driver_url: String) -> Result { self.log.debug(format!( "Reading {} version from {}", &self.driver_name, driver_url @@ -107,7 +106,7 @@ impl ChromeManager { read_version_from_link(self.get_http_client(), driver_url, self.get_logger()) } - fn request_versions_from_online(&self, driver_url: String) -> Result> + fn request_versions_from_online(&self, driver_url: String) -> Result where T: Serialize + for<'a> Deserialize<'a>, { @@ -116,7 +115,7 @@ impl ChromeManager { parse_json_from_url::(self.get_http_client(), driver_url) } - fn request_latest_driver_version_from_online(&mut self) -> Result> { + fn request_latest_driver_version_from_online(&mut self) -> Result { let driver_name = self.driver_name; self.get_logger().trace(format!( "Using Chrome for Testing (CfT) endpoints to find out latest stable {} version", @@ -152,7 +151,7 @@ impl ChromeManager { Ok(stable_channel.version) } - fn request_good_driver_version_from_online(&mut self) -> Result> { + fn request_good_driver_version_from_online(&mut self) -> Result { let browser_or_driver_version = if self.get_driver_version().is_empty() { self.get_browser_version() } else { @@ -172,13 +171,12 @@ impl ChromeManager { .filter(|r| r.version.starts_with(version_for_filtering.as_str())) .collect(); if filtered_versions.is_empty() { - return Err(format_three_args( + return Err(anyhow!(format_three_args( UNAVAILABLE_CFT_ERROR_MESSAGE, self.get_driver_name(), &version_for_filtering, &MIN_CHROMEDRIVER_VERSION_CFT.to_string(), - ) - .into()); + ))); } let driver_version = filtered_versions.last().unwrap(); @@ -196,7 +194,7 @@ impl ChromeManager { Ok(driver_version.version.to_string()) } - fn get_browser_binary_path_in_cache(&self) -> Result> { + fn get_browser_binary_path_in_cache(&self) -> Result { let browser_in_cache = self.get_browser_path_in_cache()?; if MACOS.is(self.get_os()) { Ok(browser_in_cache.join(CFT_MACOS_APP_NAME)) @@ -262,7 +260,7 @@ impl SeleniumManager for ChromeManager { ]) } - fn discover_browser_version(&mut self) -> Result, Box> { + fn discover_browser_version(&mut self) -> Result, Error> { self.general_discover_browser_version( r#"HKCU\Software\Google\Chrome\BLBeacon"#, REG_VERSION_ARG, @@ -274,7 +272,7 @@ impl SeleniumManager for ChromeManager { self.driver_name } - fn request_driver_version(&mut self) -> Result> { + fn request_driver_version(&mut self) -> Result { let major_browser_version_binding = self.get_major_browser_version(); let major_browser_version = major_browser_version_binding.as_str(); let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()?); @@ -333,11 +331,11 @@ impl SeleniumManager for ChromeManager { } } - fn request_browser_version(&mut self) -> Result, Box> { + fn request_browser_version(&mut self) -> Result, Error> { self.general_request_browser_version(self.browser_name) } - fn get_driver_url(&mut self) -> Result> { + fn get_driver_url(&mut self) -> Result { let major_driver_version = self .get_major_driver_version() .parse::() @@ -379,7 +377,7 @@ impl SeleniumManager for ChromeManager { )) } - fn get_driver_path_in_cache(&self) -> Result> { + fn get_driver_path_in_cache(&self) -> Result { Ok(compose_driver_path_in_cache( self.get_cache_path()?, self.driver_name, @@ -409,7 +407,7 @@ impl SeleniumManager for ChromeManager { self.log = log; } - fn download_browser(&mut self) -> Result, Box> { + fn download_browser(&mut self) -> Result, Error> { let browser_version; let browser_name = self.browser_name; let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()?); @@ -422,13 +420,12 @@ impl SeleniumManager for ChromeManager { && !self.is_browser_version_empty() && major_browser_version_int < MIN_CHROME_VERSION_CFT { - return Err(format_three_args( + return Err(anyhow!(format_three_args( UNAVAILABLE_CFT_ERROR_MESSAGE, browser_name, &major_browser_version, &MIN_CHROME_VERSION_CFT.to_string(), - ) - .into()); + ))); } // Browser version is checked in the local metadata @@ -540,7 +537,7 @@ impl SeleniumManager for ChromeManager { } } - fn request_latest_browser_version_from_online(&mut self) -> Result> { + fn request_latest_browser_version_from_online(&mut self) -> Result { let browser_name = self.browser_name; self.get_logger().trace(format!( "Using Chrome for Testing (CfT) endpoints to find out latest stable {} version", @@ -568,7 +565,7 @@ impl SeleniumManager for ChromeManager { Ok(browser_version) } - fn request_fixed_browser_version_from_online(&mut self) -> Result> { + fn request_fixed_browser_version_from_online(&mut self) -> Result { let browser_name = self.browser_name; let mut browser_version = self.get_browser_version().to_string(); let major_browser_version = self.get_major_browser_version(); @@ -608,13 +605,12 @@ impl SeleniumManager for ChromeManager { .filter(|r| r.version.starts_with(major_browser_version.as_str())) .collect(); if filtered_versions.is_empty() { - return Err(format_three_args( + return Err(anyhow!(format_three_args( UNAVAILABLE_CFT_ERROR_MESSAGE, browser_name, &major_browser_version, &MIN_CHROME_VERSION_CFT.to_string(), - ) - .into()); + ))); } let last_browser = filtered_versions.last().unwrap(); let platform_url: Vec<&PlatformUrl> = last_browser diff --git a/rust/src/config.rs b/rust/src/config.rs index b4d8918f2ab88..3634387355b6c 100644 --- a/rust/src/config.rs +++ b/rust/src/config.rs @@ -25,7 +25,9 @@ use crate::{ARCH_AMD64, ARCH_ARM64, ARCH_X86, TTL_SEC, WMIC_COMMAND_OS}; use std::cell::RefCell; use std::env; use std::env::consts::OS; -use std::error::Error; + +use anyhow::anyhow; +use anyhow::Error; use std::fs::read_to_string; use std::path::Path; use toml::Table; @@ -129,7 +131,7 @@ impl OS { } } -pub fn str_to_os(os: &str) -> Result> { +pub fn str_to_os(os: &str) -> Result { if WINDOWS.is(os) { Ok(WINDOWS) } else if MACOS.is(os) { @@ -137,7 +139,7 @@ pub fn str_to_os(os: &str) -> Result> { } else if LINUX.is(os) { Ok(LINUX) } else { - Err(format!("Invalid operating system: {os}").into()) + Err(anyhow!(format!("Invalid operating system: {os}"))) } } @@ -232,7 +234,7 @@ fn get_env_name(suffix: &str) -> String { concat(ENV_PREFIX, suffix_uppercase.as_str()) } -fn get_config() -> Result> { +fn get_config() -> Result { let cache_path = read_cache_path(); let config_path = Path::new(&cache_path).to_path_buf().join(CONFIG_FILE); Ok(read_to_string(config_path)?.parse()?) diff --git a/rust/src/downloads.rs b/rust/src/downloads.rs index a5d5ea8f83978..d72f4be4b77c0 100644 --- a/rust/src/downloads.rs +++ b/rust/src/downloads.rs @@ -15,10 +15,12 @@ // specific language governing permissions and limitations // under the License. +use anyhow::Error; use reqwest::{Client, StatusCode}; use serde::{Deserialize, Serialize}; use serde_json::Value; -use std::error::Error; + +use anyhow::anyhow; use std::fs::File; use std::io::copy; use std::io::Cursor; @@ -33,7 +35,7 @@ pub async fn download_to_tmp_folder( http_client: &Client, url: String, log: &Logger, -) -> Result<(TempDir, String), Box> { +) -> Result<(TempDir, String), Error> { let tmp_dir = Builder::new().prefix("selenium-manager").tempdir()?; log.trace(format!( "Downloading {} to temporal folder {:?}", @@ -44,7 +46,10 @@ pub async fn download_to_tmp_folder( let response = http_client.get(&url).send().await?; let status_code = response.status(); if status_code != StatusCode::OK { - return Err(format!("Unsuccessful response ({}) for URL {}", status_code, url).into()); + return Err(anyhow!(format!( + "Unsuccessful response ({}) for URL {}", + status_code, url + ))); } let target_path; @@ -76,15 +81,12 @@ pub fn read_version_from_link( http_client: &Client, url: String, log: &Logger, -) -> Result> { +) -> Result { parse_version(read_content_from_link(http_client, url)?, log) } #[tokio::main] -pub async fn read_content_from_link( - http_client: &Client, - url: String, -) -> Result> { +pub async fn read_content_from_link(http_client: &Client, url: String) -> Result { Ok(http_client.get(url).send().await?.text().await?) } @@ -93,14 +95,14 @@ pub async fn read_redirect_from_link( http_client: &Client, url: String, log: &Logger, -) -> Result> { +) -> Result { parse_version( http_client.get(&url).send().await?.url().path().to_string(), log, ) } -pub fn parse_json_from_url(http_client: &Client, url: String) -> Result> +pub fn parse_json_from_url(http_client: &Client, url: String) -> Result where T: Serialize + for<'a> Deserialize<'a>, { @@ -109,10 +111,7 @@ where Ok(response) } -pub fn parse_generic_json_from_url( - http_client: &Client, - url: String, -) -> Result> { +pub fn parse_generic_json_from_url(http_client: &Client, url: String) -> Result { let content = read_content_from_link(http_client, url)?; let response: Value = serde_json::from_str(&content)?; Ok(response) diff --git a/rust/src/edge.rs b/rust/src/edge.rs index dbfe49ace8b90..2d0c02f6197b5 100644 --- a/rust/src/edge.rs +++ b/rust/src/edge.rs @@ -16,9 +16,10 @@ // under the License. use crate::config::ManagerConfig; +use anyhow::Error; use reqwest::Client; use std::collections::HashMap; -use std::error::Error; + use std::path::PathBuf; use crate::config::ARCH::{ARM64, X32}; @@ -48,7 +49,7 @@ pub struct EdgeManager { } impl EdgeManager { - pub fn new() -> Result, Box> { + pub fn new() -> Result, Error> { let browser_name = EDGE_NAMES[0]; let driver_name = EDGEDRIVER_NAME; let config = ManagerConfig::default(browser_name, driver_name); @@ -120,7 +121,7 @@ impl SeleniumManager for EdgeManager { ]) } - fn discover_browser_version(&mut self) -> Result, Box> { + fn discover_browser_version(&mut self) -> Result, Error> { self.general_discover_browser_version( r#"HKCU\Software\Microsoft\Edge\BLBeacon"#, REG_VERSION_ARG, @@ -132,7 +133,7 @@ impl SeleniumManager for EdgeManager { self.driver_name } - fn request_driver_version(&mut self) -> Result> { + fn request_driver_version(&mut self) -> Result { let mut major_browser_version = self.get_major_browser_version(); let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()?); @@ -202,11 +203,11 @@ impl SeleniumManager for EdgeManager { } } - fn request_browser_version(&mut self) -> Result, Box> { + fn request_browser_version(&mut self) -> Result, Error> { Ok(None) } - fn get_driver_url(&mut self) -> Result> { + fn get_driver_url(&mut self) -> Result { let driver_version = self.get_driver_version(); let os = self.get_os(); let arch = self.get_arch(); @@ -233,7 +234,7 @@ impl SeleniumManager for EdgeManager { )) } - fn get_driver_path_in_cache(&self) -> Result> { + fn get_driver_path_in_cache(&self) -> Result { Ok(compose_driver_path_in_cache( self.get_cache_path()?, self.driver_name, @@ -263,7 +264,7 @@ impl SeleniumManager for EdgeManager { self.log = log; } - fn download_browser(&mut self) -> Result, Box> { + fn download_browser(&mut self) -> Result, Error> { Ok(None) } @@ -289,11 +290,11 @@ impl SeleniumManager for EdgeManager { } } - fn request_latest_browser_version_from_online(&mut self) -> Result> { + fn request_latest_browser_version_from_online(&mut self) -> Result { self.unavailable_download() } - fn request_fixed_browser_version_from_online(&mut self) -> Result> { + fn request_fixed_browser_version_from_online(&mut self) -> Result { self.unavailable_download() } } diff --git a/rust/src/files.rs b/rust/src/files.rs index b71240647a617..3d88326c7328b 100644 --- a/rust/src/files.rs +++ b/rust/src/files.rs @@ -15,12 +15,13 @@ // specific language governing permissions and limitations // under the License. -use std::error::Error; +use anyhow::Error; use std::fs; use std::fs::File; use std::io; use std::io::{BufReader, Cursor, Read}; +use anyhow::anyhow; use bzip2::read::BzDecoder; use std::path::{Path, PathBuf}; @@ -67,14 +68,14 @@ impl BrowserPath { } } -pub fn create_parent_path_if_not_exists(path: &Path) -> Result<(), Box> { +pub fn create_parent_path_if_not_exists(path: &Path) -> Result<(), Error> { if let Some(p) = path.parent() { create_path_if_not_exists(p)?; } Ok(()) } -pub fn create_path_if_not_exists(path: &Path) -> Result<(), Box> { +pub fn create_path_if_not_exists(path: &Path) -> Result<(), Error> { if !path.exists() { fs::create_dir_all(path)?; } @@ -89,7 +90,7 @@ pub fn uncompress( single_file: Option, volume: Option<&str>, major_browser_version: Option, -) -> Result<(), Box> { +) -> Result<(), Error> { let mut extension = match infer::get_from_path(compressed_file)? { Some(kind) => kind.extension(), _ => { @@ -97,12 +98,13 @@ pub fn uncompress( if MACOS.is(os) { PKG } else { - return Err(format_one_arg(UNCOMPRESS_MACOS_ERR_MSG, PKG).into()); + return Err(anyhow!(format_one_arg(UNCOMPRESS_MACOS_ERR_MSG, PKG))); } } else { - return Err( - format!("Format for file {} cannot be inferred", compressed_file).into(), - ); + return Err(anyhow!(format!( + "Format for file {} cannot be inferred", + compressed_file + ))); } } }; @@ -110,7 +112,7 @@ pub fn uncompress( if MACOS.is(os) { extension = DMG; } else { - return Err(format_one_arg(UNCOMPRESS_MACOS_ERR_MSG, DMG).into()); + return Err(anyhow!(format_one_arg(UNCOMPRESS_MACOS_ERR_MSG, DMG))); } } log.trace(format!( @@ -141,22 +143,17 @@ pub fn uncompress( "Wrong downloaded driver: {}", fs::read_to_string(compressed_file).unwrap_or_default() )); - return Err(PARSE_ERROR.into()); + return Err(anyhow!(PARSE_ERROR)); } else { - return Err(format!( + return Err(anyhow!(format!( "Downloaded file cannot be uncompressed ({} extension)", extension - ) - .into()); + ))); } Ok(()) } -pub fn uncompress_sfx( - compressed_file: &str, - target: &Path, - log: &Logger, -) -> Result<(), Box> { +pub fn uncompress_sfx(compressed_file: &str, target: &Path, log: &Logger) -> Result<(), Error> { let zip_parent = Path::new(compressed_file).parent().unwrap(); log.trace(format!( "Decompressing {} to {}", @@ -166,7 +163,7 @@ pub fn uncompress_sfx( let file_bytes = read_bytes_from_file(compressed_file)?; let header = find_bytes(&file_bytes, SEVEN_ZIP_HEADER); - let index_7z = header.ok_or("Incorrect SFX (self extracting exe) file")?; + let index_7z = header.ok_or(anyhow!("Incorrect SFX (self extracting exe) file"))?; let file_reader = Cursor::new(&file_bytes[index_7z..]); sevenz_rust::decompress(file_reader, zip_parent).unwrap(); @@ -189,7 +186,7 @@ pub fn uncompress_pkg( log: &Logger, os: &str, major_browser_version: i32, -) -> Result<(), Box> { +) -> Result<(), Error> { let tmp_dir = Builder::new().prefix(PKG).tempdir()?; let out_folder = format!( "{}/{}", @@ -232,7 +229,7 @@ pub fn uncompress_dmg( log: &Logger, os: &str, volume: &str, -) -> Result<(), Box> { +) -> Result<(), Error> { let dmg_file_name = Path::new(compressed_file) .file_name() .unwrap_or_default() @@ -263,7 +260,7 @@ pub fn uncompress_dmg( Ok(()) } -pub fn untargz(compressed_file: &str, target: &Path, log: &Logger) -> Result<(), Box> { +pub fn untargz(compressed_file: &str, target: &Path, log: &Logger) -> Result<(), Error> { log.trace(format!( "Untargz {} to {}", compressed_file, @@ -274,18 +271,14 @@ pub fn untargz(compressed_file: &str, target: &Path, log: &Logger) -> Result<(), let mut archive = Archive::new(tar); let parent_path = target .parent() - .ok_or(format!("Error getting parent of {:?}", file))?; + .ok_or(anyhow!(format!("Error getting parent of {:?}", file)))?; if !target.exists() { archive.unpack(parent_path)?; } Ok(()) } -pub fn uncompress_bz2( - compressed_file: &str, - target: &Path, - log: &Logger, -) -> Result<(), Box> { +pub fn uncompress_bz2(compressed_file: &str, target: &Path, log: &Logger) -> Result<(), Error> { log.trace(format!( "Uncompress {} to {}", compressed_file, @@ -312,7 +305,7 @@ pub fn unzip( target: &Path, log: &Logger, single_file: Option, -) -> Result<(), Box> { +) -> Result<(), Error> { let file = File::open(compressed_file)?; let compressed_path = Path::new(compressed_file); let tmp_path = compressed_path @@ -378,11 +371,10 @@ pub fn unzip( } } if unzipped_files == 0 { - return Err(format!( + return Err(anyhow!(format!( "Problem uncompressing zip ({} files extracted)", unzipped_files - ) - .into()); + ))); } fs::remove_file(compressed_path)?; @@ -477,10 +469,10 @@ pub fn get_binary_extension(os: &str) -> &str { } } -pub fn parse_version(version_text: String, log: &Logger) -> Result> { +pub fn parse_version(version_text: String, log: &Logger) -> Result { if version_text.to_ascii_lowercase().contains("error") { log.debug(format!("Error parsing version: {}", version_text)); - return Err(PARSE_ERROR.into()); + return Err(anyhow!(PARSE_ERROR)); } let mut parsed_version = "".to_string(); let re_numbers_dots = Regex::new(r"[^\d^.]")?; @@ -501,7 +493,7 @@ pub fn path_buf_to_string(path_buf: PathBuf) -> String { path_buf.into_os_string().into_string().unwrap_or_default() } -pub fn read_bytes_from_file(file_path: &str) -> Result, Box> { +pub fn read_bytes_from_file(file_path: &str) -> Result, Error> { let file = File::open(file_path)?; let mut reader = BufReader::new(file); let mut buffer = Vec::new(); diff --git a/rust/src/firefox.rs b/rust/src/firefox.rs index a4e850ab11dd1..53787a991859e 100644 --- a/rust/src/firefox.rs +++ b/rust/src/firefox.rs @@ -17,9 +17,11 @@ // under the License. use crate::config::ManagerConfig; +use anyhow::Error; use reqwest::Client; use std::collections::HashMap; -use std::error::Error; + +use anyhow::anyhow; use std::path::PathBuf; use crate::config::ARCH::{ARM64, X32}; @@ -74,7 +76,7 @@ pub struct FirefoxManager { } impl FirefoxManager { - pub fn new() -> Result, Box> { + pub fn new() -> Result, Error> { let browser_name = FIREFOX_NAME; let driver_name = GECKODRIVER_NAME; let config = ManagerConfig::default(browser_name, driver_name); @@ -93,10 +95,7 @@ impl FirefoxManager { format!("{}{}", FIREFOX_DETAILS_URL, endpoint) } - fn request_versions_from_online( - &mut self, - endpoint: &str, - ) -> Result, Box> { + fn request_versions_from_online(&mut self, endpoint: &str) -> Result, Error> { let browser_version = self.get_browser_version().to_string(); let firefox_versions_url = self.create_firefox_details_url(endpoint); let firefox_versions = @@ -115,10 +114,7 @@ impl FirefoxManager { .collect()) } - fn get_browser_url( - &mut self, - is_browser_version_nightly: bool, - ) -> Result> { + fn get_browser_url(&mut self, is_browser_version_nightly: bool) -> Result { let arch = self.get_arch(); let os = self.get_os(); let platform_label; @@ -189,7 +185,7 @@ impl FirefoxManager { } } - fn get_browser_binary_path_in_cache(&self) -> Result> { + fn get_browser_binary_path_in_cache(&self) -> Result { let browser_in_cache = self.get_browser_path_in_cache()?; if MACOS.is(self.get_os()) { let macos_app_name = if self.is_browser_version_nightly() { @@ -259,7 +255,7 @@ impl SeleniumManager for FirefoxManager { ]) } - fn discover_browser_version(&mut self) -> Result, Box> { + fn discover_browser_version(&mut self) -> Result, Error> { self.general_discover_browser_version( r#"HKCU\Software\Mozilla\Mozilla Firefox"#, REG_CURRENT_VERSION_ARG, @@ -271,7 +267,7 @@ impl SeleniumManager for FirefoxManager { self.driver_name } - fn request_driver_version(&mut self) -> Result> { + fn request_driver_version(&mut self) -> Result { let major_browser_version_binding = self.get_major_browser_version(); let major_browser_version = major_browser_version_binding.as_str(); let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()?); @@ -311,11 +307,11 @@ impl SeleniumManager for FirefoxManager { } } - fn request_browser_version(&mut self) -> Result, Box> { + fn request_browser_version(&mut self) -> Result, Error> { self.general_request_browser_version(self.browser_name) } - fn get_driver_url(&mut self) -> Result> { + fn get_driver_url(&mut self) -> Result { let driver_version = self.get_driver_version(); let os = self.get_os(); let arch = self.get_arch(); @@ -353,7 +349,7 @@ impl SeleniumManager for FirefoxManager { )) } - fn get_driver_path_in_cache(&self) -> Result> { + fn get_driver_path_in_cache(&self) -> Result { Ok(compose_driver_path_in_cache( self.get_cache_path()?, self.driver_name, @@ -383,7 +379,7 @@ impl SeleniumManager for FirefoxManager { self.log = log; } - fn download_browser(&mut self) -> Result, Box> { + fn download_browser(&mut self) -> Result, Error> { let browser_version; let browser_name = self.browser_name; let original_browser_version = self.get_config().browser_version.clone(); @@ -513,7 +509,7 @@ impl SeleniumManager for FirefoxManager { } } - fn request_latest_browser_version_from_online(&mut self) -> Result> { + fn request_latest_browser_version_from_online(&mut self) -> Result { let browser_name = self.browser_name; self.get_logger().trace(format!( "Using Firefox endpoints to find out latest stable {} version", @@ -532,7 +528,7 @@ impl SeleniumManager for FirefoxManager { Ok(browser_version.to_string()) } - fn request_fixed_browser_version_from_online(&mut self) -> Result> { + fn request_fixed_browser_version_from_online(&mut self) -> Result { let browser_name = self.browser_name; let browser_version = self.get_browser_version().to_string(); self.get_logger().trace(format!( @@ -572,13 +568,12 @@ impl SeleniumManager for FirefoxManager { MIN_DOWNLOADABLE_FIREFOX_VERSION_LINUX }; if major_browser_version < min_downloadable_version { - return Err(format_three_args( + return Err(anyhow!(format_three_args( UNAVAILABLE_DOWNLOAD_ERROR_MESSAGE, browser_name, &browser_version, &min_downloadable_version.to_string(), - ) - .into()); + ))); } let mut firefox_versions = @@ -587,12 +582,11 @@ impl SeleniumManager for FirefoxManager { firefox_versions = self.request_versions_from_online(FIREFOX_HISTORY_DEV_ENDPOINT)?; if firefox_versions.is_empty() { - return Err(format_two_args( + return Err(anyhow!(format_two_args( ONLINE_DISCOVERY_ERROR_MESSAGE, browser_name, self.get_browser_version(), - ) - .into()); + ))); } } @@ -605,12 +599,11 @@ impl SeleniumManager for FirefoxManager { return Ok(version.to_string()); } } - Err(format_two_args( + Err(anyhow!(format_two_args( ONLINE_DISCOVERY_ERROR_MESSAGE, browser_name, self.get_browser_version(), - ) - .into()) + ))) } } } diff --git a/rust/src/grid.rs b/rust/src/grid.rs index 65e942260bb63..038e5480920b6 100644 --- a/rust/src/grid.rs +++ b/rust/src/grid.rs @@ -16,9 +16,11 @@ // under the License. use crate::config::ManagerConfig; +use anyhow::Error; use reqwest::Client; use std::collections::HashMap; -use std::error::Error; + +use anyhow::anyhow; use std::path::PathBuf; use crate::files::BrowserPath; @@ -51,7 +53,7 @@ pub struct GridManager { } impl GridManager { - pub fn new(driver_version: String) -> Result, Box> { + pub fn new(driver_version: String) -> Result, Error> { let browser_name = GRID_NAME; let driver_name = GRID_RELEASE; let mut config = ManagerConfig::default(browser_name, driver_name); @@ -86,7 +88,7 @@ impl SeleniumManager for GridManager { HashMap::new() } - fn discover_browser_version(&mut self) -> Result, Box> { + fn discover_browser_version(&mut self) -> Result, Error> { Ok(None) } @@ -94,7 +96,7 @@ impl SeleniumManager for GridManager { self.driver_name } - fn request_driver_version(&mut self) -> Result> { + fn request_driver_version(&mut self) -> Result { let major_browser_version_binding = self.get_major_browser_version(); let major_browser_version = major_browser_version_binding.as_str(); let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()?); @@ -161,17 +163,20 @@ impl SeleniumManager for GridManager { Ok(driver_version) } else { - Err(format!("{} release not available", self.get_driver_name()).into()) + Err(anyhow!(format!( + "{} release not available", + self.get_driver_name() + ))) } } } } - fn request_browser_version(&mut self) -> Result, Box> { + fn request_browser_version(&mut self) -> Result, Error> { Ok(None) } - fn get_driver_url(&mut self) -> Result> { + fn get_driver_url(&mut self) -> Result { if self.driver_url.is_some() { return Ok(self.driver_url.as_ref().unwrap().to_string()); } @@ -187,7 +192,7 @@ impl SeleniumManager for GridManager { )) } - fn get_driver_path_in_cache(&self) -> Result> { + fn get_driver_path_in_cache(&self) -> Result { let browser_name = self.get_browser_name(); let driver_name = self.get_driver_name(); let driver_version = self.get_driver_version(); @@ -218,7 +223,7 @@ impl SeleniumManager for GridManager { self.log = log; } - fn download_browser(&mut self) -> Result, Box> { + fn download_browser(&mut self) -> Result, Error> { Ok(None) } @@ -226,11 +231,11 @@ impl SeleniumManager for GridManager { "" } - fn request_latest_browser_version_from_online(&mut self) -> Result> { + fn request_latest_browser_version_from_online(&mut self) -> Result { self.unavailable_download() } - fn request_fixed_browser_version_from_online(&mut self) -> Result> { + fn request_fixed_browser_version_from_online(&mut self) -> Result { self.unavailable_download() } } diff --git a/rust/src/iexplorer.rs b/rust/src/iexplorer.rs index 25fce196b3a00..f5dea048341b1 100644 --- a/rust/src/iexplorer.rs +++ b/rust/src/iexplorer.rs @@ -16,9 +16,11 @@ // under the License. use crate::config::ManagerConfig; +use anyhow::Error; use reqwest::Client; use std::collections::HashMap; -use std::error::Error; + +use anyhow::anyhow; use std::path::PathBuf; use crate::files::{compose_driver_path_in_cache, BrowserPath}; @@ -56,7 +58,7 @@ pub struct IExplorerManager { } impl IExplorerManager { - pub fn new() -> Result, Box> { + pub fn new() -> Result, Error> { let browser_name = IE_NAMES[0]; let driver_name = IEDRIVER_NAME; let mut config = ManagerConfig::default(browser_name, driver_name); @@ -94,7 +96,7 @@ impl SeleniumManager for IExplorerManager { )]) } - fn discover_browser_version(&mut self) -> Result, Box> { + fn discover_browser_version(&mut self) -> Result, Error> { self.general_discover_browser_version( r#"HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer"#, REG_VERSION_ARG, @@ -106,7 +108,7 @@ impl SeleniumManager for IExplorerManager { self.driver_name } - fn request_driver_version(&mut self) -> Result> { + fn request_driver_version(&mut self) -> Result { let major_browser_version_binding = self.get_major_browser_version(); let major_browser_version = major_browser_version_binding.as_str(); let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()?); @@ -169,17 +171,20 @@ impl SeleniumManager for IExplorerManager { Ok(driver_version) } else { - Err(format!("{} release not available", self.get_driver_name()).into()) + Err(anyhow!(format!( + "{} release not available", + self.get_driver_name() + ))) } } } } - fn request_browser_version(&mut self) -> Result, Box> { + fn request_browser_version(&mut self) -> Result, Error> { Ok(None) } - fn get_driver_url(&mut self) -> Result> { + fn get_driver_url(&mut self) -> Result { if self.driver_url.is_some() { return Ok(self.driver_url.as_ref().unwrap().to_string()); } @@ -194,7 +199,7 @@ impl SeleniumManager for IExplorerManager { )) } - fn get_driver_path_in_cache(&self) -> Result> { + fn get_driver_path_in_cache(&self) -> Result { Ok(compose_driver_path_in_cache( self.get_cache_path()?, self.driver_name, @@ -224,7 +229,7 @@ impl SeleniumManager for IExplorerManager { self.log = log; } - fn download_browser(&mut self) -> Result, Box> { + fn download_browser(&mut self) -> Result, Error> { Ok(None) } @@ -232,11 +237,11 @@ impl SeleniumManager for IExplorerManager { "win32" } - fn request_latest_browser_version_from_online(&mut self) -> Result> { + fn request_latest_browser_version_from_online(&mut self) -> Result { self.unavailable_download() } - fn request_fixed_browser_version_from_online(&mut self) -> Result> { + fn request_fixed_browser_version_from_online(&mut self) -> Result { self.unavailable_download() } } diff --git a/rust/src/lib.rs b/rust/src/lib.rs index e2f2649242bcf..f17233ff299c6 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -28,10 +28,12 @@ use std::{env, fs}; use crate::config::OS::{MACOS, WINDOWS}; use crate::config::{str_to_os, ManagerConfig}; +use anyhow::Error; use is_executable::IsExecutable; use reqwest::{Client, Proxy}; use std::collections::HashMap; -use std::error::Error; + +use anyhow::anyhow; use std::path::{Path, PathBuf}; use std::time::Duration; use walkdir::{DirEntry, WalkDir}; @@ -117,17 +119,17 @@ pub trait SeleniumManager { fn get_browser_path_map(&self) -> HashMap; - fn discover_browser_version(&mut self) -> Result, Box>; + fn discover_browser_version(&mut self) -> Result, Error>; fn get_driver_name(&self) -> &str; - fn request_driver_version(&mut self) -> Result>; + fn request_driver_version(&mut self) -> Result; - fn request_browser_version(&mut self) -> Result, Box>; + fn request_browser_version(&mut self) -> Result, Error>; - fn get_driver_url(&mut self) -> Result>; + fn get_driver_url(&mut self) -> Result; - fn get_driver_path_in_cache(&self) -> Result>; + fn get_driver_path_in_cache(&self) -> Result; fn get_config(&self) -> &ManagerConfig; @@ -139,19 +141,19 @@ pub trait SeleniumManager { fn set_logger(&mut self, log: Logger); - fn download_browser(&mut self) -> Result, Box>; + fn download_browser(&mut self) -> Result, Error>; fn get_platform_label(&self) -> &str; - fn request_latest_browser_version_from_online(&mut self) -> Result>; + fn request_latest_browser_version_from_online(&mut self) -> Result; - fn request_fixed_browser_version_from_online(&mut self) -> Result>; + fn request_fixed_browser_version_from_online(&mut self) -> Result; // ---------------------------------------------------------- // Shared functions // ---------------------------------------------------------- - fn download_driver(&mut self) -> Result<(), Box> { + fn download_driver(&mut self) -> Result<(), Error> { let driver_url = self.get_driver_url()?; self.get_logger().debug(format!( "Downloading {} {} from {}", @@ -281,7 +283,7 @@ pub trait SeleniumManager { browser_version } - fn discover_driver_version(&mut self) -> Result> { + fn discover_driver_version(&mut self) -> Result { let mut download_browser = self.is_force_browser_download(); let major_browser_version = self.get_major_browser_version(); @@ -362,23 +364,21 @@ pub trait SeleniumManager { browser_path.unwrap().display() )); } else if !self.is_iexplorer() && !self.is_grid() { - return Err(format!( + return Err(anyhow!(format!( "{}{} cannot be downloaded", self.get_browser_name(), self.get_browser_version_label() - ) - .into()); + ))); } } // Second, we request the driver version using online endpoints let driver_version = self.request_driver_version()?; if driver_version.is_empty() { - Err(format!( + Err(anyhow!(format!( "The {} version cannot be discovered", self.get_driver_name() - ) - .into()) + ))) } else { self.get_logger().debug(format!( "Required driver: {} {}", @@ -504,7 +504,7 @@ pub trait SeleniumManager { self.get_browser_version().eq_ignore_ascii_case(STABLE) } - fn setup(&mut self) -> Result> { + fn setup(&mut self) -> Result { let mut driver_in_path = None; let mut driver_in_path_version = None; @@ -527,7 +527,7 @@ pub trait SeleniumManager { } // Discover proper driver version - if self.get_driver_version().is_empty() { + if driver_in_path_version.is_none() && self.get_driver_version().is_empty() { match self.discover_driver_version() { Ok(driver_version) => { self.set_driver_version(driver_version); @@ -627,7 +627,7 @@ pub trait SeleniumManager { self.is_driver(entry) && match_driver_version } - fn find_best_driver_from_cache(&self) -> Result, Box> { + fn find_best_driver_from_cache(&self) -> Result, Error> { let cache_path = self.get_cache_path()?; let drivers_in_cache_matching_version: Vec = WalkDir::new(&cache_path) .into_iter() @@ -661,15 +661,15 @@ pub trait SeleniumManager { } } - fn get_major_version(&self, full_version: &str) -> Result> { + fn get_major_version(&self, full_version: &str) -> Result { get_index_version(full_version, 0) } - fn get_minor_version(&self, full_version: &str) -> Result> { + fn get_minor_version(&self, full_version: &str) -> Result { get_index_version(full_version, 1) } - fn get_selenium_release_version(&self) -> Result> { + fn get_selenium_release_version(&self) -> Result { let driver_version = self.get_driver_version(); if driver_version.contains(SNAPSHOT) { return Ok(NIGHTLY.to_string()); @@ -683,16 +683,16 @@ pub trait SeleniumManager { self.get_driver_name(), driver_version ); - let index = release_version.rfind('.').ok_or(error_message)? + 1; + let index = release_version.rfind('.').ok_or(anyhow!(error_message))? + 1; release_version = release_version[..index].to_string(); release_version.push('0'); } Ok(format!("selenium-{release_version}")) } - fn assert_online_or_err(&self, message: &str) -> Result<(), Box> { + fn assert_online_or_err(&self, message: &str) -> Result<(), Error> { if self.is_offline() { - return Err(format_one_arg(message, self.get_driver_name()).into()); + return Err(anyhow!(format_one_arg(message, self.get_driver_name()))); } Ok(()) } @@ -716,7 +716,7 @@ pub trait SeleniumManager { fn general_request_browser_version( &mut self, browser_name: &str, - ) -> Result, Box> { + ) -> Result, Error> { let browser_version; let major_browser_version = self.get_major_browser_version(); let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()?); @@ -765,7 +765,7 @@ pub trait SeleniumManager { reg_key: &'static str, reg_version_arg: &'static str, cmd_version_arg: &str, - ) -> Result, Box> { + ) -> Result, Error> { let mut browser_path = self.get_browser_path().to_string(); let mut escaped_browser_path = self.get_escaped_path(browser_path.to_string()); if browser_path.is_empty() { @@ -818,10 +818,7 @@ pub trait SeleniumManager { Ok(self.detect_browser_version(commands)) } - fn discover_safari_version( - &mut self, - safari_path: String, - ) -> Result, Box> { + fn discover_safari_version(&mut self, safari_path: String) -> Result, Error> { let mut browser_path = self.get_browser_path().to_string(); let mut commands = Vec::new(); if browser_path.is_empty() { @@ -842,7 +839,7 @@ pub trait SeleniumManager { Ok(self.detect_browser_version(commands)) } - fn get_browser_path_in_cache(&self) -> Result> { + fn get_browser_path_in_cache(&self) -> Result { Ok(self .get_cache_path()? .join(self.get_browser_name()) @@ -859,8 +856,11 @@ pub trait SeleniumManager { } } - fn unavailable_download(&mut self) -> Result> { - Err(format_one_arg(UNAVAILABLE_DOWNLOAD_ERR_MSG, self.get_browser_name()).into()) + fn unavailable_download(&mut self) -> Result { + Err(anyhow!(format_one_arg( + UNAVAILABLE_DOWNLOAD_ERR_MSG, + self.get_browser_name() + ))) } // ---------------------------------------------------------- @@ -983,7 +983,7 @@ pub trait SeleniumManager { self.get_config().proxy.as_str() } - fn set_proxy(&mut self, proxy: String) -> Result<(), Box> { + fn set_proxy(&mut self, proxy: String) -> Result<(), Error> { if !proxy.is_empty() && !self.is_offline() { self.get_logger().debug(format!("Using proxy: {}", &proxy)); self.get_config_mut().proxy = proxy; @@ -996,7 +996,7 @@ pub trait SeleniumManager { self.get_config().timeout } - fn set_timeout(&mut self, timeout: u64) -> Result<(), Box> { + fn set_timeout(&mut self, timeout: u64) -> Result<(), Error> { if timeout != REQUEST_TIMEOUT_SEC { self.get_config_mut().timeout = timeout; self.get_logger() @@ -1006,7 +1006,7 @@ pub trait SeleniumManager { Ok(()) } - fn update_http_client(&mut self) -> Result<(), Box> { + fn update_http_client(&mut self) -> Result<(), Error> { let proxy = self.get_proxy(); let timeout = self.get_timeout(); let http_client = create_http_client(timeout, proxy)?; @@ -1054,7 +1054,7 @@ pub trait SeleniumManager { } } - fn get_cache_path(&self) -> Result> { + fn get_cache_path(&self) -> Result { let path = Path::new(&self.get_config().cache_path); create_path_if_not_exists(path)?; let canon_path = self.canonicalize_path(path.to_path_buf()); @@ -1072,9 +1072,7 @@ pub trait SeleniumManager { // Public functions // ---------------------------------------------------------- -pub fn get_manager_by_browser( - browser_name: String, -) -> Result, Box> { +pub fn get_manager_by_browser(browser_name: String) -> Result, Error> { let browser_name_lower_case = browser_name.to_ascii_lowercase(); if browser_name_lower_case.eq(CHROME_NAME) { Ok(ChromeManager::new()?) @@ -1089,16 +1087,11 @@ pub fn get_manager_by_browser( } else if SAFARITP_NAMES.contains(&browser_name_lower_case.as_str()) { Ok(SafariTPManager::new()?) } else { - Err(Box::new(std::io::Error::new( - std::io::ErrorKind::InvalidInput, - format!("Invalid browser name: {browser_name}"), - ))) + Err(anyhow!(format!("Invalid browser name: {browser_name}"))) } } -pub fn get_manager_by_driver( - driver_name: String, -) -> Result, Box> { +pub fn get_manager_by_driver(driver_name: String) -> Result, Error> { if driver_name.eq_ignore_ascii_case(CHROMEDRIVER_NAME) { Ok(ChromeManager::new()?) } else if driver_name.eq_ignore_ascii_case(GECKODRIVER_NAME) { @@ -1110,10 +1103,7 @@ pub fn get_manager_by_driver( } else if driver_name.eq_ignore_ascii_case(SAFARIDRIVER_NAME) { Ok(SafariManager::new()?) } else { - Err(Box::new(std::io::Error::new( - std::io::ErrorKind::InvalidInput, - format!("Invalid driver name: {driver_name}"), - ))) + Err(anyhow!(format!("Invalid driver name: {driver_name}"))) } } @@ -1131,7 +1121,7 @@ pub fn clear_cache(log: &Logger, path: &str) { } } -pub fn create_http_client(timeout: u64, proxy: &str) -> Result> { +pub fn create_http_client(timeout: u64, proxy: &str) -> Result { let mut client_builder = Client::builder() .danger_accept_invalid_certs(true) .use_rustls_tls() @@ -1161,10 +1151,10 @@ pub fn format_three_args(string: &str, arg1: &str, arg2: &str, arg3: &str) -> St // Private functions // ---------------------------------------------------------- -fn get_index_version(full_version: &str, index: usize) -> Result> { +fn get_index_version(full_version: &str, index: usize) -> Result { let version_vec: Vec<&str> = full_version.split('.').collect(); Ok(version_vec .get(index) - .ok_or(format!("Wrong version: {}", full_version))? + .ok_or(anyhow!(format!("Wrong version: {}", full_version)))? .to_string()) } diff --git a/rust/src/main.rs b/rust/src/main.rs index 2fd4b2a837b14..314ba54ff6261 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -18,6 +18,7 @@ use std::path::Path; use std::process::exit; +use anyhow::Error; use clap::Parser; use exitcode::DATAERR; @@ -146,22 +147,22 @@ fn main() { let mut selenium_manager: Box = if !browser_name.is_empty() { get_manager_by_browser(browser_name).unwrap_or_else(|err| { - log.error(err); - flush_and_exit(DATAERR, &log); + log.error(&err); + flush_and_exit(DATAERR, &log, Some(err)); }) } else if !driver_name.is_empty() { get_manager_by_driver(driver_name).unwrap_or_else(|err| { - log.error(err); - flush_and_exit(DATAERR, &log); + log.error(&err); + flush_and_exit(DATAERR, &log, Some(err)); }) } else if grid.is_some() { GridManager::new(grid.as_ref().unwrap().to_string()).unwrap_or_else(|err| { - log.error(err); - flush_and_exit(DATAERR, &log); + log.error(&err); + flush_and_exit(DATAERR, &log, Some(err)); }) } else { log.error("You need to specify a browser or driver"); - flush_and_exit(DATAERR, &log); + flush_and_exit(DATAERR, &log, None); }; if cli.offline { @@ -202,7 +203,7 @@ fn main() { .map(|driver_path| { let log = selenium_manager.get_logger(); log_driver_and_browser_path(log, &driver_path, selenium_manager.get_browser_path()); - flush_and_exit(OK, log); + flush_and_exit(OK, log, None); }) .unwrap_or_else(|err| { let log = selenium_manager.get_logger(); @@ -219,13 +220,13 @@ fn main() { &best_driver_from_cache, selenium_manager.get_browser_path(), ); - flush_and_exit(OK, log); + flush_and_exit(OK, log, Some(err)); } else if selenium_manager.is_offline() { log.warn(err.to_string()); - flush_and_exit(OK, log); + flush_and_exit(OK, log, Some(err)); } else { log.error(err.to_string()); - flush_and_exit(DATAERR, log); + flush_and_exit(DATAERR, log, Some(err)); } }); } @@ -235,14 +236,20 @@ fn log_driver_and_browser_path(log: &Logger, driver_path: &Path, browser_path: & log.info(format!("{}{}", DRIVER_PATH, driver_path.display())); } else { log.error(format!("Driver unavailable: {}", DRIVER_PATH)); - flush_and_exit(UNAVAILABLE, log); + flush_and_exit(UNAVAILABLE, log, None); } if !browser_path.is_empty() { log.info(format!("{}{}", BROWSER_PATH, browser_path)); } } -fn flush_and_exit(code: i32, log: &Logger) -> ! { +fn flush_and_exit(code: i32, log: &Logger, err: Option) -> ! { + if let Some(error) = err { + let backtrace = error.backtrace(); + if !backtrace.to_string().ends_with("backtrace") { + log.debug(format!("Backtrace:\n{}", backtrace)); + } + } log.set_code(code); log.flush(); exit(code); diff --git a/rust/src/safari.rs b/rust/src/safari.rs index 13687d5ccd5bf..0bc54dd2c701d 100644 --- a/rust/src/safari.rs +++ b/rust/src/safari.rs @@ -16,9 +16,11 @@ // under the License. use crate::config::ManagerConfig; +use anyhow::Error; use reqwest::Client; use std::collections::HashMap; -use std::error::Error; + +use anyhow::anyhow; use std::path::PathBuf; use std::string::ToString; @@ -41,7 +43,7 @@ pub struct SafariManager { } impl SafariManager { - pub fn new() -> Result, Box> { + pub fn new() -> Result, Error> { let browser_name = SAFARI_NAME; let driver_name = SAFARIDRIVER_NAME; let config = ManagerConfig::default(browser_name, driver_name); @@ -74,7 +76,7 @@ impl SeleniumManager for SafariManager { HashMap::from([(BrowserPath::new(MACOS, STABLE), SAFARI_PATH)]) } - fn discover_browser_version(&mut self) -> Result, Box> { + fn discover_browser_version(&mut self) -> Result, Error> { self.discover_safari_version(SAFARI_FULL_PATH.to_string()) } @@ -82,19 +84,22 @@ impl SeleniumManager for SafariManager { self.driver_name } - fn request_driver_version(&mut self) -> Result> { + fn request_driver_version(&mut self) -> Result { Ok("(local)".to_string()) } - fn request_browser_version(&mut self) -> Result, Box> { + fn request_browser_version(&mut self) -> Result, Error> { Ok(None) } - fn get_driver_url(&mut self) -> Result> { - Err(format!("{} not available for download", self.get_driver_name()).into()) + fn get_driver_url(&mut self) -> Result { + Err(anyhow!(format!( + "{} not available for download", + self.get_driver_name() + ))) } - fn get_driver_path_in_cache(&self) -> Result> { + fn get_driver_path_in_cache(&self) -> Result { Ok(PathBuf::from("/usr/bin/safaridriver")) } @@ -118,7 +123,7 @@ impl SeleniumManager for SafariManager { self.log = log; } - fn download_browser(&mut self) -> Result, Box> { + fn download_browser(&mut self) -> Result, Error> { Ok(None) } @@ -126,11 +131,11 @@ impl SeleniumManager for SafariManager { "" } - fn request_latest_browser_version_from_online(&mut self) -> Result> { + fn request_latest_browser_version_from_online(&mut self) -> Result { self.unavailable_download() } - fn request_fixed_browser_version_from_online(&mut self) -> Result> { + fn request_fixed_browser_version_from_online(&mut self) -> Result { self.unavailable_download() } } diff --git a/rust/src/safaritp.rs b/rust/src/safaritp.rs index a3beed8a795c2..487dfb3d4f4d0 100644 --- a/rust/src/safaritp.rs +++ b/rust/src/safaritp.rs @@ -16,9 +16,11 @@ // under the License. use crate::config::ManagerConfig; +use anyhow::Error; use reqwest::Client; use std::collections::HashMap; -use std::error::Error; + +use anyhow::anyhow; use std::path::PathBuf; use std::string::ToString; @@ -47,7 +49,7 @@ pub struct SafariTPManager { } impl SafariTPManager { - pub fn new() -> Result, Box> { + pub fn new() -> Result, Error> { let browser_name = SAFARITP_NAMES[0]; let driver_name = SAFARITPDRIVER_NAME; let config = ManagerConfig::default(browser_name, driver_name); @@ -80,7 +82,7 @@ impl SeleniumManager for SafariTPManager { HashMap::from([(BrowserPath::new(MACOS, STABLE), SAFARITP_PATH)]) } - fn discover_browser_version(&mut self) -> Result, Box> { + fn discover_browser_version(&mut self) -> Result, Error> { self.discover_safari_version(SAFARITP_FULL_PATH.to_string()) } @@ -88,19 +90,22 @@ impl SeleniumManager for SafariTPManager { self.driver_name } - fn request_driver_version(&mut self) -> Result> { + fn request_driver_version(&mut self) -> Result { Ok("(local)".to_string()) } - fn request_browser_version(&mut self) -> Result, Box> { + fn request_browser_version(&mut self) -> Result, Error> { Ok(None) } - fn get_driver_url(&mut self) -> Result> { - Err(format!("{} not available for download", self.get_driver_name()).into()) + fn get_driver_url(&mut self) -> Result { + Err(anyhow!(format!( + "{} not available for download", + self.get_driver_name() + ))) } - fn get_driver_path_in_cache(&self) -> Result> { + fn get_driver_path_in_cache(&self) -> Result { Ok(PathBuf::from( "/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver", )) @@ -126,7 +131,7 @@ impl SeleniumManager for SafariTPManager { self.log = log; } - fn download_browser(&mut self) -> Result, Box> { + fn download_browser(&mut self) -> Result, Error> { Ok(None) } @@ -134,11 +139,11 @@ impl SeleniumManager for SafariTPManager { "" } - fn request_latest_browser_version_from_online(&mut self) -> Result> { + fn request_latest_browser_version_from_online(&mut self) -> Result { self.unavailable_download() } - fn request_fixed_browser_version_from_online(&mut self) -> Result> { + fn request_fixed_browser_version_from_online(&mut self) -> Result { self.unavailable_download() } } diff --git a/rust/src/shell.rs b/rust/src/shell.rs index d81b0efbaf8d3..1c50d88cb77e3 100644 --- a/rust/src/shell.rs +++ b/rust/src/shell.rs @@ -16,7 +16,7 @@ // under the License. use crate::{Logger, WINDOWS}; -use std::error::Error; +use anyhow::Error; pub const CRLF: &str = "\r\n"; pub const LF: &str = "\n"; @@ -68,14 +68,14 @@ pub fn run_shell_command_with_log( log: &Logger, os: &str, command: Command, -) -> Result> { +) -> Result { log.debug(format!("Running command: {}", command.display())); let output = run_shell_command_by_os(os, command)?; log.debug(format!("Output: {:?}", output)); Ok(output) } -pub fn run_shell_command_by_os(os: &str, command: Command) -> Result> { +pub fn run_shell_command_by_os(os: &str, command: Command) -> Result { let (shell, flag) = if WINDOWS.is(os) { ("cmd", "/c") } else { @@ -84,11 +84,7 @@ pub fn run_shell_command_by_os(os: &str, command: Command) -> Result Result> { +pub fn run_shell_command(shell: &str, flag: &str, command: Command) -> Result { let mut process = std::process::Command::new(shell); process.arg(flag);