From fa5a7cd8f0eaaf9d5b572b58c31a2b4d00b3d533 Mon Sep 17 00:00:00 2001 From: Boni Garcia Date: Mon, 7 Aug 2023 18:15:32 +0200 Subject: [PATCH 1/3] [rust] Allow to change default folder for Selenium Manager cache (#11688) --- rust/README.md | 2 ++ rust/src/chrome.rs | 26 ++++++++++++--------- rust/src/config.rs | 45 ++++++++++++++++++++++++++++++------ rust/src/edge.rs | 12 +++++++--- rust/src/files.rs | 11 +++------ rust/src/firefox.rs | 12 +++++++--- rust/src/grid.rs | 8 +++---- rust/src/iexplorer.rs | 12 +++++++--- rust/src/lib.rs | 20 ++++++++++++---- rust/src/main.rs | 32 ++++++++++++++++++-------- rust/src/metadata.rs | 17 +++++++------- rust/tests/cache_tests.rs | 48 +++++++++++++++++++++++++++++++++++++++ rust/tests/common.rs | 16 +++++++++---- 13 files changed, 195 insertions(+), 66 deletions(-) create mode 100644 rust/tests/cache_tests.rs diff --git a/rust/README.md b/rust/README.md index e6f3eafaf42fa..d112a01851ef4 100644 --- a/rust/README.md +++ b/rust/README.md @@ -47,6 +47,8 @@ Options: Driver TTL (time-to-live) [default: 3600] --browser-ttl Browser TTL (time-to-live) [default: 3600] + --cache-path + Local folder used to store downloaded assets (drivers and browsers), local metadata, and configuration file [default: ~/.cache/selenium] --clear-cache Clear cache folder (~/.cache/selenium) --clear-metadata diff --git a/rust/src/chrome.rs b/rust/src/chrome.rs index 45aad9c4e8592..8ef5e52409b97 100644 --- a/rust/src/chrome.rs +++ b/rust/src/chrome.rs @@ -26,9 +26,7 @@ use std::path::PathBuf; use crate::config::ARCH::{ARM64, X32}; use crate::config::OS::{LINUX, MACOS, WINDOWS}; use crate::downloads::{parse_json_from_url, read_version_from_link}; -use crate::files::{ - compose_driver_path_in_cache, get_cache_folder, path_buf_to_string, BrowserPath, -}; +use crate::files::{compose_driver_path_in_cache, path_buf_to_string, BrowserPath}; use crate::logger::Logger; use crate::metadata::{ create_driver_metadata, get_driver_version_from_metadata, get_metadata, write_metadata, @@ -315,7 +313,7 @@ impl ChromeManager { } fn get_browser_path_in_cache(&self) -> PathBuf { - get_cache_folder() + self.get_cache_path() .join(self.get_browser_name()) .join(self.get_platform_label()) .join(self.get_browser_version()) @@ -402,7 +400,7 @@ impl SeleniumManager for ChromeManager { 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()); + let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()); match get_driver_version_from_metadata( &metadata.drivers, @@ -447,7 +445,7 @@ impl SeleniumManager for ChromeManager { &driver_version, driver_ttl, )); - write_metadata(&metadata, self.get_logger()); + write_metadata(&metadata, self.get_logger(), self.get_cache_path()); } Ok(driver_version) } @@ -458,7 +456,7 @@ impl SeleniumManager for ChromeManager { let browser_name = self.browser_name; let browser_version; let major_browser_version = self.get_major_browser_version(); - let mut metadata = get_metadata(self.get_logger()); + let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()); // First, browser version is checked in the local metadata match get_browser_version_from_metadata( @@ -486,7 +484,7 @@ impl SeleniumManager for ChromeManager { &browser_version, browser_ttl, )); - write_metadata(&metadata, self.get_logger()); + write_metadata(&metadata, self.get_logger(), self.get_cache_path()); } } } @@ -540,7 +538,13 @@ impl SeleniumManager for ChromeManager { let driver_version = self.get_driver_version(); let os = self.get_os(); let arch_folder = self.get_platform_label(); - compose_driver_path_in_cache(self.driver_name, os, arch_folder, driver_version) + compose_driver_path_in_cache( + self.get_cache_path(), + self.driver_name, + os, + arch_folder, + driver_version, + ) } fn get_config(&self) -> &ManagerConfig { @@ -566,7 +570,7 @@ impl SeleniumManager for ChromeManager { fn download_browser(&mut self) -> Result, Box> { let browser_version; let browser_name = self.browser_name; - let mut metadata = get_metadata(self.get_logger()); + let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()); let major_browser_version = self.get_major_browser_version(); let major_browser_version_int = major_browser_version.parse::().unwrap_or_default(); @@ -618,7 +622,7 @@ impl SeleniumManager for ChromeManager { &browser_version, browser_ttl, )); - write_metadata(&metadata, self.get_logger()); + write_metadata(&metadata, self.get_logger(), self.get_cache_path()); } } } diff --git a/rust/src/config.rs b/rust/src/config.rs index 59b85007167e9..c5ce272127c4d 100644 --- a/rust/src/config.rs +++ b/rust/src/config.rs @@ -16,22 +16,30 @@ // under the License. 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, Command, REQUEST_TIMEOUT_SEC, UNAME_COMMAND}; +use crate::{ + default_cache_folder, format_one_arg, path_buf_to_string, 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::cell::RefCell; use std::env; use std::env::consts::OS; use std::error::Error; use std::fs::read_to_string; +use std::path::Path; use toml::Table; +thread_local!(static CACHE_PATH: RefCell = RefCell::new(path_buf_to_string(default_cache_folder()))); + pub const CONFIG_FILE: &str = "selenium-manager-config.toml"; pub const ENV_PREFIX: &str = "SE_"; pub const VERSION_PREFIX: &str = "-version"; pub const PATH_PREFIX: &str = "-path"; +pub const CACHE_PATH_KEY: &str = "cache-path"; pub struct ManagerConfig { + pub cache_path: String, pub browser_version: String, pub driver_version: String, pub browser_path: String, @@ -47,6 +55,8 @@ pub struct ManagerConfig { impl ManagerConfig { pub fn default(browser_name: &str, driver_name: &str) -> ManagerConfig { + let cache_path = StringKey(vec![CACHE_PATH_KEY], &read_cache_path()).get_value(); + let self_os = OS; let self_arch = if WINDOWS.is(self_os) { let wmic_command = Command::new_single(WMIC_COMMAND_OS.to_string()); @@ -77,12 +87,12 @@ impl ManagerConfig { let browser_path_label = concat(browser_name, PATH_PREFIX); ManagerConfig { - browser_version: StringKey(vec!["browser-version", browser_version_label.as_str()], "") + cache_path, + browser_version: StringKey(vec!["browser-version", &browser_version_label], "") .get_value(), - driver_version: StringKey(vec!["driver-version", driver_version_label.as_str()], "") - .get_value(), - browser_path: StringKey(vec!["browser-path", browser_path_label.as_str()], "") + driver_version: StringKey(vec!["driver-version", &driver_version_label], "") .get_value(), + browser_path: StringKey(vec!["browser-path", &browser_path_label], "").get_value(), os: StringKey(vec!["os"], self_os).get_value(), arch: StringKey(vec!["arch"], self_arch.as_str()).get_value(), proxy: StringKey(vec!["proxy"], "").get_value(), @@ -168,6 +178,9 @@ impl StringKey<'_> { result = env::var(get_env_name(key)).unwrap_or_default() } if !result.is_empty() { + if key.eq(CACHE_PATH_KEY) { + write_cache_path(result.clone()); + } return result; } } @@ -215,7 +228,8 @@ fn get_env_name(suffix: &str) -> String { } fn get_config() -> Result> { - let config_path = get_cache_folder().join(CONFIG_FILE); + 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()?) } @@ -224,3 +238,20 @@ fn concat(prefix: &str, suffix: &str) -> String { version_label.push_str(suffix); version_label } + +fn write_cache_path(cache_path: String) { + CACHE_PATH.with(|value| { + *value.borrow_mut() = cache_path; + }); +} + +fn read_cache_path() -> String { + let mut cache_path: String = path_buf_to_string(default_cache_folder()); + CACHE_PATH.with(|value| { + let path: String = (&*value.borrow().to_string()).into(); + if !path.is_empty() { + cache_path = path; + } + }); + cache_path +} diff --git a/rust/src/edge.rs b/rust/src/edge.rs index b2a25375bf29e..31677edbbee3d 100644 --- a/rust/src/edge.rs +++ b/rust/src/edge.rs @@ -134,7 +134,7 @@ impl SeleniumManager for EdgeManager { 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()); + let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()); match get_driver_version_from_metadata( &metadata.drivers, @@ -191,7 +191,7 @@ impl SeleniumManager for EdgeManager { &driver_version, driver_ttl, )); - write_metadata(&metadata, self.get_logger()); + write_metadata(&metadata, self.get_logger(), self.get_cache_path()); } Ok(driver_version) @@ -251,7 +251,13 @@ impl SeleniumManager for EdgeManager { } else { "linux64" }; - compose_driver_path_in_cache(self.driver_name, os, arch_folder, driver_version) + compose_driver_path_in_cache( + self.get_cache_path(), + self.driver_name, + os, + arch_folder, + driver_version, + ) } fn get_config(&self) -> &ManagerConfig { diff --git a/rust/src/files.rs b/rust/src/files.rs index 563f9c5e295f0..c6ac40feff04c 100644 --- a/rust/src/files.rs +++ b/rust/src/files.rs @@ -186,7 +186,7 @@ pub fn get_raw_file_name(file_name: &str) -> &str { raw_file_name } -pub fn compose_cache_folder() -> PathBuf { +pub fn default_cache_folder() -> PathBuf { if let Some(base_dirs) = BaseDirs::new() { return Path::new(base_dirs.home_dir()) .join(String::from(CACHE_FOLDER).replace('/', std::path::MAIN_SEPARATOR_STR)); @@ -194,19 +194,14 @@ pub fn compose_cache_folder() -> PathBuf { PathBuf::new() } -pub fn get_cache_folder() -> PathBuf { - let cache_path = compose_cache_folder(); - create_path_if_not_exists(&cache_path); - cache_path -} - pub fn compose_driver_path_in_cache( + driver_path: PathBuf, driver_name: &str, os: &str, arch_folder: &str, driver_version: &str, ) -> PathBuf { - get_cache_folder() + driver_path .join(driver_name) .join(arch_folder) .join(driver_version) diff --git a/rust/src/firefox.rs b/rust/src/firefox.rs index 27878c7dcd7b1..8726e0a6d0a61 100644 --- a/rust/src/firefox.rs +++ b/rust/src/firefox.rs @@ -132,7 +132,7 @@ impl SeleniumManager for FirefoxManager { 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()); + let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()); match get_driver_version_from_metadata( &metadata.drivers, @@ -161,7 +161,7 @@ impl SeleniumManager for FirefoxManager { &driver_version, driver_ttl, )); - write_metadata(&metadata, self.get_logger()); + write_metadata(&metadata, self.get_logger(), self.get_cache_path()); } Ok(driver_version) @@ -241,7 +241,13 @@ impl SeleniumManager for FirefoxManager { } else { "linux64" }; - compose_driver_path_in_cache(self.driver_name, os, arch_folder, driver_version) + compose_driver_path_in_cache( + self.get_cache_path(), + self.driver_name, + os, + arch_folder, + driver_version, + ) } fn get_config(&self) -> &ManagerConfig { diff --git a/rust/src/grid.rs b/rust/src/grid.rs index a86c4d28190d8..360ed103ac5c7 100644 --- a/rust/src/grid.rs +++ b/rust/src/grid.rs @@ -21,7 +21,7 @@ use std::collections::HashMap; use std::error::Error; use std::path::PathBuf; -use crate::files::{get_cache_folder, BrowserPath}; +use crate::files::BrowserPath; use crate::downloads::parse_json_from_url; use crate::{ @@ -97,7 +97,7 @@ impl SeleniumManager for GridManager { 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()); + let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()); match get_driver_version_from_metadata( &metadata.drivers, @@ -156,7 +156,7 @@ impl SeleniumManager for GridManager { &driver_version, driver_ttl, )); - write_metadata(&metadata, self.get_logger()); + write_metadata(&metadata, self.get_logger(), self.get_cache_path()); } Ok(driver_version) @@ -191,7 +191,7 @@ impl SeleniumManager for GridManager { let browser_name = self.get_browser_name(); let driver_name = self.get_driver_name(); let driver_version = self.get_driver_version(); - get_cache_folder() + self.get_cache_path() .join(browser_name) .join(driver_version) .join(format!("{driver_name}-{driver_version}.{GRID_EXTENSION}")) diff --git a/rust/src/iexplorer.rs b/rust/src/iexplorer.rs index d73759f09d41c..34941c3ad1ff3 100644 --- a/rust/src/iexplorer.rs +++ b/rust/src/iexplorer.rs @@ -109,7 +109,7 @@ impl SeleniumManager for IExplorerManager { 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()); + let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()); match get_driver_version_from_metadata( &metadata.drivers, @@ -164,7 +164,7 @@ impl SeleniumManager for IExplorerManager { &driver_version, driver_ttl, )); - write_metadata(&metadata, self.get_logger()); + write_metadata(&metadata, self.get_logger(), self.get_cache_path()); } Ok(driver_version) @@ -201,7 +201,13 @@ impl SeleniumManager for IExplorerManager { .unwrap_or_default() .parse::() .unwrap_or_default(); - compose_driver_path_in_cache(self.driver_name, "Windows", "win32", driver_version) + compose_driver_path_in_cache( + self.get_cache_path(), + self.driver_name, + "Windows", + "win32", + driver_version, + ) } fn get_config(&self) -> &ManagerConfig { diff --git a/rust/src/lib.rs b/rust/src/lib.rs index e247e9907f4c4..045fa6586bcf6 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -18,8 +18,8 @@ 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, - path_buf_to_string, + create_parent_path_if_not_exists, create_path_if_not_exists, default_cache_folder, + get_binary_extension, path_buf_to_string, }; use crate::firefox::{FirefoxManager, FIREFOX_NAME, GECKODRIVER_NAME}; use crate::iexplorer::{IExplorerManager, IEDRIVER_NAME, IE_NAMES}; @@ -853,6 +853,19 @@ pub trait SeleniumManager { self.get_config_mut().force_browser_download = true; } } + + fn get_cache_path(&self) -> PathBuf { + 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()); + Path::new(&canon_path).to_path_buf() + } + + fn set_cache_path(&mut self, cache_path: String) { + if !cache_path.is_empty() { + self.get_config_mut().cache_path = cache_path; + } + } } // ---------------------------------------------------------- @@ -904,8 +917,7 @@ pub fn get_manager_by_driver( } } -pub fn clear_cache(log: &Logger) { - let cache_path = compose_cache_folder(); +pub fn clear_cache(log: &Logger, cache_path: PathBuf) { if cache_path.exists() { log.debug(format!("Clearing cache at: {}", cache_path.display())); fs::remove_dir_all(&cache_path).unwrap_or_else(|err| { diff --git a/rust/src/main.rs b/rust/src/main.rs index 5b9c68de916e6..eee06039209fb 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -22,7 +22,7 @@ use clap::Parser; use exitcode::DATAERR; use exitcode::OK; use exitcode::UNAVAILABLE; -use selenium_manager::config::BooleanKey; +use selenium_manager::config::{BooleanKey, StringKey, CACHE_PATH_KEY}; use selenium_manager::grid::GridManager; use selenium_manager::logger::{Logger, BROWSER_PATH, DRIVER_PATH}; use selenium_manager::REQUEST_TIMEOUT_SEC; @@ -96,6 +96,11 @@ struct Cli { #[clap(long, value_parser, default_value_t = TTL_BROWSERS_SEC)] browser_ttl: u64, + /// Local folder used to store downloaded assets (drivers and browsers), local metadata, + /// and configuration file [default: ~/.cache/selenium] + #[clap(long, value_parser)] + cache_path: Option, + /// Clear cache folder (~/.cache/selenium) #[clap(long)] clear_cache: bool, @@ -123,19 +128,12 @@ struct Cli { fn main() { let cli = Cli::parse(); + let cache_path = + StringKey(vec![CACHE_PATH_KEY], &cli.cache_path.unwrap_or_default()).get_value(); let debug = cli.debug || BooleanKey("debug", false).get_value(); let trace = cli.trace || BooleanKey("trace", false).get_value(); let log = Logger::create(&cli.output, debug, trace); let grid = cli.grid; - - if cli.clear_cache || BooleanKey("clear-cache", false).get_value() { - clear_cache(&log); - } - - if cli.clear_metadata || BooleanKey("clear-metadata", false).get_value() { - clear_metadata(&log); - } - let browser_name: String = cli.browser.unwrap_or_default(); let driver_name: String = cli.driver.unwrap_or_default(); @@ -169,6 +167,20 @@ fn main() { selenium_manager.set_browser_ttl(cli.browser_ttl); selenium_manager.set_offline(cli.offline); selenium_manager.set_force_browser_download(cli.force_browser_download); + selenium_manager.set_cache_path(cache_path.clone()); + + if cli.clear_cache || BooleanKey("clear-cache", false).get_value() { + clear_cache( + selenium_manager.get_logger(), + selenium_manager.get_cache_path(), + ); + } + if cli.clear_metadata || BooleanKey("clear-metadata", false).get_value() { + clear_metadata( + selenium_manager.get_logger(), + selenium_manager.get_cache_path(), + ); + } selenium_manager .set_timeout(cli.timeout) diff --git a/rust/src/metadata.rs b/rust/src/metadata.rs index 2342923b0f6ed..5dbb1aa25d5d2 100644 --- a/rust/src/metadata.rs +++ b/rust/src/metadata.rs @@ -23,7 +23,6 @@ use std::time::{SystemTime, UNIX_EPOCH}; use serde::{Deserialize, Serialize}; -use crate::files::get_cache_folder; use crate::Logger; const METADATA_FILE: &str = "selenium-manager.json"; @@ -50,8 +49,8 @@ pub struct Metadata { pub drivers: Vec, } -fn get_metadata_path() -> PathBuf { - get_cache_folder().join(METADATA_FILE) +fn get_metadata_path(cache_path: PathBuf) -> PathBuf { + cache_path.join(METADATA_FILE) } pub fn now_unix_timestamp() -> u64 { @@ -69,8 +68,8 @@ fn new_metadata(log: &Logger) -> Metadata { } } -pub fn get_metadata(log: &Logger) -> Metadata { - let metadata_path = get_metadata_path(); +pub fn get_metadata(log: &Logger, cache_path: PathBuf) -> Metadata { + let metadata_path = get_metadata_path(cache_path); log.trace(format!("Reading metadata from {}", metadata_path.display())); if metadata_path.exists() { @@ -154,8 +153,8 @@ pub fn create_driver_metadata( } } -pub fn write_metadata(metadata: &Metadata, log: &Logger) { - let metadata_path = get_metadata_path(); +pub fn write_metadata(metadata: &Metadata, log: &Logger, cache_path: PathBuf) { + let metadata_path = get_metadata_path(cache_path); log.trace(format!("Writing metadata to {}", metadata_path.display())); fs::write( metadata_path, @@ -164,8 +163,8 @@ pub fn write_metadata(metadata: &Metadata, log: &Logger) { .unwrap(); } -pub fn clear_metadata(log: &Logger) { - let metadata_path = get_metadata_path(); +pub fn clear_metadata(log: &Logger, cache_path: PathBuf) { + let metadata_path = get_metadata_path(cache_path); log.debug(format!( "Deleting metadata file {}", metadata_path.display() diff --git a/rust/tests/cache_tests.rs b/rust/tests/cache_tests.rs new file mode 100644 index 0000000000000..22e45e8ff730d --- /dev/null +++ b/rust/tests/cache_tests.rs @@ -0,0 +1,48 @@ +// Licensed to the Software Freedom Conservancy (SFC) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The SFC licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +use crate::common::get_driver_path; +use assert_cmd::Command; +use std::fs; +use std::path::Path; + +mod common; + +#[test] +fn cache_path_test() { + let mut cmd = Command::new(env!("CARGO_BIN_EXE_selenium-manager")); + let tmp_cache_folder_name = "../tmp"; + cmd.args([ + "--browser", + "chrome", + "--cache-path", + tmp_cache_folder_name, + "--output", + "json", + ]) + .assert() + .success() + .code(0); + + let driver_path = get_driver_path(&mut cmd); + println!("*** Custom cache path: {}", driver_path); + assert!(!driver_path.contains("cache")); + + let tmp_cache_path = Path::new(tmp_cache_folder_name); + fs::remove_dir_all(&tmp_cache_path).unwrap(); + assert!(!tmp_cache_path.exists()); +} diff --git a/rust/tests/common.rs b/rust/tests/common.rs index 6fcd074e6b710..916e548c2b4d3 100644 --- a/rust/tests/common.rs +++ b/rust/tests/common.rs @@ -16,14 +16,17 @@ // under the License. use assert_cmd::Command; +use std::borrow::BorrowMut; use std::env::consts::OS; use std::path::Path; use is_executable::is_executable; +use selenium_manager::files::path_buf_to_string; use selenium_manager::logger::JsonOutput; use selenium_manager::shell; use selenium_manager::shell::run_shell_command_by_os; +#[allow(dead_code)] pub fn assert_driver(cmd: &mut Command) { let stdout = &cmd.unwrap().stdout; let output = std::str::from_utf8(stdout).unwrap(); @@ -35,6 +38,7 @@ pub fn assert_driver(cmd: &mut Command) { assert!(is_executable(driver_path)); } +#[allow(dead_code)] pub fn assert_browser(cmd: &mut Command) { let stdout = &cmd.unwrap().stdout; let output = std::str::from_utf8(stdout).unwrap(); @@ -45,14 +49,18 @@ pub fn assert_browser(cmd: &mut Command) { } #[allow(dead_code)] -pub fn exec_driver(cmd: &mut Command) -> String { +pub fn get_driver_path(cmd: &mut Command) -> String { let stdout = &cmd.unwrap().stdout; let output = std::str::from_utf8(stdout).unwrap(); let json: JsonOutput = serde_json::from_str(output).unwrap(); - let driver_path = Path::new(&json.result.driver_path); + path_buf_to_string(Path::new(&json.result.driver_path).to_path_buf()) +} - let driver_version_command = - shell::Command::new_single(format!("{} --version", driver_path.to_str().unwrap())); +#[allow(dead_code)] +pub fn exec_driver(cmd: &mut Command) -> String { + let mut cmd_mut = cmd.borrow_mut(); + let driver_path = get_driver_path(&mut cmd_mut); + let driver_version_command = shell::Command::new_single(format!("{} --version", &driver_path)); let output = run_shell_command_by_os(OS, driver_version_command).unwrap(); println!("**** EXEC DRIVER: {}", output); output From 694f67e3858a50e3f8a6f8d1139f6e25fef82735 Mon Sep 17 00:00:00 2001 From: Boni Garcia Date: Mon, 7 Aug 2023 20:19:19 +0200 Subject: [PATCH 2/3] [rust] Enhance assertion in cache test --- rust/tests/cache_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/tests/cache_tests.rs b/rust/tests/cache_tests.rs index 22e45e8ff730d..54371fe9fd4da 100644 --- a/rust/tests/cache_tests.rs +++ b/rust/tests/cache_tests.rs @@ -40,7 +40,7 @@ fn cache_path_test() { let driver_path = get_driver_path(&mut cmd); println!("*** Custom cache path: {}", driver_path); - assert!(!driver_path.contains("cache")); + assert!(!driver_path.contains(r#"cache\selenium"#)); let tmp_cache_path = Path::new(tmp_cache_folder_name); fs::remove_dir_all(&tmp_cache_path).unwrap(); From f4fa3fad8ca68713b13c6e03384baa905ae6a664 Mon Sep 17 00:00:00 2001 From: Boni Garcia Date: Tue, 8 Aug 2023 03:04:34 +0200 Subject: [PATCH 3/3] [rust] Avoid unwrap when creating cache path --- rust/src/chrome.rs | 39 ++++++++++++++++++++------------------- rust/src/edge.rs | 12 ++++++------ rust/src/files.rs | 14 ++++++++------ rust/src/firefox.rs | 12 ++++++------ rust/src/grid.rs | 11 ++++++----- rust/src/iexplorer.rs | 12 ++++++------ rust/src/lib.rs | 23 ++++++++++++----------- rust/src/main.rs | 20 ++++++++++---------- rust/src/metadata.rs | 5 +++-- rust/src/safari.rs | 4 ++-- rust/src/safaritp.rs | 6 ++++-- 11 files changed, 83 insertions(+), 75 deletions(-) diff --git a/rust/src/chrome.rs b/rust/src/chrome.rs index 8ef5e52409b97..e4183d8fc8cf3 100644 --- a/rust/src/chrome.rs +++ b/rust/src/chrome.rs @@ -312,19 +312,20 @@ impl ChromeManager { } } - fn get_browser_path_in_cache(&self) -> PathBuf { - self.get_cache_path() + fn get_browser_path_in_cache(&self) -> Result> { + Ok(self + .get_cache_path()? .join(self.get_browser_name()) .join(self.get_platform_label()) - .join(self.get_browser_version()) + .join(self.get_browser_version())) } - fn get_browser_binary_path_in_cache(&self) -> PathBuf { - let browser_in_cache = self.get_browser_path_in_cache(); + 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()) { - browser_in_cache.join(CFT_MACOS_APP_NAME) + Ok(browser_in_cache.join(CFT_MACOS_APP_NAME)) } else { - browser_in_cache.join(self.get_browser_name_with_extension()) + Ok(browser_in_cache.join(self.get_browser_name_with_extension())) } } } @@ -400,7 +401,7 @@ impl SeleniumManager for ChromeManager { 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()); + let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()?); match get_driver_version_from_metadata( &metadata.drivers, @@ -445,7 +446,7 @@ impl SeleniumManager for ChromeManager { &driver_version, driver_ttl, )); - write_metadata(&metadata, self.get_logger(), self.get_cache_path()); + write_metadata(&metadata, self.get_logger(), self.get_cache_path()?); } Ok(driver_version) } @@ -456,7 +457,7 @@ impl SeleniumManager for ChromeManager { let browser_name = self.browser_name; let browser_version; let major_browser_version = self.get_major_browser_version(); - let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()); + let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()?); // First, browser version is checked in the local metadata match get_browser_version_from_metadata( @@ -484,7 +485,7 @@ impl SeleniumManager for ChromeManager { &browser_version, browser_ttl, )); - write_metadata(&metadata, self.get_logger(), self.get_cache_path()); + write_metadata(&metadata, self.get_logger(), self.get_cache_path()?); } } } @@ -534,17 +535,17 @@ impl SeleniumManager for ChromeManager { )) } - fn get_driver_path_in_cache(&self) -> PathBuf { + fn get_driver_path_in_cache(&self) -> Result> { let driver_version = self.get_driver_version(); let os = self.get_os(); let arch_folder = self.get_platform_label(); - compose_driver_path_in_cache( - self.get_cache_path(), + Ok(compose_driver_path_in_cache( + self.get_cache_path()?, self.driver_name, os, arch_folder, driver_version, - ) + )) } fn get_config(&self) -> &ManagerConfig { @@ -570,7 +571,7 @@ impl SeleniumManager for ChromeManager { fn download_browser(&mut self) -> Result, Box> { let browser_version; let browser_name = self.browser_name; - let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()); + let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()?); let major_browser_version = self.get_major_browser_version(); let major_browser_version_int = major_browser_version.parse::().unwrap_or_default(); @@ -622,7 +623,7 @@ impl SeleniumManager for ChromeManager { &browser_version, browser_ttl, )); - write_metadata(&metadata, self.get_logger(), self.get_cache_path()); + write_metadata(&metadata, self.get_logger(), self.get_cache_path()?); } } } @@ -632,7 +633,7 @@ impl SeleniumManager for ChromeManager { )); // Checking if browser version is in the cache - let browser_binary_path = self.get_browser_binary_path_in_cache(); + let browser_binary_path = self.get_browser_binary_path_in_cache()?; if browser_binary_path.exists() { self.get_logger().debug(format!( "{} {} already in the cache", @@ -661,7 +662,7 @@ impl SeleniumManager for ChromeManager { uncompress( &driver_zip_file, - &self.get_browser_path_in_cache(), + &self.get_browser_path_in_cache()?, self.get_logger(), None, )?; diff --git a/rust/src/edge.rs b/rust/src/edge.rs index 31677edbbee3d..651c14278bf0f 100644 --- a/rust/src/edge.rs +++ b/rust/src/edge.rs @@ -134,7 +134,7 @@ impl SeleniumManager for EdgeManager { 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()); + let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()?); match get_driver_version_from_metadata( &metadata.drivers, @@ -191,7 +191,7 @@ impl SeleniumManager for EdgeManager { &driver_version, driver_ttl, )); - write_metadata(&metadata, self.get_logger(), self.get_cache_path()); + write_metadata(&metadata, self.get_logger(), self.get_cache_path()?); } Ok(driver_version) @@ -230,7 +230,7 @@ impl SeleniumManager for EdgeManager { )) } - fn get_driver_path_in_cache(&self) -> PathBuf { + fn get_driver_path_in_cache(&self) -> Result> { let driver_version = self.get_driver_version(); let os = self.get_os(); let arch = self.get_arch(); @@ -251,13 +251,13 @@ impl SeleniumManager for EdgeManager { } else { "linux64" }; - compose_driver_path_in_cache( - self.get_cache_path(), + Ok(compose_driver_path_in_cache( + self.get_cache_path()?, self.driver_name, os, arch_folder, driver_version, - ) + )) } fn get_config(&self) -> &ManagerConfig { diff --git a/rust/src/files.rs b/rust/src/files.rs index c6ac40feff04c..51b46172c63eb 100644 --- a/rust/src/files.rs +++ b/rust/src/files.rs @@ -54,16 +54,18 @@ impl BrowserPath { } } -pub fn create_parent_path_if_not_exists(path: &Path) { +pub fn create_parent_path_if_not_exists(path: &Path) -> Result<(), Box> { if let Some(p) = path.parent() { - create_path_if_not_exists(p); + create_path_if_not_exists(p)?; } + Ok(()) } -pub fn create_path_if_not_exists(path: &Path) { +pub fn create_path_if_not_exists(path: &Path) -> Result<(), Box> { if !path.exists() { - fs::create_dir_all(path).unwrap(); + fs::create_dir_all(path)?; } + Ok(()) } pub fn uncompress( @@ -132,7 +134,7 @@ pub fn unzip( None => continue, }; if single_file.is_none() { - create_path_if_not_exists(target); + create_path_if_not_exists(target)?; out_path = target.join(path); } @@ -148,7 +150,7 @@ pub fn unzip( out_path.display(), file.size() )); - create_parent_path_if_not_exists(out_path.as_path()); + create_parent_path_if_not_exists(out_path.as_path())?; let mut outfile = File::create(&out_path)?; io::copy(&mut file, &mut outfile)?; diff --git a/rust/src/firefox.rs b/rust/src/firefox.rs index 8726e0a6d0a61..1659628f4efbb 100644 --- a/rust/src/firefox.rs +++ b/rust/src/firefox.rs @@ -132,7 +132,7 @@ impl SeleniumManager for FirefoxManager { 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()); + let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()?); match get_driver_version_from_metadata( &metadata.drivers, @@ -161,7 +161,7 @@ impl SeleniumManager for FirefoxManager { &driver_version, driver_ttl, )); - write_metadata(&metadata, self.get_logger(), self.get_cache_path()); + write_metadata(&metadata, self.get_logger(), self.get_cache_path()?); } Ok(driver_version) @@ -211,7 +211,7 @@ impl SeleniumManager for FirefoxManager { )) } - fn get_driver_path_in_cache(&self) -> PathBuf { + fn get_driver_path_in_cache(&self) -> Result> { let driver_version = self.get_driver_version(); let os = self.get_os(); let arch = self.get_arch(); @@ -241,13 +241,13 @@ impl SeleniumManager for FirefoxManager { } else { "linux64" }; - compose_driver_path_in_cache( - self.get_cache_path(), + Ok(compose_driver_path_in_cache( + self.get_cache_path()?, self.driver_name, os, arch_folder, driver_version, - ) + )) } fn get_config(&self) -> &ManagerConfig { diff --git a/rust/src/grid.rs b/rust/src/grid.rs index 360ed103ac5c7..6f477f9cc817d 100644 --- a/rust/src/grid.rs +++ b/rust/src/grid.rs @@ -97,7 +97,7 @@ impl SeleniumManager for GridManager { 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()); + let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()?); match get_driver_version_from_metadata( &metadata.drivers, @@ -156,7 +156,7 @@ impl SeleniumManager for GridManager { &driver_version, driver_ttl, )); - write_metadata(&metadata, self.get_logger(), self.get_cache_path()); + write_metadata(&metadata, self.get_logger(), self.get_cache_path()?); } Ok(driver_version) @@ -187,14 +187,15 @@ impl SeleniumManager for GridManager { )) } - fn get_driver_path_in_cache(&self) -> PathBuf { + 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(); - self.get_cache_path() + Ok(self + .get_cache_path()? .join(browser_name) .join(driver_version) - .join(format!("{driver_name}-{driver_version}.{GRID_EXTENSION}")) + .join(format!("{driver_name}-{driver_version}.{GRID_EXTENSION}"))) } fn get_config(&self) -> &ManagerConfig { diff --git a/rust/src/iexplorer.rs b/rust/src/iexplorer.rs index 34941c3ad1ff3..5a73176fa81c9 100644 --- a/rust/src/iexplorer.rs +++ b/rust/src/iexplorer.rs @@ -109,7 +109,7 @@ impl SeleniumManager for IExplorerManager { 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()); + let mut metadata = get_metadata(self.get_logger(), self.get_cache_path()?); match get_driver_version_from_metadata( &metadata.drivers, @@ -164,7 +164,7 @@ impl SeleniumManager for IExplorerManager { &driver_version, driver_ttl, )); - write_metadata(&metadata, self.get_logger(), self.get_cache_path()); + write_metadata(&metadata, self.get_logger(), self.get_cache_path()?); } Ok(driver_version) @@ -194,20 +194,20 @@ impl SeleniumManager for IExplorerManager { )) } - fn get_driver_path_in_cache(&self) -> PathBuf { + fn get_driver_path_in_cache(&self) -> Result> { let driver_version = self.get_driver_version(); let _minor_driver_version = self .get_minor_version(driver_version) .unwrap_or_default() .parse::() .unwrap_or_default(); - compose_driver_path_in_cache( - self.get_cache_path(), + Ok(compose_driver_path_in_cache( + self.get_cache_path()?, self.driver_name, "Windows", "win32", driver_version, - ) + )) } fn get_config(&self) -> &ManagerConfig { diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 045fa6586bcf6..becc2657ec9ef 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -118,7 +118,7 @@ pub trait SeleniumManager { fn get_driver_url(&mut self) -> Result>; - fn get_driver_path_in_cache(&self) -> PathBuf; + fn get_driver_path_in_cache(&self) -> Result>; fn get_config(&self) -> &ManagerConfig; @@ -144,18 +144,18 @@ pub trait SeleniumManager { download_to_tmp_folder(self.get_http_client(), driver_url, self.get_logger())?; if self.is_grid() { - let driver_path_in_cache = Self::get_driver_path_in_cache(self); - create_parent_path_if_not_exists(&driver_path_in_cache); + let driver_path_in_cache = self.get_driver_path_in_cache()?; + create_parent_path_if_not_exists(&driver_path_in_cache)?; Ok(fs::rename(driver_zip_file, driver_path_in_cache)?) } else { - let driver_path_in_cache = Self::get_driver_path_in_cache(self); + let driver_path_in_cache = self.get_driver_path_in_cache()?; let driver_name_with_extension = self.get_driver_name_with_extension(); - uncompress( + Ok(uncompress( &driver_zip_file, &driver_path_in_cache, self.get_logger(), Some(driver_name_with_extension), - ) + )?) } } @@ -525,7 +525,7 @@ pub trait SeleniumManager { } // If driver was not in the PATH, try to find it in the cache - let driver_path = self.get_driver_path_in_cache(); + let driver_path = self.get_driver_path_in_cache()?; if driver_path.exists() { if !self.is_safari() { self.get_logger().debug(format!( @@ -854,11 +854,11 @@ pub trait SeleniumManager { } } - fn get_cache_path(&self) -> PathBuf { + fn get_cache_path(&self) -> Result> { let path = Path::new(&self.get_config().cache_path); - create_path_if_not_exists(path); + create_path_if_not_exists(path)?; let canon_path = self.canonicalize_path(path.to_path_buf()); - Path::new(&canon_path).to_path_buf() + Ok(Path::new(&canon_path).to_path_buf()) } fn set_cache_path(&mut self, cache_path: String) { @@ -917,7 +917,8 @@ pub fn get_manager_by_driver( } } -pub fn clear_cache(log: &Logger, cache_path: PathBuf) { +pub fn clear_cache(log: &Logger, path: &str) { + let cache_path = Path::new(path).to_path_buf(); if cache_path.exists() { log.debug(format!("Clearing cache at: {}", cache_path.display())); fs::remove_dir_all(&cache_path).unwrap_or_else(|err| { diff --git a/rust/src/main.rs b/rust/src/main.rs index eee06039209fb..45309fe0cb53d 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -23,6 +23,7 @@ use exitcode::DATAERR; use exitcode::OK; use exitcode::UNAVAILABLE; use selenium_manager::config::{BooleanKey, StringKey, CACHE_PATH_KEY}; +use selenium_manager::files::{default_cache_folder, path_buf_to_string}; use selenium_manager::grid::GridManager; use selenium_manager::logger::{Logger, BROWSER_PATH, DRIVER_PATH}; use selenium_manager::REQUEST_TIMEOUT_SEC; @@ -128,8 +129,13 @@ struct Cli { fn main() { let cli = Cli::parse(); - let cache_path = - StringKey(vec![CACHE_PATH_KEY], &cli.cache_path.unwrap_or_default()).get_value(); + + let default_cache_path = path_buf_to_string(default_cache_folder()); + let cache_path = StringKey( + vec![CACHE_PATH_KEY], + &cli.cache_path.unwrap_or(default_cache_path), + ) + .get_value(); let debug = cli.debug || BooleanKey("debug", false).get_value(); let trace = cli.trace || BooleanKey("trace", false).get_value(); let log = Logger::create(&cli.output, debug, trace); @@ -170,16 +176,10 @@ fn main() { selenium_manager.set_cache_path(cache_path.clone()); if cli.clear_cache || BooleanKey("clear-cache", false).get_value() { - clear_cache( - selenium_manager.get_logger(), - selenium_manager.get_cache_path(), - ); + clear_cache(selenium_manager.get_logger(), &cache_path); } if cli.clear_metadata || BooleanKey("clear-metadata", false).get_value() { - clear_metadata( - selenium_manager.get_logger(), - selenium_manager.get_cache_path(), - ); + clear_metadata(selenium_manager.get_logger(), &cache_path); } selenium_manager diff --git a/rust/src/metadata.rs b/rust/src/metadata.rs index 5dbb1aa25d5d2..4541b648bb7c6 100644 --- a/rust/src/metadata.rs +++ b/rust/src/metadata.rs @@ -18,7 +18,7 @@ use std::fs; use std::fs::File; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::time::{SystemTime, UNIX_EPOCH}; use serde::{Deserialize, Serialize}; @@ -163,7 +163,8 @@ pub fn write_metadata(metadata: &Metadata, log: &Logger, cache_path: PathBuf) { .unwrap(); } -pub fn clear_metadata(log: &Logger, cache_path: PathBuf) { +pub fn clear_metadata(log: &Logger, path: &str) { + let cache_path = Path::new(path).to_path_buf(); let metadata_path = get_metadata_path(cache_path); log.debug(format!( "Deleting metadata file {}", diff --git a/rust/src/safari.rs b/rust/src/safari.rs index f5170e235ee5a..5b44f6d0afe1d 100644 --- a/rust/src/safari.rs +++ b/rust/src/safari.rs @@ -94,8 +94,8 @@ impl SeleniumManager for SafariManager { Err(format!("{} not available for download", self.get_driver_name()).into()) } - fn get_driver_path_in_cache(&self) -> PathBuf { - PathBuf::from("/usr/bin/safaridriver") + fn get_driver_path_in_cache(&self) -> Result> { + Ok(PathBuf::from("/usr/bin/safaridriver")) } fn get_config(&self) -> &ManagerConfig { diff --git a/rust/src/safaritp.rs b/rust/src/safaritp.rs index 2163f7e3049ad..6c3606bc1e755 100644 --- a/rust/src/safaritp.rs +++ b/rust/src/safaritp.rs @@ -100,8 +100,10 @@ impl SeleniumManager for SafariTPManager { Err(format!("{} not available for download", self.get_driver_name()).into()) } - fn get_driver_path_in_cache(&self) -> PathBuf { - PathBuf::from("/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver") + fn get_driver_path_in_cache(&self) -> Result> { + Ok(PathBuf::from( + "/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver", + )) } fn get_config(&self) -> &ManagerConfig {