Skip to main content

claw_branch/commit/
cherry.rs

1//! Cherry-pick selection models for selective branch promotion.
2
3use serde::{Deserialize, Serialize};
4use uuid::Uuid;
5
6use crate::types::EntityType;
7
8/// Selects a subset of entities (and optionally fields) from a branch to promote.
9///
10/// # Example
11/// ```rust,ignore
12/// let pick = CherryPick::specific_entities(src, tgt, EntityType::MemoryRecord, vec!["id1".to_string()]);
13/// ```
14#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
15pub struct CherryPick {
16    /// The branch from which entities are sourced.
17    pub source_branch_id: Uuid,
18    /// The branch into which the entities are written.
19    pub target_branch_id: Uuid,
20    /// Ordered list of entity selections to process.
21    pub entity_selections: Vec<EntitySelection>,
22    /// Optional human-readable commit message.
23    pub message: Option<String>,
24}
25
26/// Describes which entities (and which fields) to promote for one entity type.
27#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
28pub struct EntitySelection {
29    /// The entity table to read from.
30    pub entity_type: EntityType,
31    /// The entity identifiers to cherry-pick.  An empty vec means *all* entities of this type.
32    pub entity_ids: Vec<String>,
33    /// Restrict promotion to these fields only.  `None` means all fields.
34    pub fields: Option<Vec<String>>,
35}
36
37impl CherryPick {
38    /// Promotes every entity of `entity_type` from `source` to `target`.
39    ///
40    /// # Example
41    /// ```rust,ignore
42    /// let pick = CherryPick::all_of_type(src_id, tgt_id, EntityType::MemoryRecord);
43    /// ```
44    pub fn all_of_type(source: Uuid, target: Uuid, entity_type: EntityType) -> Self {
45        Self {
46            source_branch_id: source,
47            target_branch_id: target,
48            entity_selections: vec![EntitySelection {
49                entity_type,
50                entity_ids: Vec::new(),
51                fields: None,
52            }],
53            message: None,
54        }
55    }
56
57    /// Promotes specific entities of `entity_type` from `source` to `target`.
58    ///
59    /// # Example
60    /// ```rust,ignore
61    /// let pick = CherryPick::specific_entities(src_id, tgt_id, EntityType::MemoryRecord, ids);
62    /// ```
63    pub fn specific_entities(
64        source: Uuid,
65        target: Uuid,
66        entity_type: EntityType,
67        ids: Vec<String>,
68    ) -> Self {
69        Self {
70            source_branch_id: source,
71            target_branch_id: target,
72            entity_selections: vec![EntitySelection {
73                entity_type,
74                entity_ids: ids,
75                fields: None,
76            }],
77            message: None,
78        }
79    }
80
81    /// Restricts the last added selection to only the specified field names.
82    ///
83    /// Useful for chaining with [`specific_entities`](Self::specific_entities).
84    pub fn specific_fields(mut self, fields: Vec<String>) -> Self {
85        if let Some(sel) = self.entity_selections.last_mut() {
86            sel.fields = Some(fields);
87        }
88        self
89    }
90
91    /// Attaches a commit message to the cherry-pick.
92    pub fn with_message(mut self, message: impl Into<String>) -> Self {
93        self.message = Some(message.into());
94        self
95    }
96}