Skip to main content

WalkVisitor

Trait WalkVisitor 

Source
pub trait WalkVisitor:
    Send
    + Sync
    + 'static {
    type Summary: WalkSummary;
    type DirContext: Clone + Send + Sync + 'static;
    type DirState: Send;

    // Required methods
    fn root_dir_context(&self) -> Self::DirContext;
    fn permit_kind(&self) -> PermitKind;
    fn want_permit(&self, hint: Option<EntryKind>) -> bool;
    fn fail_early(&self) -> bool;
    fn filter(&self) -> Option<&FilterSettings>;
    fn visit_leaf(
        &self,
        cx: &EntryCx,
        parent_ctx: &Self::DirContext,
        handle: Handle,
        kind: EntryKind,
        permit: Option<LeafPermit>,
    ) -> impl Future<Output = Result<Self::Summary, OperationError<Self::Summary>>> + Send;
    fn dir_pre(
        &self,
        cx: &EntryCx,
        parent_ctx: &Self::DirContext,
        handle: &Handle,
    ) -> impl Future<Output = DirPreResult<Self>> + Send;
    fn dir_post(
        &self,
        cx: &EntryCx,
        state: Self::DirState,
        processed: &ProcessedChildren,
        child_result: Result<Self::Summary, OperationError<Self::Summary>>,
    ) -> impl Future<Output = Result<Self::Summary, OperationError<Self::Summary>>> + Send;

    // Provided method
    fn on_skip(
        &self,
        _cx: &EntryCx,
        _kind: EntryKind,
        _skip_result: &FilterResult,
    ) -> Self::Summary { ... }
}
Expand description

A tool’s policy for a single-tree safe walk.

The driver calls these to make the per-entry decisions it cannot know itself; it owns everything else (enumeration, permit lifecycle, spawning, the drop-before-recurse invariant, error fold). All futures are + Send (RPITIT) so the driver can spawn them; the visitor is shared as Arc<V>.

Required Associated Types§

Source

type Summary: WalkSummary

Per-run summary type (the tool’s Summary).

Source

type DirContext: Clone + Send + Sync + 'static

Inherited per-directory context: what a directory’s children need from that directory (an “inherited attribute” of the tree walk). The driver clones it into each child task and hands it to the child’s Self::visit_leaf / Self::dir_pre.

This is the single-tree driver’s bridge to copy’s second (destination) tree: copy puts the open destination directory handle (plus its freshness) here, so each child can create/overwrite its own destination entry without the driver ever modeling a second tree. chmod and rm — which only ever need the source parent the driver already provides — use ().

Source

type DirState: Send

State threaded from Self::dir_pre to Self::dir_post within one task (so it need not be Send across the per-child spawn boundary — dir_pre/recurse/dir_post all run in the same task).

Required Methods§

Source

fn root_dir_context(&self) -> Self::DirContext

The inherited context for the walk root’s children — the seed of the DirContext chain. copy returns its top-level destination directory here; chmod/rm return (). (The root entry itself is processed with this same context as its “parent” context.)

Source

fn permit_kind(&self) -> PermitKind

Which backpressure pool a leaf permit comes from for this tool.

Source

fn want_permit(&self, hint: Option<EntryKind>) -> bool

Whether to pre-acquire a leaf permit for a child with this getdents d_type hint. Must return false for a hinted directory (it would recurse and a held permit could deadlock); the canonical policy is “known non-directory only”. hint == None (DT_UNKNOWN) is a tool choice.

Source

fn fail_early(&self) -> bool

Whether the walk stops at the first error (--fail-early).

Source

fn filter(&self) -> Option<&FilterSettings>

The active filter, if any (drives walk::filter_is_dir / walk::should_skip_entry_ref).

Source

fn visit_leaf( &self, cx: &EntryCx, parent_ctx: &Self::DirContext, handle: Handle, kind: EntryKind, permit: Option<LeafPermit>, ) -> impl Future<Output = Result<Self::Summary, OperationError<Self::Summary>>> + Send

Process a non-directory entry (file / symlink / special). parent_ctx is the inherited context of the directory containing this entry (copy’s destination parent + freshness). The pre-acquired permit (if any) is held for the duration and dropped on return.

Source

fn dir_pre( &self, cx: &EntryCx, parent_ctx: &Self::DirContext, handle: &Handle, ) -> impl Future<Output = DirPreResult<Self>> + Send

Pre-order step for a directory entry, run after the leaf permit has been dropped and before the contents are walked. parent_ctx is the inherited context of the containing directory. Returns DirAction::Skip to prune the subtree or DirAction::Descend to walk it (supplying the child context for this directory’s own children, and the dir_post state).

chmod applies the pre-order mode change here (unless deferred) and opens the dir; copy resolves the destination directory (mkdir/overwrite/skip) and puts it in the child context; rm snapshots metadata and arms its RelaxedDirGuard.

Source

fn dir_post( &self, cx: &EntryCx, state: Self::DirState, processed: &ProcessedChildren, child_result: Result<Self::Summary, OperationError<Self::Summary>>, ) -> impl Future<Output = Result<Self::Summary, OperationError<Self::Summary>>> + Send

Post-order step for a directory entry, run after its contents are walked, in the same task as dir_pre. state is the DirAction::Descend state; processed lists the spawned children; child_result is the contents’ folded outcome — Ok(summary) when every child succeeded, or Err carrying the combined child error and the partial summary when one or more children failed without fail_early. (Neither has dir_pre’s own contribution folded in — the visitor carries that in state and folds it here.)

dir_post is not called when fail_early is set and a child failed: that case aborts the subtree immediately (the surrounding JoinSet drops, aborting siblings) and the error is returned without any post-order work — so a fail-early abort never applies post-order finalization (copy’s directory metadata / --delete prune). When fail_early is unset, dir_post IS called with Err(..) so the visitor can still apply safe post-order finalization (copy applies directory metadata even after a partial failure, but skips the destructive --delete prune) and then return the combined error.

copy applies directory metadata, empty-dir cleanup, and --delete prune; chmod applies the deferred post-order change; rm runs the time filter, the rmdir, and defuses its guard. A visitor that wants the historical “finalize only on full success” behavior simply propagates the Err.

Provided Methods§

Source

fn on_skip( &self, _cx: &EntryCx, _kind: EntryKind, _skip_result: &FilterResult, ) -> Self::Summary

Account for an entry the filter excluded, returning its summary contribution. Called by the driver for each filtered-out child instead of spawning it, so the tool’s *_skipped counters and dry-run skip reporting stay tool-owned (the driver is generic over the summary and dry-run mode).

kind is the cheap getdents-hint classification (DT_UNKNOWN treated as a file), matching the per-tool walks’ skip dispatch; skip_result is the FilterResult that caused the exclusion. The driver still increments the shared progress counter via EntryKind::inc_skipped — override only to add the summary counters and the --dry-run “skip …” line.

The default does nothing (returns Default), which suits metadata-only walks and the smoke tests; copy/chmod/rm override it to mirror their existing skipped_summary_for + report_skip behavior.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§