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
23pub struct Worktree {
25 root: FsRoot,
26 options: WorktreeOptions,
27}
28
29impl Worktree {
30 pub fn open(root: impl AsRef<Path>) -> Result<Self, WorktreeError> {
32 Self::open_with(root, WorktreeOptions::default())
33 }
34
35 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 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 pub fn prepare(&self, plan: &EditPlan) -> Result<PreparedTransaction, WorktreeError> {
65 prepare_transaction(&self.root, self.options, plan)
66 }
67
68 pub fn apply(&self, plan: &EditPlan) -> Result<ApplyReport, WorktreeError> {
70 self.prepare(plan)?.commit()
71 }
72
73 pub fn dry_run_plan(&self, plan: &WorktreePlan) -> Result<WorktreeDryRunReport, WorktreeError> {
75 dry_run_operation_plan(&self.root, self.options, plan)
76 }
77
78 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 pub fn apply_plan(&self, plan: &WorktreePlan) -> Result<WorktreeApplyReport, WorktreeError> {
88 self.prepare_plan(plan)?.commit()
89 }
90
91 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 pub fn undo_receipts(&self) -> Result<Vec<UndoReceipt>, WorktreeError> {
102 undo_receipts(&self.root, self.options)
103 }
104
105 pub fn undo_usage(&self) -> Result<UndoStoreUsage, WorktreeError> {
107 undo_usage(&self.root, self.options)
108 }
109
110 pub fn rollback_undo(&self, id: &UndoId) -> Result<UndoRollbackReport, WorktreeError> {
112 undo_rollback(&self.root, self.options, id)
113 }
114
115 pub fn discard_undo(&self, id: &UndoId) -> Result<usize, WorktreeError> {
117 undo_discard(&self.root, self.options, id)
118 }
119
120 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}