use crate::application::ports::RuntimeVcsPort;
use crate::json::Value as JsonValue;
use crate::storage::transaction::snapshot::Xid;
use crate::RedDBResult;
pub type CommitHash = String;
pub type RefName = String;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Author {
pub name: String,
pub email: String,
}
#[derive(Debug, Clone)]
pub struct Commit {
pub hash: CommitHash,
pub root_xid: Xid,
pub parents: Vec<CommitHash>,
pub height: u64,
pub author: Author,
pub committer: Author,
pub message: String,
pub timestamp_ms: i64,
pub signature: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RefKind {
Branch,
Tag,
Head,
}
#[derive(Debug, Clone)]
pub struct Ref {
pub name: RefName,
pub kind: RefKind,
pub target: String,
pub protected: bool,
}
#[derive(Debug, Clone)]
pub struct CreateCommitInput {
pub connection_id: u64,
pub message: String,
pub author: Author,
pub committer: Option<Author>,
pub amend: bool,
pub allow_empty: bool,
}
#[derive(Debug, Clone)]
pub struct CreateBranchInput {
pub name: String,
pub from: Option<String>,
pub connection_id: u64,
}
#[derive(Debug, Clone)]
pub struct CreateTagInput {
pub name: String,
pub target: String,
pub annotation: Option<String>,
}
#[derive(Debug, Clone)]
pub enum CheckoutTarget {
Branch(String),
Commit(CommitHash),
Tag(String),
}
#[derive(Debug, Clone)]
pub struct CheckoutInput {
pub connection_id: u64,
pub target: CheckoutTarget,
pub force: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MergeStrategy {
Auto,
NoFastForward,
FastForwardOnly,
}
#[derive(Debug, Clone)]
pub struct MergeOpts {
pub strategy: MergeStrategy,
pub message: Option<String>,
pub abort_on_conflict: bool,
}
impl Default for MergeOpts {
fn default() -> Self {
Self {
strategy: MergeStrategy::Auto,
message: None,
abort_on_conflict: false,
}
}
}
#[derive(Debug, Clone)]
pub struct MergeInput {
pub connection_id: u64,
pub from: String,
pub opts: MergeOpts,
pub author: Author,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ResetMode {
Soft,
Mixed,
Hard,
}
#[derive(Debug, Clone)]
pub struct ResetInput {
pub connection_id: u64,
pub target: String,
pub mode: ResetMode,
}
#[derive(Debug, Clone, Default)]
pub struct LogRange {
pub to: Option<String>,
pub from: Option<String>,
pub limit: Option<usize>,
pub skip: Option<usize>,
pub no_merges: bool,
}
#[derive(Debug, Clone)]
pub struct LogInput {
pub connection_id: u64,
pub range: LogRange,
}
#[derive(Debug, Clone)]
pub struct DiffInput {
pub from: String,
pub to: String,
pub collection: Option<String>,
pub summary_only: bool,
}
#[derive(Debug, Clone)]
pub struct StatusInput {
pub connection_id: u64,
}
#[derive(Debug, Clone)]
pub enum AsOfSpec {
Commit(CommitHash),
Branch(String),
Tag(String),
TimestampMs(i64),
Snapshot(Xid),
}
#[derive(Debug, Clone)]
pub struct DiffEntry {
pub collection: String,
pub entity_id: String,
pub change: DiffChange,
}
#[derive(Debug, Clone)]
pub enum DiffChange {
Added { after: JsonValue },
Removed { before: JsonValue },
Modified { before: JsonValue, after: JsonValue },
}
#[derive(Debug, Clone, Default)]
pub struct Diff {
pub from: CommitHash,
pub to: CommitHash,
pub entries: Vec<DiffEntry>,
pub added: usize,
pub removed: usize,
pub modified: usize,
}
#[derive(Debug, Clone)]
pub struct MergeOutcome {
pub merge_commit: Option<Commit>,
pub fast_forward: bool,
pub conflicts: Vec<Conflict>,
pub merge_state_id: Option<String>,
}
impl MergeOutcome {
pub fn is_clean(&self) -> bool {
self.conflicts.is_empty()
}
}
#[derive(Debug, Clone)]
pub struct Conflict {
pub id: String,
pub collection: String,
pub entity_id: String,
pub base: JsonValue,
pub ours: JsonValue,
pub theirs: JsonValue,
pub conflicting_paths: Vec<String>,
pub merge_state_id: String,
}
#[derive(Debug, Clone)]
pub struct Status {
pub connection_id: u64,
pub head_ref: Option<RefName>,
pub head_commit: Option<CommitHash>,
pub detached: bool,
pub staged_changes: usize,
pub working_changes: usize,
pub unresolved_conflicts: usize,
pub merge_state_id: Option<String>,
}
pub struct VcsUseCases<'a, P: ?Sized> {
runtime: &'a P,
}
impl<'a, P: RuntimeVcsPort + ?Sized> VcsUseCases<'a, P> {
pub fn new(runtime: &'a P) -> Self {
Self { runtime }
}
pub fn commit(&self, input: CreateCommitInput) -> RedDBResult<Commit> {
self.runtime.vcs_commit(input)
}
pub fn branch_create(&self, input: CreateBranchInput) -> RedDBResult<Ref> {
self.runtime.vcs_branch_create(input)
}
pub fn branch_list(&self) -> RedDBResult<Vec<Ref>> {
self.runtime.vcs_list_refs(Some("refs/heads/"))
}
pub fn branch_delete(&self, name: &str) -> RedDBResult<()> {
self.runtime.vcs_branch_delete(name)
}
pub fn tag(&self, input: CreateTagInput) -> RedDBResult<Ref> {
self.runtime.vcs_tag_create(input)
}
pub fn tag_list(&self) -> RedDBResult<Vec<Ref>> {
self.runtime.vcs_list_refs(Some("refs/tags/"))
}
pub fn checkout(&self, input: CheckoutInput) -> RedDBResult<Ref> {
self.runtime.vcs_checkout(input)
}
pub fn merge(&self, input: MergeInput) -> RedDBResult<MergeOutcome> {
self.runtime.vcs_merge(input)
}
pub fn cherry_pick(
&self,
connection_id: u64,
commit: &str,
author: Author,
) -> RedDBResult<MergeOutcome> {
self.runtime.vcs_cherry_pick(connection_id, commit, author)
}
pub fn revert(&self, connection_id: u64, commit: &str, author: Author) -> RedDBResult<Commit> {
self.runtime.vcs_revert(connection_id, commit, author)
}
pub fn reset(&self, input: ResetInput) -> RedDBResult<()> {
self.runtime.vcs_reset(input)
}
pub fn log(&self, input: LogInput) -> RedDBResult<Vec<Commit>> {
self.runtime.vcs_log(input)
}
pub fn diff(&self, input: DiffInput) -> RedDBResult<Diff> {
self.runtime.vcs_diff(input)
}
pub fn status(&self, input: StatusInput) -> RedDBResult<Status> {
self.runtime.vcs_status(input)
}
pub fn lca(&self, a: &str, b: &str) -> RedDBResult<Option<CommitHash>> {
self.runtime.vcs_lca(a, b)
}
pub fn conflicts_list(&self, merge_state_id: &str) -> RedDBResult<Vec<Conflict>> {
self.runtime.vcs_conflicts_list(merge_state_id)
}
pub fn conflict_resolve(&self, conflict_id: &str, resolved: JsonValue) -> RedDBResult<()> {
self.runtime.vcs_conflict_resolve(conflict_id, resolved)
}
pub fn resolve_as_of(&self, spec: AsOfSpec) -> RedDBResult<Xid> {
self.runtime.vcs_resolve_as_of(spec)
}
pub fn set_versioned(&self, collection: &str, enabled: bool) -> RedDBResult<()> {
self.runtime.vcs_set_versioned(collection, enabled)
}
pub fn list_versioned(&self) -> RedDBResult<Vec<String>> {
self.runtime.vcs_list_versioned()
}
pub fn is_versioned(&self, collection: &str) -> RedDBResult<bool> {
self.runtime.vcs_is_versioned(collection)
}
pub fn resolve_commitish(&self, spec: &str) -> RedDBResult<CommitHash> {
self.runtime.vcs_resolve_commitish(spec)
}
}