Skip to main content

rskit_git/cli/
runner.rs

1use std::path::{Path, PathBuf};
2
3use rskit_errors::AppResult;
4use rskit_process::{ProcessConfig, ProcessResult, ProcessSpec};
5
6use crate::core::Executor;
7use crate::error::GitError;
8
9/// Git CLI command runner rooted at a repository.
10pub struct GitCli {
11    root: PathBuf,
12}
13
14impl GitCli {
15    /// Creates a Git CLI runner rooted at the repository path.
16    pub fn new(root: PathBuf) -> Self {
17        Self { root }
18    }
19
20    /// Returns the repository root.
21    pub fn root(&self) -> &Path {
22        &self.root
23    }
24
25    pub(crate) fn run(&self, args: &[&str]) -> AppResult<Vec<u8>> {
26        let output = self.run_result(args)?;
27        if output.success() && !output.stdout_truncated && !output.stderr_truncated {
28            Ok(output.stdout_bytes)
29        } else {
30            Err(Self::command_failed(args, output))
31        }
32    }
33
34    pub(crate) fn run_result(&self, args: &[&str]) -> AppResult<ProcessResult> {
35        let command = ProcessSpec::new("git")
36            .args(args.iter().copied())
37            .dir(&self.root)
38            .env("GIT_TERMINAL_PROMPT", "0");
39        let config = ProcessConfig::default().with_timeout(None);
40        rskit_process::run(&command, &config)
41    }
42
43    #[allow(dead_code)]
44    pub(crate) fn not_implemented<T>(&self, operation: &'static str) -> AppResult<T> {
45        Err(GitError::NotImplemented { operation }.into())
46    }
47
48    pub(crate) fn command_failed(args: &[&str], output: ProcessResult) -> rskit_errors::AppError {
49        GitError::CommandFailed {
50            args: args.iter().map(|arg| (*arg).to_string()).collect(),
51            exit_code: output.exit_code,
52            stdout: output.stdout.trim().to_string(),
53            stderr: output.stderr.trim().to_string(),
54            stdout_truncated: output.stdout_truncated,
55            stderr_truncated: output.stderr_truncated,
56        }
57        .into()
58    }
59}
60
61impl Executor for GitCli {
62    fn exec(&self, args: &[&str]) -> AppResult<Vec<u8>> {
63        self.run(args)
64    }
65}