Skip to main content

rtb_update/
options.rs

1//! Value types that flow into and out of [`crate::Updater`].
2
3use std::sync::Arc;
4
5/// Outcome of an [`Updater::check`](crate::Updater::check) call. Cheap
6/// — no asset downloads.
7#[derive(Debug, Clone)]
8#[non_exhaustive]
9pub enum CheckOutcome {
10    /// The installed version is already at the latest available.
11    UpToDate {
12        /// The installed version.
13        current: semver::Version,
14    },
15    /// A newer release is available.
16    Newer {
17        /// The installed version.
18        current: semver::Version,
19        /// The newer version discovered upstream.
20        latest: semver::Version,
21        /// Full release metadata — pass to `run()` if you want to skip
22        /// re-fetching it.
23        release: rtb_vcs::Release,
24    },
25    /// Installed version is newer than anything the upstream provider
26    /// surfaces. Typically a tool-author misconfiguration; the updater
27    /// never auto-downgrades — callers inspect and decide.
28    Older {
29        /// The installed version.
30        current: semver::Version,
31        /// The latest version upstream reports.
32        latest: semver::Version,
33    },
34}
35
36/// Options controlling a single [`Updater::run`](crate::Updater::run).
37///
38/// Construct via `RunOptions::default()` + field mutation, or via a
39/// struct literal with field update syntax. Not `#[non_exhaustive]` —
40/// adding a field is treated as a breaking change (it is), so callers
41/// retain full struct-literal access. Adding fields requires a minor
42/// bump per the pre-1.0 API-stability policy (framework spec
43/// § API Stability).
44#[derive(Clone, Default)]
45pub struct RunOptions {
46    /// Re-install even when the current version already matches. Used
47    /// to repair a corrupted binary.
48    pub force: bool,
49    /// Target a specific version instead of "latest". Downgrades
50    /// require `force = true`.
51    pub target: Option<semver::Version>,
52    /// Include prereleases when selecting "latest".
53    pub include_prereleases: bool,
54    /// Progress callback. `None` means silent.
55    pub progress: Option<ProgressSink>,
56    /// Verify + stage the binary but do not swap. Leaves the staged
57    /// binary in the cache dir for inspection.
58    pub dry_run: bool,
59}
60
61impl std::fmt::Debug for RunOptions {
62    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63        f.debug_struct("RunOptions")
64            .field("force", &self.force)
65            .field("target", &self.target)
66            .field("include_prereleases", &self.include_prereleases)
67            .field("progress", &self.progress.as_ref().map(|_| "<callback>"))
68            .field("dry_run", &self.dry_run)
69            .finish()
70    }
71}
72
73/// Outcome of a successful [`Updater::run`](crate::Updater::run).
74#[derive(Debug, Clone, serde::Serialize)]
75#[non_exhaustive]
76pub struct RunOutcome {
77    /// Version before the run.
78    #[serde(serialize_with = "serialize_version")]
79    pub from_version: semver::Version,
80    /// Version after the run (or target, if dry-run).
81    #[serde(serialize_with = "serialize_version")]
82    pub to_version: semver::Version,
83    /// Bytes downloaded for the asset.
84    pub bytes: u64,
85    /// `false` when `RunOptions::dry_run` was set.
86    pub swapped: bool,
87    /// Where the staged binary lives on disk — `Some` only for dry-runs.
88    pub staged_at: Option<std::path::PathBuf>,
89}
90
91fn serialize_version<S: serde::Serializer>(
92    v: &semver::Version,
93    s: S,
94) -> std::result::Result<S::Ok, S::Error> {
95    s.collect_str(v)
96}
97
98/// Progress event emitted during a [`Updater::run`](crate::Updater::run).
99#[derive(Debug, Clone)]
100#[non_exhaustive]
101pub enum ProgressEvent {
102    /// The updater has started a version check.
103    Checking,
104    /// Bytes have been received from the provider's asset stream.
105    Downloading {
106        /// Bytes written to the staged file so far.
107        bytes_done: u64,
108        /// Content-length the provider reported (or `0` if unknown).
109        bytes_total: u64,
110    },
111    /// Signature + checksum verification is in progress.
112    Verifying,
113    /// The self-test subprocess is being invoked on the staged binary.
114    SelfTesting,
115    /// `self-replace` is about to run.
116    Swapping,
117    /// The flow completed successfully.
118    Done {
119        /// Version now on disk (and about to replace the running process
120        /// on its next invocation).
121        version: semver::Version,
122    },
123}
124
125/// Cloneable boxed callback. Pass `None` in [`RunOptions::progress`]
126/// for silent runs.
127pub type ProgressSink = Arc<dyn Fn(ProgressEvent) + Send + Sync + 'static>;