Skip to main content

weavatrix_worktree/
worktree.rs

1use std::path::Path;
2
3use weavatrix_refactor_plan::EditPlan;
4
5use crate::{
6    WorktreePlan,
7    error::{TransactionPhase, WorktreeError, WorktreeErrorCode},
8    filesystem::FsRoot,
9    operation::{
10        PreparedWorktreeTransaction, RetainedApplyReport, UndoId, UndoReceipt, UndoRetention,
11        UndoRollbackReport, UndoStoreUsage, dry_run_operation_plan, prepare_operation_plan,
12        recover_operation_transaction, undo_discard, undo_receipts, undo_rollback, undo_usage,
13    },
14    options::WorktreeOptions,
15    report::{
16        ApplyReport, DryRunReport, RecoveryReport, WorktreeApplyReport, WorktreeDryRunReport,
17    },
18    transaction::{
19        PreparedTransaction, dry_run_report, prepare_transaction, project_plan, recover_transaction,
20    },
21};
22
23/// Capability-rooted facade for deterministic multi-file edit transactions.
24pub struct Worktree {
25    root: FsRoot,
26    options: WorktreeOptions,
27}
28
29impl Worktree {
30    /// Opens a worktree with bounded default limits and automatic parallelism.
31    pub fn open(root: impl AsRef<Path>) -> Result<Self, WorktreeError> {
32        Self::open_with(root, WorktreeOptions::default())
33    }
34
35    /// Opens a worktree with explicit limits and preparation parallelism.
36    pub fn open_with(
37        root: impl AsRef<Path>,
38        options: WorktreeOptions,
39    ) -> Result<Self, WorktreeError> {
40        options.validate()?;
41        let root = FsRoot::open(root.as_ref()).map_err(|error| {
42            WorktreeError::with_source(
43                WorktreeErrorCode::InvalidRoot,
44                TransactionPhase::Open,
45                "failed to open a real worktree root capability",
46                error,
47            )
48        })?;
49        Ok(Self { root, options })
50    }
51
52    #[must_use]
53    pub const fn options(&self) -> WorktreeOptions {
54        self.options
55    }
56
57    /// Validates, reads, hashes, and projects a plan without creating state.
58    pub fn dry_run(&self, plan: &EditPlan) -> Result<DryRunReport, WorktreeError> {
59        let projected = project_plan(&self.root, self.options, plan)?;
60        Ok(dry_run_report(plan, &projected))
61    }
62
63    /// Locks, validates, backs up, stages, and journals the complete plan.
64    pub fn prepare(&self, plan: &EditPlan) -> Result<PreparedTransaction, WorktreeError> {
65        prepare_transaction(&self.root, self.options, plan)
66    }
67
68    /// Prepares and commits a complete plan.
69    pub fn apply(&self, plan: &EditPlan) -> Result<ApplyReport, WorktreeError> {
70        self.prepare(plan)?.commit()
71    }
72
73    /// Validates and projects create/delete/modify/rename operations without writing state.
74    pub fn dry_run_plan(&self, plan: &WorktreePlan) -> Result<WorktreeDryRunReport, WorktreeError> {
75        dry_run_operation_plan(&self.root, self.options, plan)
76    }
77
78    /// Validates, locks, stages, and journals every submitted refactor operation.
79    pub fn prepare_plan(
80        &self,
81        plan: &WorktreePlan,
82    ) -> Result<PreparedWorktreeTransaction, WorktreeError> {
83        prepare_operation_plan(&self.root, self.options, plan)
84    }
85
86    /// Prepares and durably commits every submitted filesystem operation.
87    pub fn apply_plan(&self, plan: &WorktreePlan) -> Result<WorktreeApplyReport, WorktreeError> {
88        self.prepare_plan(plan)?.commit()
89    }
90
91    /// Commits a plan while retaining exact rollback evidence and a receipt.
92    pub fn apply_plan_retained(
93        &self,
94        plan: &WorktreePlan,
95        retention: UndoRetention,
96    ) -> Result<RetainedApplyReport, WorktreeError> {
97        self.prepare_plan(plan)?.commit_retained(retention)
98    }
99
100    /// Lists every retained undo receipt in deterministic identifier order.
101    pub fn undo_receipts(&self) -> Result<Vec<UndoReceipt>, WorktreeError> {
102        undo_receipts(&self.root, self.options)
103    }
104
105    /// Reports the bounded usage of the retained undo store.
106    pub fn undo_usage(&self) -> Result<UndoStoreUsage, WorktreeError> {
107        undo_usage(&self.root, self.options)
108    }
109
110    /// Exactly restores the state captured by one retained commit.
111    pub fn rollback_undo(&self, id: &UndoId) -> Result<UndoRollbackReport, WorktreeError> {
112        undo_rollback(&self.root, self.options, id)
113    }
114
115    /// Verifies and removes one retained receipt without changing any target.
116    pub fn discard_undo(&self, id: &UndoId) -> Result<usize, WorktreeError> {
117        undo_discard(&self.root, self.options, id)
118    }
119
120    /// Replays and safely resolves an interrupted transaction journal.
121    pub fn recover(&self) -> Result<RecoveryReport, WorktreeError> {
122        if let Some(report) = recover_operation_transaction(&self.root, self.options)? {
123            return Ok(report);
124        }
125        recover_transaction(&self.root, self.options)
126    }
127}