use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GitRef {
pub name: String,
pub oid: String,
pub is_head: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RefUpdate {
pub ref_name: String,
pub old_oid: String,
pub new_oid: String,
#[serde(default)]
pub force: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RefUpdateStatus {
pub ref_name: String,
pub status: String,
pub message: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PushResult {
pub status: String,
pub ref_updates: Vec<RefUpdateStatus>,
}
impl PushResult {
#[must_use]
pub fn is_success(&self) -> bool {
self.status == "ok"
}
#[must_use]
pub fn failed_refs(&self) -> Vec<&RefUpdateStatus> {
self.ref_updates
.iter()
.filter(|r| r.status == "error")
.collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ref_update_deserialize() {
let json = r#"{
"refName": "refs/heads/main",
"oldOid": "abc123",
"newOid": "def456",
"force": false
}"#;
let update: RefUpdate = serde_json::from_str(json).expect("Should deserialize");
assert_eq!(update.ref_name, "refs/heads/main");
assert!(!update.force);
}
#[test]
fn test_push_result_success() {
let result = PushResult {
status: "ok".to_string(),
ref_updates: vec![RefUpdateStatus {
ref_name: "refs/heads/main".to_string(),
status: "ok".to_string(),
message: None,
}],
};
assert!(result.is_success());
assert!(result.failed_refs().is_empty());
}
#[test]
fn test_push_result_failure() {
let result = PushResult {
status: "error".to_string(),
ref_updates: vec![RefUpdateStatus {
ref_name: "refs/heads/main".to_string(),
status: "error".to_string(),
message: Some("Non-fast-forward".to_string()),
}],
};
assert!(!result.is_success());
assert_eq!(result.failed_refs().len(), 1);
}
}