The `OnSystem.os_condition_met?` method only handles Linux and macOS
values for the current OS, so this fails when testing with a generic
OS. This shortcoming is only being surfaced now because there weren't
any tests for `OnSystem` before.
This addresses the issue by accounting for macOS values (`:macos` or
a symbol from `MacOSVersion::SYMBOLS`) and returning `false` for any
other values (`:linux`, `:generic`, etc.).
This adds more type signatures to `MacOSRequirement` to move it closer
to `typed: strict`. There are a few areas that aren't quite clear to
me based on the code and existing tests, so I've done what I can at
the moment.
This adds a `#highest_allowed` method to `MacOSRequirement`, so we can
easily identify the highest supported macOS version that a requirement
allows, if any.
This can be used when producing a minimal set of supported macOS
versions that meet requirements in `UsesOnSystem.macos_requirements`.
One of the intended use cases for this is to identify which macOS
versions we could simulate to work with all variations of a cask that
uses macOS on_system blocks.
When determining macOS requirements for a cask, we may need to
reference requirements from related on_system blocks (e.g.,
`on_monterey :or_older`, `on_ventura`, `on_sonoma :or_newer`) when
`depends_on macos` isn't adequate.
Sometimes casks specify different `depends_on macos` values in macOS
on_system blocks but that value is only set when the cask is loaded
in an environment that satisfies the on_system block's requirements.
There are other casks that contain macOS on_system blocks and use
`depends_on macos` outside of the on_system blocks but it may only
use the macOS version of the lowest on_system block (e.g.,
`>= :monterey`), which isn't sufficient if the cask's values vary
based on macOS version.
To be able to simulate macOS versions that meet the requirements of
all the on_system blocks in a cask, we need to collect the macOS
requirements in a way that doesn't require OS simulation. This is also
something that's easy to do in on_system methods, so this adds a
`macos_requirements` array to `UsesOnSystem`, containing
`MacOSRequirement` objects created from the cask's macOS on_system
block conditions.
This adds a `UsesOnSystem` class to `OnSystem`, containing boolean
instance variables to indicate which types of on_system methods are
used in a formula or cask. This is intended as a replacement for
`@on_system_blocks_exist`, which doesn't allow us to determine what
kinds of on_system calls were used. This provides more granularity
but we can still use `@uses_on_system.present?` to determine whether
any on_system calls were used (and this doubles as a `nil` check in
`Formula`, as the `self.class` instance variable has to use a nilable
type).
The `UsesOnSystem` instance variables cover the current
`ARCH_OPTIONS` and `BASE_OS_OPTIONS`. At the moment, we mostly need
to tell whether there are macOS/Linux or Intel/ARM on_system calls,
so I've omitted instance variables for specific macOS version until
we have a need for them.
As a practical example, if you wanted to determine whether a cask
uses Linux on_system calls, you can call
`cask.uses_on_system.linux?`. The `linux` boolean will be `true` if
the cask has an `on_linux` block, an `on_system` block (which requires
Linux), or uses `os linux: ...`. This is something that would be
challenging to determine from outside of `OnSystem` but it's
relatively easy to collect the information in `OnSystem` methods and
make it available like this.
`OnSystem` is exercised by other tests that include its modules but
this adds some baseline tests to ensure some of these methods work as
expected when tested in isolation. Between these added tests and
existing tests, we should have 100% coverage when run on Homebrew/brew
CI.
Instead of repeatedly outputting the same identical messages across
multiple packages and repeating them all for every package after they
were all installed: just output the identical messages in the final
caveats output instead.
This was more painful that I expected but will allow `brew bundle sh`
and `brew sh` to use the user's configuration but use our custom prompt
for Bash and ZSH.
Add a new `brew mcp-server` command for a Model Context Protocol (MCP)
server for Homebrew. This integrates with AI/LLM tools like Claude,
Claude Code and Cursor.
It currently supports the calls needed/used by the MCP Inspector and
Cursor (where I've tested it).
It provides as `tools` the subcommands output by `brew help` but should
be fairly straightforward to add more in future.
It is implemented in a slightly strange way (a standalone Ruby command
called from a shell command) as MCP servers need a faster startup time
than a normal Homebrew Ruby command allows and fail if they don't get
it.
There are a few Ruby libraries available but, given how relatively
simplistic the implementation is, it didn't feel worthwhile to use and
vendor them.
Let's move this from `bin/brew` to make things like e.g. `brew --prefix`
or `brew shellenv` not reset the sudo timestamp.
This is still in a place that ensures that e.g. no untrusted formula or
tap code has been run yet so should have no security implications but
provide mild usability improvements.
The flag used to work well, but at some point started to run more and
more git actions. We use this to update formula and casks in other
homebrew taps, and it works well except for this issue.