diff options
Diffstat (limited to 'crates/shirabe/src/util')
| -rw-r--r-- | crates/shirabe/src/util/auth_helper.rs | 6 | ||||
| -rw-r--r-- | crates/shirabe/src/util/bitbucket.rs | 23 | ||||
| -rw-r--r-- | crates/shirabe/src/util/filesystem.rs | 10 | ||||
| -rw-r--r-- | crates/shirabe/src/util/git.rs | 98 | ||||
| -rw-r--r-- | crates/shirabe/src/util/github.rs | 14 | ||||
| -rw-r--r-- | crates/shirabe/src/util/gitlab.rs | 24 | ||||
| -rw-r--r-- | crates/shirabe/src/util/hg.rs | 49 | ||||
| -rw-r--r-- | crates/shirabe/src/util/perforce.rs | 9 | ||||
| -rw-r--r-- | crates/shirabe/src/util/platform.rs | 2 | ||||
| -rw-r--r-- | crates/shirabe/src/util/process_executor.rs | 32 | ||||
| -rw-r--r-- | crates/shirabe/src/util/svn.rs | 8 |
11 files changed, 131 insertions, 144 deletions
diff --git a/crates/shirabe/src/util/auth_helper.rs b/crates/shirabe/src/util/auth_helper.rs index 72f50aa3..5e6ea16e 100644 --- a/crates/shirabe/src/util/auth_helper.rs +++ b/crates/shirabe/src/util/auth_helper.rs @@ -213,7 +213,7 @@ impl AuthHelper { } } - if !git_hub_util.authorize_oauth(origin) + if !git_hub_util.authorize_oauth(origin)? && (!self.io.is_interactive() || !git_hub_util.authorize_oauth_interactively(origin, Some(&message))?) { @@ -257,7 +257,7 @@ impl AuthHelper { } let scheme = parse_url(url).and_then(|parsed| parsed.scheme); - if !git_lab_util.authorize_oauth(origin) + if !git_lab_util.authorize_oauth(origin)? && (!self.io.is_interactive() || !git_lab_util.authorize_oauth_interactively( scheme.as_deref().unwrap_or(""), @@ -337,7 +337,7 @@ impl AuthHelper { ); let mut bit_bucket_util = Bitbucket::new(self.io.clone(), self.config.clone(), None, None, None)?; - if !bit_bucket_util.authorize_oauth(&origin) + if !bit_bucket_util.authorize_oauth(&origin)? && (!self.io.is_interactive() || !bit_bucket_util .authorize_oauth_interactively(&origin, Some(&message))?) diff --git a/crates/shirabe/src/util/bitbucket.rs b/crates/shirabe/src/util/bitbucket.rs index 9a16c9a6..f50dc878 100644 --- a/crates/shirabe/src/util/bitbucket.rs +++ b/crates/shirabe/src/util/bitbucket.rs @@ -71,22 +71,17 @@ impl Bitbucket { } } - pub fn authorize_oauth(&mut self, origin_url: &str) -> bool { + pub fn authorize_oauth(&mut self, origin_url: &str) -> anyhow::Result<bool> { if origin_url != "bitbucket.org" { - return false; + return Ok(false); } let mut output = PhpMixed::Null; - if self - .process - .borrow_mut() - .execute( - &["git", "config", "bitbucket.accesstoken"], - &mut output, - None, - ) - .unwrap_or(1) - == 0 + if self.process.borrow_mut().execute( + &["git", "config", "bitbucket.accesstoken"], + &mut output, + None, + )? == 0 { let output_str = output.as_string().unwrap_or("").trim().to_string(); self.io.borrow_mut().set_authentication( @@ -94,10 +89,10 @@ impl Bitbucket { "x-token-auth".to_string(), Some(output_str), ); - return true; + return Ok(true); } - false + Ok(false) } fn request_access_token(&mut self) -> anyhow::Result<bool> { diff --git a/crates/shirabe/src/util/filesystem.rs b/crates/shirabe/src/util/filesystem.rs index 8726df63..bca18771 100644 --- a/crates/shirabe/src/util/filesystem.rs +++ b/crates/shirabe/src/util/filesystem.rs @@ -475,7 +475,7 @@ impl Filesystem { if Platform::is_windows() { // Try to copy & delete - this is a workaround for random "Access denied" errors. let mut output = String::new(); - let result = self.get_process().execute_args( + let result = self.get_process().execute( &[ "xcopy".to_string(), source.to_string(), @@ -487,7 +487,7 @@ impl Filesystem { ], &mut output, None, - ); + )?; // clear stat cache because external processes aren't tracked by the php stat cache clearstatcache2(false, ""); @@ -501,11 +501,11 @@ impl Filesystem { // We do not use PHP's "rename" function here since it does not support // the case where $source, and $target are located on different partitions. let mut output = String::new(); - let result = self.get_process().execute_args( + let result = self.get_process().execute( &["mv".to_string(), source.to_string(), target.to_string()], &mut output, None, - ); + )?; // clear stat cache because external processes aren't tracked by the php stat cache clearstatcache2(false, ""); @@ -932,7 +932,7 @@ impl Filesystem { Platform::realpath(target), ]; let mut output = String::new(); - if self.get_process().execute_args(&cmd, &mut output, None) != 0 { + if self.get_process().execute(&cmd, &mut output, None)? != 0 { return Err(IOException::new( format!( "Failed to create junction to \"{}\" at \"{}\".", diff --git a/crates/shirabe/src/util/git.rs b/crates/shirabe/src/util/git.rs index 5577250f..aea8b7b8 100644 --- a/crates/shirabe/src/util/git.rs +++ b/crates/shirabe/src/util/git.rs @@ -362,8 +362,8 @@ impl Git { )?; let message = "Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos"; - if !git_hub_util.authorize_oauth(&m1) && self.io.is_interactive() { - git_hub_util.authorize_oauth_interactively(&m1, Some(message)); + if !git_hub_util.authorize_oauth(&m1)? && self.io.is_interactive() { + git_hub_util.authorize_oauth_interactively(&m1, Some(message))?; } } @@ -423,8 +423,8 @@ impl Git { if !self.io.has_authentication(&domain) { let message = "Enter your Bitbucket credentials to access private repos"; - if !bitbucket_util.authorize_oauth(&domain) && self.io.is_interactive() { - bitbucket_util.authorize_oauth_interactively(&domain, Some(message)); + if !bitbucket_util.authorize_oauth(&domain)? && self.io.is_interactive() { + bitbucket_util.authorize_oauth_interactively(&domain, Some(message))?; let access_token = bitbucket_util.get_token(); self.io.borrow_mut().set_authentication( domain.clone(), @@ -575,8 +575,8 @@ impl Git { let message = "Cloning failed, enter your GitLab credentials to access private repos"; - if !git_lab_util.authorize_oauth(&m2) && self.io.is_interactive() { - git_lab_util.authorize_oauth_interactively(&m1, &m2, Some(message)); + if !git_lab_util.authorize_oauth(&m2)? && self.io.is_interactive() { + git_lab_util.authorize_oauth_interactively(&m1, &m2, Some(message))?; } } @@ -783,7 +783,7 @@ impl Git { // update the repo if it is a valid git repository let mut output = String::new(); if is_dir(dir) - && self.process.borrow_mut().execute_args( + && self.process.borrow_mut().execute( &[ "git".to_string(), "rev-parse".to_string(), @@ -791,7 +791,7 @@ impl Git { ], &mut output, Some(dir), - ) == 0 + )? == 0 && trim(&output, None) == "." { // PHP try/finally @@ -915,20 +915,20 @@ impl Git { let mut branches: Option<String> = None; let mut tags: Option<String> = None; let mut output = String::new(); - if self.process.borrow_mut().execute_args( + if self.process.borrow_mut().execute( &["git".to_string(), "branch".to_string()], &mut output, Some(dir), - ) == 0 + )? == 0 { branches = Some(output); } let mut output = String::new(); - if self.process.borrow_mut().execute_args( + if self.process.borrow_mut().execute( &["git".to_string(), "tag".to_string()], &mut output, Some(dir), - ) == 0 + )? == 0 { tags = Some(output); } @@ -964,26 +964,26 @@ impl Git { pub fn get_no_show_signature_flag( process: &std::rc::Rc<std::cell::RefCell<ProcessExecutor>>, - ) -> String { - let git_version = Self::get_version(process); + ) -> anyhow::Result<String> { + let git_version = Self::get_version(process)?; if let Some(v) = git_version && version_compare(&v, "2.10.0-rc0", CmpOp::Ge) { - return " --no-show-signature".to_string(); + return Ok(" --no-show-signature".to_string()); } - String::new() + Ok(String::new()) } pub fn get_no_show_signature_flags( process: &std::rc::Rc<std::cell::RefCell<ProcessExecutor>>, - ) -> Vec<String> { - let flags = Self::get_no_show_signature_flag(process); + ) -> anyhow::Result<Vec<String>> { + let flags = Self::get_no_show_signature_flag(process)?; if flags.is_empty() { - return vec![]; + return Ok(vec![]); } - explode(" ", &substr(&flags, 1, None)) + Ok(explode(" ", &substr(&flags, 1, None))) } /// Checks if git version supports --no-commit-header flag (git 2.33+) @@ -991,12 +991,12 @@ impl Git { /// @internal pub fn supports_no_commit_header_flag( process: &std::rc::Rc<std::cell::RefCell<ProcessExecutor>>, - ) -> bool { - let git_version = Self::get_version(process); + ) -> anyhow::Result<bool> { + let git_version = Self::get_version(process)?; - git_version + Ok(git_version .map(|v| version_compare(&v, "2.33.0-rc0", CmpOp::Ge)) - .unwrap_or(false) + .unwrap_or(false)) } /// Builds a git rev-list command with --no-commit-header flag when supported (git 2.33+) @@ -1006,14 +1006,14 @@ impl Git { pub fn build_rev_list_command( process: &std::rc::Rc<std::cell::RefCell<ProcessExecutor>>, arguments: Vec<String>, - ) -> Vec<String> { + ) -> anyhow::Result<Vec<String>> { let mut command = vec!["git".to_string(), "rev-list".to_string()]; - if Self::supports_no_commit_header_flag(process) { + if Self::supports_no_commit_header_flag(process)? { command.push("--no-commit-header".to_string()); } command.extend(arguments); - command + Ok(command) } /// Parses git rev-list output, removing 'commit <hash>' header lines for git < 2.33. @@ -1025,20 +1025,24 @@ impl Git { pub fn parse_rev_list_output( output: &str, process: &std::rc::Rc<std::cell::RefCell<ProcessExecutor>>, - ) -> String { + ) -> anyhow::Result<String> { // If git supports --no-commit-header, output is already clean - if Self::supports_no_commit_header_flag(process) { - return output.to_string(); + if Self::supports_no_commit_header_flag(process)? { + return Ok(output.to_string()); } // Filter out "commit <hash>" lines for older git versions - preg_replace(php_regex!(r"{^commit [a-f0-9]{40}\n?}m"), "", output) + Ok(preg_replace( + php_regex!(r"{^commit [a-f0-9]{40}\n?}m"), + "", + output, + )) } fn check_ref_is_in_mirror(&mut self, dir: &str, r#ref: &str) -> anyhow::Result<bool> { let mut output = String::new(); if is_dir(dir) - && self.process.borrow_mut().execute_args( + && self.process.borrow_mut().execute( &[ "git".to_string(), "rev-parse".to_string(), @@ -1046,11 +1050,11 @@ impl Git { ], &mut output, Some(dir), - ) == 0 + )? == 0 && trim(&output, None) == "." { let mut ignored_output = String::new(); - let exit_code = self.process.borrow_mut().execute_args( + let exit_code = self.process.borrow_mut().execute( &[ "git".to_string(), "rev-parse".to_string(), @@ -1060,7 +1064,7 @@ impl Git { ], &mut ignored_output, Some(dir), - ); + )?; if exit_code == 0 { return Ok(true); } @@ -1108,7 +1112,7 @@ impl Git { let mut output_mixed = PhpMixed::Null; if is_local_path_repository { let mut output = String::new(); - self.process.borrow_mut().execute_args( + self.process.borrow_mut().execute( &[ "git".to_string(), "remote".to_string(), @@ -1117,7 +1121,7 @@ impl Git { ], &mut output, Some(dir), - ); + )?; output_mixed = PhpMixed::String(output); } else { let commands = vec![ @@ -1178,9 +1182,11 @@ impl Git { } } - pub fn clean_env(process: &std::rc::Rc<std::cell::RefCell<ProcessExecutor>>) { + pub fn clean_env( + process: &std::rc::Rc<std::cell::RefCell<ProcessExecutor>>, + ) -> anyhow::Result<()> { // PHP: $process ?? new ProcessExecutor() - let git_version = Self::get_version(process); + let git_version = Self::get_version(process)?; if let Some(v) = git_version { if version_compare(&v, "2.3.0", CmpOp::Ge) { // added in git 2.3.0, prevents prompting the user for username/password @@ -1210,6 +1216,8 @@ impl Git { // clean up env for OSX, see https://github.com/composer/composer/issues/2146#issuecomment-35478940 Platform::clear_env("DYLD_LIBRARY_PATH"); + + Ok(()) } pub fn get_github_domains_regex(config: &Config) -> String { @@ -1241,11 +1249,11 @@ impl Git { clearstatcache(); let mut ignored_output = String::new(); - if self.process.borrow_mut().execute_args( + if self.process.borrow_mut().execute( &["git".to_string(), "--version".to_string()], &mut ignored_output, Option::<&str>::None, - ) != 0 + )? != 0 { return Err(RuntimeException::new(Url::sanitize(format!( "Failed to clone {}, git was not found, check that it is installed and in your PATH env.\n\n{}", @@ -1263,16 +1271,16 @@ impl Git { /// @return string|null The git version number, if present. pub fn get_version( process: &std::rc::Rc<std::cell::RefCell<ProcessExecutor>>, - ) -> Option<String> { + ) -> anyhow::Result<Option<String>> { let mut version = VERSION.lock().unwrap(); if version.is_none() { *version = Some(None); let mut output = String::new(); - let exit_code: i64 = process.borrow_mut().execute_args( + let exit_code: i64 = process.borrow_mut().execute( &["git".to_string(), "--version".to_string()], &mut output, Option::<&str>::None, - ); + )?; if exit_code == 0 && let Some(matches) = preg_match(php_regex!(r"/^git version (\d+(?:\.\d+)+)/m"), &output) @@ -1280,7 +1288,7 @@ impl Git { *version = Some(matches.get(1).map(str::to_string)); } } - version.clone().unwrap_or(None) + Ok(version.clone().unwrap_or(None)) } /// For testing only. Resets the cached git `version` static so the next diff --git a/crates/shirabe/src/util/github.rs b/crates/shirabe/src/util/github.rs index ccfedcf8..d4fd3283 100644 --- a/crates/shirabe/src/util/github.rs +++ b/crates/shirabe/src/util/github.rs @@ -52,14 +52,14 @@ impl GitHub { }) } - pub fn authorize_oauth(&mut self, origin_url: &str) -> bool { + pub fn authorize_oauth(&mut self, origin_url: &str) -> anyhow::Result<bool> { let github_domains = self.config.borrow_mut().get("github-domains"); if !in_array_loose(origin_url.to_string(), github_domains.values()) { - return false; + return Ok(false); } let mut output = String::new(); - if self.process.borrow_mut().execute_args( + if self.process.borrow_mut().execute( &[ "git".to_string(), "config".to_string(), @@ -67,17 +67,17 @@ impl GitHub { ], &mut output, None, - ) == 0 + )? == 0 { self.io.borrow_mut().set_authentication( origin_url.to_string(), output.trim().to_string(), Some("x-oauth-basic".to_string()), ); - return true; + return Ok(true); } - false + Ok(false) } pub fn authorize_oauth_interactively( @@ -101,7 +101,7 @@ impl GitHub { if self .process .borrow_mut() - .execute_args(&["hostname".to_string()], &mut output, None) + .execute(&["hostname".to_string()], &mut output, None)? == 0 { note += &format!(" on {}", output.trim()); diff --git a/crates/shirabe/src/util/gitlab.rs b/crates/shirabe/src/util/gitlab.rs index c101b1f9..fa9bef69 100644 --- a/crates/shirabe/src/util/gitlab.rs +++ b/crates/shirabe/src/util/gitlab.rs @@ -51,7 +51,7 @@ impl GitLab { }) } - pub fn authorize_oauth(&mut self, origin_url: &str) -> bool { + pub fn authorize_oauth(&mut self, origin_url: &str) -> anyhow::Result<bool> { // before composer 1.9, origin URLs had no port number in them let bc_origin_url = preg_replace(php_regex!("{:\\d+}"), "", origin_url); @@ -59,12 +59,12 @@ impl GitLab { if !in_array_strict(origin_url.to_string(), gitlab_domains.values()) && !in_array_strict(bc_origin_url.clone(), gitlab_domains.values()) { - return false; + return Ok(false); } // if available use token from git config let mut output = String::new(); - if self.process.borrow_mut().execute_args( + if self.process.borrow_mut().execute( &[ "git".to_string(), "config".to_string(), @@ -72,20 +72,20 @@ impl GitLab { ], &mut output, None, - ) == 0 + )? == 0 { self.io.borrow_mut().set_authentication( origin_url.to_string(), output.trim().to_string(), Some("oauth2".to_string()), ); - return true; + return Ok(true); } // if available use deploy token from git config let mut token_user = String::new(); let mut token_password = String::new(); - if self.process.borrow_mut().execute_args( + if self.process.borrow_mut().execute( &[ "git".to_string(), "config".to_string(), @@ -93,8 +93,8 @@ impl GitLab { ], &mut token_user, None, - ) == 0 - && self.process.borrow_mut().execute_args( + )? == 0 + && self.process.borrow_mut().execute( &[ "git".to_string(), "config".to_string(), @@ -102,14 +102,14 @@ impl GitLab { ], &mut token_password, None, - ) == 0 + )? == 0 { self.io.borrow_mut().set_authentication( origin_url.to_string(), token_user.trim().to_string(), Some(token_password.trim().to_string()), ); - return true; + return Ok(true); } // if available use token from composer config @@ -165,10 +165,10 @@ impl GitLab { ); } - return true; + return Ok(true); } - false + Ok(false) } pub fn authorize_oauth_interactively( diff --git a/crates/shirabe/src/util/hg.rs b/crates/shirabe/src/util/hg.rs index 3180f4f9..575c2c1f 100644 --- a/crates/shirabe/src/util/hg.rs +++ b/crates/shirabe/src/util/hg.rs @@ -6,9 +6,9 @@ use crate::io::IOInterfaceImmutable; use crate::util::ProcessExecutor; use crate::util::Url; use shirabe_php_shim::{php_regex, preg_match, rawurlencode}; -use std::sync::OnceLock; +use std::sync::Mutex; -static VERSION: OnceLock<Option<String>> = OnceLock::new(); +static VERSION: Mutex<Option<Option<String>>> = Mutex::new(None); #[derive(Debug)] pub struct Hg { @@ -48,7 +48,7 @@ impl Hg { if self .process .borrow_mut() - .execute_args(&command, &mut ignored_output, cwd.as_deref()) + .execute(&command, &mut ignored_output, cwd.as_deref())? == 0 { return Ok(()); @@ -107,7 +107,7 @@ impl Hg { if self .process .borrow_mut() - .execute_args(&command, &mut ignored_output, cwd.as_deref()) + .execute(&command, &mut ignored_output, cwd.as_deref())? == 0 { return Ok(()); @@ -125,7 +125,7 @@ impl Hg { } fn throw_exception(&self, message: &str, url: &str) -> anyhow::Result<()> { - if Self::get_version(&self.process).is_none() { + if Self::get_version(&self.process)?.is_none() { anyhow::bail!( "{}", Url::sanitize(format!( @@ -141,24 +141,25 @@ impl Hg { pub fn get_version( process: &std::rc::Rc<std::cell::RefCell<ProcessExecutor>>, - ) -> Option<&'static str> { - VERSION - .get_or_init(|| { - let mut output = String::new(); - if process.borrow_mut().execute_args( - &["hg".to_string(), "--version".to_string()], - &mut output, - None, - ) == 0 - && let Some(matches) = preg_match( - php_regex!(r"/^.+? (\d+(?:\.\d+)+)(?:\+.*?)?\)?\r?\n/"), - &output, - ) - { - return matches.get(1).map(str::to_string); - } - None - }) - .as_deref() + ) -> anyhow::Result<Option<String>> { + let mut version = VERSION.lock().unwrap(); + if version.is_none() { + *version = Some(None); + let mut output = String::new(); + if process.borrow_mut().execute( + &["hg".to_string(), "--version".to_string()], + &mut output, + None, + )? == 0 + && let Some(matches) = preg_match( + php_regex!(r"/^.+? (\d+(?:\.\d+)+)(?:\+.*?)?\)?\r?\n/"), + &output, + ) + { + *version = Some(matches.get(1).map(str::to_string)); + } + } + + Ok(version.clone().unwrap_or(None)) } } diff --git a/crates/shirabe/src/util/perforce.rs b/crates/shirabe/src/util/perforce.rs index 95cff0ca..295851c6 100644 --- a/crates/shirabe/src/util/perforce.rs +++ b/crates/shirabe/src/util/perforce.rs @@ -78,9 +78,12 @@ impl Perforce { Self::new(repo_config, port, path, process, Platform::is_windows(), io) } - pub fn check_server_exists(url: &str, process_executor: &mut ProcessExecutor) -> bool { + pub fn check_server_exists( + url: &str, + process_executor: &mut ProcessExecutor, + ) -> anyhow::Result<bool> { let mut ignored_output = String::new(); - process_executor.execute_args( + Ok(process_executor.execute( &[ "p4".to_string(), "-p".to_string(), @@ -90,7 +93,7 @@ impl Perforce { ], &mut ignored_output, Option::<&str>::None, - ) == 0 + )? == 0) } pub fn initialize(&mut self, repo_config: &IndexMap<String, PhpMixed>) { diff --git a/crates/shirabe/src/util/platform.rs b/crates/shirabe/src/util/platform.rs index c40f3ec5..ad530db3 100644 --- a/crates/shirabe/src/util/platform.rs +++ b/crates/shirabe/src/util/platform.rs @@ -310,7 +310,7 @@ impl Platform { let mut process = ProcessExecutor::new(None); let mut output = String::new(); let result: anyhow::Result<()> = (|| { - if process.execute_args(&["lsmod".to_string()], &mut output, None) == 0 + if process.execute(&["lsmod".to_string()], &mut output, None)? == 0 && output.contains("vboxguest") { *cached = Some(true); diff --git a/crates/shirabe/src/util/process_executor.rs b/crates/shirabe/src/util/process_executor.rs index c1be0e18..eae6692b 100644 --- a/crates/shirabe/src/util/process_executor.rs +++ b/crates/shirabe/src/util/process_executor.rs @@ -160,32 +160,6 @@ impl ProcessExecutor { self.do_execute(command, cwd, false, output) } - /// Convenience wrapper used by phase-A code that calls - /// `process.execute(&[String], &mut String, Option<&str>) == 0`. - /// Forwards to `execute`, returning the status code (1 on Err for compatibility) — this - /// mirrors PHP call sites that check the `int` return of `execute()` without a surrounding - /// `try`/`catch`, where an uncaught mock-mismatch exception would otherwise propagate. - // TODO(mock): under a strict `ProcessExecutorMock`, an incomplete expectation list now - // surfaces here as a swallowed "exit code 1" instead of the old `panic!`, so a future test - // ported through this call site could silently take a wrong branch instead of failing loudly. - // `ProcessExecutorMockGuard::__assert_complete` still catches unconsumed expectations at - // scope exit, but not a mismatch that happened to consume nothing. Distinguishing "expectation - // mismatch" from "real process failure" here would need a marker type incompatible with - // `RuntimeException` (see `mock_match`'s doc comment) — deferred until a concrete test needs it. - pub fn execute_args( - &mut self, - command: &[String], - output: &mut String, - cwd: Option<&str>, - ) -> i64 { - let mut buf = String::new(); - let rc = self - .execute(CommandLine::Args(command.to_vec()), &mut buf, cwd) - .unwrap_or(1); - *output = buf; - rc - } - /// runs a process on the commandline in TTY mode pub fn execute_tty<C>(&mut self, command: C, cwd: Option<&str>) -> anyhow::Result<i64> where @@ -984,6 +958,12 @@ impl IntoExecCommand for &[String] { } } +impl<const N: usize> IntoExecCommand for &[String; N] { + fn into_exec_command(self) -> CommandLine { + CommandLine::Args(self.to_vec()) + } +} + /// Models the `mixed &$output` parameter of `ProcessExecutor::execute` (cf. /// `composer/src/Composer/Util/ProcessExecutor.php`). In PHP the behaviour is selected by /// `func_num_args()` and `is_callable($output)`; here each behaviour is a distinct implementing type: diff --git a/crates/shirabe/src/util/svn.rs b/crates/shirabe/src/util/svn.rs index b4f53470..aab90133 100644 --- a/crates/shirabe/src/util/svn.rs +++ b/crates/shirabe/src/util/svn.rs @@ -396,20 +396,20 @@ impl Svn { } /// Returns the version of the svn binary contained in PATH - pub fn binary_version(&mut self) -> Option<String> { + pub fn binary_version(&mut self) -> anyhow::Result<Option<String>> { let mut cached = VERSION.lock().unwrap(); if cached.is_none() { let mut output = String::new(); - if 0 == self.process.borrow_mut().execute_args( + if 0 == self.process.borrow_mut().execute( &["svn".to_string(), "--version".to_string()], &mut output, None, - ) && let Some(matches) = preg_match(php_regex!(r"{(\d+(?:\.\d+)+)}"), &output) + )? && let Some(matches) = preg_match(php_regex!(r"{(\d+(?:\.\d+)+)}"), &output) { *cached = Some(matches.get(1).unwrap_or_default().to_string()); } } - cached.clone() + Ok(cached.clone()) } } |
