Skip to content

v0.28.0

Choose a tag to compare

@smm-h smm-h released this 17 Aug 13:04
· 1276 commits to main since this release

Migrate onto go-strictcli v0.33.0: presence declared on every flag and argument, push and doctor take a required choice, scrub match and scrub run take member-spelled selectors, and author rewrite declares its constraints.

Context

The declaration-regime campaign's Phase F for safegit. strictcli v0.33.0 refuses a
declaration whose presence is unstated, and refuses a value default on any flag or
positional arg of a mutating command -- on a mutating command a value the framework
picked is a value the framework writes. Together with the deletion of MutexGroup and
CoRequired, that turns four hand-rolled selections and one hand-written guard into
declarations the parser enforces and --help renders.

Two CLI spellings change and one does not, and the split is deliberate. push's four
mode bools and doctor's three collapse into one required choices flag each, because a
bool member could be negated into a state that elected nothing -- which is exactly how
--no-only-tags used to push HEAD. scrub match's --replace/--mangle and scrub
match/run's --from/--entire-history become member-spelled selectors, which keeps every
flag an operator types unchanged and reproduces the old refusal sentences byte for
byte; the tools that drive those commands need no change.

Exit codes move at every converted site: a hand guard returned safegit's own usage
code (2, or 70 for the unreachable-state refusals) and a framework parse error exits 1.

Breaking

  • The CLI declares what it accepts; three hand-written guards are gone, and two spellings changed. safegit push --only-head|--only-branches|--only-tags|--both-branches-and-tags becomes safegit push --refs head|branches|tags|both, and safegit doctor --diagnose|--fix|--uninstall becomes safegit doctor --action diagnose|fix|uninstall — neither has a default, and the negation that made --no-only-tags push HEAD and --no-fix run the diagnose path no longer exists at all. scrub match's --replace/--mangle and scrub match/scrub run's --from/--entire-history keep their exact spellings and their exact refusal messages, now as declared selections rather than mutex groups. author rewrite declares its two pairs and its at-least-one rule as constraints, rendered in --help; a missing or half-typed pair is refused by the parser and exits 1 instead of 2, and the two states push and scrub match used to refuse with exit 70 are unrepresentable. Every flag and positional argument now declares its presence, so --help marks each one [required], [optional] or [default: v]; --amend, --allow-empty, --pre-push-hook, --force-with-lease, --bypass-session, --count, --diff, --limit, --overwrite-remote-backup and --allow-public-remote carry no default value any more and name their fallback in their own help text, behaving exactly as before when omitted.
  • The machine envelope declares interface_version: 2. Machine mode (--json) is the CLI framework's, and the framework's envelope contract advanced with the release safegit now builds against: the document gains a writes member (always null here — safegit declares no update command) and the version it reports is 2. A consumer that pins interface_version == 1 must be updated before it can read safegit's output.

Fixes

  • Released binaries report their real version again. The goreleaser build stamped main.Version, a variable that does not exist; every published binary fell back to the module pseudo-version, so safegit version and safegit --version reported something like 0.27.1-0.20260814034848-8737c897423a instead of the release tag.