fix(cli): align mops update with outdated, and say it rewrites mops.toml - #742
Merged
Conversation
`mops update <not-installed-pkg>` printed `Package "<name>" is not installed!` and exited 0, so a typo in a scripted update looked like success. It now exits 2 — the same code `mops outdated` uses for "the check could not be completed" — for an unknown package and for a missing mops.toml. 1 is deliberately not used: it means "updates are available", which cannot be a terminal state for update. #734 extracted getAvailableGithubUpdates so outdated and update could not drift apart on what "out of date" means for a repo = "..." dependency, but update kept its own inline loop resolving branch heads. It now uses the helper, so the rule exists once. The helper needed no changes. Behaviour is preserved, including which section the re-pin is written back to, the lock: "skip" batching, and carrying on past a failed lookup — lookups are now concurrent rather than sequential, at the same request count. `mops update` is cargo upgrade semantics, not cargo update: it rewrites the manifest. Neither --help nor the doc page said so, which is the actual confusion risk behind keeping the name. Both now say it, and list the exit codes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
Cursor AI review👍 APPROVE — looks safe to merge
VerdictDecision: APPROVE Generated for commit 8319328 |
automation-sa-sre
previously approved these changes
Aug 12, 2026
automation-sa-sre
left a comment
There was a problem hiding this comment.
Automated approval: the AI review verdict for 5141264 is APPROVE. See the "Cursor AI review" comment for details.
automation-sa-sre
approved these changes
Aug 13, 2026
automation-sa-sre
left a comment
There was a problem hiding this comment.
Automated approval: the AI review verdict for 8319328 is APPROVE. See the "Cursor AI review" comment for details.
This was referenced Aug 13, 2026
Kamirus
added a commit
that referenced
this pull request
Aug 13, 2026
Establishes the manual tracking convention for the install benchmark from [#744](#744): the most recent meaningful run lives in `perf/install-bench/RESULTS.md`, replaced wholesale on each re-run, with a one-line history of prior headline numbers. Deliberately not a CI gate — runs are only comparable within one host and network, so a committed run is a point of reference. ## The run itself v2.22.0 vs v3 at f8c619c — the first measurement with the whole performance stack landed (#741 sorted lock, #742 update alignment, #743 resolve memo, #745 parallel installs, #746 in-flight re-check). Medians of 3 against the live registry: | scenario | v2 | v3 | v3 vs v2 | | --- | --- | --- | --- | | install-cold-nolock | 139.6s | 107.4s | 0.77x | | install-cold-validlock | 106.6s | 61.1s | 0.57x | | install-cold-stalelock | 128.0s | 95.7s | 0.75x | | install-warm-nolock | 3.20s | 5.62s | 1.76x † | | install-warm-validlock | 6.20s | 2.99s | 0.48x † | | install-warm-stalelock | 3.31s | 2.45s | 0.74x | | add-two | 4.00s | 3.84s | 0.96x | | update-few | 8.02s | 5.42s | 0.68x | | update-all | 14.9s | 2.87s | 0.19x | † transient registry-latency window, not code: v2's own warm numbers tripled against every prior run of the same released binary. A warm-only re-check half an hour later returned to line — v3 warm-nolock 2.33s (0.75x), warm-validlock 1.08s (0.42x) — and is recorded in RESULTS.md as the representative warm numbers, with the main table kept unedited. **v3 now beats released v2 in every scenario.** The cold no-lock install — v3's one regression before #745 (1.23–1.25x in both pre-parallel baselines) — is 0.77x, and CI-shaped installs (cold + committed lock) are 43% faster. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three consistency gaps between
mops updateandmops outdated, all of which make a scripted update quietly misbehave.mops updatereported failure and exited 0A typo in a scripted update looked like success. It now exits
2— the same codemops outdateduses for "the check could not be completed" (#734) — for an unknown package and for a missingmops.toml.1is deliberately not reused: it means "updates are available", which cannot be a terminal state for a command whose job is to apply them.The two commands could disagree about GitHub deps
#734 extracted
getAvailableGithubUpdatesprecisely sooutdatedandupdatecould not drift apart on what "out of date" means for arepo = "..."dependency — butupdatekept its own inline loop resolving branch heads, so the rule still existed twice. It now uses the helper. The helper needed no changes: it already carries the repo, branch, resolved head and dependency name, which is exactly enough to rebuild the pin URL.Behaviour is preserved deliberately and specifically: the same
add(url, { dev, lock: "skip" }, name)call,devstill derived from where the dependency is declared, the alias key still passed through as the manifest key, and a failed lookup still prints and lets the rest of the run continue. Two visible nuances: lookups now run concurrently rather than sequentially (same request count against GitHub's 60/hour limit), and lookup errors print after the re-pins rather than interleaved with them.Neither
--helpnor the docs said it rewrites your manifestmops updateiscargo upgradesemantics — it rewritesmops.toml— notcargo update, which only touches the lockfile. #723 records the decision to keep the name (under exact pins there is only one update operation that can exist, so there is no ambiguity to resolve, and renaming would be breaking). The agreed remedy was to say so plainly, which neither the help text nor the doc page did:Follow-up worth flagging
One divergence of the same family is left in place:
updatestill exits0when a GitHub lookup fails — it printsFailed to update <name>: …and carries on — whereoutdatedexits2. Changing it would alter behaviour beyond the scope of aligning the "not installed" case, so it is called out rather than folded in.Items 35, 36 and 37 in #723.
🤖 Generated with Claude Code