Skip to main content

grex_core/execute/
mod.rs

1//! Action execution framework.
2//!
3//! Stage 5a of M3B wires the surface through which any
4//! [`crate::pack::Action`] is consumed at run time. The [`ActionExecutor`]
5//! trait is the uniform boundary:
6//!
7//! * [`PlanExecutor`] — produces [`ExecStep`] records describing what a
8//!   wet-run _would_ do without mutating state. Safe to call over any pack.
9//! * [`FsExecutor`] (slice 5b) performs the side effects and returns the
10//!   same [`ExecStep`] shape with [`ExecResult::PerformedChange`].
11//!
12//! Keeping the trait narrow (one `execute` method, read-only [`ExecCtx`])
13//! means implementations can be tested in isolation and swapped freely.
14//!
15//! # Scope (5a)
16//!
17//! The planner applies variable expansion, evaluates predicates, reads the
18//! filesystem for idempotency (`path.exists()`, symlink target), but never
19//! writes. `RegKey` and `PsVersion` predicates probe the Windows registry
20//! and PowerShell on Windows (M4-C) and surface
21//! [`ExecError::PredicateNotSupported`] on other platforms.
22
23pub mod error;
24pub mod fs_executor;
25pub mod plan;
26
27mod ctx;
28mod predicate;
29mod step;
30
31use crate::pack::Action;
32
33pub use ctx::{ExecCtx, MetaVisitedSet, Platform};
34pub use error::{ExecError, EXEC_STDERR_CAPTURE_MAX};
35pub use fs_executor::FsExecutor;
36pub use plan::PlanExecutor;
37pub use step::{ExecResult, ExecStep, PredicateOutcome, StepKind};
38
39/// Uniform surface for anything that consumes an [`Action`].
40///
41/// Implementations MUST treat [`ExecCtx`] as read-only and MUST return a
42/// [`ExecStep`] on success even for no-op paths (e.g. a predicate that was
43/// not satisfied under `on_fail: skip`). A [`ExecStep`] with
44/// [`ExecResult::NoOp`] is NOT an error — errors are reserved for
45/// authoring bugs (bad var expansion, exec shape invariants, hard predicate
46/// failure under `on_fail: error`).
47pub trait ActionExecutor: Send + Sync {
48    /// Short stable identifier for the implementation. Used in logs / audit
49    /// trails. Never rendered to end users as a translation key.
50    fn name(&self) -> &'static str;
51
52    /// Execute a single [`Action`] against `ctx`.
53    ///
54    /// # Errors
55    ///
56    /// Returns [`ExecError`] on variable-expansion failure, invalid post-
57    /// expansion paths, `require` predicates that fail with `on_fail:
58    /// error`, or `exec`-shape invariant violations.
59    fn execute(&self, action: &Action, ctx: &ExecCtx<'_>) -> Result<ExecStep, ExecError>;
60}