rtb-update¶
Self-update for tools built on this family: select a release, download it, verify
it, swap the running binary. Registers the
update command into BUILTIN_COMMANDS, gated on
Feature::Update, and a pre-run hook into BUILTIN_PRERUN_HOOKS.
What it composes, and what it adds¶
Three existing pieces do the heavy lifting:
| Piece | Job |
|---|---|
rtb-forge |
Release metadata and asset bytes from GitHub, GitLab, Bitbucket, Gitea, Codeberg or a direct URL |
minisign-verify |
Signature verification |
self-replace |
Replacing a running executable |
The crate's own contribution is the flow: the order those steps run in, what is checked before each, and the guarantee that falls out of it — the binary on disk is always either the old version or the fully verified new one, never anything between. What a self-update trusts covers why that ordering is what it is.
The library API goes further than the CLI¶
update check and update run are thin wrappers over Updater. Three parts of
the type have no CLI surface at all:
Updater::run_from_file— verify and swap from a locally staged archive, with no provider access. The airgap path. No subcommand calls it.swap_fnandself_test_fn— builder overrides that replace the two steps which are hard to exercise for real. They are how the flow is tested end to end without a test run actually replacing the test binary.cache_dir— per-invocation staging isolation, for CI runners or parallel test processes.
A tool that needs an offline install path writes a command over run_from_file
rather than waiting for one.
Why check and run are separate¶
check fetches metadata and compares versions. It downloads no assets, verifies
nothing, and cannot fail the way run can. That makes it cheap enough to run on a
throttle from a pre-run hook, which is exactly what the update policy does.
CheckOutcome has three variants rather than a boolean, and the third is the
interesting one. Older — the running version is newer than anything upstream
reports — is almost always a tool-author mistake: a Cargo.toml version that ran
ahead of the release tags, or a release source pointing at the wrong project. The
updater never auto-downgrades; it reports and lets the caller decide.
Why progress is a callback¶
RunOptions::progress is an Option<Arc<dyn Fn(ProgressEvent) + Send + Sync>>,
and None means silent. The crate prints nothing on its own.
A CLI wants lines on stderr; a TUI wants a progress bar; a library caller wants
neither. Emitting events and letting the caller render them keeps all three
possible without the crate knowing which one it is in. The --progress flag is
just the CLI's own sink.