Expand description
lev update - bring this copy of Leviath up to date, then everything that
shipped with it.
Three steps, in the order that matters: the binary, the bundled blueprints, and the config file. The binary first because the other two are decided by what the new binary ships, and a user who updates the agents against the old one has done half a job.
All three run every time. The binary step is never a reason to skip the
other two, and this is the whole point: brew upgrade and scoop update
hand over a new binary and say nothing about the blueprints in the user’s
agents directory or the config beside them, so anyone who has ever updated
that way is carrying blueprints from whenever they last ran lev setup. A
binary that needs no update is not evidence that anything else is current,
which is why “already up to date” is a sentence this command never says on
its own.
§Why the install method is detected rather than guessed
Every channel installs the same CARGO_PKG_VERSION: the -alpha and
-beta suffixes live in the tap manifests the release workflow bumps, not
in Cargo.toml. So the version string says nothing about which channel this
binary came from, and nothing about which installer put it there. What does
say something is where the file is: a Homebrew Cellar path carries the
formula name, and the formula name carries the channel; a Scoop apps path
carries the package the same way; ~/.cargo/bin means somebody compiled it.
The hosted install script is the one method that records nothing. It writes
a plain binary into an ordinary directory and keeps no receipt, so a copy
that came from it is indistinguishable from any other loose binary. That is
what UpdateArgs::channel is for, and why the script arm defaults to
stable and says so rather than inferring a channel it cannot know.
§Seams
Running the upgrade and asking the user a question are both injected (see
UpdateEnv), so the tests assert the command that would run without a
single process being spawned - the same shape lev mcp uses for the browser
and the daemon uses for seed commands.
Structs§
- Migration
- One config change
lev updateknows how to make on the user’s behalf. - Update
Args - Arguments for
lev update. - Update
Env - The real I/O
lev updatedepends on, injected so the command logic is testable without a package manager, a terminal, or the real home directory. - Update
Plan - Everything
lev updateintends to do, as plain data.
Enums§
- Binary
Step - What to do about the binary.
- Channel
- A release channel.
- Config
State - What the plan found when it read the config file.
- Install
Method - How this copy of
levgot onto the machine.
Constants§
- MIGRATIONS
- The migrations this build knows about, oldest first.
- UPDATE_
LONG_ ABOUT lev update --help.
Functions§
- binary_
step - The upgrade step for an install method: the commands to run, or the reason there are none.
- detect
- Work out how
exewas installed. - execute_
with - Run
lev updateagainst an injected environment. - format_
plan - Render the plan the way
lev updateprints it. - plan
- Work out everything the command would do, without doing any of it.
- plan_
json - The plan as JSON. Built by hand, like
lev toolsandlev doctor, so the shape is explicit and does not move when a type gains a field. - render_
commands - One line naming every command a
BinaryStep::Runwill run, in order.
Type Aliases§
- Command
Runner - Runs the upgrade command: argv in, success or the reason it failed out.
- Confirm
- Asks the user a yes/no question. Injected for the same reason: a unit test has no terminal, and which questions a flag answers on the user’s behalf - and, for a blueprint they edited, which ones no flag answers - is something the tests have to be able to prove rather than describe.