1use std::io::ErrorKind;
2
3pub(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 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}