diff options
Diffstat (limited to 'crates/shirabe/src/util')
| -rw-r--r-- | crates/shirabe/src/util/bitbucket.rs | 2 | ||||
| -rw-r--r-- | crates/shirabe/src/util/filesystem.rs | 11 | ||||
| -rw-r--r-- | crates/shirabe/src/util/git.rs | 41 | ||||
| -rw-r--r-- | crates/shirabe/src/util/perforce.rs | 64 | ||||
| -rw-r--r-- | crates/shirabe/src/util/process_executor.rs | 277 |
5 files changed, 142 insertions, 253 deletions
diff --git a/crates/shirabe/src/util/bitbucket.rs b/crates/shirabe/src/util/bitbucket.rs index d8e245a9..9a16c9a6 100644 --- a/crates/shirabe/src/util/bitbucket.rs +++ b/crates/shirabe/src/util/bitbucket.rs @@ -81,7 +81,7 @@ impl Bitbucket { .process .borrow_mut() .execute( - PhpMixed::from(vec!["git", "config", "bitbucket.accesstoken"]), + &["git", "config", "bitbucket.accesstoken"], &mut output, None, ) diff --git a/crates/shirabe/src/util/filesystem.rs b/crates/shirabe/src/util/filesystem.rs index 2395d1cd..8726df63 100644 --- a/crates/shirabe/src/util/filesystem.rs +++ b/crates/shirabe/src/util/filesystem.rs @@ -145,11 +145,7 @@ impl Filesystem { let mut output = PhpMixed::Null; let result = self .get_process() - .execute( - PhpMixed::List(cmd.iter().map(|s| PhpMixed::String(s.clone())).collect()), - &mut output, - None, - ) + .execute(&cmd, &mut output, None) .map(|n| n == 0) .unwrap_or(false); @@ -198,10 +194,7 @@ impl Filesystem { (fs.get_process_handle(), cmd) }; - let process_future = process_executor.borrow_mut().execute_async( - PhpMixed::List(cmd.iter().map(|s| PhpMixed::String(s.clone())).collect()), - None, - ); + let process_future = process_executor.borrow_mut().execute_async(&cmd, None); let mut process = process_future.await?; // clear stat cache because external processes aren't tracked by the php stat cache diff --git a/crates/shirabe/src/util/git.rs b/crates/shirabe/src/util/git.rs index 78c1acb5..5577250f 100644 --- a/crates/shirabe/src/util/git.rs +++ b/crates/shirabe/src/util/git.rs @@ -5,6 +5,7 @@ use crate::io::IOInterface; use crate::io::IOInterfaceImmutable; use crate::io::io_interface; use crate::util::Bitbucket; +use crate::util::CommandLine; use crate::util::Filesystem; use crate::util::GitHub; use crate::util::GitLab; @@ -101,10 +102,10 @@ impl Git { initial_clone: bool, command_output: impl RunCommandOutput, ) -> anyhow::Result<()> { - let mut callables: Vec<Box<dyn Fn(&str) -> Vec<String>>> = vec![]; + let mut callables: Vec<Box<dyn Fn(&str) -> CommandLine>> = vec![]; for cmd in commands { let cmd_clone = cmd.clone(); - callables.push(Box::new(move |url: &str| -> Vec<String> { + callables.push(Box::new(move |url: &str| -> CommandLine { let mut map: IndexMap<String, String> = IndexMap::new(); map.insert("%url%".to_string(), url.to_string()); map.insert( @@ -112,10 +113,10 @@ impl Git { preg_replace(php_regex!(r"{://([^@]+?):(.+?)@}"), "://", url), ); - array_map( + CommandLine::Args(array_map( |value: &String| map.get(value).cloned().unwrap_or_else(|| value.clone()), &cmd_clone, - ) + )) })); } @@ -127,7 +128,7 @@ impl Git { /// mirroring `Git::runCommand` as exercised by `GitTest`. pub fn __run_command( &mut self, - command_callable: Vec<Box<dyn Fn(&str) -> Vec<String>>>, + command_callable: Vec<Box<dyn Fn(&str) -> CommandLine>>, url: &str, cwd: Option<&str>, initial_clone: bool, @@ -140,14 +141,14 @@ impl Git { /// if a callable is passed it will be used as output handler fn run_command( &mut self, - command_callable: Vec<Box<dyn Fn(&str) -> Vec<String>>>, + command_callable: Vec<Box<dyn Fn(&str) -> CommandLine>>, url: &str, cwd: Option<&str>, initial_clone: bool, mut command_output: impl RunCommandOutput, ) -> anyhow::Result<()> { let command_callables = command_callable; - let mut last_command: PhpMixed = PhpMixed::String(String::new()); + let mut last_command = CommandLine::Shell(String::new()); // Ensure we are allowed to use this URL by config self.config.borrow_mut().prohibit_url_by_config( @@ -167,7 +168,7 @@ impl Git { // PHP closure: $runCommands = function ($url) use (...) { ... }; let run_commands_inline = |url_arg: &str, this_process: &mut ProcessExecutor, - last_cmd: &mut PhpMixed, + last_cmd: &mut CommandLine, output: &mut dyn RunCommandOutput| -> i64 { let collect_outputs = output.collect_outputs(); @@ -176,8 +177,7 @@ impl Git { let mut status: i64 = 0; for (counter, callable) in command_callables.iter().enumerate() { let cmd = callable(url_arg); - *last_cmd = - PhpMixed::List(cmd.iter().map(|s| PhpMixed::String(s.clone())).collect()); + *last_cmd = cmd.clone(); let exec_cwd = if initial_clone && counter == 0 { None } else { @@ -185,16 +185,13 @@ impl Git { }; if collect_outputs { let mut local_output = String::new(); - status = - this_process.execute_args(&cmd, &mut local_output, exec_cwd.as_deref()); + status = this_process + .execute(cmd, &mut local_output, exec_cwd.as_deref()) + .unwrap_or(1); outputs.push(local_output); } else { status = this_process - .execute( - &cmd[..], - output.make_handler().unwrap(), - exec_cwd.as_deref(), - ) + .execute(cmd, output.make_handler().unwrap(), exec_cwd.as_deref()) .unwrap_or(1); } if status != 0 { @@ -747,14 +744,8 @@ impl Git { } let mut last_command_str = match &last_command { - PhpMixed::List(l) => { - let parts: Vec<String> = l - .iter() - .filter_map(|v| v.as_string().map(|s| s.to_string())) - .collect(); - implode(" ", &parts) - } - _ => last_command.as_string().unwrap_or("").to_string(), + CommandLine::Args(args) => implode(" ", args), + CommandLine::Shell(command) => command.clone(), }; if (credentials.len() as i64) > 0 { last_command_str = self.mask_credentials(&last_command_str, &credentials); diff --git a/crates/shirabe/src/util/perforce.rs b/crates/shirabe/src/util/perforce.rs index 32e3e9cd..95cff0ca 100644 --- a/crates/shirabe/src/util/perforce.rs +++ b/crates/shirabe/src/util/perforce.rs @@ -2,6 +2,7 @@ use crate::io::IOInterface; use crate::io::IOInterfaceImmutable; +use crate::util::CommandLine; use crate::util::Filesystem; use crate::util::Platform; use crate::util::ProcessExecutor; @@ -138,28 +139,19 @@ impl Perforce { let task = vec!["client".to_string(), "-d".to_string(), client]; let use_p4_client = false; let command = self.generate_p4_command(task, use_p4_client); - self.execute_command(PhpMixed::List( - command.into_iter().map(PhpMixed::String).collect(), - )); + self.execute_command(CommandLine::Args(command)); let client_spec = self.get_p4_client_spec(); let file_system = self.get_filesystem(); file_system.borrow_mut().remove(&client_spec); } - fn execute_command(&mut self, command: PhpMixed) -> i64 { + fn execute_command(&mut self, command: CommandLine) -> i64 { self.command_result = String::new(); - let cmd_vec: Vec<String> = match &command { - PhpMixed::List(l) => l - .iter() - .filter_map(|v| v.as_string().map(|s| s.to_string())) - .collect(), - PhpMixed::String(s) => vec![s.clone()], - _ => vec![], - }; self.process .borrow_mut() - .execute_args(&cmd_vec, &mut self.command_result, None) + .execute(command, &mut self.command_result, None) + .unwrap_or(1) } pub fn get_client(&mut self) -> String { @@ -272,7 +264,7 @@ impl Perforce { ProcessExecutor::escape(self.p4_user.as_deref().unwrap_or("")) ) }; - self.execute_command(PhpMixed::String(command)); + self.execute_command(CommandLine::Shell(command)); Ok(()) } @@ -280,7 +272,7 @@ impl Perforce { fn get_p4_variable(&mut self, name: &str) -> Option<String> { if self.windows_flag { let command = format!("{} set", Self::get_p4_executable()); - self.execute_command(PhpMixed::String(command)); + self.execute_command(CommandLine::Shell(command)); let result = trim(&self.command_result, None); let res_array = explode(PHP_EOL, &result); for line in &res_array { @@ -302,7 +294,7 @@ impl Perforce { } let command = format!("echo ${}", name); - self.execute_command(PhpMixed::String(command)); + self.execute_command(CommandLine::Shell(command)); let result = trim(&self.command_result, None); Some(result) @@ -346,9 +338,7 @@ impl Perforce { pub fn is_logged_in(&mut self) -> anyhow::Result<bool> { let command = self.generate_p4_command(vec!["login".to_string(), "-s".to_string()], false); - let exit_code = self.execute_command(PhpMixed::List( - command.into_iter().map(PhpMixed::String).collect(), - )); + let exit_code = self.execute_command(CommandLine::Args(command)); if exit_code != 0 { let error_output = self.process.borrow().get_error_output().to_string(); let user = self.get_user().unwrap_or_default(); @@ -395,9 +385,7 @@ impl Perforce { if let Some(source_reference) = source_reference { p4_sync_command.push(format!("@{}", source_reference)); } - self.execute_command(PhpMixed::List( - p4_sync_command.into_iter().map(PhpMixed::String).collect(), - )); + self.execute_command(CommandLine::Args(p4_sync_command)); chdir(&prev_dir); Ok(()) @@ -587,9 +575,7 @@ impl Perforce { let path = self.get_file_path(file, identifier)?; let command = self.generate_p4_command(vec!["print".to_string(), path], true); - self.execute_command(PhpMixed::List( - command.into_iter().map(PhpMixed::String).collect(), - )); + self.execute_command(CommandLine::Args(command)); let result = self.command_result.clone(); if trim(&result, None).is_empty() { @@ -613,9 +599,7 @@ impl Perforce { substr(identifier, idx, None) ); let command = self.generate_p4_command(vec!["files".to_string(), path], false); - self.execute_command(PhpMixed::List( - command.into_iter().map(PhpMixed::String).collect(), - )); + self.execute_command(CommandLine::Args(command)); let result = self.command_result.clone(); let index2 = strpos(&result, "no such file(s)."); if index2.is_none() { @@ -651,9 +635,7 @@ impl Perforce { ], true, ); - self.execute_command(PhpMixed::List( - command.into_iter().map(PhpMixed::String).collect(), - )); + self.execute_command(CommandLine::Args(command)); let result = self.command_result.clone(); let res_array = explode(PHP_EOL, &result); for line in &res_array { @@ -673,9 +655,7 @@ impl Perforce { vec!["changes".to_string(), format!("{}/...", stream)], false, ); - self.execute_command(PhpMixed::List( - command.into_iter().map(PhpMixed::String).collect(), - )); + self.execute_command(CommandLine::Args(command)); let result = self.command_result.clone(); let res_array = explode(PHP_EOL, &result); let last_commit = res_array.first().cloned().unwrap_or_default(); @@ -699,9 +679,7 @@ impl Perforce { pub fn get_tags(&mut self) -> IndexMap<String, String> { let command = self.generate_p4_command(vec!["labels".to_string()], true); - self.execute_command(PhpMixed::List( - command.into_iter().map(PhpMixed::String).collect(), - )); + self.execute_command(CommandLine::Args(command)); let result = self.command_result.clone(); let res_array = explode(PHP_EOL, &result); let mut tags: IndexMap<String, String> = IndexMap::new(); @@ -719,9 +697,7 @@ impl Perforce { pub fn check_stream(&mut self) -> bool { let command = self.generate_p4_command(vec!["depots".to_string()], false); - self.execute_command(PhpMixed::List( - command.into_iter().map(PhpMixed::String).collect(), - )); + self.execute_command(CommandLine::Args(command)); let result = self.command_result.clone(); let res_array = explode(PHP_EOL, &result); for line in &res_array { @@ -747,9 +723,7 @@ impl Perforce { let label = substr(reference, index as i64, None); let command = self.generate_p4_command(vec!["changes".to_string(), "-m1".to_string(), label], true); - self.execute_command(PhpMixed::List( - command.into_iter().map(PhpMixed::String).collect(), - )); + self.execute_command(CommandLine::Args(command)); let changes = self.command_result.clone(); if strpos(&changes, "Change") != Some(0) { return None; @@ -771,9 +745,7 @@ impl Perforce { ], true, ); - self.execute_command(PhpMixed::List( - command.into_iter().map(PhpMixed::String).collect(), - )); + self.execute_command(CommandLine::Args(command)); Some(self.command_result.clone()) } diff --git a/crates/shirabe/src/util/process_executor.rs b/crates/shirabe/src/util/process_executor.rs index 6d609421..c1be0e18 100644 --- a/crates/shirabe/src/util/process_executor.rs +++ b/crates/shirabe/src/util/process_executor.rs @@ -10,10 +10,9 @@ use indexmap::IndexMap; use shirabe_php_shim::Catch as _; use shirabe_php_shim::{ LogicException, PHP_EOL, PhpMixed, PregMatches, RuntimeException, array_intersect, array_map, - escapeshellarg, explode, implode, in_array_strict, is_array, is_dir, is_numeric, is_string, - php_regex, preg_is_match, preg_match, preg_replace, preg_replace_callback, preg_replace2, - preg_split, rtrim, str_replace, strcspn, strlen, strpbrk, strtolower, strtr_array, - substr_replace, trim, + escapeshellarg, explode, implode, in_array_strict, is_dir, is_numeric, php_regex, + preg_is_match, preg_match, preg_replace, preg_replace_callback, preg_replace2, preg_split, + rtrim, str_replace, strcspn, strlen, strpbrk, strtolower, strtr_array, substr_replace, trim, }; use shirabe_symfony_process::ExecutableFinder; use shirabe_symfony_process::Process; @@ -27,6 +26,12 @@ static EXECUTABLES: LazyLock<Mutex<IndexMap<String, String>>> = static TIMEOUT: LazyLock<Mutex<i64>> = LazyLock::new(|| Mutex::new(300)); +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum CommandLine { + Shell(String), + Args(Vec<String>), +} + #[derive(Debug)] pub struct ProcessExecutor { /// @var bool @@ -63,8 +68,7 @@ pub struct ProcessExecutorMockState { /// A single expected command (`array{cmd, return, stdout, stderr, callback}` in PHP). pub struct MockExpectation { - /// `string|list<string>`: a `PhpMixed::String` or `PhpMixed::List`. - pub cmd: PhpMixed, + pub cmd: CommandLine, pub r#return: i64, pub stdout: String, pub stderr: String, @@ -87,7 +91,7 @@ impl std::fmt::Debug for MockExpectation { impl MockExpectation { /// Builds an expectation from just a command (string or list), defaulting the rest, matching /// PHP's handling of bare `string`/`list` entries in `expects`. - pub fn from_cmd(cmd: PhpMixed) -> Self { + pub fn from_cmd(cmd: CommandLine) -> Self { Self { cmd, r#return: 0, @@ -174,15 +178,11 @@ impl ProcessExecutor { output: &mut String, cwd: Option<&str>, ) -> i64 { - let cmd = PhpMixed::List( - command - .iter() - .map(|s| PhpMixed::String(s.clone())) - .collect(), - ); - let mut buf = PhpMixed::String(String::new()); - let rc = self.execute(cmd, &mut buf, cwd).unwrap_or(1); - *output = buf.as_string().unwrap_or("").to_string(); + let mut buf = String::new(); + let rc = self + .execute(CommandLine::Args(command.to_vec()), &mut buf, cwd) + .unwrap_or(1); + *output = buf; rc } @@ -201,7 +201,7 @@ impl ProcessExecutor { fn run_process<'o, O>( &mut self, - command: PhpMixed, + command: CommandLine, cwd: Option<&str>, env: Option<IndexMap<String, String>>, tty: bool, @@ -213,48 +213,44 @@ impl ProcessExecutor { // On Windows, we don't rely on the OS to find the executable if possible to avoid lookups // in the current directory which could be untrusted. Instead we use the ExecutableFinder. - let mut process: Process; - if is_string(&command) { - let mut command_str = command.as_string().unwrap_or("").to_string(); - if Platform::is_windows() - && let Some(m) = preg_match(php_regex!(r"{^([^:/\\]++) }"), &command_str) - { - let m1 = m.get(1).unwrap_or_default().to_string(); - command_str = substr_replace( - &command_str, - &Self::escape(&Self::get_executable(&m1)), - 0, - Some(strlen(&m1)), - ); - } + let mut process: Process = match command { + CommandLine::Shell(mut command) => { + if Platform::is_windows() + && let Some(m) = preg_match(php_regex!(r"{^([^:/\\]++) }"), &command) + { + let m1 = m.get(1).unwrap_or_default().to_string(); + command = substr_replace( + &command, + &Self::escape(&Self::get_executable(&m1)), + 0, + Some(strlen(&m1)), + ); + } - process = Process::from_shell_commandline( - &command_str, - cwd, - env, - PhpMixed::Null, - Some(Self::get_timeout() as f64), - )?; - } else if let PhpMixed::List(ref list) = command { - let mut cmd_vec: Vec<String> = list - .iter() - .map(|v| v.as_string().unwrap_or("").to_string()) - .collect(); - if Platform::is_windows() && strlen(&cmd_vec[0]) == strcspn(&cmd_vec[0], ":/\\") as i64 - { - cmd_vec[0] = Self::get_executable(&cmd_vec[0]); + Process::from_shell_commandline( + &command, + cwd, + env, + PhpMixed::Null, + Some(Self::get_timeout() as f64), + )? } + CommandLine::Args(mut command) => { + if Platform::is_windows() + && strlen(&command[0]) == strcspn(&command[0], ":/\\") as i64 + { + command[0] = Self::get_executable(&command[0]); + } - process = Process::new( - cmd_vec, - cwd.map(String::from), - env, - PhpMixed::Null, - Some(Self::get_timeout() as f64), - )?; - } else { - return Err(LogicException::new("Invalid command type".to_string()).into()); - } + Process::new( + command, + cwd.map(String::from), + env, + PhpMixed::Null, + Some(Self::get_timeout() as f64), + )? + } + }; if !Platform::is_windows() && tty { // PHP: try { $process->setTty(true); } catch (RuntimeException $e) { /* ignore */ } @@ -324,7 +320,7 @@ impl ProcessExecutor { fn do_execute<'o, O>( &mut self, - command: PhpMixed, + command: CommandLine, cwd: Option<&str>, tty: bool, output: O, @@ -349,21 +345,21 @@ impl ProcessExecutor { { let is_bare_repository = !is_dir(format!("{}/.git", rtrim(cwd, Some("/")))); if is_bare_repository { - let mut config_value = PhpMixed::String(String::new()); + let mut config_value = String::new(); let mut git_env: IndexMap<String, String> = IndexMap::new(); git_env.insert("GIT_DIR".to_string(), cwd.to_string()); self.run_process( - PhpMixed::List(vec![ - PhpMixed::String("git".to_string()), - PhpMixed::String("config".to_string()), - PhpMixed::String("safe.bareRepository".to_string()), + CommandLine::Args(vec![ + "git".to_string(), + "config".to_string(), + "safe.bareRepository".to_string(), ]), Some(cwd), Some(git_env.clone()), tty, &mut config_value, )?; - let trimmed = trim(config_value.as_string().unwrap_or(""), None); + let trimmed = trim(&config_value, None); if trimmed == "explicit" { env = Some(git_env); } @@ -386,27 +382,12 @@ impl ProcessExecutor { /// `execute_async`'s `&self` receiver can still consume it. fn mock_match( &self, - command: &PhpMixed, + command: &CommandLine, cwd: Option<&str>, ) -> anyhow::Result<(String, String, i64)> { - let command_string = if is_array(command) { - match command { - PhpMixed::List(l) => implode( - " ", - &l.iter() - .map(|v| v.as_string().unwrap_or("").to_string()) - .collect::<Vec<_>>(), - ), - PhpMixed::Array(m) => implode( - " ", - &m.values() - .map(|v| v.as_string().unwrap_or("").to_string()) - .collect::<Vec<_>>(), - ), - _ => String::new(), - } - } else { - command.as_string().unwrap_or("").to_string() + let command_string = match command { + CommandLine::Args(args) => implode(" ", args), + CommandLine::Shell(command) => command.clone(), }; let mut mock = self.mock.as_ref().unwrap().borrow_mut(); @@ -473,7 +454,7 @@ impl ProcessExecutor { /// emits stdout/stderr through the output target and records `error_output`. fn mock_do_execute<'o, O>( &mut self, - command: PhpMixed, + command: CommandLine, cwd: Option<&str>, output: O, ) -> anyhow::Result<i64> @@ -546,26 +527,9 @@ impl ProcessExecutor { if !expectations.is_empty() { let remaining: Vec<String> = expectations .iter() - .map(|expect| { - if is_array(&expect.cmd) { - match &expect.cmd { - PhpMixed::List(l) => implode( - " ", - &l.iter() - .map(|v| v.as_string().unwrap_or("").to_string()) - .collect::<Vec<_>>(), - ), - PhpMixed::Array(m) => implode( - " ", - &m.values() - .map(|v| v.as_string().unwrap_or("").to_string()) - .collect::<Vec<_>>(), - ), - _ => String::new(), - } - } else { - expect.cmd.as_string().unwrap_or("").to_string() - } + .map(|expect| match &expect.cmd { + CommandLine::Args(args) => implode(" ", args), + CommandLine::Shell(command) => command.clone(), }) .collect(); panic!( @@ -648,26 +612,21 @@ impl ProcessExecutor { Self::output_command_run_with(&io, &command, cwd.as_deref(), true); // PHP: $job['reject']($e) on process construction/start failure — surfaced as Err here. - let mut process = if is_string(&command) { - Process::from_shell_commandline( - command.as_string().unwrap_or(""), + let mut process = match command { + CommandLine::Shell(command) => Process::from_shell_commandline( + &command, cwd.as_deref(), None, PhpMixed::Null, Some(Self::get_timeout() as f64), - )? - } else if let PhpMixed::List(ref list) = command { - Process::new( - list.iter() - .map(|v| v.as_string().unwrap_or("").to_string()) - .collect(), + )?, + CommandLine::Args(command) => Process::new( + command, cwd.clone(), None, PhpMixed::Null, Some(Self::get_timeout() as f64), - )? - } else { - return Err(LogicException::new("Invalid command type".to_string()).into()); + )?, }; process.start(None, IndexMap::new())?; @@ -802,7 +761,7 @@ impl ProcessExecutor { Self::escape_argument(argument) } - fn output_command_run(&self, command: &PhpMixed, cwd: Option<&str>, r#async: bool) { + fn output_command_run(&self, command: &CommandLine, cwd: Option<&str>, r#async: bool) { Self::output_command_run_with(&self.io, command, cwd, r#async); } @@ -810,7 +769,7 @@ impl ProcessExecutor { /// clone of the io handle instead of borrowing the executor. fn output_command_run_with( io: &Option<std::rc::Rc<std::cell::RefCell<dyn IOInterface>>>, - command: &PhpMixed, + command: &CommandLine, cwd: Option<&str>, r#async: bool, ) { @@ -818,16 +777,9 @@ impl ProcessExecutor { return; } - let command_string = if is_string(command) { - command.as_string().unwrap_or("").to_string() - } else if let PhpMixed::List(list) = command { - let parts: Vec<String> = array_map( - |v| Self::escape(v.as_string().unwrap_or("")), - &list.to_vec(), - ); - implode(" ", &parts) - } else { - String::new() + let command_string = match command { + CommandLine::Shell(command) => command.clone(), + CommandLine::Args(args) => implode(" ", &array_map(|arg| Self::escape(arg), args)), }; let safe_command = preg_replace_callback( php_regex!(r"{://(?P<user>[^:/\s]+):(?P<password>[^@\s/]+)@}i"), @@ -920,21 +872,10 @@ impl ProcessExecutor { argument } - pub fn requires_git_dir_env(&self, command: &PhpMixed) -> bool { - let cmd: Vec<String> = if !is_array(command) { - explode(" ", command.as_string().unwrap_or("")) - } else { - match command { - PhpMixed::List(l) => l - .iter() - .map(|v| v.as_string().unwrap_or("").to_string()) - .collect(), - PhpMixed::Array(m) => m - .values() - .map(|v| v.as_string().unwrap_or("").to_string()) - .collect(), - _ => vec![], - } + pub fn requires_git_dir_env(&self, command: &CommandLine) -> bool { + let cmd: Vec<String> = match command { + CommandLine::Shell(command) => explode(" ", command), + CommandLine::Args(args) => args.clone(), }; if cmd.first().map(|s| s.as_str()) != Some("git") { return false; @@ -978,76 +919,68 @@ impl ProcessExecutor { } } -/// Helper trait: convert various command argument forms into `PhpMixed`. +/// Helper trait: convert various command argument forms into a [`CommandLine`]. pub trait IntoExecCommand { - fn into_exec_command(self) -> PhpMixed; + fn into_exec_command(self) -> CommandLine; } -impl IntoExecCommand for PhpMixed { - fn into_exec_command(self) -> PhpMixed { +impl IntoExecCommand for CommandLine { + fn into_exec_command(self) -> CommandLine { self } } -impl IntoExecCommand for &PhpMixed { - fn into_exec_command(self) -> PhpMixed { +impl IntoExecCommand for &CommandLine { + fn into_exec_command(self) -> CommandLine { self.clone() } } impl IntoExecCommand for &str { - fn into_exec_command(self) -> PhpMixed { - PhpMixed::String(self.to_string()) + fn into_exec_command(self) -> CommandLine { + CommandLine::Shell(self.to_string()) } } impl IntoExecCommand for String { - fn into_exec_command(self) -> PhpMixed { - PhpMixed::String(self) + fn into_exec_command(self) -> CommandLine { + CommandLine::Shell(self) } } impl IntoExecCommand for &String { - fn into_exec_command(self) -> PhpMixed { - PhpMixed::String(self.clone()) + fn into_exec_command(self) -> CommandLine { + CommandLine::Shell(self.clone()) } } impl IntoExecCommand for Vec<String> { - fn into_exec_command(self) -> PhpMixed { - PhpMixed::List(self.into_iter().map(PhpMixed::String).collect()) + fn into_exec_command(self) -> CommandLine { + CommandLine::Args(self) } } impl IntoExecCommand for &Vec<String> { - fn into_exec_command(self) -> PhpMixed { - PhpMixed::List(self.iter().map(|s| PhpMixed::String(s.clone())).collect()) + fn into_exec_command(self) -> CommandLine { + CommandLine::Args(self.clone()) } } impl<const N: usize> IntoExecCommand for &[&str; N] { - fn into_exec_command(self) -> PhpMixed { - PhpMixed::List( - self.iter() - .map(|s| PhpMixed::String(s.to_string())) - .collect(), - ) + fn into_exec_command(self) -> CommandLine { + CommandLine::Args(self.iter().map(|s| s.to_string()).collect()) } } impl IntoExecCommand for &[&str] { - fn into_exec_command(self) -> PhpMixed { - PhpMixed::List( - self.iter() - .map(|s| PhpMixed::String(s.to_string())) - .collect(), - ) + fn into_exec_command(self) -> CommandLine { + CommandLine::Args(self.iter().map(|s| s.to_string()).collect()) } } impl IntoExecCommand for &[String] { - fn into_exec_command(self) -> PhpMixed { - PhpMixed::List(self.iter().map(|s| PhpMixed::String(s.clone())).collect()) + fn into_exec_command(self) -> CommandLine { + CommandLine::Args(self.to_vec()) } } |
