1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# SPDX-FileCopyrightText: 2026 Ken Tobias
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Homebrew formula for retch.
#
# THIS IS A TEMPLATE, NOT A PUBLISHABLE FORMULA.
# ----------------------------------------------
# `@VERSION@` and `@SHA256@` are filled in by `scripts/render_packaging.py` at publish
# time, from the tag being released and the sha256 of the tarball that was actually
# downloaded. `just brew-publish <version>` renders it and pushes the *rendered* file to
# the tap at github.com/l1a/homebrew-retch. Nothing is hand-edited in the tap.
#
# It records no version, because recording one is what went wrong elsewhere: `packaging/
# aur/PKGBUILD` was an inert "reference copy" that nothing rendered, published or checked,
# and it reached **eleven releases** of drift (0.6.12 in-repo while the AUR served 0.6.23)
# while every CI run stayed green. v0.7.1 answered that with a guard and v0.17.2 gave this
# formula one on day one -- but a guard only ever detects a disagreement between two
# recordings of the same fact. Writing the fact down once, at publish time, removes the
# disagreement instead. See scripts/render_packaging.py.
#
# WHY A TAP RATHER THAN homebrew-core
# ------------------------------------
# homebrew-core has notability requirements comparable to the tldr-pages submission that
# was already declined for this project (NOTES.md §3). A tap needs no approval and is the
# realistic first step; moving to core later is a separate decision, not a prerequisite.
#
# WHY A SOURCE BUILD AND NOT A BOTTLE
# ------------------------------------
# A bottle is a prebuilt binary that CI must build, sign and upload per macOS version and
# architecture. This formula builds from source and needs only Rust, which Homebrew can
# supply as a build-time dependency. The trade is a slower first install against no new CI
# secrets and no release-asset plumbing. Revisit when install time is an actual complaint.
#
# `url` and `sha256` carry sentinels rather than a release, so there is no "trailing
# Cargo.toml" state to reason about and no bump to forget. `scripts/brew_check.py` asserts
# the sentinels are still there; `scripts/render_packaging.py` refuses to write a file that
# still contains one.
desc
homepage
url
sha256
license
head , branch:
depends_on => :build
# `std_cargo_args` ALREADY passes `--locked` (along with `--root` and `--path`), so it
# must not be repeated: cargo rejects a duplicate outright with
# "the argument '--locked' cannot be used multiple times". Found by the `brew` CI job;
# the formula parsed and the guard passed, and only a real install surfaced it.
#
# `--locked` is load-bearing here for the same reason the COPR spec says never to drop
# it: Homebrew builds with network access and no vendored dependencies, so Cargo.lock
# is the only thing pinning resolution to what CI actually tested. That is why
# brew_check.py asserts `std_cargo_args` is still used rather than merely looking for
# the flag — dropping it would silently unpin resolution.
system , , *std_cargo_args
# Install the COMMITTED man page rather than regenerating it. The AUR PKGBUILD
# regenerated its own with mandown and shipped a page footed `$DATE` / `retch $pkgver`
# for months (fixed in v0.7.0); the tarball already carries a correct page, so there is
# nothing to gain and a whole failure mode to avoid.
man1.install
# Generated by the binary that was just built, so completions cannot disagree with the
# CLI they describe. `--completions=<shell>` is the flag's `=`-joined form, which is
# what `shell_parameter_format` produces here.
#
# `shells:` is deliberately omitted: bash/zsh/fish is the default, and passing it
# explicitly is flagged by `brew audit --strict` as redundant. The `brew` CI job
# asserts all three completion files are installed and non-empty, so relying on the
# default is checked rather than assumed.
generate_completions_from_executable(bin/, shell_parameter_format: )
end
test do
# `--version` proves the binary runs and is the version the formula claims.
assert_match version.to_s, shell_output()
# `--fields os` proves it can actually probe the machine — the thing that would break
# under a missing framework link — while touching nothing but local system calls.
# (It is also 3.4 ms against `--short`'s 31 ms, and reaches no network at all.)
#
# **THE OUTPUT IS ANSI-STRIPPED BEFORE MATCHING.** Up to 0.17.x retch colourised even
# when piped, so the label and its colon were separated by escapes and a literal
# `/OS:/` never matched:
# "\e[38;2;0;255;255mOS\e[39m\e[38;2;128;128;128m:\e[39m \e[...mmacOS 26.6.2"
# Two earlier versions of this test failed on exactly that. Since 0.18.0 piped output
# is plain by default (`--color auto`), but the strip stays: it costs nothing, and it
# keeps this assertion independent of how retch decides whether to colour.
#
# The pattern matches the whole `ESC [ ... <final byte>` form rather than SGR (`m`)
# only: chafa opens a run with `\e[?25l`, and an SGR-only strip leaves six characters
# behind — the measurement bug recorded in v0.9.2 and re-recorded in v0.11.5.
plain = shell_output().gsub(, )
assert_match(, plain)
# The man page must be installed and carry a real version footer — the `$DATE` /
# `$pkgver` defect the AUR package shipped for months would pass a mere existence check.
assert_path_exists man1/
assert_match , (man1/).read
end
end