Files bucketed by how long ago they were last modified, relative to a
single now captured once when the walk starts — not re-read per
entry, so results are deterministic within one run regardless of how
long the walk takes. Each entry lands in the first bucket whose
boundary it’s younger than.
Structurally similar to Handle<T> (event stream + .cancel() +
awaitable) but a distinct type, following the same precedent
WatchHandle already sets: Handle<T>’s progress stream is hard-coded
to crate::progress::Progress, which lives behind the operations
feature — analyze doesn’t require operations, and AnalysisProgress
isn’t Progress, so genericizing the shared Handle<T> would mean
either coupling analyze to operations or threading a second type
parameter through every existing call site for no benefit to them.
#[non_exhaustive]: a new aggregate (e.g. permission-mode breakdown)
is additive, not a breaking change for callers who construct nothing
and only read fields — mirrors Progress’s reasoning in
src/progress.rs.
One generic type reused across every operation (T =
OperationOutcome for copy/move/compress, SyncOutcome for sync)
rather than a handle type per operation.
Aggregate result of running an ExecutionPlan. Replaces a bare
Result<(), Error> because ErrorStrategy::ContinueAndCollect can
finish with a mix of successes and failures that a single Result
can’t represent.
#[non_exhaustive]: an output type, built by this crate and read by
the caller, so blocking downstream construction costs nothing —
Default and ..-destructuring both still work. Adding duration
was a breaking change for exhaustive struct literals; marked now so
the next field isn’t, same reasoning as Progress.
How AnalyzeBuilder::start() handles a per-entry error mid-walk
(e.g. a permission-denied subdirectory, or a symlink loop under
.follow_symlinks(true)).
Deliberately a separate, smaller enum from crate::progress::Progress
rather than a reuse: Progress (and the Handle<T> it’s threaded
through) live behind the operations feature, which analyze
doesn’t require — see AnalysisHandle’s doc comment for the same
reasoning applied one level up.
Discrete per-entry events rather than a cumulative snapshot;
EntryFailed carries only the Entry, not the Error — Error isn’t
Clone (it wraps std::io::Error), and the failure detail is already
available from the operation’s final OperationOutcome.failed once the
handle resolves.
#[non_exhaustive]: adding a variant here is otherwise a breaking
change for any downstream exhaustive match, which is exactly what
adding Planned was. Marked now so the next addition isn’t.
Default cap on how many (path, Error) pairs AnalysisReport::errors
retains — see AnalysisReport::errors_total for the uncapped count.
Chosen to keep a report from a badly-permissioned tree bounded in
memory; override with AnalyzeBuilder::max_reported_errors.