use khive_runtime::portability::KgArchive;
use crate::error::VcsError;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum MergeStrategy {
#[default]
Auto,
Ours,
Theirs,
}
#[derive(Debug)]
pub enum MergeResult {
Clean { merged: KgArchive },
Conflicts { conflicts: Vec<MergeConflict> },
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum MergeConflict {
NameConflict {
entity_id: uuid::Uuid,
ours: String,
theirs: String,
},
KindConflict {
entity_id: uuid::Uuid,
ours: String,
theirs: String,
},
PropertyMismatch {
entity_id: uuid::Uuid,
key: String,
ours: serde_json::Value,
theirs: serde_json::Value,
},
ModifyDelete {
entity_id: uuid::Uuid,
modified_in: BranchSide,
deleted_in: BranchSide,
},
EdgeModifyDelete {
source_id: uuid::Uuid,
target_id: uuid::Uuid,
relation: String,
modified_in: BranchSide,
deleted_in: BranchSide,
},
DanglingEdge {
source_id: uuid::Uuid,
target_id: uuid::Uuid,
relation: String,
missing_endpoint: uuid::Uuid,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum BranchSide {
Ours,
Theirs,
}
pub trait MergeEngine: Send + Sync {
fn merge(
&self,
base: &KgArchive,
ours: &KgArchive,
theirs: &KgArchive,
strategy: MergeStrategy,
) -> Result<MergeResult, VcsError>;
}
pub struct NoOpMergeEngine;
impl MergeEngine for NoOpMergeEngine {
fn merge(
&self,
_base: &KgArchive,
_ours: &KgArchive,
_theirs: &KgArchive,
_strategy: MergeStrategy,
) -> Result<MergeResult, VcsError> {
Err(VcsError::MergeNotImplemented)
}
}