file_engine/planner/outcome.rs
1use std::path::PathBuf;
2use std::time::Duration;
3
4use crate::error::Error;
5use crate::profiler::Entry;
6
7/// `#[non_exhaustive]`: a downstream `match` needs a `_` arm, so a new
8/// way for an operation to stop early isn't a breaking change. Same
9/// reasoning as `Progress`.
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11#[non_exhaustive]
12pub enum StopReason {
13 Fatal,
14 AbortOnError,
15 Cancelled,
16 Undo,
17}
18
19/// Aggregate result of running an `ExecutionPlan`. Replaces a bare
20/// `Result<(), Error>` because `ErrorStrategy::ContinueAndCollect` can
21/// finish with a mix of successes and failures that a single `Result`
22/// can't represent.
23/// `#[non_exhaustive]`: an output type, built by this crate and read by
24/// the caller, so blocking downstream construction costs nothing —
25/// `Default` and `..`-destructuring both still work. Adding `duration`
26/// was a breaking change for exhaustive struct literals; marked now so
27/// the next field isn't, same reasoning as `Progress`.
28#[derive(Debug, Default)]
29#[non_exhaustive]
30pub struct OperationOutcome {
31 pub succeeded: Vec<Entry>,
32 pub failed: Vec<(Entry, Error)>,
33 /// Populated only by move's deferred deletion sweep: entries that
34 /// copied successfully but whose original source could not be
35 /// removed afterward (data duplicated, not lost). Copy never
36 /// populates this field.
37 pub cleanup_failed: Vec<(Entry, Error)>,
38 pub stopped_early: Option<StopReason>,
39 /// Populated only by the directory-permissions pass
40 /// (`.preserve_permissions()`), which always runs to completion
41 /// regardless of individual failures and never affects
42 /// `stopped_early` — a directory `chmod` failure is a best-effort
43 /// finishing touch, not an interruption of the actual data transfer.
44 /// Unconditional (not `#[cfg(unix)]`-gated), same reasoning as
45 /// `Entry.mode`: avoids a platform-conditional shape for a type with
46 /// many existing construction sites. Always empty on non-Unix or
47 /// when permission preservation wasn't requested.
48 pub directories_failed: Vec<(PathBuf, Error)>,
49 /// Wall time the operation took, stamped where the outcome is
50 /// produced for the caller. The counterpart to `Handle::elapsed()`
51 /// for after the handle has been consumed by `.await`.
52 ///
53 /// `SyncOutcome`'s two outcomes are timed per phase, so they don't
54 /// sum to the whole run — the diff that precedes them belongs to
55 /// neither. `Handle::elapsed()` remains the figure for the run as a
56 /// whole.
57 ///
58 /// `Duration::ZERO` on a phase that never ran (sync's delete sweep
59 /// when the copy phase stopped early) and on outcomes built by hand
60 /// in tests, which take the `Default`.
61 pub duration: Duration,
62}