git-file-history 0.1.0

TUI for browsing the Git history of a single file
use std::{io, process::ExitStatus};

use thiserror::Error;

pub(crate) type Result<T> = std::result::Result<T, AppError>;

#[derive(Debug, Error)]
pub(crate) enum AppError {
    #[error("{0}")]
    Message(String),
    #[error("{context}: {source}")]
    Io {
        context: String,
        #[source]
        source: io::Error,
    },
    #[error("Git executable was not found on PATH. Install Git or make sure `git` is available on PATH.")]
    GitNotFound,
    #[error("{command} exited with {status}: {output}")]
    GitCommandFailed {
        command: &'static str,
        status: ExitStatus,
        output: String,
    },
    #[error("{command} exited with {status}")]
    GitCommandFailedWithoutOutput {
        command: &'static str,
        status: ExitStatus,
    },
}

impl AppError {
    pub(crate) fn message(message: impl Into<String>) -> Self {
        Self::Message(message.into())
    }

    pub(crate) fn io(context: impl Into<String>, source: io::Error) -> Self {
        Self::Io {
            context: context.into(),
            source,
        }
    }

    pub(crate) fn git_spawn(source: io::Error) -> Self {
        if source.kind() == io::ErrorKind::NotFound {
            Self::GitNotFound
        } else {
            Self::io("failed to run git", source)
        }
    }

    pub(crate) fn git_command_failed(
        command: &'static str,
        status: ExitStatus,
        output: String,
    ) -> Self {
        Self::GitCommandFailed {
            command,
            status,
            output,
        }
    }

    pub(crate) fn git_command_failed_without_output(
        command: &'static str,
        status: ExitStatus,
    ) -> Self {
        Self::GitCommandFailedWithoutOutput { command, status }
    }
}