Hey, so I built this thing, most of it at so far at least. And yeah, right now it isn't doing many things better than Homebrew.
Setting of relative paths for bottle installs is still not perfect, well it works for every bottle I have tested except rust. Getting bottles working 100% is very doable though imo.
Build from source formulae is still pretty f*ed + I do not know if it is really feasible given that the json API lacks information there and a full on Ruby -> Rust transpiler is way out of scope. Will probably settle for automatic build system detection based on archive structure there. + Maybe do my own version of the .rb scripts but in a more general machine readable format, not .rs lol
Casks seem to work but I have only tested some .dmg -> .app ones and .pkg installers so far though. As with bottles 100% doable.
Given that almost all formulae are available as bottles for modern ARM mac this could become a fully featured package manager. Actually didn't think so many people would look at it, started building it for myself because Homebrew just isn't cutting it for what I want.
Started working on a declarative package + system manager for mac because I feel ansible is overkill for one machine and not really made for that and nix-darwin worms itself into the system so deep. Wrapping Brew commands was abysmally slow though so I started working on this and by now I am deep enough in I won't stop xD
Anyway I am grateful for every bug report, Issue and well meaning pull request.
One of my biggest gripes about brew is how they manage dependencies. The devs have a conflicting philosophy that creates bloat. Package maintainers must define settings, settings should always use the latest Python version. It makes no sense. Maintainers won't update unless things break so you got a bunch of Python versions running around. And it won't use system Python!
Uv seems to provide an elegant solution for this. You can build a venv for each package and rust version will only have the specified deps. Since uv finds all your Python instances (and packages) and soft links them you have way less bloat and venvs become really useful. You can also use run and other tools to handle executables
You should only be using Homebrew for installing software that happens to be written in Python, not dependencies for your own Python projects. If you do that, the Python version does not matter, it's just whatever version is required to make the package work.
love uv <3 I will look into integrating that. Have not decided if and how to implement my own packaging / source build dsl though and will probably open a git poll for that the coming days
You mentioned a declarative package manager for Mac. I've really liked using Homebrew Bundle [1] over the last couple years. It's about the level of declarative that I've wanted and has made it really easy to bootstrap new laptop or VM (since it also works on Linux). The format for a Brewfile was pretty easy to figure out.
The way I ended up using it was that `brew install` would temporarily install something, without adding it to my Brewfile. And a little `brew add` wrapper would add the package to my Brewfile to keep it on the system permanently. That part with the wrapper could have used some love and would be a nice fit for a new brew-compatible frontend IMO. Maybe you could expand on that for Sapphire, if that also scratches your declarative itch?
What makes you interested in a rust implementation of brew?
I'm guessing it's that you hoping that it is eventually more performant -- are there specific areas of current brew you have identified as performance bottlenecks likely to eventually benefit from a rust implementation?
Or any more info to share about assumptions/hopes that motivated this or any other motivations?
Building from source, obviously, will never be really that much more performant as it mainly relies on the underlying build systems and things like ninja, cmake, cargo etc. are usually optimized very very well.
Thanks to rust just being (slightly, significantly? no idea about ruby's speed) faster + concurrent downloading & pouring of bottles, most "regular" formula installs feel a good bit faster than brew already. Mainly noticeable when installing multiple formulae at once.
Casks, especially those with pkg installers, seem to profit a bit less here.
Performance was a reason, not the main one though, like I said I wanted and still want, to build a declarative package + system managing solution on top. The idea was to get into rust with that. Imo having the base written in the same language instead of wrapping commands also gives more flexibility there.
Another reason is that I never liked the way brew looks and feels. Right now the ui/ux for Sapphire is far from finished, more like a clusterf*k and only the search command really looks the way I want it. Aiming for something modern, clean and information rich without beeing overly verbose. I really like dnf5 and what AerynOS is doing and will probably take some inspiration there.
Like mentioned, Bottles and Casks should be 100% doable and that would cover most package needs on macOS, I do not see why I should also define a new repo and packaging ecosystem when such a big and popular one exists.
Source build capability will probably stay(for easy integration of source building in the system management part later) but not be focused on brew formulae as the ruby dsl would be a horror to parse.
Well and sh*t I am not trying to compete really. This is the first time building something with rust and I really really had no idea what a giant never ending rabbit hole macOS package management is and how massive and complex Brew is.
This went from should I to can I pretty quick for me xD
I say this from ignorance, but coming from a lineage of linux package managers; brew must be doing something wrong - and upon immediate introspection I doubt that its language specific.
The performance of apt/dnf in comparison is surreal; but dnf (or at least yum, its predecessor) is written in Python; which has even worse performance characteristics than Ruby.
Clearly something is wrong, I wonder how different they are architecturally.
Just FYI you are describing a ports system, of which there are many. From macports, to alpine packages, to nixpkgs... Tons of research and automation in this area already. Would encourage looking at Nix and distri in particular. Many Nix packages can be built on/for macOS!
If I may surface one use case: Several years ago I had to manage a bunch of Macs for CI jobs. The build process (Unreal's UAT) didn't support running more than one build process at a time, and Docker was really slow, so I'd hoped to use different user accounts to bypass that and get some parallelization gains. Homebrew made that very difficult with its penchant for system-wide installs. So a feature request: I'd love to see a competitive package manager that limits itself to operating somewhere (overridable) in the user's home directory.
Initial idea for this really came from my dayjob too, we have macs but no way to centrally manage them. The client / server part for the declarative system manager I want to build on top of this is quite far out yet though. At least several months
> probably settle for automatic build system detection based on archive structure there
Please add knobs for the end user to manually configure this per package and global default before adding autodetection. As a user to is very frustrating to have to patch the package manager to override some well-intentioned automagic which didn't consider my setup or dig through sources to uncover some undocumented assumption. yarn is a cautionary example.
> Build from source formulae is still pretty f*ed + I do not know if it is really feasible given that the json API lacks information there and a full on Ruby -> Rust transpiler is way out of scope. Will probably settle for automatic build system detection based on archive structure there. + Maybe do my own version of the .rb scripts but in a more general machine readable format, not .rs lol
Last I checked (which was about a year ago), Homebrew had ~7000 formulas (not including casks).
I think it would be feasible to transcribe most of them to your format of choice with AI, run the build in a loop and ask the LLM to fix errors, and reserve manual intervention for the few cases that the LLM can't fix.
Yeah, this would 100% be feasible. Great idea. It's during the week now so I don't have much time besides work.
I'll probably open a Poll on git within the next couple days about what to do about a real from source packaging system with it's own dsl, maybe just yaml/toml or something a bit more powerful like lua with mlua. No matter the choice of packaging apporach I would like to keep the generated packages "bottle compliant" -> at least with the json api spec, since this also installs from there.
There seems to be at least some in my project so even though I am very opinionated on a lot of things I don't think I should decide on that completely alone, especially given that this is the first time I play with packaging.
Looked at that. I do not really think implementing something like artichoke or rutie would be a good idea. I do not want my project to become overly bloated and to achieve my real goal of a declarative system management thing I think sticking to bottles (that cover almost all formulae thanks to the amazing homebrew community) and casks, getting those to work 100% is the better approach. Thank you for the suggestion though!
Yes, this is only a replacement for the Homebrew CLI. It doesn’t have its own package repository and moreover it doesn’t have the ability to build packages (yet)—it’s just downloading and installing the binaries built by Homebrew.
Good luck. Homebrew hasn't cut it since they started disallowing custom compile flags, and making the user jump through hoops if they want anything slightly different.
With my Homebrew hat on, but not speaking for others: I think this is pretty cool, and demonstrates something that we've discussed indirectly for years.
At its core, there are really two parts to Homebrew:
1. There's the client side, i.e. `brew`, which 99.9% of users stick to happy paths (bottle installs, supported platforms) within. These users could be supported with relative ease by a small native-code installer, since the majority of the work done by the installer in the happy path is fetching bottles, exploding them, and doing a bit of relocation.
2. There's literally everything else, i.e. all of the developer, repository, and CI/CD machinery that keeps homebrew-core humming. This is the largely invisible infrastructure that makes `brew install` work smoothly, and it's very hard to RIIR (in a large part because it's tied heavily to the formula DSL, which is arbitrary Ruby).
(1) is a nice experimental space, because Homebrew does (IMO) a decent job of isolating the client-facing side from the complexity of (2). However, (2) is where the meat-and-potatoes of packaging happens, and where Homebrew's differentiators really lie (specifically, in how easy it is to contribute new packages and bump existing ones).
Edit: Another noteworthy aspect here around performance: I mentioned this in another comment[1], but parallel downloads of things like bottles and DMGs is not an architectural limitation of Homebrew itself, but instead a conscious decision to trade some install speed for courtesy towards the services we fetch from (including GitHub itself). Smaller projects can sidestep this because they're not directing nearly the same degree of volume; I think this project will discover if/when its volumes grow that it will need to serialize downloads to avoid being throttled or outright limited.
It's not _just_ the infrastructure that is awesome for homebrew. The help I got from the team, answering in real-time when I didn't know how to get through the CI bugs is amazing. It's the boring maintainence work that makes it so special for me.
I also feel that there could be a lot of automation in the backend part, catching bugs early (maybe even on local machine before CI run) for example.
Yeah, to me the language (ruby) has nothing to do with the success of Homebrew, it is entirely about the DX around backend packaging. The main reason I switched from MacPorts to Homebrew back in the day is because when a new version of [insert software here] was released, I could expect the brew package to be updated within days. MacPorts always lagged significantly behind, and oftentimes didn't have certain packages at all.
As best I can tell, that's partially due to the size of the community, but also because Homebrew went out of their way to teach the system to fish via the 3(?) different kinds of "check for updates" built into the Formulae:
I kept hearing how great macports was with “separation from the system” and being more unixy and tried it two times. Both times it ended up borked. To their credit, it is very easy to uninstall (but not “one task” as it should be). I have never broken brew. I mean I've had packages not work, but the systems itself never got broken because of libraries or broken installs, I could always back out a broken package easily.
I can't remember the last time my "brewup" alias failed me
I completely agree. I think Ruby has actually been a pretty great boon of a language choice because of the formula DSL, but that goes back to the DX point and not something fundamental to the language.
> but parallel downloads of things like bottles and DMGs is not an architectural limitation of Homebrew itself, but instead a conscious decision to trade some install speed for courtesy towards the services we fetch from
That doesn't make sense. As you say you're directing a huge volume of traffic so it makes no difference exactly when a user downloads a byte. It all gets smeared out. Only the total amount of data matters and that is unaffected by parallelism.
> As you say you're directing a huge volume of traffic so it makes no difference exactly when a user downloads a byte. It all gets smeared out.
Homebrew's traffic pattern is not a uniform distribution. Package updates go out, and users download those packages in structured ways: there are spikes for MDM-managed Homebrew installations, spikes for cronjobs and CI/CD systems, spikes at 9AM on different coasts when developers sign into their machines, etc.
(How much this matters is also not uniform: it matters somewhat less for GitHub Packages - they should have a hefty CDN - and it matters somewhat more for Casks, which tend to be large DMGs hosted on individual servers.)
I'm not a big fan of keeping the Homebrew terminology though. I never know what a formula, keg, cask, cellar, tap or bottle is. Why not keep to the standard terms of package and repository etc? I don't know beer brewing terminology or how beer brewing is analogous to package management, and I honestly wish that it wasn't something which my tools expect me to learn.
Please kill the Homebrew terminology if you can! Its idiosyncratic names are the bane of my existence; it might have been cute in 2010, but it's frustrated me ever since.
I don't want to memorise their twee names; I'd much rather the name tell me what the entity / operation does by itself.
Cute names for standard things is one of my software bug bears, i.e. pet peeves, i.e. annoyances. Ruby gems and rust crates and something something beans. It is cute jargon and it annoys me to hide the definition inside a language specific terminology.
It's actually one of the main reasons I landed on using Axum for a web server in Rust instead of Rocket: I got fed up with the additional level of semantic indirection the cutesy names added. I didn't wanna burn brain cycles decoding what it means to install fairings or launch rockets, or what "ignition" means contra "liftoff". I like boring names for things.
Löve (lua thing for graphics / games) historically had this but the names were all sex-related (SECS, LUBE, COCK, AnAl, HUMP, Polygamy, Swingers, Quickie). None of the project names were metaphorically related to their functions.
It's toned down lately and a ton of projects have been renamed, though not scrubbed, so the old names are still in the code and some documentation uses the old names. Also, you can't rewrite tens of thousands of forum posts from 2010 that use the older names that show up while searching for issues.
I will probably change the terminology at some point for this. For initially building it it is way easier to keep them the same though as trying to understand brew itself (at least for me) isn't so straight forward. It's a massive project
As an experienced homebrewer, I don't think knowing about making beer makes it any clearer to me. Why do I need to install Docker from a Cask? Oh, it's because on Mac, a Cask is actually a Mac package (DMG or PKG or something). It's just arbitrary beer-flavored terminology.
No different than the Windows registry, which apparently uses a honeybee / hive metaphor because some Windows dev hated bees and their teammates liked trolling them.
That one was non-obvious to me as well, but I am sympathetic to the need to call them something. Not trying to bikeshed, but if there was a single obvious name for them then you would have used it instead of “DMG or PKG or something”.
That said, the registry has been around for ~30 years and the terminology is well known to Windows users. It didn't build off of previously available terminology.
Homebrew just made shit up on the spot based on the project's name to be internally consistent with itself.
Microsoft has it's own fsckery of randomly named cute crap elsewhere, of course.
Yes! A thousand times yes. Homebrew terminology makes absolutely zero sense whatsoever and I find it irritating when I encounter it every now and then (like when a package says tap something and then install it blah blah)
I wish they’d just call them binaries, macOS packages, packages, gui-packages, etc.
To be clear, all those words are also jargon but they’re reusable concepts across software.
Agreed. Come to think of it Homebrew has pretty bad ergonomics in general. What i want is an overview of compiled binaries, where they are, and what their versions are. That’s it.
I disagree. I need to understand what Homebrew means when it says that a cask is keg-only or whatever, or what it means to tap a cellar or whatever when I wanna add repositories. The documentation and '--help' output also refers to the beer brewing terms, not standard package management terms.
I agreee with this, but is there a “standard” of terms? “repo” I understand to be a git repo, with all it entails. But, “package”, “library”, “module”? It seems like different languages have differenct usages.
I was a macports user but had to switch to homebrew because most new projects went there and it was generally easier to write Formulars etc. But I never really liked the project. I think writing a new package manager on top of brew infrastructure won‘t create a better setup. I don‘t know if all casks and Formulars only use the DSL stanzas or if still some use custom ruby functions and helpers. Because otherwise this new tool might need to eval ruby scripts for backwards compatibility.
I loved macports, mostly because I wanted to create a new user account for a project and got bitten with the permissions thing by homebrew. I don’t mind typing sudo.
Any idea what's up with MacPorts lately? Packages I needed to install were uncharacteristically broken or out of date which wasn't a thing ever since I switched from Fink ages ago. Apple used to use MacPorts internally and put resources into but they stopped doing so?
Didn‘t use it for quite some time now. I actually switched to nix packages for a while and was happy. Even worked in tandem with brew but I had a glibc issue on my shared Linux setup I could not resolve. I‘m still on nixos on Linux and tested nix on macOS again with flakes. I‘m not there yet to fully commit though.
Why didn't you like the project if it was a better project by most definitions of what makes a good package manager? e.g. what did you want from a package manager besides 1. easy to install packages 2. readily updated packages.
macports had the cleaner packages. Macports created its own base library so that packages are not based on the macOS system libraries which managed to break them when doing system updates with brew or when you decided to stay longer on an older macOS version. That meant that packages from macports took longer to install and compile. That was from the time when bottles where not a thing yet.
Brew was fast but unstable. In my opinion the inferior project won. But to brews defence they also addressed the issues over the years. Don‘t have any sources at hand but I remember a time when the brew project compared itself to macports and pointed out that their faster because they don‘t recompile all base libraries etc etc. And they had to realize that this wasn‘t a great idea. Now packages are practically split between different os versions. And different bottles are served depending which macOS version you run.
Edit: And I got reminded that it was possible to run and install packages for and from multiple users. Brew took over /usr/local/bin and other /usr/local/homebrew for the running user. Managing a system with multiple users with brew was and still is hard. With macports you needed sudo like with most other package managers. The sudo less nature was a huge deal for its adoption. And now maybe a security risk if you ask me.
> 1. easy to install packages 2. readily updated packages.
Not OP, but I want my package manager to have good UX around package installs and updates, not it deciding to update a Python major version because a random small thing I'm installing it requests it.
Suggestion: create a Goals/Motivation/Rationale section in the README. What are the problems with Homebrew you're trying to solve? Why should a prospective user install and try this tool instead of staying with Homebrew?
Homebrew sure has room for improvement, as most software does, and I appreciate every effort to replace and renew what we have with something better. But my own grievances with Homebrew isn't with the codebase itself.
What discourages me from using Homebrew is the intent and the mindset of its developers and packagers, who, I think, see their goal building an "unstable" distribution, as Debian defines it: "[a distribution that] is run by developers and those who like to live on the edge".
I am not blaming the Homebrew developers for building a Sid rather than Bookworm. Some people want just that. Heck, I used to run Debian Sid myself, but have lost my patience for maintaining my own computers since: I am kept busy enough by fixing the software I write, I don't want to spend more time fixing software I did not.
I mainly disagree with the Homebrew stance on sudo/root. They claim it's better to install everything under a user dir, but 10% of the time that doesn't work for whatever reason, and tons of users have screwed up their permissions trying to fix it. No other package manager has this issue.
I would've been alright if they actually installed stuff in a user dir under the user's home folder, but it's insane to have a system-wide /opt/homebrew owned by whatever user happened to run the installer. Very icky.
I am not too fond of this design for reasons of privilege separation and FHS-alignment, but can accept it as most Homebrew users don't have their Macintosh computers used by multiple people.
If I understand correctly, running a Debian-style stable repo would essentially require forking all distributed software and backporting security fixes to them.
With many macOS users coming from a different communities than Debian users, I really wonder how well that would go over with the folks whose software was being distributed.
Caveat lector, as I didn't collect the data to back this, but I would be extremeley surprised to find more than a few dozen of non-cask packages in Homebrew that contain Macintosh only software.
There are rolling distros on Linux that are remarkably stable. My current Linux distribution openSUSE Tumbleweed is one. And on macOS you already have an immutable system partition that provides a stable base to build on top of, so I fail to see the value proposition of a package manager on macOS that's deliberately slow.
I used to be a big fan of Homebrew but switch to Nix about 2 years ago. For the most part, it works great with home manager for me. Many tools can be installed with breeze just like breeze albeit a bit quicker. The critical thing for me is that Nix doesn't polute my Mac environment like Brew does. But, I admit that this is just for tools. For dev environment I usually just fall back to the language specific methods like cargo, uv or npm.
Some GUI-based applications tend to require too much hassle with Nix so I personally install those with brew. But I still use home manager on top of everything.
Anyway, please do not expect progress to be too rapid. I have a full time job and do most work on this on weekends. I fully intend to make it a stable, "finished" (as much as this is possible in software) thing, it will take a while though. If anyone want's to help out I do open the bugs I find as Issues to keep track and give people an idea of things that do not work. Good Night!
Setting of relative paths for bottle installs is still not perfect, well it works for every bottle I have tested except rust. Getting bottles working 100% is very doable though imo.
Build from source formulae is still pretty f*ed + I do not know if it is really feasible given that the json API lacks information there and a full on Ruby -> Rust transpiler is way out of scope. Will probably settle for automatic build system detection based on archive structure there. + Maybe do my own version of the .rb scripts but in a more general machine readable format, not .rs lol
Casks seem to work but I have only tested some .dmg -> .app ones and .pkg installers so far though. As with bottles 100% doable.
Given that almost all formulae are available as bottles for modern ARM mac this could become a fully featured package manager. Actually didn't think so many people would look at it, started building it for myself because Homebrew just isn't cutting it for what I want.
Started working on a declarative package + system manager for mac because I feel ansible is overkill for one machine and not really made for that and nix-darwin worms itself into the system so deep. Wrapping Brew commands was abysmally slow though so I started working on this and by now I am deep enough in I won't stop xD
Anyway I am grateful for every bug report, Issue and well meaning pull request.
Is there uv support?[0]
One of my biggest gripes about brew is how they manage dependencies. The devs have a conflicting philosophy that creates bloat. Package maintainers must define settings, settings should always use the latest Python version. It makes no sense. Maintainers won't update unless things break so you got a bunch of Python versions running around. And it won't use system Python!
Uv seems to provide an elegant solution for this. You can build a venv for each package and rust version will only have the specified deps. Since uv finds all your Python instances (and packages) and soft links them you have way less bloat and venvs become really useful. You can also use run and other tools to handle executables
Plus is also rust so good synergy ;)
[0] https://astral.sh/blog/uv
The way I ended up using it was that `brew install` would temporarily install something, without adding it to my Brewfile. And a little `brew add` wrapper would add the package to my Brewfile to keep it on the system permanently. That part with the wrapper could have used some love and would be a nice fit for a new brew-compatible frontend IMO. Maybe you could expand on that for Sapphire, if that also scratches your declarative itch?
[1] https://docs.brew.sh/Brew-Bundle-and-Brewfile
I'm guessing it's that you hoping that it is eventually more performant -- are there specific areas of current brew you have identified as performance bottlenecks likely to eventually benefit from a rust implementation?
Or any more info to share about assumptions/hopes that motivated this or any other motivations?
Thanks to rust just being (slightly, significantly? no idea about ruby's speed) faster + concurrent downloading & pouring of bottles, most "regular" formula installs feel a good bit faster than brew already. Mainly noticeable when installing multiple formulae at once.
Casks, especially those with pkg installers, seem to profit a bit less here.
Performance was a reason, not the main one though, like I said I wanted and still want, to build a declarative package + system managing solution on top. The idea was to get into rust with that. Imo having the base written in the same language instead of wrapping commands also gives more flexibility there.
Another reason is that I never liked the way brew looks and feels. Right now the ui/ux for Sapphire is far from finished, more like a clusterf*k and only the search command really looks the way I want it. Aiming for something modern, clean and information rich without beeing overly verbose. I really like dnf5 and what AerynOS is doing and will probably take some inspiration there.
Like mentioned, Bottles and Casks should be 100% doable and that would cover most package needs on macOS, I do not see why I should also define a new repo and packaging ecosystem when such a big and popular one exists.
Source build capability will probably stay(for easy integration of source building in the system management part later) but not be focused on brew formulae as the ruby dsl would be a horror to parse.
Well and sh*t I am not trying to compete really. This is the first time building something with rust and I really really had no idea what a giant never ending rabbit hole macOS package management is and how massive and complex Brew is.
This went from should I to can I pretty quick for me xD
The performance of apt/dnf in comparison is surreal; but dnf (or at least yum, its predecessor) is written in Python; which has even worse performance characteristics than Ruby.
Clearly something is wrong, I wonder how different they are architecturally.
https://nixos.org/manual/nixpkgs/stable/#preface
https://michael.stapelberg.ch/posts/tags/distri/
Maybe that could be a place where sapphire differentiates?
Deleted Comment
If I may surface one use case: Several years ago I had to manage a bunch of Macs for CI jobs. The build process (Unreal's UAT) didn't support running more than one build process at a time, and Docker was really slow, so I'd hoped to use different user accounts to bypass that and get some parallelization gains. Homebrew made that very difficult with its penchant for system-wide installs. So a feature request: I'd love to see a competitive package manager that limits itself to operating somewhere (overridable) in the user's home directory.
I didn't check, but there is a chance that path is also hardcoded in (some) formulae, so even building from the source might not help here.
Deleted Comment
Please add knobs for the end user to manually configure this per package and global default before adding autodetection. As a user to is very frustrating to have to patch the package manager to override some well-intentioned automagic which didn't consider my setup or dig through sources to uncover some undocumented assumption. yarn is a cautionary example.
Last I checked (which was about a year ago), Homebrew had ~7000 formulas (not including casks).
I think it would be feasible to transcribe most of them to your format of choice with AI, run the build in a loop and ask the LLM to fix errors, and reserve manual intervention for the few cases that the LLM can't fix.
I'll probably open a Poll on git within the next couple days about what to do about a real from source packaging system with it's own dsl, maybe just yaml/toml or something a bit more powerful like lua with mlua. No matter the choice of packaging apporach I would like to keep the generated packages "bottle compliant" -> at least with the json api spec, since this also installs from there.
There seems to be at least some in my project so even though I am very opinionated on a lot of things I don't think I should decide on that completely alone, especially given that this is the first time I play with packaging.
At its core, there are really two parts to Homebrew:
1. There's the client side, i.e. `brew`, which 99.9% of users stick to happy paths (bottle installs, supported platforms) within. These users could be supported with relative ease by a small native-code installer, since the majority of the work done by the installer in the happy path is fetching bottles, exploding them, and doing a bit of relocation.
2. There's literally everything else, i.e. all of the developer, repository, and CI/CD machinery that keeps homebrew-core humming. This is the largely invisible infrastructure that makes `brew install` work smoothly, and it's very hard to RIIR (in a large part because it's tied heavily to the formula DSL, which is arbitrary Ruby).
(1) is a nice experimental space, because Homebrew does (IMO) a decent job of isolating the client-facing side from the complexity of (2). However, (2) is where the meat-and-potatoes of packaging happens, and where Homebrew's differentiators really lie (specifically, in how easy it is to contribute new packages and bump existing ones).
Edit: Another noteworthy aspect here around performance: I mentioned this in another comment[1], but parallel downloads of things like bottles and DMGs is not an architectural limitation of Homebrew itself, but instead a conscious decision to trade some install speed for courtesy towards the services we fetch from (including GitHub itself). Smaller projects can sidestep this because they're not directing nearly the same degree of volume; I think this project will discover if/when its volumes grow that it will need to serialize downloads to avoid being throttled or outright limited.
[1]: https://news.ycombinator.com/item?id=43765605
RIIR - "Rewrite It In Rust" (maybe obvious in context? sharing in case not)
Deleted Comment
I also feel that there could be a lot of automation in the backend part, catching bugs early (maybe even on local machine before CI run) for example.
I wonder if anything changed substantially over the years to make you say that?
- GitHub release sniffing https://github.com/Homebrew/homebrew-core/blob/b331b99b9f24f...
- page scraping https://github.com/Homebrew/homebrew-core/blob/b331b99b9f24f... (and also per-content-type flavors json and presumably xml)
- links to other formulae (IOW cascading updates): https://github.com/Homebrew/homebrew-core/blob/b331b99b9f24f...
and then the $(brew livecheck) invocation which will do a subset, a curated list, or hypothetically all of them
I can't imagine why MacPorts or our new Sapphire friend couldn't adopt a similar strategy
I can't remember the last time my "brewup" alias failed me
brew update && brew upgrade -g -f && brew cleanup --prune=all
That doesn't make sense. As you say you're directing a huge volume of traffic so it makes no difference exactly when a user downloads a byte. It all gets smeared out. Only the total amount of data matters and that is unaffected by parallelism.
Homebrew's traffic pattern is not a uniform distribution. Package updates go out, and users download those packages in structured ways: there are spikes for MDM-managed Homebrew installations, spikes for cronjobs and CI/CD systems, spikes at 9AM on different coasts when developers sign into their machines, etc.
(How much this matters is also not uniform: it matters somewhat less for GitHub Packages - they should have a hefty CDN - and it matters somewhat more for Casks, which tend to be large DMGs hosted on individual servers.)
I'm not a big fan of keeping the Homebrew terminology though. I never know what a formula, keg, cask, cellar, tap or bottle is. Why not keep to the standard terms of package and repository etc? I don't know beer brewing terminology or how beer brewing is analogous to package management, and I honestly wish that it wasn't something which my tools expect me to learn.
I don't want to memorise their twee names; I'd much rather the name tell me what the entity / operation does by itself.
It's toned down lately and a ton of projects have been renamed, though not scrubbed, so the old names are still in the code and some documentation uses the old names. Also, you can't rewrite tens of thousands of forum posts from 2010 that use the older names that show up while searching for issues.
I'd agree that the current homebrew terms are inappropriately whimsical and hard to grasp, but you are right in your intuition and goal, IMO.
That is, taking care of the gears first and then carefully adjusting the public API.
No different than the Windows registry, which apparently uses a honeybee / hive metaphor because some Windows dev hated bees and their teammates liked trolling them.
https://learn.microsoft.com/en-us/windows/win32/sysinfo/stru...
That said, the registry has been around for ~30 years and the terminology is well known to Windows users. It didn't build off of previously available terminology.
Homebrew just made shit up on the spot based on the project's name to be internally consistent with itself.
Microsoft has it's own fsckery of randomly named cute crap elsewhere, of course.
I wish they’d just call them binaries, macOS packages, packages, gui-packages, etc.
To be clear, all those words are also jargon but they’re reusable concepts across software.
Everything you need is there...
Edit: And I got reminded that it was possible to run and install packages for and from multiple users. Brew took over /usr/local/bin and other /usr/local/homebrew for the running user. Managing a system with multiple users with brew was and still is hard. With macports you needed sudo like with most other package managers. The sudo less nature was a huge deal for its adoption. And now maybe a security risk if you ask me.
Not OP, but I want my package manager to have good UX around package installs and updates, not it deciding to update a Python major version because a random small thing I'm installing it requests it.
What discourages me from using Homebrew is the intent and the mindset of its developers and packagers, who, I think, see their goal building an "unstable" distribution, as Debian defines it: "[a distribution that] is run by developers and those who like to live on the edge".
I am not blaming the Homebrew developers for building a Sid rather than Bookworm. Some people want just that. Heck, I used to run Debian Sid myself, but have lost my patience for maintaining my own computers since: I am kept busy enough by fixing the software I write, I don't want to spend more time fixing software I did not.
With many macOS users coming from a different communities than Debian users, I really wonder how well that would go over with the folks whose software was being distributed.
Trying to manage nix was more work than I wanted to do.