Skip to main content

ExecCtx

Struct ExecCtx 

Source
#[non_exhaustive]
pub struct ExecCtx<'a> { pub vars: &'a VarEnv, pub pack_root: &'a Path, pub workspace: &'a Path, pub platform: Platform, pub registry: Option<&'a Arc<Registry>>, pub pack_type_registry: Option<&'a Arc<PackTypeRegistry>>, pub visited_meta: Option<&'a MetaVisitedSet>, pub scheduler: Option<&'a Arc<Scheduler>>, }
Expand description

Read-only context passed to every crate::execute::ActionExecutor::execute call.

Lifetimes are carried through rather than cloning so the planner can run over a borrowed VarEnv without incurring a copy per action. The ctx is Copy-cheap in the sense that all fields are &-references — callers typically pass &ctx rather than cloning.

§Why references, not owned data

Executors are stateless by contract; any “state” lives in the caller’s driver. Owning data inside ExecCtx would either force clones per action or require interior mutability — both violate the framework goal of “future-proof, maximally decoupled”.

Marked #[non_exhaustive] so future slots (plugin registry handle, scheduler token, teardown hook …) can land without breaking library consumers who destructure the struct.

Fields (Non-exhaustive)§

This struct is marked as non-exhaustive
Non-exhaustive structs could have additional fields added in future. Therefore, non-exhaustive structs cannot be constructed in external crates using the traditional Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.
§vars: &'a VarEnv

Variable lookup table used by every expand_* call.

§pack_root: &'a Path

Pack workdir (the pack’s on-disk root). Relative src paths in symlink/exec actions resolve against this directory.

§workspace: &'a Path

Workspace root (the user’s configured grex workspace). Relative destination paths (though rare — spec encourages absolute) resolve here.

§platform: Platform

Platform tag. Defaults to Platform::current but is overridable in tests to exercise when.os branches deterministically.

§registry: Option<&'a Arc<Registry>>

Outer Registry handle for plugins that recurse into nested actions (today: when). Populated by the concrete executors (FsExecutor, PlanExecutor) right before plugin dispatch so nested execute calls go through the caller’s registry instead of a freshly bootstrapped default. None outside an executor-driven call (e.g. direct plugin invocation in tests) — plugins must treat absence as “no nested dispatch available” and fall back to their own bootstrap.

§pack_type_registry: Option<&'a Arc<PackTypeRegistry>>

Outer PackTypeRegistry handle for pack-type plugins that recurse across sibling pack types (today: meta dispatching into child packs of arbitrary type). Populated by the pack-level driver before invoking crate::plugin::PackTypePlugin methods. None outside a driver-scoped call — see ExecCtx::registry for the same pattern at the action level.

Stage B (M5-1B) only exposes the slot; the dispatch swap that actually threads a pack-type registry through the executor chain lands in Stage C.

§visited_meta: Option<&'a MetaVisitedSet>

Shared cycle-detection set owned by the outer sync driver.

M5-2c: crate::plugin::pack_type::MetaPlugin mutates this set under a lock at every recursion boundary. Absent (None) means no outer driver is tracking recursion — MetaPlugin treats that as “caller promises a single-level dispatch” and skips the check. The sync driver attaches a fresh empty set at the top of every install / update / sync run so the first plugin call observes an empty history. Teardown runs do NOT attach a set: crate::sync::teardown drives every pack through the walker’s reverse post-order, so each crate::plugin::PackTypePlugin::teardown invocation corresponds to a single pack and has no in-process recursion to guard. The cycle-detection set stays defense-in-depth for direct plugin callers (e.g. the meta_recursion integration tests) that recurse through MetaPlugin::recurse_children.

§scheduler: Option<&'a Arc<Scheduler>>

Bounded parallel Scheduler handle — feat-m6-1.

Populated by crate::sync::run at the top of every sync run so plugins that fan out can bound in-flight children via the same permit pool used by the outer walker. None outside a sync-driven call (e.g. direct plugin invocation in tests) — plugins that need to respect the cap must treat absence as “no bound configured” and fall back to unbounded/serial per their own policy.

feat-m6-1 lands the slot and CLI flag; plugin acquisition sites land in feat-m6-2 alongside per-pack .grex-lock coordination.

Implementations§

Source§

impl<'a> ExecCtx<'a>

Source

pub fn new(vars: &'a VarEnv, pack_root: &'a Path, workspace: &'a Path) -> Self

Build a context with platform defaulted to the current target and no outer registry attached. Executors attach the registry via ExecCtx::with_registry before invoking plugin dispatch.

Source

pub fn with_platform(self, p: Platform) -> Self

Override the platform tag (useful for tests and dry-run overrides).

Source

pub fn with_registry(self, reg: &'a Arc<Registry>) -> Self

Attach the outer Registry so plugins that recurse (today: when) dispatch nested actions through the caller’s registry instead of a fresh Registry::bootstrap. Used by crate::execute::FsExecutor and crate::execute::PlanExecutor just before they hand control to a plugin.

Source

pub fn with_pack_type_registry(self, reg: &'a Arc<PackTypeRegistry>) -> Self

Attach the outer PackTypeRegistry so pack-type plugins that recurse across child packs (today: meta) dispatch through the caller’s registry rather than a fresh PackTypeRegistry::bootstrap. The dispatch swap that exercises this slot ships in M5-1 Stage C; Stage B only lands the slot and the builder method.

Source

pub fn with_visited_meta(self, visited: &'a MetaVisitedSet) -> Self

Attach the shared cycle-detection set used by crate::plugin::pack_type::MetaPlugin recursion. The sync driver builds one empty set per run() invocation and threads it through every ExecCtx it constructs so nested install / sync / update / teardown calls observe the same history.

Source

pub fn with_scheduler(self, scheduler: &'a Arc<Scheduler>) -> Self

Attach a bounded parallel Scheduler handle. The sync driver builds one Scheduler per run() invocation (permits == --parallel N) and threads the same Arc through every ExecCtx so sibling plugin dispatch shares the permit pool.

feat-m6-1 only plumbs the slot; acquisition sites land in feat-m6-2. Callers may still attach a scheduler today — it is observably inert until the per-pack lock wiring lands.

Trait Implementations§

Source§

impl<'a> Debug for ExecCtx<'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<'a> Freeze for ExecCtx<'a>

§

impl<'a> !RefUnwindSafe for ExecCtx<'a>

§

impl<'a> Send for ExecCtx<'a>

§

impl<'a> Sync for ExecCtx<'a>

§

impl<'a> Unpin for ExecCtx<'a>

§

impl<'a> UnsafeUnpin for ExecCtx<'a>

§

impl<'a> !UnwindSafe for ExecCtx<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more