gh_cli_rs/
executor.rs

1use crate::error::{GhError, Result};
2use std::process::{Command, Stdio};
3
4/// Executor for GitHub CLI commands
5#[derive(Debug, Clone)]
6pub struct GhExecutor {
7    /// Path to the gh binary (defaults to "gh")
8    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    /// Create a new executor with a custom gh binary path
21    pub fn new(gh_path: String) -> Self {
22        Self { gh_path }
23    }
24
25    /// Check if gh CLI is installed and accessible
26    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    /// Execute a gh command with the given arguments
40    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}