Skip to content

Commit 1668d6d

Browse files
committed
[rust] Refactor shell functions in a separate module
1 parent 2c1ae5a commit 1668d6d

File tree

3 files changed

+103
-65
lines changed

3 files changed

+103
-65
lines changed

rust/src/config.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717

1818
use crate::config::OS::{LINUX, MACOS, WINDOWS};
1919
use crate::files::get_cache_folder;
20-
use crate::{format_one_arg, run_shell_command_by_os, REQUEST_TIMEOUT_SEC, UNAME_COMMAND};
20+
use crate::shell::run_shell_command_by_os;
21+
use crate::{format_one_arg, REQUEST_TIMEOUT_SEC, UNAME_COMMAND};
2122
use crate::{ARCH_AMD64, ARCH_ARM64, ARCH_X86, TTL_BROWSERS_SEC, TTL_DRIVERS_SEC, WMIC_COMMAND_OS};
2223
use std::env;
2324
use std::env::consts::OS;
@@ -50,7 +51,7 @@ impl ManagerConfig {
5051
let self_os = OS;
5152
let self_arch = if WINDOWS.is(self_os) {
5253
let wmic_output =
53-
run_shell_command_by_os(self_os, WMIC_COMMAND_OS.to_string()).unwrap_or_default();
54+
run_shell_command_by_os(self_os, vec![WMIC_COMMAND_OS]).unwrap_or_default();
5455
if wmic_output.contains("32") {
5556
ARCH_X86.to_string()
5657
} else if wmic_output.contains("ARM") {
@@ -60,15 +61,15 @@ impl ManagerConfig {
6061
}
6162
} else {
6263
let uname_a = format_one_arg(UNAME_COMMAND, "a");
63-
if run_shell_command_by_os(self_os, uname_a)
64+
if run_shell_command_by_os(self_os, vec![&uname_a])
6465
.unwrap_or_default()
6566
.to_ascii_lowercase()
6667
.contains(ARCH_ARM64)
6768
{
6869
ARCH_ARM64.to_string()
6970
} else {
7071
let uname_m = format_one_arg(UNAME_COMMAND, "m");
71-
run_shell_command_by_os(self_os, uname_m).unwrap_or_default()
72+
run_shell_command_by_os(self_os, vec![&uname_m]).unwrap_or_default()
7273
}
7374
};
7475

rust/src/lib.rs

Lines changed: 23 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ use reqwest::{Client, Proxy};
3030
use std::collections::HashMap;
3131
use std::error::Error;
3232
use std::path::{Path, PathBuf};
33-
use std::process::Command;
3433
use std::time::Duration;
3534

3635
use crate::downloads::download_to_tmp_folder;
@@ -39,6 +38,7 @@ use crate::grid::GRID_NAME;
3938
use crate::logger::Logger;
4039
use crate::metadata::{create_browser_metadata, get_browser_version_from_metadata};
4140
use crate::safaritp::{SafariTPManager, SAFARITP_NAMES};
41+
use crate::shell::{run_shell_command, run_shell_command_with_log, split_lines};
4242

4343
pub mod chrome;
4444
pub mod config;
@@ -53,6 +53,7 @@ pub mod metadata;
5353
pub mod mirror;
5454
pub mod safari;
5555
pub mod safaritp;
56+
pub mod shell;
5657

5758
pub const REQUEST_TIMEOUT_SEC: u64 = 300; // The timeout is applied from when the request starts connecting until the response body has finished
5859
pub const STABLE: &str = "stable";
@@ -84,8 +85,6 @@ pub const TTL_BROWSERS_SEC: u64 = 3600;
8485
pub const TTL_DRIVERS_SEC: u64 = 3600;
8586
pub const UNAME_COMMAND: &str = "uname -{}";
8687
pub const ESCAPE_COMMAND: &str = "printf %q \"{}\"";
87-
pub const CRLF: &str = "\r\n";
88-
pub const LF: &str = "\n";
8988
pub const SNAPSHOT: &str = "SNAPSHOT";
9089
pub const OFFLINE_REQUEST_ERR_MSG: &str = "Unable to discover proper {} version in offline mode";
9190
pub const OFFLINE_DOWNLOAD_ERR_MSG: &str = "Unable to download {} in offline mode";
@@ -227,10 +226,11 @@ pub trait SeleniumManager {
227226
));
228227
let mut browser_version: Option<String> = None;
229228
for command in commands.iter() {
230-
let output = match self.run_shell_command_with_log(command.to_string()) {
231-
Ok(out) => out,
232-
Err(_e) => continue,
233-
};
229+
let output =
230+
match run_shell_command_with_log(self.get_logger(), self.get_os(), vec![command]) {
231+
Ok(out) => out,
232+
Err(_e) => continue,
233+
};
234234
let full_browser_version = parse_version(output, self.get_logger()).unwrap_or_default();
235235
if full_browser_version.is_empty() {
236236
continue;
@@ -357,12 +357,16 @@ pub trait SeleniumManager {
357357
}
358358

359359
fn find_driver_in_path(&self) -> (Option<String>, Option<String>) {
360-
match self.run_shell_command_with_log(format_three_args(
361-
DASH_DASH_VERSION,
362-
self.get_driver_name(),
363-
"",
364-
"",
365-
)) {
360+
match run_shell_command_with_log(
361+
self.get_logger(),
362+
self.get_os(),
363+
vec![&format_three_args(
364+
DASH_DASH_VERSION,
365+
self.get_driver_name(),
366+
"",
367+
"",
368+
)],
369+
) {
366370
Ok(output) => {
367371
let parsed_version = parse_version(output, self.get_logger()).unwrap_or_default();
368372
if !parsed_version.is_empty() {
@@ -381,7 +385,11 @@ pub trait SeleniumManager {
381385
} else {
382386
WHICH_COMMAND
383387
};
384-
let path = match self.run_shell_command_with_log(format_one_arg(which_command, command)) {
388+
let path = match run_shell_command_with_log(
389+
self.get_logger(),
390+
self.get_os(),
391+
vec![&format_one_arg(which_command, command)],
392+
) {
385393
Ok(path) => {
386394
let path_vector = split_lines(path.as_str());
387395
if path_vector.len() == 1 {
@@ -529,14 +537,6 @@ pub trait SeleniumManager {
529537
Ok(driver_path)
530538
}
531539

532-
fn run_shell_command_with_log(&self, command: String) -> Result<String, Box<dyn Error>> {
533-
self.get_logger()
534-
.debug(format!("Running command: {}", command));
535-
let output = run_shell_command_by_os(self.get_os(), command)?;
536-
self.get_logger().debug(format!("Output: {:?}", output));
537-
Ok(output)
538-
}
539-
540540
fn get_major_version(&self, full_version: &str) -> Result<String, Box<dyn Error>> {
541541
get_index_version(full_version, 0)
542542
}
@@ -683,7 +683,7 @@ pub trait SeleniumManager {
683683
escaped_path = run_shell_command(
684684
"bash",
685685
"-c",
686-
format_one_arg(ESCAPE_COMMAND, escaped_path.as_str()),
686+
vec![format_one_arg(ESCAPE_COMMAND, escaped_path.as_str()).as_str()],
687687
)
688688
.unwrap_or_default();
689689
if escaped_path.is_empty() {
@@ -844,29 +844,6 @@ pub fn create_http_client(timeout: u64, proxy: &str) -> Result<Client, Box<dyn E
844844
Ok(client_builder.build().unwrap_or_default())
845845
}
846846

847-
pub fn run_shell_command(
848-
shell: &str,
849-
flag: &str,
850-
command: String,
851-
) -> Result<String, Box<dyn Error>> {
852-
let output = Command::new(shell)
853-
.args([flag, command.as_str()])
854-
.output()?;
855-
Ok(
856-
strip_trailing_newline(String::from_utf8_lossy(&output.stdout).to_string().as_str())
857-
.to_string(),
858-
)
859-
}
860-
861-
pub fn run_shell_command_by_os(os: &str, command: String) -> Result<String, Box<dyn Error>> {
862-
let (shell, flag) = if WINDOWS.is(os) {
863-
("cmd", "/c")
864-
} else {
865-
("sh", "-c")
866-
};
867-
run_shell_command(shell, flag, command)
868-
}
869-
870847
pub fn format_one_arg(string: &str, arg1: &str) -> String {
871848
string.replacen("{}", arg1, 1)
872849
}
@@ -893,18 +870,3 @@ fn get_index_version(full_version: &str, index: usize) -> Result<String, Box<dyn
893870
.ok_or(format!("Wrong version: {}", full_version))?
894871
.to_string())
895872
}
896-
897-
fn strip_trailing_newline(input: &str) -> &str {
898-
input
899-
.strip_suffix(CRLF)
900-
.or_else(|| input.strip_suffix(LF))
901-
.unwrap_or(input)
902-
}
903-
904-
fn split_lines(string: &str) -> Vec<&str> {
905-
if string.contains(CRLF) {
906-
string.split(CRLF).collect()
907-
} else {
908-
string.split(LF).collect()
909-
}
910-
}

rust/src/shell.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
use crate::{Logger, WINDOWS};
19+
use std::error::Error;
20+
use std::process::Command;
21+
22+
pub const CRLF: &str = "\r\n";
23+
pub const LF: &str = "\n";
24+
25+
pub fn run_shell_command_with_log(
26+
log: &Logger,
27+
os: &str,
28+
args: Vec<&str>,
29+
) -> Result<String, Box<dyn Error>> {
30+
log.debug(format!("Running command: {:?}", args));
31+
let output = run_shell_command_by_os(os, args)?;
32+
log.debug(format!("Output: {:?}", output));
33+
Ok(output)
34+
}
35+
36+
pub fn run_shell_command_by_os(os: &str, args: Vec<&str>) -> Result<String, Box<dyn Error>> {
37+
let (shell, flag) = if WINDOWS.is(os) {
38+
("cmd", "/c")
39+
} else {
40+
("sh", "-c")
41+
};
42+
run_shell_command(shell, flag, args)
43+
}
44+
45+
pub fn run_shell_command(
46+
shell: &str,
47+
flag: &str,
48+
args: Vec<&str>,
49+
) -> Result<String, Box<dyn Error>> {
50+
let mut command = Command::new(shell);
51+
command.arg(flag);
52+
for arg in args.iter() {
53+
command.arg(arg);
54+
}
55+
let output = command.output()?;
56+
Ok(
57+
strip_trailing_newline(String::from_utf8_lossy(&output.stdout).to_string().as_str())
58+
.to_string(),
59+
)
60+
}
61+
62+
pub fn strip_trailing_newline(input: &str) -> &str {
63+
input
64+
.strip_suffix(CRLF)
65+
.or_else(|| input.strip_suffix(LF))
66+
.unwrap_or(input)
67+
}
68+
69+
pub fn split_lines(string: &str) -> Vec<&str> {
70+
if string.contains(CRLF) {
71+
string.split(CRLF).collect()
72+
} else {
73+
string.split(LF).collect()
74+
}
75+
}

0 commit comments

Comments
 (0)