1use crate::error::{GhError, Result};
2use std::process::{Command, Stdio};
3
4#[derive(Debug, Clone)]
6pub struct GhExecutor {
7 pub gh_path: String,
9}
10
11impl Default for GhExecutor {
12 fn default() -> Self {
13 Self {
14 gh_path: "gh".to_string(),
15 }
16 }
17}
18
19impl GhExecutor {
20 pub fn new(gh_path: String) -> Self {
22 Self { gh_path }
23 }
24
25 pub fn check_installation(&self) -> Result<String> {
27 let output = Command::new(&self.gh_path)
28 .arg("--version")
29 .output()
30 .map_err(|_| GhError::GhNotFound)?;
31
32 if output.status.success() {
33 Ok(String::from_utf8_lossy(&output.stdout).to_string())
34 } else {
35 Err(GhError::GhNotFound)
36 }
37 }
38
39 pub fn execute(&self, args: &[String]) -> Result<String> {
41 let output = Command::new(&self.gh_path)
42 .args(args)
43 .stdout(Stdio::piped())
44 .stderr(Stdio::piped())
45 .output()?;
46
47 if output.status.success() {
48 Ok(String::from_utf8(output.stdout)?)
49 } else {
50 Err(GhError::from_output(output))
51 }
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 #[test]
60 fn test_executor_creation() {
61 let executor = GhExecutor::default();
62 assert_eq!(executor.gh_path, "gh");
63
64 let custom_executor = GhExecutor::new("/custom/path/gh".to_string());
65 assert_eq!(custom_executor.gh_path, "/custom/path/gh");
66 }
67}