From 72f083c89d713851c74771da4d48db2d97a397c1 Mon Sep 17 00:00:00 2001 From: Boni Garcia Date: Sun, 6 Aug 2023 16:58:44 +0200 Subject: [PATCH] [rust] Refactor logic to execute commands in the shell --- rust/src/chrome.rs | 43 +++---------- rust/src/config.rs | 14 ++--- rust/src/edge.rs | 43 +++---------- rust/src/firefox.rs | 44 +++---------- rust/src/iexplorer.rs | 35 +++-------- rust/src/lib.rs | 142 ++++++++++++++++++++++++++++++++---------- rust/src/safari.rs | 21 +------ rust/src/safaritp.rs | 21 +------ rust/src/shell.rs | 71 +++++++++++++++++---- rust/tests/common.rs | 6 +- 10 files changed, 216 insertions(+), 224 deletions(-) diff --git a/rust/src/chrome.rs b/rust/src/chrome.rs index 829e9d4250abf..87a3de96995fd 100644 --- a/rust/src/chrome.rs +++ b/rust/src/chrome.rs @@ -34,10 +34,9 @@ use crate::metadata::{ create_driver_metadata, get_driver_version_from_metadata, get_metadata, write_metadata, }; use crate::{ - create_browser_metadata, create_http_client, download_to_tmp_folder, format_one_arg, - format_three_args, get_browser_version_from_metadata, uncompress, SeleniumManager, BETA, - DASH_DASH_VERSION, DEV, DOUBLE_QUOTE, NIGHTLY, OFFLINE_REQUEST_ERR_MSG, REG_QUERY, - SINGLE_QUOTE, STABLE, WMIC_COMMAND, + create_browser_metadata, create_http_client, download_to_tmp_folder, format_three_args, + get_browser_version_from_metadata, uncompress, SeleniumManager, BETA, DASH_DASH_VERSION, DEV, + NIGHTLY, OFFLINE_REQUEST_ERR_MSG, REG_VERSION_ARG, STABLE, }; pub const CHROME_NAME: &str = "chrome"; @@ -389,37 +388,11 @@ impl SeleniumManager for ChromeManager { } fn discover_browser_version(&mut self) -> Option { - let mut commands; - let mut browser_path = self.get_browser_path().to_string(); - let escaped_browser_path; - if browser_path.is_empty() { - match self.detect_browser_path() { - Some(path) => { - browser_path = path_buf_to_string(path); - escaped_browser_path = self.get_escaped_path(browser_path.to_string()); - commands = vec![format_one_arg(WMIC_COMMAND, &escaped_browser_path)]; - if !self.is_browser_version_unstable() { - commands.push(format_one_arg( - REG_QUERY, - r#"HKCU\Software\Google\Chrome\BLBeacon"#, - )); - } - } - _ => return None, - } - } else { - escaped_browser_path = self.get_escaped_path(browser_path.to_string()); - commands = vec![format_one_arg(WMIC_COMMAND, &escaped_browser_path)]; - } - if !WINDOWS.is(self.get_os()) { - commands = vec![ - format_three_args(DASH_DASH_VERSION, "", &escaped_browser_path, ""), - format_three_args(DASH_DASH_VERSION, DOUBLE_QUOTE, &browser_path, DOUBLE_QUOTE), - format_three_args(DASH_DASH_VERSION, SINGLE_QUOTE, &browser_path, SINGLE_QUOTE), - format_three_args(DASH_DASH_VERSION, "", &browser_path, ""), - ] - } - self.detect_browser_version(commands) + self.discover_general_browser_version( + r#"HKCU\Software\Google\Chrome\BLBeacon"#, + REG_VERSION_ARG, + DASH_DASH_VERSION, + ) } fn get_driver_name(&self) -> &str { diff --git a/rust/src/config.rs b/rust/src/config.rs index 84ecaa3ddea2b..5297d53650564 100644 --- a/rust/src/config.rs +++ b/rust/src/config.rs @@ -18,7 +18,7 @@ use crate::config::OS::{LINUX, MACOS, WINDOWS}; use crate::files::get_cache_folder; use crate::shell::run_shell_command_by_os; -use crate::{format_one_arg, REQUEST_TIMEOUT_SEC, UNAME_COMMAND}; +use crate::{format_one_arg, Command, REQUEST_TIMEOUT_SEC, UNAME_COMMAND}; use crate::{ARCH_AMD64, ARCH_ARM64, ARCH_X86, TTL_BROWSERS_SEC, TTL_DRIVERS_SEC, WMIC_COMMAND_OS}; use std::env; use std::env::consts::OS; @@ -50,8 +50,8 @@ impl ManagerConfig { pub fn default(browser_name: &str, driver_name: &str) -> ManagerConfig { let self_os = OS; let self_arch = if WINDOWS.is(self_os) { - let wmic_output = - run_shell_command_by_os(self_os, vec![WMIC_COMMAND_OS]).unwrap_or_default(); + let wmic_command = Command::new_single(WMIC_COMMAND_OS.to_string()); + let wmic_output = run_shell_command_by_os(self_os, wmic_command).unwrap_or_default(); if wmic_output.contains("32") { ARCH_X86.to_string() } else if wmic_output.contains("ARM") { @@ -60,16 +60,16 @@ impl ManagerConfig { ARCH_AMD64.to_string() } } else { - let uname_a = format_one_arg(UNAME_COMMAND, "a"); - if run_shell_command_by_os(self_os, vec![&uname_a]) + let uname_a_command = Command::new_single(format_one_arg(UNAME_COMMAND, "a")); + if run_shell_command_by_os(self_os, uname_a_command) .unwrap_or_default() .to_ascii_lowercase() .contains(ARCH_ARM64) { ARCH_ARM64.to_string() } else { - let uname_m = format_one_arg(UNAME_COMMAND, "m"); - run_shell_command_by_os(self_os, vec![&uname_m]).unwrap_or_default() + let uname_m_command = Command::new_single(format_one_arg(UNAME_COMMAND, "m")); + run_shell_command_by_os(self_os, uname_m_command).unwrap_or_default() } }; diff --git a/rust/src/edge.rs b/rust/src/edge.rs index f4b05990a9380..07fc5f8558559 100644 --- a/rust/src/edge.rs +++ b/rust/src/edge.rs @@ -24,14 +24,13 @@ use std::path::PathBuf; use crate::config::ARCH::{ARM64, X32}; use crate::config::OS::{LINUX, MACOS, WINDOWS}; use crate::downloads::read_version_from_link; -use crate::files::{compose_driver_path_in_cache, path_buf_to_string, BrowserPath}; +use crate::files::{compose_driver_path_in_cache, BrowserPath}; use crate::metadata::{ create_driver_metadata, get_driver_version_from_metadata, get_metadata, write_metadata, }; use crate::{ - create_http_client, format_one_arg, format_three_args, Logger, SeleniumManager, BETA, - DASH_DASH_VERSION, DEV, DOUBLE_QUOTE, NIGHTLY, OFFLINE_REQUEST_ERR_MSG, REG_QUERY, - SINGLE_QUOTE, STABLE, WMIC_COMMAND, + create_http_client, Logger, SeleniumManager, BETA, DASH_DASH_VERSION, DEV, NIGHTLY, + OFFLINE_REQUEST_ERR_MSG, REG_VERSION_ARG, STABLE, }; pub const EDGE_NAMES: &[&str] = &["edge", "msedge", "microsoftedge"]; @@ -122,37 +121,11 @@ impl SeleniumManager for EdgeManager { } fn discover_browser_version(&mut self) -> Option { - let mut commands; - let mut browser_path = self.get_browser_path().to_string(); - let escaped_browser_path; - if browser_path.is_empty() { - match self.detect_browser_path() { - Some(path) => { - browser_path = path_buf_to_string(path); - escaped_browser_path = self.get_escaped_path(browser_path.to_string()); - commands = vec![format_one_arg(WMIC_COMMAND, &escaped_browser_path)]; - if !self.is_browser_version_unstable() { - commands.push(format_one_arg( - REG_QUERY, - r#"HKCU\Software\Microsoft\Edge\BLBeacon"#, - )); - } - } - _ => return None, - } - } else { - escaped_browser_path = self.get_escaped_path(browser_path.to_string()); - commands = vec![format_one_arg(WMIC_COMMAND, &escaped_browser_path)]; - } - if !WINDOWS.is(self.get_os()) { - commands = vec![ - format_three_args(DASH_DASH_VERSION, "", &escaped_browser_path, ""), - format_three_args(DASH_DASH_VERSION, DOUBLE_QUOTE, &browser_path, DOUBLE_QUOTE), - format_three_args(DASH_DASH_VERSION, SINGLE_QUOTE, &browser_path, SINGLE_QUOTE), - format_three_args(DASH_DASH_VERSION, "", &browser_path, ""), - ] - } - self.detect_browser_version(commands) + self.discover_general_browser_version( + r#"HKCU\Software\Microsoft\Edge\BLBeacon"#, + REG_VERSION_ARG, + DASH_DASH_VERSION, + ) } fn get_driver_name(&self) -> &str { diff --git a/rust/src/firefox.rs b/rust/src/firefox.rs index 1d35892394bad..37651b72ed8a8 100644 --- a/rust/src/firefox.rs +++ b/rust/src/firefox.rs @@ -24,14 +24,13 @@ use std::path::PathBuf; use crate::config::ARCH::{ARM64, X32}; use crate::config::OS::{LINUX, MACOS, WINDOWS}; use crate::downloads::read_redirect_from_link; -use crate::files::{compose_driver_path_in_cache, path_buf_to_string, BrowserPath}; +use crate::files::{compose_driver_path_in_cache, BrowserPath}; use crate::metadata::{ create_driver_metadata, get_driver_version_from_metadata, get_metadata, write_metadata, }; use crate::{ - create_http_client, format_one_arg, format_three_args, format_two_args, Logger, - SeleniumManager, BETA, DASH_VERSION, DEV, DOUBLE_QUOTE, NIGHTLY, OFFLINE_REQUEST_ERR_MSG, - REG_QUERY_FIND, SINGLE_QUOTE, STABLE, WMIC_COMMAND, + create_http_client, Logger, SeleniumManager, BETA, DASH_VERSION, DEV, NIGHTLY, + OFFLINE_REQUEST_ERR_MSG, REG_CURRENT_VERSION_ARG, STABLE, }; pub const FIREFOX_NAME: &str = "firefox"; @@ -119,38 +118,11 @@ impl SeleniumManager for FirefoxManager { } fn discover_browser_version(&mut self) -> Option { - let mut commands; - let mut browser_path = self.get_browser_path().to_string(); - let escaped_browser_path; - if browser_path.is_empty() { - match self.detect_browser_path() { - Some(path) => { - browser_path = path_buf_to_string(path); - escaped_browser_path = self.get_escaped_path(browser_path.to_string()); - commands = vec![format_one_arg(WMIC_COMMAND, &escaped_browser_path)]; - if !self.is_browser_version_unstable() { - commands.push(format_two_args( - REG_QUERY_FIND, - r#"HKCU\Software\Mozilla"#, - self.browser_name, - )); - } - } - _ => return None, - } - } else { - escaped_browser_path = self.get_escaped_path(browser_path.to_string()); - commands = vec![format_one_arg(WMIC_COMMAND, &escaped_browser_path)]; - } - if !WINDOWS.is(self.get_os()) { - commands = vec![ - format_three_args(DASH_VERSION, "", &escaped_browser_path, ""), - format_three_args(DASH_VERSION, DOUBLE_QUOTE, &browser_path, DOUBLE_QUOTE), - format_three_args(DASH_VERSION, SINGLE_QUOTE, &browser_path, SINGLE_QUOTE), - format_three_args(DASH_VERSION, "", &browser_path, ""), - ] - } - self.detect_browser_version(commands) + self.discover_general_browser_version( + r#"HKCU\Software\Mozilla\Mozilla Firefox"#, + REG_CURRENT_VERSION_ARG, + DASH_VERSION, + ) } fn get_driver_name(&self) -> &str { diff --git a/rust/src/iexplorer.rs b/rust/src/iexplorer.rs index 6c6c812cf1f3b..8181c2529fd9b 100644 --- a/rust/src/iexplorer.rs +++ b/rust/src/iexplorer.rs @@ -21,12 +21,12 @@ use std::collections::HashMap; use std::error::Error; use std::path::PathBuf; -use crate::files::{compose_driver_path_in_cache, path_buf_to_string, BrowserPath}; +use crate::files::{compose_driver_path_in_cache, BrowserPath}; use crate::downloads::parse_json_from_url; use crate::{ - create_http_client, format_one_arg, parse_version, Logger, SeleniumManager, - OFFLINE_REQUEST_ERR_MSG, REG_QUERY, STABLE, WINDOWS, WMIC_COMMAND, + create_http_client, parse_version, Logger, SeleniumManager, OFFLINE_REQUEST_ERR_MSG, + REG_VERSION_ARG, STABLE, WINDOWS, }; use crate::metadata::{ @@ -95,30 +95,11 @@ impl SeleniumManager for IExplorerManager { } fn discover_browser_version(&mut self) -> Option { - let commands; - let mut browser_path = self.get_browser_path().to_string(); - let escaped_browser_path; - if browser_path.is_empty() { - match self.detect_browser_path() { - Some(path) => { - browser_path = path_buf_to_string(path); - escaped_browser_path = self.get_escaped_path(browser_path.to_string()); - commands = vec![format_one_arg(WMIC_COMMAND, &escaped_browser_path)]; - } - None => { - commands = vec![ - (format_one_arg( - REG_QUERY, - r#"HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer"#, - )), - ]; - } - } - } else { - escaped_browser_path = self.get_escaped_path(browser_path.to_string()); - commands = vec![format_one_arg(WMIC_COMMAND, &escaped_browser_path)]; - } - self.detect_browser_version(commands) + self.discover_general_browser_version( + r#"HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer"#, + REG_VERSION_ARG, + "", + ) } fn get_driver_name(&self) -> &str { diff --git a/rust/src/lib.rs b/rust/src/lib.rs index cf62373fa00cf..1c6fb5d166ee1 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -17,13 +17,16 @@ use crate::chrome::{ChromeManager, CHROMEDRIVER_NAME, CHROME_NAME}; use crate::edge::{EdgeManager, EDGEDRIVER_NAME, EDGE_NAMES}; -use crate::files::{compose_cache_folder, create_parent_path_if_not_exists, get_binary_extension}; +use crate::files::{ + compose_cache_folder, create_parent_path_if_not_exists, get_binary_extension, + path_buf_to_string, +}; use crate::firefox::{FirefoxManager, FIREFOX_NAME, GECKODRIVER_NAME}; use crate::iexplorer::{IExplorerManager, IEDRIVER_NAME, IE_NAMES}; use crate::safari::{SafariManager, SAFARIDRIVER_NAME, SAFARI_NAME}; use std::{env, fs}; -use crate::config::OS::WINDOWS; +use crate::config::OS::{MACOS, WINDOWS}; use crate::config::{str_to_os, ManagerConfig}; use is_executable::IsExecutable; use reqwest::{Client, Proxy}; @@ -39,7 +42,7 @@ use crate::logger::Logger; use crate::metadata::{create_browser_metadata, get_browser_version_from_metadata}; use crate::safaritp::{SafariTPManager, SAFARITP_NAMES}; use crate::shell::{ - run_shell_command, run_shell_command_by_os, run_shell_command_with_log, split_lines, + run_shell_command, run_shell_command_by_os, run_shell_command_with_log, split_lines, Command, }; pub mod chrome; @@ -65,8 +68,8 @@ pub const CANARY: &str = "canary"; pub const NIGHTLY: &str = "nightly"; pub const WMIC_COMMAND: &str = r#"wmic datafile where name='{}' get Version /value"#; pub const WMIC_COMMAND_OS: &str = r#"wmic os get osarchitecture"#; -pub const REG_QUERY: &str = r#"REG QUERY {} /v version"#; -pub const REG_QUERY_FIND: &str = r#"REG QUERY {} /f {}"#; +pub const REG_VERSION_ARG: &str = "version"; +pub const REG_CURRENT_VERSION_ARG: &str = "CurrentVersion"; pub const PLIST_COMMAND: &str = r#"/usr/libexec/PlistBuddy -c "print :CFBundleShortVersionString" {}/Contents/Info.plist"#; pub const DASH_VERSION: &str = "{}{}{} -v"; @@ -219,7 +222,7 @@ pub trait SeleniumManager { } } - fn detect_browser_version(&self, commands: Vec) -> Option { + fn detect_browser_version(&self, commands: Vec) -> Option { let browser_name = &self.get_browser_name(); self.get_logger().trace(format!( @@ -227,12 +230,15 @@ pub trait SeleniumManager { browser_name )); let mut browser_version: Option = None; - for command in commands.iter() { - let output = - match run_shell_command_with_log(self.get_logger(), self.get_os(), vec![command]) { - Ok(out) => out, - Err(_e) => continue, - }; + for driver_version_command in commands.into_iter() { + let output = match run_shell_command_with_log( + self.get_logger(), + self.get_os(), + driver_version_command, + ) { + Ok(out) => out, + Err(_e) => continue, + }; let full_browser_version = parse_version(output, self.get_logger()).unwrap_or_default(); if full_browser_version.is_empty() { continue; @@ -359,15 +365,13 @@ pub trait SeleniumManager { } fn find_driver_in_path(&self) -> (Option, Option) { - match run_shell_command_by_os( - self.get_os(), - vec![&format_three_args( - DASH_DASH_VERSION, - self.get_driver_name(), - "", - "", - )], - ) { + let driver_version_command = Command::new_single(format_three_args( + DASH_DASH_VERSION, + self.get_driver_name(), + "", + "", + )); + match run_shell_command_by_os(self.get_os(), driver_version_command) { Ok(output) => { let parsed_version = parse_version(output, self.get_logger()).unwrap_or_default(); if !parsed_version.is_empty() { @@ -380,17 +384,14 @@ pub trait SeleniumManager { } } - fn execute_which_in_shell(&self, command: &str) -> Option { - let which_command = if WINDOWS.is(self.get_os()) { + fn execute_which_in_shell(&self, arg: &str) -> Option { + let which_or_where = if WINDOWS.is(self.get_os()) { WHERE_COMMAND } else { WHICH_COMMAND }; - let path = match run_shell_command_with_log( - self.get_logger(), - self.get_os(), - vec![&format_one_arg(which_command, command)], - ) { + let which_command = Command::new_single(format_one_arg(which_or_where, arg)); + let path = match run_shell_command_by_os(self.get_os(), which_command) { Ok(path) => { let path_vector = split_lines(path.as_str()); if path_vector.len() == 1 { @@ -590,6 +591,82 @@ pub trait SeleniumManager { ) } + fn discover_general_browser_version( + &mut self, + reg_key: &'static str, + reg_version_arg: &'static str, + cmd_version_arg: &str, + ) -> Option { + 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() { + if let Some(path) = self.detect_browser_path() { + browser_path = path_buf_to_string(path); + escaped_browser_path = self.get_escaped_path(browser_path.to_string()); + } + } + + let mut commands = Vec::new(); + if WINDOWS.is(self.get_os()) { + let wmic_command = + Command::new_single(format_one_arg(WMIC_COMMAND, &escaped_browser_path)); + commands.push(wmic_command); + if !self.is_browser_version_unstable() { + let reg_command = + Command::new_multiple(vec!["REG", "QUERY", reg_key, "/v", reg_version_arg]); + commands.push(reg_command); + } + } else { + commands.push(Command::new_single(format_three_args( + cmd_version_arg, + "", + &escaped_browser_path, + "", + ))); + commands.push(Command::new_single(format_three_args( + cmd_version_arg, + DOUBLE_QUOTE, + &browser_path, + DOUBLE_QUOTE, + ))); + commands.push(Command::new_single(format_three_args( + cmd_version_arg, + SINGLE_QUOTE, + &browser_path, + SINGLE_QUOTE, + ))); + commands.push(Command::new_single(format_three_args( + cmd_version_arg, + "", + &browser_path, + "", + ))); + } + + self.detect_browser_version(commands) + } + + fn discover_safari_version(&mut self, safari_path: String) -> Option { + let mut browser_path = self.get_browser_path().to_string(); + let mut commands = Vec::new(); + if browser_path.is_empty() { + match self.detect_browser_path() { + Some(path) => { + browser_path = self.get_escaped_path(path_buf_to_string(path)); + } + _ => return None, + } + } + if MACOS.is(self.get_os()) { + let plist_command = Command::new_single(format_one_arg(PLIST_COMMAND, &browser_path)); + commands.push(plist_command); + } else { + return None; + } + self.set_browser_path(safari_path); + self.detect_browser_version(commands) + } + // ---------------------------------------------------------- // Getters and setters for configuration parameters // ---------------------------------------------------------- @@ -681,12 +758,9 @@ pub trait SeleniumManager { if WINDOWS.is(self.get_os()) { escaped_path = escaped_path.replace('\\', "\\\\"); } else { - escaped_path = run_shell_command( - "bash", - "-c", - vec![format_one_arg(ESCAPE_COMMAND, escaped_path.as_str()).as_str()], - ) - .unwrap_or_default(); + let escape_command = + Command::new_single(format_one_arg(ESCAPE_COMMAND, escaped_path.as_str())); + escaped_path = run_shell_command("bash", "-c", escape_command).unwrap_or_default(); if escaped_path.is_empty() { escaped_path = original_path.clone(); } diff --git a/rust/src/safari.rs b/rust/src/safari.rs index 511b91c80268a..3aa62e2f46d27 100644 --- a/rust/src/safari.rs +++ b/rust/src/safari.rs @@ -22,10 +22,10 @@ use std::error::Error; use std::path::PathBuf; use std::string::ToString; -use crate::files::{path_buf_to_string, BrowserPath}; +use crate::files::BrowserPath; use crate::config::OS::MACOS; -use crate::{create_http_client, format_one_arg, Logger, SeleniumManager, PLIST_COMMAND, STABLE}; +use crate::{create_http_client, Logger, SeleniumManager, STABLE}; pub const SAFARI_NAME: &str = "safari"; pub const SAFARIDRIVER_NAME: &str = "safaridriver"; @@ -75,22 +75,7 @@ impl SeleniumManager for SafariManager { } fn discover_browser_version(&mut self) -> Option { - let mut browser_path = self.get_browser_path().to_string(); - if browser_path.is_empty() { - match self.detect_browser_path() { - Some(path) => { - browser_path = self.get_escaped_path(path_buf_to_string(path)); - } - _ => return None, - } - } - let command = if MACOS.is(self.get_os()) { - vec![format_one_arg(PLIST_COMMAND, &browser_path)] - } else { - return None; - }; - self.set_browser_path(SAFARI_FULL_PATH.to_string()); - self.detect_browser_version(command) + self.discover_safari_version(SAFARI_FULL_PATH.to_string()) } fn get_driver_name(&self) -> &str { diff --git a/rust/src/safaritp.rs b/rust/src/safaritp.rs index 76e870277dbe6..3f2cecd4c17e7 100644 --- a/rust/src/safaritp.rs +++ b/rust/src/safaritp.rs @@ -22,10 +22,10 @@ use std::error::Error; use std::path::PathBuf; use std::string::ToString; -use crate::files::{path_buf_to_string, BrowserPath}; +use crate::files::BrowserPath; use crate::config::OS::MACOS; -use crate::{create_http_client, format_one_arg, Logger, SeleniumManager, PLIST_COMMAND, STABLE}; +use crate::{create_http_client, Logger, SeleniumManager, STABLE}; pub const SAFARITP_NAMES: &[&str] = &[ "safaritp", @@ -81,22 +81,7 @@ impl SeleniumManager for SafariTPManager { } fn discover_browser_version(&mut self) -> Option { - let mut browser_path = self.get_browser_path().to_string(); - if browser_path.is_empty() { - match self.detect_browser_path() { - Some(path) => { - browser_path = self.get_escaped_path(path_buf_to_string(path)); - } - _ => return None, - } - } - let command = if MACOS.is(self.get_os()) { - vec![format_one_arg(PLIST_COMMAND, &browser_path)] - } else { - return None; - }; - self.set_browser_path(SAFARITP_FULL_PATH.to_string()); - self.detect_browser_version(command) + self.discover_safari_version(SAFARITP_FULL_PATH.to_string()) } fn get_driver_name(&self) -> &str { diff --git a/rust/src/shell.rs b/rust/src/shell.rs index 404337dc438c5..d81b0efbaf8d3 100644 --- a/rust/src/shell.rs +++ b/rust/src/shell.rs @@ -17,42 +17,89 @@ use crate::{Logger, WINDOWS}; use std::error::Error; -use std::process::Command; pub const CRLF: &str = "\r\n"; pub const LF: &str = "\n"; +pub struct Command { + pub single_arg: Option, + pub multiple_args: Option>, +} + +impl Command { + pub fn new_single(single_arg: String) -> Self { + Command { + single_arg: Some(single_arg), + multiple_args: None, + } + } + + pub fn new_multiple(multiple_args: Vec<&'static str>) -> Self { + Command { + single_arg: None, + multiple_args: Some(multiple_args), + } + } + + pub fn is_single(&self) -> bool { + self.single_arg.is_some() + } + + pub fn is_multiple(&self) -> bool { + self.multiple_args.is_some() + } + + pub fn display(&self) -> String { + if self.is_single() { + self.single_arg.clone().unwrap() + } else { + self.multiple_args + .clone() + .unwrap() + .into_iter() + .map(|c| c.to_string()) + .collect::>() + .join(" ") + } + } +} + pub fn run_shell_command_with_log( log: &Logger, os: &str, - args: Vec<&str>, + command: Command, ) -> Result> { - log.debug(format!("Running command: {:?}", args)); - let output = run_shell_command_by_os(os, args)?; + 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, args: Vec<&str>) -> Result> { +pub fn run_shell_command_by_os(os: &str, command: Command) -> Result> { let (shell, flag) = if WINDOWS.is(os) { ("cmd", "/c") } else { ("sh", "-c") }; - run_shell_command(shell, flag, args) + run_shell_command(shell, flag, command) } pub fn run_shell_command( shell: &str, flag: &str, - args: Vec<&str>, + command: Command, ) -> Result> { - let mut command = Command::new(shell); - command.arg(flag); - for arg in args.iter() { - command.arg(arg); + let mut process = std::process::Command::new(shell); + process.arg(flag); + + if command.is_single() { + process.arg(command.single_arg.unwrap()); + } else { + for arg in command.multiple_args.unwrap().iter() { + process.arg(arg); + } } - let output = command.output()?; + let output = process.output()?; Ok( strip_trailing_newline(String::from_utf8_lossy(&output.stdout).to_string().as_str()) .to_string(), diff --git a/rust/tests/common.rs b/rust/tests/common.rs index 383f51e374d6a..6fcd074e6b710 100644 --- a/rust/tests/common.rs +++ b/rust/tests/common.rs @@ -21,6 +21,7 @@ use std::path::Path; use is_executable::is_executable; use selenium_manager::logger::JsonOutput; +use selenium_manager::shell; use selenium_manager::shell::run_shell_command_by_os; pub fn assert_driver(cmd: &mut Command) { @@ -50,8 +51,9 @@ pub fn exec_driver(cmd: &mut Command) -> String { let json: JsonOutput = serde_json::from_str(output).unwrap(); let driver_path = Path::new(&json.result.driver_path); - let driver_version_command = format!("{} --version", driver_path.to_str().unwrap()); - let output = run_shell_command_by_os(OS, vec![&driver_version_command]).unwrap(); + let driver_version_command = + shell::Command::new_single(format!("{} --version", driver_path.to_str().unwrap())); + let output = run_shell_command_by_os(OS, driver_version_command).unwrap(); println!("**** EXEC DRIVER: {}", output); output }