Skip to main content

cli/apps/
recovery.rs

1//! Explicit CLI recovery for interrupted App action-journal operations.
2
3use crate::config::Config;
4use anyhow::{Result, bail};
5use shine_core::plan::PermissionV1;
6
7pub async fn handle_recover_approved(config: &Config, yes: bool) -> Result<()> {
8    let reviewed = crate::lifecycle_plan::review_plans(
9        config,
10        [crate::lifecycle_plan::LifecyclePlanRequest::app_recovery()],
11        yes,
12    )
13    .await?
14    .into_iter()
15    .next()
16    .expect("one reviewed App recovery Plan");
17    if reviewed
18        .approved
19        .permissions()
20        .contains(&PermissionV1::Administrator)
21        && !crate::privilege::ensure_admin(1).await?
22    {
23        bail!("administrator permission was not granted");
24    }
25    let runtime = crate::lifecycle_plan::prepare_runtime(config, &reviewed).await?;
26    let report = match crate::lifecycle_plan::execute_reviewed(
27        config,
28        runtime,
29        reviewed,
30        shine_core::frontend::ExecutionOptions::default(),
31        &mut shine_core::runtime::NullObserver,
32        &mut crate::presentation::TerminalInteraction,
33    )
34    .await?
35    {
36        shine_core::frontend::OperationDetails::AppRecovery(report) => *report,
37        _ => unreachable!("reviewed operation result type"),
38    };
39
40    if report.rolled_back_actions.is_empty() {
41        println!(
42            "App recovery complete: cleared the interrupted operation journal; no transaction-created files were removed."
43        );
44    } else {
45        println!(
46            "App recovery complete: rolled back {} interrupted file change(s) and cleared the operation journal.",
47            report.rolled_back_actions.len()
48        );
49    }
50    Ok(())
51}