spin_templates/
git.rs

1use std::io::ErrorKind;
2
3// TODO: the following and the second half of plugins/git.rs are duplicates
4
5pub(crate) enum GitError {
6    ProgramFailed(Vec<u8>),
7    ProgramNotFound,
8    Other(anyhow::Error),
9}
10
11impl std::fmt::Display for GitError {
12    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13        match self {
14            Self::ProgramNotFound => f.write_str("`git` command not found - is git installed?"),
15            Self::Other(e) => e.fmt(f),
16            Self::ProgramFailed(stderr) => match std::str::from_utf8(stderr) {
17                Ok(s) => f.write_str(s),
18                Err(_) => f.write_str("(cannot get error)"),
19            },
20        }
21    }
22}
23
24pub(crate) trait UnderstandGitResult {
25    fn understand_git_result(self) -> Result<Vec<u8>, GitError>;
26}
27
28impl UnderstandGitResult for Result<std::process::Output, std::io::Error> {
29    fn understand_git_result(self) -> Result<Vec<u8>, GitError> {
30        match self {
31            Ok(output) => {
32                if output.status.success() {
33                    Ok(output.stdout)
34                } else {
35                    Err(GitError::ProgramFailed(output.stderr))
36                }
37            }
38            Err(e) => match e.kind() {
39                // TODO: consider cases like insufficient permission?
40                ErrorKind::NotFound => Err(GitError::ProgramNotFound),
41                _ => {
42                    let err = anyhow::Error::from(e).context("Failed to run `git` command");
43                    Err(GitError::Other(err))
44                }
45            },
46        }
47    }
48}