axodotdev / axodotdev/cargo-dist
Homebrew: no way to add a `head` stanza to the generated formula
- Dominant language
- Rust
- Stars
- 2.1k
- Forks
- 149
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 32
Description
I use dist to publish a Rust CLI through my own tap, and I wanted a development channel next to the
stable formula — `brew install --HEAD` to build the tip of `main`. As far as I can tell there's no
way to get a [`head` stanza](https://docs.brew.sh/Formula-Cookbook#unstable-versions-head) into the
formula dist generates.
The Homebrew installer config is `tap` / `formula` / `bin-aliases`, and none of those reach it.
There's no template or hook, and the formula is rewritten on every release, so hand-editing it
doesn't survive. The docs also mention that building a formula from source isn't supported, which
is what `head` needs — there's no artifact to checksum.
What I ended up with is a second formula in the same tap, hand-written, carrying only a `head`
spec:
```ruby
class BirchDev < Formula
desc "Modern interactive file tree for the terminal (development build)"
homepage "https://github.com/slukyano/birch"
license "MIT"
head "https://github.com/slukyano/birch.git", branch: "main"
depends_on "rust" => :build
conflicts_with "birch", because: "both install a birch binary"
def install
system "cargo", "install", *std_cargo_args(path: "crates/birch")
pkgshare.install "contrib/birch-cmux", "contrib/birch-tmux", "contrib/birch-herdr"
end
end
```
Then `brew install --HEAD slukyano/tap/birch-dev`, and `brew upgrade --fetch-HEAD birch-dev` to
pick up new commits. It works, and dist leaves it alone since it only regenerates the formula it
owns. The annoying parts are that the build recipe now lives in a second place by hand and will
drift as the project changes, that both formulae install the same binary so only one can be linked
at a time, and that a head-only formula can't be installed without passing `--HEAD` explicitly.
Two directions seem plausible to me, and they're not exclusive:
- An escape hatch — a file whose contents get injected into the generated class body, the way
`github-build-setup` and the custom `*-jobs` files work for CI. That needs no per-language
knowledge, and it would cover `caveats`, `service`, `livecheck`, `post_install` and a real
`test do` too.
- An opt-in `head` feature — `homebrew-head = true` or similar, with dist emitting the stanza and a
source-build install path. Nicer to use, though the install differs per project type.
Contributor guide
Research direction
Start at the Homebrew generator handling tap, formula, and bin-aliases, then compare the existing github-build-setup and custom *-jobs extension points. Define whether the change supports injected formula content or an opt-in head source build; done should preserve generated formulas across releases and cover the selected installation path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- ruby, rust
- Domain
- build-system, release
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100