rustic-git 0.6.0

A Rustic Git - clean type-safe API over git cli
Documentation
use std::fmt;
use std::io;

pub type Result<T> = std::result::Result<T, GitError>;

#[derive(Debug, Clone)]
pub enum GitError {
    IoError(String),
    CommandFailed(String),
}

impl fmt::Display for GitError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            GitError::IoError(msg) => write!(f, "IO error: {}", msg),
            GitError::CommandFailed(msg) => write!(f, "Git command failed: {}", msg),
        }
    }
}

impl std::error::Error for GitError {}

impl From<io::Error> for GitError {
    fn from(error: io::Error) -> Self {
        GitError::IoError(error.to_string())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io;

    #[test]
    fn test_git_error_io_error_variant() {
        let error = GitError::IoError("test io error".to_string());
        match error {
            GitError::IoError(msg) => assert_eq!(msg, "test io error"),
            _ => panic!("Expected IoError variant"),
        }
    }

    #[test]
    fn test_git_error_command_failed_variant() {
        let error = GitError::CommandFailed("test command failed".to_string());
        match error {
            GitError::CommandFailed(msg) => assert_eq!(msg, "test command failed"),
            _ => panic!("Expected CommandFailed variant"),
        }
    }

    #[test]
    fn test_git_error_clone() {
        let error1 = GitError::IoError("test error".to_string());
        let error2 = error1.clone();

        match (error1, error2) {
            (GitError::IoError(msg1), GitError::IoError(msg2)) => assert_eq!(msg1, msg2),
            _ => panic!("Clone failed or wrong variant"),
        }
    }

    #[test]
    fn test_git_error_debug() {
        let io_error = GitError::IoError("io test".to_string());
        let cmd_error = GitError::CommandFailed("cmd test".to_string());

        let io_debug = format!("{:?}", io_error);
        let cmd_debug = format!("{:?}", cmd_error);

        assert!(io_debug.contains("IoError"));
        assert!(io_debug.contains("io test"));
        assert!(cmd_debug.contains("CommandFailed"));
        assert!(cmd_debug.contains("cmd test"));
    }

    #[test]
    fn test_from_io_error() {
        let io_err = io::Error::new(io::ErrorKind::NotFound, "file not found");
        let git_err: GitError = io_err.into();

        match git_err {
            GitError::IoError(msg) => assert!(msg.contains("file not found")),
            _ => panic!("Expected IoError variant from io::Error conversion"),
        }
    }

    #[test]
    fn test_from_io_error_different_kinds() {
        let permission_err = io::Error::new(io::ErrorKind::PermissionDenied, "access denied");
        let git_err: GitError = permission_err.into();

        match git_err {
            GitError::IoError(msg) => assert!(msg.contains("access denied")),
            _ => panic!("Expected IoError variant"),
        }
    }

    #[test]
    fn test_result_type_alias() {
        fn test_function() -> Result<String> {
            Ok("success".to_string())
        }

        let result = test_function();
        assert!(result.is_ok());
        assert_eq!(result.unwrap(), "success");
    }

    #[test]
    fn test_result_type_alias_error() {
        fn test_function() -> Result<String> {
            Err(GitError::CommandFailed("test error".to_string()))
        }

        let result = test_function();
        assert!(result.is_err());
        match result.unwrap_err() {
            GitError::CommandFailed(msg) => assert_eq!(msg, "test error"),
            _ => panic!("Expected CommandFailed variant"),
        }
    }
}