#[non_exhaustive]pub enum Progress {
Planned {
directories: usize,
small_files: usize,
small_bytes: u64,
large_files: usize,
large_bytes: u64,
small_file_threshold: u64,
},
Started {
bytes_total: Option<u64>,
entries_total: usize,
},
EntryStarted {
entry: Entry,
},
EntryProgress {
entry: Entry,
bytes_copied: u64,
},
EntryCompleted {
entry: Entry,
},
EntryFailed {
entry: Entry,
},
DirectoriesStarted {
total: usize,
},
DirectoryCompleted {
path: PathBuf,
},
DirectoryFailed {
path: PathBuf,
},
}Expand description
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.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Planned
The shape of the work about to be performed, emitted once per
phase before DirectoriesStarted and Started — i.e. before
the directory pre-pass that Started doesn’t cover.
Exists for cost estimation (EtaEstimator): the small/large
split is the difference between work whose cost is per-file
(syscall-bound) and work whose cost is per-byte (bandwidth-bound),
and Started’s single bytes_total can’t distinguish them. A
consumer that only wants a progress bar can ignore this variant
entirely.
Not emitted by the delete sweeps (sync’s orphan sweep,
move_path’s source cleanup) — those are metadata-only phases
with no byte-sized work to model, so they emit a bare Started.
Fields
Started
Emitted once per phase, before any entries in that phase start.
bytes_total is None for phases with nothing byte-sized to
report (the delete sweeps). Can be emitted more than once per
operation — sync emits it once per phase (copy, then delete).
EntryStarted
EntryProgress
Bytes written so far for an entry still in flight, sampled by watching the destination file grow. Emitted only for large (streamed) entries, and only while they take long enough to be sampled at all — a copy that the filesystem satisfies by copy-on-write finishes before the first sample and emits none.
bytes_copied is cumulative, not a delta, and is clamped to the
entry’s size. It is monotonically non-decreasing per entry.
Exists because tokio::fs::copy is opaque while it runs: without
this, a single large file emits EntryStarted and then nothing
until it finishes, so its transfer rate is unmeasurable for exactly
as long as it takes to copy.
EntryCompleted
EntryFailed
DirectoriesStarted
The directory-creation pre-pass (operations/pipeline.rs’s
ensure_directories_exist), separate from Started/Entry*
since it operates on DirEntry, not Entry — carrying only the
destination path (not the full DirEntry) is enough for a
caller to show “N/M directories created” without extending
every Entry-typed variant to also accept DirEntry. Added
after a real run against a USB-connected exFAT drive spent about
a minute silently creating ~7,700 directories one at a time
before Started (for the file-copy phase) was ever emitted.