Merge pull request #14152 from EricFromCanada/docs-contributors-fixes

docs: update Contributors section
This commit is contained in:
Mike McQuaid 2022-11-17 15:02:09 +00:00 committed by GitHub
commit 129c5c2845
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 305 additions and 381 deletions

View File

@ -1,12 +1,10 @@
# Acceptable Casks
Some casks should not go in
[homebrew/cask](https://github.com/Homebrew/homebrew-cask). But there are
additional [Interesting Taps and Forks](Interesting-Taps-and-Forks.md) and anyone can [start their own](Taps.md)!
Some casks should not go in [homebrew/cask](https://github.com/Homebrew/homebrew-cask). But there are additional [Interesting Taps and Forks](Interesting-Taps-and-Forks.md) and anyone can [start their own](How-to-Create-and-Maintain-a-Tap.md)!
## Finding a Home For Your Cask
We maintain separate Taps for different types of binaries. Our nomenclature is:
We maintain separate taps for different types of binaries. Our nomenclature is:
+ **Stable**: The latest version provided by the developer defined by them as such.
+ **Beta, Development, Unstable**: Subsequent versions to **stable**, yet incomplete and under development, aiming to eventually become the new **stable**. Also includes alternate versions specifically targeted at developers.
@ -17,16 +15,16 @@ We maintain separate Taps for different types of binaries. Our nomenclature is:
+ **Freemium**: Gratis version that works indefinitely but with limitations that can be removed by paying.
+ **Fork**: An alternate version of an existing project, with a based-on but modified source and binary.
+ **Unofficial**: An *allegedly* unmodified compiled binary, by a third-party, of a binary that has no existing build by the owner of the source code.
+ **Vendorless**: A binary distributed without an official website, like a forum posting.
+ **Vendorless**: A binary distributed via means other than an official website, like a forum posting.
+ **Walled**: When the download URL is both behind a login/registration form and from a host that differs from the homepage.
+ **Font**: Data file containing a set of glyphs, characters, or symbols, that changes typed text.
+ **Driver**: Software to make a hardware peripheral recognisable and usable by the system. If the software is useless without the peripheral, its considered a driver.
### Stable Versions
### Stable versions
Stable versions live in the main repository at [Homebrew/homebrew-cask](https://github.com/Homebrew/homebrew-cask). They should run on the latest release of macOS or the previous point release (Monterey and Ventura as of late 2022).
### But There Is No Stable Version!
#### But there is no Stable version!
When software is only available as a beta, development, or unstable version, its cask can go in the main repo. When stable versions become available, only those will be accepted as subsequent updates.
@ -36,64 +34,62 @@ Alternative versions should be submitted to [Homebrew/homebrew-cask-versions](ht
### Regional and Localized
When an App exists in more than one language or has different regional editions, [the `language` stanza should be used to switch between languages or regions](https://docs.brew.sh/Cask-Cookbook#stanza-language).
When an app exists in more than one language or has different regional editions, [the `language` stanza should be used to switch between languages or regions](https://docs.brew.sh/Cask-Cookbook#stanza-language).
### Trial and Freemium Versions
### Trial and Freemium versions
Before submitting a trial, make sure it can be made into a full working version without the need to be redownloaded. If an App provides a trial but the only way to buy the full version is via the Mac App Store, it does not belong in any of the official repos. Freemium versions are fine.
Before submitting a trial, make sure it can be made into a full working version without needing to be redownloaded. If an app provides a trial but the only way to buy the full version is via the Mac App Store, it does not belong in any of the official repos. Freemium versions are fine.
### Forks and Apps with Conflicting Names
### Forks and apps with conflicting names
Forks must have the vendors name as a prefix on the Casks file name and token. If the original software is discontinued, forks still need to follow this rule so as to not be surprising to the user. There are two exceptions which allow the fork to replace the main cask:
Forks must have the vendors name as a prefix on the casks filename and token. If the original software is discontinued, forks still need to follow this rule so as to not be surprising to the user. There are two exceptions which allow the fork to replace the main cask:
* The original discontinued software recommends that fork.
* The fork is so overwhelmingly popular that it surpasses the original and is now the de facto project when people think of the name.
1. The original discontinued software recommends that fork.
2. The fork is so overwhelmingly popular that it surpasses the original and is now the de facto project when people think of the name.
For unrelated Apps that share a name, the most popular one (usually the one already present) stays unprefixed. Since this can be subjective, if you disagree with a decision, open an issue and make your case to the maintainers.
For unrelated apps that share a name, the most popular one (usually the one already present) stays unprefixed. Since this can be subjective, if you disagree with a decision, open an issue and make your case to the maintainers.
### Unofficial, Vendorless, and Walled Builds
### Unofficial, Vendorless, and Walled builds
We do not accept these casks since they offer a higher-than-normal security risk.
We do not accept these casks since they involve a higher-than-normal security risk.
### Fonts
Font Casks live in the [Homebrew/homebrew-cask-fonts](https://github.com/Homebrew/homebrew-cask-fonts) repository. See the font repo [CONTRIBUTING.md](https://github.com/Homebrew/homebrew-cask-fonts/blob/HEAD/CONTRIBUTING.md)
for details.
Font casks live in the [Homebrew/homebrew-cask-fonts](https://github.com/Homebrew/homebrew-cask-fonts) repository. See the fonts repo [CONTRIBUTING.md](https://github.com/Homebrew/homebrew-cask-fonts/blob/HEAD/CONTRIBUTING.md) for details.
### Drivers
Driver Casks live in the [Homebrew/homebrew-cask-drivers](https://github.com/Homebrew/homebrew-cask-drivers) repository. See the drivers repo [CONTRIBUTING.md](https://github.com/Homebrew/homebrew-cask-drivers/blob/master/CONTRIBUTING.md)
for details.
Driver casks live in the [Homebrew/homebrew-cask-drivers](https://github.com/Homebrew/homebrew-cask-drivers) repository. See the drivers repo [CONTRIBUTING.md](https://github.com/Homebrew/homebrew-cask-drivers/blob/master/CONTRIBUTING.md) for details.
## Apps that bundle malware
Unfortunately, in the world of software there are bad actors that bundle malware with their apps. Even so, Homebrew Cask has long decided it will not be an active gatekeeper ([macOS already has one](https://support.apple.com/en-us/HT202491)) and [users are expected to know about the software they are installing](#homebrew-cask-is-not-a-discoverability-service). This means we will not always remove casks that link to these apps, in part because there is no clear line between useful app, potentially unwanted program, and the different shades of malware what is useful to one user may be seen as malicious by another.
Unfortunately, in the world of software there are bad actors that bundle malware with their apps. Even so, Homebrew Cask has long decided it will not be an active gatekeeper ([macOS already has one](https://support.apple.com/en-us/HT202491)) and [users are expected to know about the software they are installing](#homebrew-cask-is-not-a-discoverability-service). This means we will not always remove casks that link to these apps, in part because there is no clear line between useful app, potentially unwanted program, and the different shades of malware—what is useful to one user may be seen as malicious by another.
But wed still like for users to enjoy some kind of protection while minimising occurrences of legitimate developers being branded as malware carriers. To do so, we evaluate casks on a case-by-case basis and any user is free to bring a potential malware case to our attention. However, it is important to never forget the last line of defence is *always* the user.
If an app that bundles malware was not signed with an Apple Developer ID and you purposefully disabled or bypassed Gatekeeper, no action will be taken on our part. When you disable security features, you do so at your own risk. If, however, an app that bundles malware is signed, Apple can revoke its permissions and it will no longer run on the computers of users that keep security features on we all benefit, Homebrew Cask users or not. To report a signed app that bundles malware, use [Apples Feedback Assistant](https://feedbackassistant.apple.com)
If an app that bundles malware was not signed with an Apple Developer ID and you purposefully disabled or bypassed Gatekeeper, no action will be taken on our part. When you disable security features, you do so at your own risk. If, however, an app that bundles malware is signed, Apple can revoke its permissions and it will no longer run on the computers of users that keep security features on—we all benefit, Homebrew Cask users or not. To report a signed app that bundles malware, use [Apples Feedback Assistant](https://feedbackassistant.apple.com).
We are also open to removing casks where we feel there is enough evidence that the app is malicious. To suggest a cask for removal, submit a Pull Request to delete it, together with your reasoning. Typically, this will mean presenting a [VirusTotal](https://www.virustotal.com) scan of the app showing it is malicious, ideally with some other reporting indicating its not a false positive.
We are also open to removing casks where we feel there is enough evidence that the app is malicious. To suggest a cask for removal, submit a pull request to delete it along with your reasoning. Typically, this will mean presenting a [VirusTotal](https://www.virustotal.com) scan of the app showing it is malicious, ideally with some other reporting indicating its not a false positive.
Likewise, software which provides both “clean” and malware-infested versions might be removed from the repo even if we could have access to the *good* version if its developers push for users to install the *bad* version. We do so because in these cases theres a higher than normal risk that both versions are (or will soon become) compromised in some manner.
Likewise, software which provides both “clean” and malware-infested versions might be removed from the repo—even if we could have access to the *good* version—if its developers push for users to install the *bad* version. We do so because in these cases theres a higher than normal risk that both versions are (or will soon become) compromised in some manner.
If a cask you depend on was removed due to these rules, fear not. Removal of a cask from the official repositories means we wont support it, but you can do so by hosting your own [tap](How-to-Create-and-Maintain-a-Tap.md).
If a cask you depend on was removed due to these rules, fear not. Removal of a cask from the official repositories means we wont support it, but you can do so by [hosting your own tap](How-to-Create-and-Maintain-a-Tap.md).
## Exceptions to the Notability Threshold
## Exceptions to the notability threshold
Casks which do not reach a minimum notability threshold (see [Rejected Casks](#rejected-casks)) arent accepted in the main repositories because the increased maintenance burden doesnt justify the poor usage numbers they will likely get. This notability check is performed automatically by the audit commands we provide, but its decisions arent set in stone. A cask which fails the notability check can be added if it is:
1. A popular app that has their own website but the developers use GitHub for hosting the binaries. That repository wont be notable but the app may be.
1. A popular app that has its own website but the developers use GitHub for hosting the binaries. That repository wont be notable but the app may be.
2. Submitted by a maintainer or prolific contributor. A big part of the reasoning for the notability rule is unpopular software garners less attention and the cask gets abandoned, outdated, and broken. Someone with a proven investment in Hombrew Cask is less likely to let that happen for software they depend on.
3. A piece of software that was recently released to great fanfare—everyone is talking about it on Twitter and Hacker News and weve even gotten multiple premature submissions for it. Thats a clear case of an app that will reach the threshold in no time so thats a PR we wont close immediately (but may wait to merge).
3. A piece of software that was recently released to great fanfare—everyone is talking about it on Twitter and Hacker News and weve even gotten multiple premature submissions for it. Thatd be a clear case of an app that will reach the threshold in no time so thats a PR we wont close immediately (but may wait to merge).
Note none of these exceptions is a guarantee for inclusion, but examples of situations where we may take a second look.
Note that none of these exceptions is a guarantee for inclusion, but examples of situations where we may take a second look.
## Homebrew Cask is not a discoverability service
From the inception of Homebrew Cask, various requests fell under the umbrella of this reply. Though a somewhat popular request, after careful consideration on multiple occasions weve always come back to the same conclusion: were not a discoverability service and our users are expected to have reasonable knowledge about the apps theyre installing through us before doing so. For example, [grouping casks by categories](https://github.com/Homebrew/homebrew-cask/issues/5425) is not within the scope of the project.
From the inception of Homebrew Cask, various requests have fallen under the umbrella of this reply. Though a somewhat popular request, after careful consideration on multiple occasions weve always come back to the same conclusion: were not a discoverability service and our users are expected to have reasonable knowledge about the apps theyre installing through us before doing so. For example, [grouping casks by categories](https://github.com/Homebrew/homebrew-cask/issues/5425) is not within the scope of the project.
Amongst other things, the logistics of such requests are unsustainable for Homebrew Cask. Before making a request of this nature, you must read through previous related issues, as well as any other issues they link to, to get a full understanding of why that is the case, and why “but project *x* does *y*” arguments arent applicable, and not every package manager is the same.
Amongst other things, the logistics of such requests are unsustainable for Homebrew Cask. Before making a request of this nature, you must read through previous related issues, as well as any other issues they link to, to get a full understanding of why that is the case, and why “but project *x* does *y*” arguments arent applicable, and how not every package manager is the same.
You should also be able to present clear actionable fixes to those concerns. Simply asking for it without solutions will get your issue closed.
@ -101,32 +97,32 @@ However, there is a difference between discoverability (finding new apps you did
## Rejected Casks
Before submitting a Cask to any of our repos, you must read [our documentation on acceptable Casks](#finding-a-home-for-your-cask) and perform a (at least quick) search to see if there were any previous attempts to introduce it.
Before submitting a cask to any of our repos, you must read our [documentation on acceptable casks](#finding-a-home-for-your-cask) and perform a (at least quick) search to see if there were any previous attempts to introduce it.
Common reasons to reject a Cask entirely:
Common reasons to reject a cask entirely:
+ We have strong reasons to believe including the Cask can put the whole project at risk. Happened only once so far, [with Popcorn Time](https://github.com/Homebrew/homebrew-cask/pull/3954).
+ The Cask is unreasonably difficult to maintain. Examples once included [Audacity](https://github.com/Homebrew/homebrew-cask/pull/27517) and [older Java development Casks](https://github.com/Homebrew/homebrew-cask/issues/57387).
+ The app is a trial version, and the only way to acquire the full version is through the Mac App Store.
+ We have strong reasons to believe including the cask can put the whole project at risk. Happened only once so far, [with Popcorn Time](https://github.com/Homebrew/homebrew-cask/pull/3954).
+ Cask is unreasonably difficult to maintain. Examples have included [Audacity](https://github.com/Homebrew/homebrew-cask/pull/27517) and [older Java development casks](https://github.com/Homebrew/homebrew-cask/issues/57387).
+ App is a trial version, and the only way to acquire the full version is through the Mac App Store.
+ Similarly (and trickier to spot), the app has moved to the Mac App Store but still provides old versions via direct download. We reject these in all official repos so users dont get stuck using an old version, wrongly thinking theyre using the most up-to-date one (which, amongst other things, might be a security risk).
+ The app is both open-source and CLI-only (i.e. it only uses the `binary` artifact). In that case, and [in the spirit of deduplication](https://github.com/Homebrew/homebrew-cask/issues/15603), submit it first to [Homebrew/core](https://github.com/Homebrew/homebrew-core) as a formula that builds from source. If it is rejected, you may then try again as a cask (link us to the issue so we can see the discussion and reasoning for rejection).
+ The app is open-source and has a GUI but no compiled versions (or only old ones) are provided. Its better to have them in [Homebrew/core](https://github.com/Homebrew/homebrew-core) so users dont get perpetually outdated versions. See [`gedit`](https://github.com/Homebrew/homebrew-cask/pull/23360) for example.
+ The app has been rejected before due to an issue we cannot fix, and the new submission doesnt fix that. An example would be [the first submission of `soapui`](https://github.com/Homebrew/homebrew-cask/pull/4939), whose installation problems were not fixed in the two subsequent submissions ([#9969](https://github.com/Homebrew/homebrew-cask/pull/9969), [#10606](https://github.com/Homebrew/homebrew-cask/pull/10606)).
+ The Cask is a duplicate. These submissions mostly occur when the [token reference](https://docs.brew.sh/Cask-Cookbook#token-reference) was not followed.
+ The download URL for the app is both behind a login/registration form and from a host that differs from the homepage, meaning users cant easily verify its authenticity.
+ The Cask is for an unmaintained app (no releases in the last year, or [explicitly discontinued](https://github.com/Homebrew/homebrew-cask/pull/22699)).
+ The Cask is for an app that is too obscure. Examples:
+ App is both open-source and CLI-only (i.e. it only uses the `binary` artifact). In that case, and [in the spirit of deduplication](https://github.com/Homebrew/homebrew-cask/issues/15603), submit it first to [homebrew/core](https://github.com/Homebrew/homebrew-core) as a formula that builds from source. If it is rejected, you may then try again as a cask (link to the issue from your pull request so we can see the discussion and reasoning for rejection).
+ App is open-source and has a GUI but no compiled versions (or only old ones) are provided. Its better to have them in [homebrew/core](https://github.com/Homebrew/homebrew-core) so users dont get perpetually outdated versions. See [`gedit`](https://github.com/Homebrew/homebrew-cask/pull/23360) for example.
+ Cask has been rejected before due to an issue we cannot fix, and the new submission doesnt fix that. An example would be the [first submission of `soapui`](https://github.com/Homebrew/homebrew-cask/pull/4939), whose installation problems were not fixed in the two [subsequent](https://github.com/Homebrew/homebrew-cask/pull/9969) [submissions](https://github.com/Homebrew/homebrew-cask/pull/10606).
+ Cask is a duplicate. These submissions mostly occur when the [token reference](https://docs.brew.sh/Cask-Cookbook#token-reference) was not followed.
+ Cask has a download URL that is both behind a login/registration form and from a host that differs from the homepage, meaning users cant easily verify its authenticity.
+ App is unmaintained, i.e. no releases in the last year, or [explicitly discontinued](https://github.com/Homebrew/homebrew-cask/pull/22699).
+ App is too obscure. Examples:
+ An app from a code repository that is not notable enough (under 30 forks, 30 watchers, 75 stars).
+ [Electronic Identification (eID) software](https://github.com/Homebrew/homebrew-cask/issues/59021).
+ The Cask is for an app with no information on the homepage (example: a GitHub repository without a README).
+ App has no information on its homepage (example: a GitHub repository without a README).
+ The author has [specifically asked us not to include it](https://github.com/Homebrew/homebrew-cask/pull/5342).
+ The Cask requires [SIP to be disabled](https://github.com/Homebrew/homebrew-cask/pull/41890) to be installed and/or used.
+ The Cask is a `pkg` that requires [`allow_untrusted: true`](https://docs.brew.sh/Cask-Cookbook#pkg-allow_untrusted).
+ App requires [SIP to be disabled](https://github.com/Homebrew/homebrew-cask/pull/41890) to be installed and/or used.
+ App installer is a `pkg` that requires [`allow_untrusted: true`](https://docs.brew.sh/Cask-Cookbook#pkg-allow_untrusted).
Common reasons to reject a Cask from the main repo:
Common reasons to reject a cask from the main repo:
+ The cask was submitted to the wrong repo. When drafting a cask, consult [Finding a Home For Your Cask](#finding-a-home-for-your-cask) to see where it belongs.
+ Cask was submitted to the wrong repo. When drafting a cask, consult [Finding a Home For Your Cask](#finding-a-home-for-your-cask) to see where it belongs.
## No cask is guaranteed to be accepted
### No cask is guaranteed to be accepted
Follow the guidelines above and your submission has a great chance of being accepted. But remember documentation tends to lag behind current decision-making and we cant predict every case. Maintainers may override these rules when experience tells us it will lead to a better overall Homebrew.
Follow the guidelines above and your submission has a great chance of being accepted. But remember that documentation tends to lag behind current decision-making and we cant predict every case. Maintainers may override these rules when experience tells us it will lead to a better overall Homebrew.

View File

@ -1,91 +1,82 @@
# Acceptable Formulae
Some formulae should not go in
[homebrew/core](https://github.com/Homebrew/homebrew-core). But there are
additional [Interesting Taps and Forks](Interesting-Taps-and-Forks.md) and anyone can start their
own!
Some formulae should not go in [homebrew/core](https://github.com/Homebrew/homebrew-core). But there are additional [Interesting Taps and Forks](Interesting-Taps-and-Forks.md) and anyone can [start their own](How-to-Create-and-Maintain-a-Tap.md)!
### Supported platforms in `homebrew/core`
## Requirements for `homebrew/core`
The formula needs to build and pass tests on the latest 3 supported macOS versions ([x86_64 and Apple Silicon/ARM](Installation.md#macos-requirements)) and on x86_64 [Linux](Linux-CI.md).
Please have a look at the continuous integration jobs on a pull request in `homebrew/core` to see the full list of OSs.
If upstream does not support one of these platforms, an exception can be made and the formula can be disabled for that platform.
### Supported platforms
The formula needs to build and pass tests on the latest 3 supported macOS versions ([x86_64 and Apple Silicon/ARM](Installation.md#macos-requirements)) and on x86_64 [Linux](Linux-CI.md). Please have a look at the continuous integration jobs on a pull request in `homebrew/core` to see the full list of OSs. If upstream does not support one of these platforms, an exception can be made and the formula can be disabled for that platform.
### Duplicates of system packages
### Dupes in `homebrew/core`
We now accept stuff that comes with macOS as long as it uses `keg_only :provided_by_macos` to be keg-only by default.
### Versioned formulae in `homebrew/core`
### Versioned formulae
We now accept versioned formulae as long as they [meet the requirements](Versions.md).
### We dont like tools that upgrade themselves
Software that can upgrade itself does not integrate well with Homebrew's own
upgrade functionality. The self-update functionality should be disabled (while minimising complication to the formula).
Software that can upgrade itself does not integrate well with Homebrew's own upgrade functionality. The self-update functionality should be disabled (while minimising complication to the formula).
### We dont like install scripts that download unversioned things
We don't like install scripts that are pulling from the `master` branch of Git repositories or unversioned, unchecksummed tarballs. These should use `resource` blocks with specific revisions or checksummed tarballs instead. Note that we now allow tools like `cargo`, `gem` and `pip` to download specifically versioned libraries during installation.
We don't like install scripts that are pulling from the master branch of Git repositories or unversioned, unchecksummed tarballs. These should use `resource` blocks with specific revisions or checksummed tarballs instead. Note that we now allow tools like `cargo`, `gem` and `pip` to download specifically versioned libraries during installation.
### We dont like binary formulae
Our policy is that formulae in the core tap
([homebrew/core](https://github.com/Homebrew/homebrew-core)) must be open-source
with an [Debian Free Software Guidelines license](https://wiki.debian.org/DFSGLicenses) and either built
from source or produce cross-platform binaries (e.g. Java, Mono). Binary-only
formulae should go to [homebrew/cask](https://github.com/Homebrew/homebrew-cask).
Additionally, [homebrew/core](https://github.com/Homebrew/homebrew-core) formulae must also not depend on casks or any other proprietary software.
Our policy is that formulae in the core tap ([homebrew/core](https://github.com/Homebrew/homebrew-core)) must be open-source with a [Debian Free Software Guidelines license](https://wiki.debian.org/DFSGLicenses) and either built from source or producing cross-platform binaries (e.g. Java, Mono). Binary-only formulae should go in [homebrew/cask](https://github.com/Homebrew/homebrew-cask).
This includes automatic installation of casks at runtime.
Additionally, core formulae must also not depend on casks or any other proprietary software. This includes automatic installation of casks at runtime.
### Stable versions
Formulae in the core repository must have a stable version tagged by
the upstream project. Tarballs are preferred to Git checkouts, and
tarballs should include the version in the filename whenever possible.
We dont accept software without a tagged version because they regularly break
due to upstream changes and we cant provide [bottles](Bottles.md) for them.
Formulae in the core repository must have a stable version tagged by the upstream project. Tarballs are preferred to Git checkouts, and tarballs should include the version in the filename whenever possible.
We dont accept software without a tagged version because they regularly break due to upstream changes and we cant provide [bottles](Bottles.md) for them.
### Niche (or self-submitted) stuff
The software in question must:
* be maintained (i.e. the last release wasn't ages ago, it works without patching on all Homebrew-supported OS versions and has no outstanding, unpatched security vulnerabilities)
* be known
* be stable (e.g. not declared "unstable" or "beta" by upstream)
* be known
* be used
* have a homepage
We will reject formulae that seem too obscure, partly because they wont
get maintained and partly because we have to draw the line somewhere.
We will reject formulae that seem too obscure, partly because they wont get maintained and partly because we have to draw the line somewhere.
We frown on authors submitting their own work unless it is very popular.
Dont forget Homebrew is all Git underneath!
[Maintain your own tap](How-to-Create-and-Maintain-a-Tap.md) if you have to!
Dont forget Homebrew is all Git underneath! [Maintain your own tap](How-to-Create-and-Maintain-a-Tap.md) if you have to!
There may be exceptions to these rules in the main repository; we may
include things that don't meet these criteria or reject things that do.
Please trust that we need to use our discretion based on our experience
running a package manager.
There may be exceptions to these rules in the main repository; we may include things that don't meet these criteria or reject things that do. Please trust that we need to use our discretion based on our experience running a package manager.
### Stuff that builds an `.app`
Dont make your formula build an `.app` (native macOS Application); we
dont want those things in Homebrew. Encourage upstream projects to build and support a `.app` that can be distributed by [homebrew/cask](https://github.com/Homebrew/homebrew-cask) (and used without it, too).
Dont make your formula build an `.app` (native macOS Application); we dont want those things in Homebrew. Encourage upstream projects to build and support a `.app` that can be distributed by [homebrew/cask](https://github.com/Homebrew/homebrew-cask) (and used without it, too).
### Stuff that builds a GUI by default (but doesn't have to)
Make it build a command-line tool or a library by default and, if the GUI is useful and would be widely used, also build the GUI. Dont build X11/XQuartz GUIs as they are a bad user experience on macOS.
### Stuff that doesn't build with the latest, stable Xcode Clang
Clang is the default C/C++ compiler on macOS (and has been for a long time). Software that doesn't build with it hasn't been adequately ported to macOS.
### Stuff that requires heavy manual pre/post-install intervention
We're a package manager so we want to do things like resolve dependencies and set up applications for our users. If things require too much manual intervention then they aren't useful in a package manager.
## Stuff that requires vendored versions of Homebrew formulae
Homebrew formulae should avoid having multiple, separate, upstream projects bundled together in a single package to avoid shipping outdated/insecure versions of software that is already a formula. Veracode's [State of Software Security report](https://www.veracode.com/blog/research/announcing-state-software-security-v11-open-source-edition) concludes
### Stuff that requires vendored versions of Homebrew formulae
Homebrew formulae should avoid having multiple, separate, upstream projects bundled together in a single package to avoid shipping outdated/insecure versions of software that is already a formula. Veracode's [State of Software Security report](https://www.veracode.com/blog/research/announcing-state-software-security-v11-open-source-edition) concludes:
> In fact, 79% of the time, developers never update third-party libraries after including them in a codebase.
For more info see [Debian's](https://www.debian.org/doc/debian-policy/ch-source.html#s-embeddedfiles) and [Fedora's](https://docs.fedoraproject.org/en-US/packaging-guidelines/#bundling) stances on this.
### Sometimes there are exceptions
Even if all criteria are met we may not accept the formula.
Documentation tends to lag behind current decision-making. Although some
rejections may seem arbitrary or strange they are based on years of
experience making Homebrew work acceptably for our users.
## Sometimes there are exceptions
Even if all criteria are met we may not accept the formula. Documentation tends to lag behind current decision-making. Although some rejections may seem arbitrary or strange they are based on years of experience making Homebrew work acceptably for our users.

View File

@ -1,6 +1,6 @@
# `brew livecheck`
The `brew livecheck` command finds the newest version of a formula or cask's software by checking upstream. Livecheck has [strategies](https://rubydoc.brew.sh/Homebrew/Livecheck/Strategy.html) to identify versions from various sources, such as Git repositories, websites, etc.
The `brew livecheck` command finds the newest version of a formula or cask's software by checking upstream. Livecheck has [strategies](https://rubydoc.brew.sh/Homebrew/Livecheck/Strategy) to identify versions from various sources, such as Git repositories, websites, etc.
## Behavior
@ -13,21 +13,21 @@ When livecheck isn't given instructions for how to check for upstream versions,
It's sometimes necessary to override this default behavior to create a working check. If a source doesn't provide the newest version, we need to check a different one. If livecheck doesn't correctly match version text, we need to provide an appropriate regex or `strategy` block.
This can be accomplished by adding a `livecheck` block to the formula/cask/resource. For more information on the available methods, please refer to the [`Livecheck` class documentation](https://rubydoc.brew.sh/Livecheck.html).
This can be accomplished by adding a `livecheck` block to the formula/cask/resource. For more information on the available methods, please refer to the [`Livecheck` class documentation](https://rubydoc.brew.sh/Livecheck).
## Creating a check
1. **Use the debug output to understand the situation**. `brew livecheck --debug <formula>|<cask>` provides information about which URLs livecheck tries, any strategies that apply, matched versions, etc.
1. **Research available sources to select a URL**. Try removing the file name from `stable`/`url`, to see if this is a directory listing page. If that doesn't work, try to find a page that links to the file (e.g. a download page). If it's not possible to find the newest version on the website, try checking other sources from the formula/cask. When necessary, search for other sources outside of the formula/cask.
1. **Research available sources to select a URL**. Try removing the file name from `stable`/`url` to see if it provides a directory listing page. If that doesn't work, try to find a page that links to the file (e.g. a download page). If it's not possible to find the newest version on the website, try checking other sources from the formula/cask. When necessary, search for other sources outside of the formula/cask.
1. **Create a regex, if necessary**. If the check works without a regex and wouldn't benefit from having one, it's usually fine to omit it. More information on creating regexes can be found in the [regex guidelines](#regex-guidelines) section.
### General guidelines
* **Only use `strategy` when it's necessary**. For example, if livecheck is already using `Git` for a URL, it's not necessary to use `strategy :git`. However, if `Git` applies to a URL but we need to use `PageMatch`, it's necessary to specify `strategy :page_match`.
* **Only use `strategy` when it's necessary**. For example, if livecheck is already using the `Git` strategy for a URL, it's not necessary to use `strategy :git`. However, if `Git` applies to a URL but we need to use `PageMatch`, it's necessary to specify `strategy :page_match`.
* **Only use the `GithubLatest` strategy when it's necessary and correct**. `github.com` rate limits requests and we try to minimize our use of this strategy to avoid hitting the rate limit on CI or when using `brew livecheck --tap` on large taps (e.g. homebrew/core). The `Git` strategy is often sufficient and we only need to use `GithubLatest` when the "latest" release is different than the newest version from the tags.
* **Only use the `GithubLatest` strategy when it's necessary and correct**. GitHub rate-limits requests so we try to minimize our use of this strategy to avoid hitting the rate limit on CI or when using `brew livecheck --tap` on large taps (e.g. `homebrew/core`). The `Git` strategy is often sufficient and we only need to use `GithubLatest` when the "latest" release is different than the newest version from the tags.
### URL guidelines

View File

@ -5,21 +5,15 @@ image: https://brew.sh/assets/img/brewtestbot.png
# Brew Test Bot
`brew test-bot` is the name for the automated review and testing system funded
by [our Kickstarter in 2013](https://www.kickstarter.com/projects/homebrew/brew-test-bot).
`brew test-bot` is the name for the automated review and testing system funded by [our Kickstarter in 2013](https://www.kickstarter.com/projects/homebrew/brew-test-bot).
It comprises three Mac Pros hosting virtual machines that run the
[`test-bot.rb`](https://github.com/Homebrew/homebrew-test-bot/) external
command to perform automated testing of commits to the master branch, pull
requests and custom builds requested by maintainers.
It comprises three Mac Pros hosting virtual machines, several M1 Mac minis and some cloud Ubuntu instances that run the [`test-bot.rb`](https://github.com/Homebrew/homebrew-test-bot) external command to perform automated testing of commits to the master branch, pull requests and custom builds requested by maintainers.
## Pull Requests
The bot automatically builds pull requests and updates their status depending
on the result of the job.
The bot automatically builds pull requests and updates their status depending on the result of the job.
For example, a job which has been queued but not yet completed will have a
section in the pull request that looks like this:
For example, a job which has been queued but not yet completed will have a section in the pull request that looks like this:
![Triggered Pull Request](assets/img/docs/brew-test-bot-triggered-pr.png)
@ -37,6 +31,5 @@ A passed build looks like this:
---
On failed or passed builds you can click the "Details" link to view the result
in GitHub Actions.
On failed or passed builds you can click the "Details" link to view the result in GitHub Actions.

View File

@ -1,20 +1,20 @@
# Deprecating, Disabling, and Removing Formulae
# Deprecating, Disabling and Removing Formulae
There are many reasons why formulae may be deprecated, disabled, or removed. This document explains the differences between each method as well as explaining when one method should be used over another.
There are many reasons why formulae may be deprecated, disabled or removed. This document explains the differences between each method as well as explaining when one method should be used over another.
## Overview
This general rule of thumb can be followed:
These general rules of thumb can be followed:
- `deprecate!` should be used for formulae that _should_ no longer be used.
- `disable!` should be used for formulae that _cannot_ be used.
- Formulae that are no longer acceptable in homebrew/core or have been disabled for over a year should be removed.
- Formulae that are no longer acceptable in `homebrew/core` or have been disabled for over a year _should_ be removed.
## Deprecation
If a user attempts to install a deprecated formula, they will be shown a warning message but the install will proceed.
A formula should be deprecated to indicate to users that the formula should not be used and will be disabled in the future. Deprecated formulae should be maintained by the Homebrew maintainers so they can still build from source and their bottles continue to work (even if unmaintained upstream). If this is not possible, they should be disabled.
A formula should be deprecated to indicate to users that the formula should not be used and will be disabled in the future. Deprecated formulae should continue to be maintained by the Homebrew maintainers so they still build from source and their bottles continue to work (even if unmaintained upstream). If this is not possible, they should be disabled.
The most common reasons for deprecation are when the upstream project is deprecated, unmaintained, or archived.
@ -30,7 +30,7 @@ To deprecate a formula, add a `deprecate!` call. This call should include a depr
deprecate! date: "YYYY-MM-DD", because: :reason
```
The `date` parameter should be set to the date that the project or version became (or will become) deprecated. If there is no clear date but the formula needs to be deprecated, use today's date. If the `date` parameter is set to a date in the future, the formula will not become deprecated until that date. This can be useful if the upstream developers have indicated a date where the project or version will stop being supported.
The `date` parameter should be set to the date that the project or version became (or will become) deprecated. If there is no clear date but the formula needs to be deprecated, use today's date. If the `date` parameter is set to a date in the future, the formula will not become deprecated until that date. This can be useful if the upstream developers have indicated a date when the project or version will stop being supported.
The `because` parameter can be a preset reason (using a symbol) or a custom reason. See the [Deprecate and Disable Reasons](#deprecate-and-disable-reasons) section below for more details about the `because` parameter.
@ -49,7 +49,7 @@ The most common reasons for disabling a formula are:
Formulae should not be disabled without a deprecation period of at least three months unless the circumstances are exceptional (e.g. the formula does not build on any supported macOS version or Linux). Popular formulae should have longer deprecation periods. The popularity of a formula should be based on our analytics data.
**Note: disabled formulae in homebrew/core will be automatically removed one year after their disable date**
**Note: disabled formulae in `homebrew/core` will be automatically removed one year after their disable date**.
To disable a formula, add a `disable!` call. This call should include a deprecation date (in the ISO 8601 format) and a deprecation reason:
@ -76,9 +76,10 @@ There are two ways to indicate the reason. The preferred way is to use a pre-exi
- `:repo_archived`: the upstream repository has been archived
- `:repo_removed`: the upstream repository has been removed
- `:unmaintained`: the project appears to be abandoned
- `:unsupported`: Homebrew's application of the software is not supported by the upstream developers (e.g. upstream only supports macOS versions prior to 10.14)
- `:unsupported`: Homebrew's compilation of the software is not supported by the upstream developers (e.g. upstream only supports macOS versions older than 10.15)
- `:deprecated_upstream`: the project is deprecated upstream
- `:versioned_formula`: the formula is a versioned formula
- `:checksum_mismatch`: the checksum of the source for the formula's current version has changed since bottles were built
These reasons can be specified by their symbols (the comments show the message that will be displayed to users):
@ -92,7 +93,7 @@ deprecate! date: "2020-01-01", because: :deprecated_upstream
disable! date: "2020-01-01", because: :does_not_build
```
If these pre-existing reasons do not fit, a custom reason can be specified. These reasons should be written to fit into the sentence `<formula> has been deprecated/disabled because it <reason>!`.
If these pre-existing reasons do not fit, a custom reason can be specified. Such reasons should be written to fit into the sentence `<formula> has been deprecated/disabled because it <reason>!`.
A well-worded example of a custom reason would be:

View File

@ -1,13 +1,15 @@
# How To Open a Homebrew Pull Request
# How to Open a Homebrew Pull Request
The following commands are used by Homebrew contributors to set up a fork of Homebrew's Git repository on GitHub, create a new branch and create a GitHub pull request ("PR") of the changes in that branch.
Depending on the change you want to make, you need to send the pull request to the appropriate one of Homebrew's main repositories. If you want to submit a change to Homebrew core code (the `brew` implementation), you should open the pull request on [Homebrew/brew](https://github.com/Homebrew/brew). If you want to submit a change for a formula, you should open the pull request on the [homebrew/core](https://github.com/Homebrew/homebrew-core) tap, for casks you should open the pull request on the [homebrew/cask](https://github.com/Homebrew/homebrew-cask) tap or another [official tap](https://github.com/Homebrew), based on the formula type.
The type of change you want to make influences which of Homebrew's main repositories you'll need to send your pull request to. If you want to submit a change to Homebrew's core code (the `brew` implementation), you should open a pull request on [Homebrew/brew](https://github.com/Homebrew/brew). If you want to submit a change for a formula, you should open a pull request on the [homebrew/core](https://github.com/Homebrew/homebrew-core) tap, while for casks you should open the pull request on the [homebrew/cask](https://github.com/Homebrew/homebrew-cask) tap or another [official tap](https://github.com/Homebrew), based on the formula type.
## Submit a new version of an existing formula
1. Use `brew bump-formula-pr` to do everything (i.e. forking, committing, pushing) with a single command. Run `brew bump-formula-pr --help` to learn more.
## Submit a new version of an existing cask
1. Use `brew bump-cask-pr` to do everything (i.e. forking, committing, pushing) with a single command. Run `brew bump-cask-pr --help` to learn more.
## Set up your own fork of the Homebrew repository
@ -15,77 +17,99 @@ Depending on the change you want to make, you need to send the pull request to t
### Core `brew` code related pull request
1. [Fork the Homebrew/brew repository on GitHub](https://github.com/Homebrew/brew/fork).
* This creates a personal remote repository that you can push to. This is needed because only Homebrew maintainers have push access to the main repositories.
* This creates a personal remote repository that you can push to. This is needed because only Homebrew maintainers have push access to the main repositories.
2. Change to the directory containing your Homebrew installation:
```sh
cd "$(brew --repository)"
```
```sh
cd "$(brew --repository)"
```
3. Add your pushable forked repository as a new remote:
```sh
git remote add <YOUR_USERNAME> https://github.com/<YOUR_USERNAME>/brew.git
```
* `<YOUR_USERNAME>` is your GitHub username, not your local machine username.
```sh
git remote add <YOUR_USERNAME> https://github.com/<YOUR_USERNAME>/brew.git
```
* `<YOUR_USERNAME>` is your GitHub username, not your local machine username.
### Formulae related pull request
1. [Fork the Homebrew/homebrew-core repository on GitHub](https://github.com/Homebrew/homebrew-core/fork).
* This creates a personal remote repository that you can push to. This is needed because only Homebrew maintainers have push access to the main repositories.
* This creates a personal remote repository that you can push to. This is needed because only Homebrew maintainers have push access to the main repositories.
2. Change to the directory containing Homebrew formulae:
```sh
cd "$(brew --repository homebrew/core)"
```
```sh
cd "$(brew --repository homebrew/core)"
```
3. Add your pushable forked repository as a new remote:
```sh
git remote add <YOUR_USERNAME> https://github.com/<YOUR_USERNAME>/homebrew-core.git
```
* `<YOUR_USERNAME>` is your GitHub username, not your local machine username.
```sh
git remote add <YOUR_USERNAME> https://github.com/<YOUR_USERNAME>/homebrew-core.git
```
* `<YOUR_USERNAME>` is your GitHub username, not your local machine username.
### Cask related pull request
1. [Fork the Homebrew/homebrew-cask repository on GitHub](https://github.com/Homebrew/homebrew-cask/fork).
* This creates a personal remote repository that you can push to. This is needed because only Homebrew maintainers have push access to the main repositories.
* This creates a personal remote repository that you can push to. This is needed because only Homebrew maintainers have push access to the main repositories.
2. Change to the directory containing Homebrew casks:
```sh
cd "$(brew --repository homebrew/cask)"
```
```sh
cd "$(brew --repository homebrew/cask)"
```
3. Add your pushable forked repository as a new remote:
```sh
git remote add <YOUR_USERNAME> https://github.com/<YOUR_USERNAME>/homebrew-cask.git
```
* `<YOUR_USERNAME>` is your GitHub username, not your local machine username.
```sh
git remote add <YOUR_USERNAME> https://github.com/<YOUR_USERNAME>/homebrew-cask.git
```
* `<YOUR_USERNAME>` is your GitHub username, not your local machine username.
## Create your pull request from a new branch
To make a new branch and submit it for review, create a GitHub pull request with the following steps:
To make changes on a new branch and submit it for review, create a GitHub pull request with the following steps:
1. Check out the `master` branch:
```sh
git checkout master
```
```sh
git checkout master
```
2. Retrieve new changes to the `master` branch:
```sh
brew update
```
```sh
brew update
```
3. Create a new branch from the latest `master` branch:
```sh
git checkout -b <YOUR_BRANCH_NAME> origin/master
```
```sh
git checkout -b <YOUR_BRANCH_NAME> origin/master
```
4. Make your changes. For formulae or casks, use `brew edit` or your favourite text editor, following all the guidelines in the [Formula Cookbook](Formula-Cookbook.md) or [Cask Cookbook](Cask-Cookbook.md).
* If there's a `bottle do` block in the formula, don't remove or change it; we'll update it when we pull your PR.
5. Test your changes by running the following, and ensure they all pass without issue. For changed formulae and casks, make sure you do the `brew audit` step while your changed formula/cask is installed.
```sh
brew tests
brew install --build-from-source <CHANGED_FORMULA|CHANGED_CASK>
brew test <CHANGED_FORMULA|CHANGED_CASK>
brew audit --strict --online <CHANGED_FORMULA|CHANGED_CASK>
```
* If there's a `bottle do` block in the formula, don't remove or change it; we'll update it when we merge your PR.
5. Test your changes by running the following, and ensure they all pass without issue. For changed formulae and casks, make sure you do the `brew audit` step after your changed formula/cask has been installed.
```sh
brew tests
brew install --build-from-source <CHANGED_FORMULA|CHANGED_CASK>
brew test <CHANGED_FORMULA|CHANGED_CASK>
brew audit --strict --online <CHANGED_FORMULA|CHANGED_CASK>
```
6. [Make a separate commit](Formula-Cookbook.md#commit) for each changed formula with `git add` and `git commit`.
* Please note that our preferred commit message format for simple version updates is "`<FORMULA_NAME> <NEW_VERSION>`", e.g. "`source-highlight 3.1.8`".
* Please note that our preferred commit message format for simple version updates is "`<FORMULA_NAME> <NEW_VERSION>`", e.g. "`source-highlight 3.1.8`".
7. Upload your branch of new commits to your fork:
```sh
git push --set-upstream <YOUR_USERNAME> <YOUR_BRANCH_NAME>
```
8. Go to the relevant repository (e.g. <https://github.com/Homebrew/brew>, <https://github.com/Homebrew/homebrew-core>, etc.) and create a pull request to request review and merging of the commits in your pushed branch. Explain why the change is needed and, if fixing a bug, how to reproduce the bug. Make sure you have done each step in the checklist that appears in your new PR.
```sh
git push --set-upstream <YOUR_USERNAME> <YOUR_BRANCH_NAME>
```
8. Go to the relevant repository (e.g. <https://github.com/Homebrew/brew>, <https://github.com/Homebrew/homebrew-core>, etc.) and create a pull request to request review and merging of the commits from your pushed branch. Explain why the change is needed and, if fixing a bug, how to reproduce the bug. Make sure you have done each step in the checklist that appears in your new PR.
9. Await feedback or a merge from Homebrew's maintainers. We typically respond to all PRs within a couple days, but it may take up to a week, depending on the maintainers' workload.
Thank you!
@ -96,7 +120,7 @@ To respond well to feedback:
1. Ask for clarification of anything you don't understand and for help with anything you don't know how to do.
2. Post a comment on your pull request if you've provided all the requested changes/information and it hasn't been merged after a week. Post a comment on your pull request if you're stuck and need help.
* A `needs response` label on a PR means that the Homebrew maintainers need you to respond to previous comments.
* A `needs response` label on a PR means that the Homebrew maintainers need you to respond to previous comments.
3. Keep discussion in the pull request unless requested otherwise (i.e. do not email maintainers privately).
4. Do not continue discussion in closed pull requests.
5. Do not argue with Homebrew maintainers. You may disagree but unless they change their mind, please implement what they request. Ultimately they control what is included in Homebrew, as they have to support any changes that are made.
@ -104,20 +128,25 @@ To respond well to feedback:
To make changes based on feedback:
1. Check out your branch again:
```sh
git checkout <YOUR_BRANCH_NAME>
```
```sh
git checkout <YOUR_BRANCH_NAME>
```
2. Make any requested changes and commit them with `git add` and `git commit`.
3. Squash new commits into one commit per formula:
```sh
git rebase --interactive origin/master
```
* If you are working on a PR for a single formula, `git commit --amend` is a convenient way of keeping your commits squashed as you go.
4. Push to your remote fork's branch and the pull request:
```sh
git push --force
```
Once all feedback has been addressed and if it's a change we want to include (we include most changes), then we'll add your commit to Homebrew. Note that the PR status may show up as "Closed" instead of "Merged" because of the way we merge contributions. Don't worry: you will still get author credit in the actual merged commit.
```sh
git rebase --interactive origin/master
```
* If you are working on a PR for a single formula, `git commit --amend` is a convenient way of keeping your commits squashed as you go.
4. Push to your remote fork's branch and the pull request:
```sh
git push --force
```
Once all feedback has been addressed and if it's a change we want to include (we include most changes), then we'll add your changes to Homebrew. Note that the PR status may show up as "Closed" instead of "Merged" because of the way we merge contributions. Don't worry: you will still get author credit in the actual merged commit.
Well done, you are now a Homebrew contributor!

View File

@ -1,87 +1,52 @@
# How to Create and Maintain a Tap
[Taps](Taps.md) are external sources of Homebrew formulae, casks and/or external commands. They
can be created by anyone to provide their own formulae, casks and/or external commands
to any Homebrew user.
[Taps](Taps.md) are external sources of Homebrew formulae, casks and/or external commands. They can be created by anyone to provide their own formulae, casks and/or external commands to any Homebrew user.
## Creating a tap
A tap is usually a Git repository available online, but you can use anything as
long as its a protocol that Git understands, or even just a directory with
files in it.
If hosted on GitHub, we recommend that the repositorys name start with
`homebrew-` so the short `brew tap` command can be used.
See the [manpage](Manpage.md) for more information on repository naming.
A tap is usually a Git repository available online, but you can use anything as long as its a protocol that Git understands, or even just a directory with files in it. If hosted on GitHub, we recommend that the repositorys name start with `homebrew-` so the short `brew tap` command can be used. See the [manpage](Manpage.md) for more information on repository naming.
The `brew tap-new` command can be used to create a new tap along with some
template files.
The `brew tap-new` command can be used to create a new tap along with some template files.
Tap formulae follow the same format as the cores ones, and can be added under
either the `Formula` subdirectory, the `HomebrewFormula` subdirectory or the
repositorys root. The first available directory is used, other locations will
be ignored. We recommend use of subdirectories because it makes the repository
organisation easier to grasp, and top-level files are not mixed with formulae.
Tap formulae follow the same format as the cores ones, and can be added under either the `Formula` subdirectory, the `HomebrewFormula` subdirectory or the repositorys root. The first available directory is used, other locations will be ignored. We recommend the use of subdirectories because it makes the repository organisation easier to grasp, and top-level files are not mixed with formulae.
See [homebrew/core](https://github.com/Homebrew/homebrew-core) for an example of
a tap with a `Formula` subdirectory.
See [homebrew/core](https://github.com/Homebrew/homebrew-core) for an example of a tap with a `Formula` subdirectory.
## Naming your formulae to avoid clashes
### Naming your formulae to avoid clashes
If your formulae have the same name as Homebrew/homebrew-core formulae they cannot be installed side-by-side. If you wish to create a different version of a formula that's in Homebrew/homebrew-core (e.g. with `option`s) consider giving it a different name e.g. `nginx-full` for more fully-featured `nginx` formula. This will allow both `nginx` and `nginx-full` to be installed at the same time (assuming one is `keg_only` or the linked files do not clash).
If a formula in your tap has the same name as a Homebrew/homebrew-core formula they cannot be installed side-by-side. If you wish to create a different version of a formula that's in Homebrew/homebrew-core (e.g. with `option`s) consider giving it a different name; e.g. `nginx-full` for a more full-featured `nginx` formula. This will allow both `nginx` and `nginx-full` to be installed at the same time (assuming one is [`keg_only`](https://rubydoc.brew.sh/Formula#keg_only-class_method) or the linked files do not clash).
### Installing
## Installing
If its on GitHub, users can install any of your formulae with
`brew install user/repo/formula`. Homebrew will automatically add your
`github.com/user/homebrew-repo` tap before installing the formula.
`user/repo/formula` points to the `github.com/user/homebrew-repo/**/formula.rb`
file here.
If its on GitHub, users can install any of your formulae with `brew install user/repo/formula`. Homebrew will automatically add your `github.com/user/homebrew-repo` tap before installing the formula. `user/repo/formula` points to the `github.com/user/homebrew-repo/**/formula.rb` file here.
If they want to get your tap without installing any formula at the same time,
users can add it with the [`brew tap` command](Taps.md).
To install your tap without installing any formula at the same time, users can add it with the [`brew tap` command](Taps.md). If its on GitHub, they can use `brew tap user/repo`, where `user` is your GitHub username and `homebrew-repo` is your repository. If its hosted outside of GitHub, they have to use `brew tap user/repo <URL>`, where `user` and `repo` will be used to refer to your tap and `<URL>` is your Git clone URL.
If its on GitHub, they can use `brew tap user/repo`, where `user` is your
GitHub username and `homebrew-repo` is your repository.
If its hosted outside of GitHub, they have to use `brew tap user/repo <URL>`,
where `user` and `repo` will be used to refer to your tap and `<URL>` is your
Git clone URL.
Users can then install your formulae either with `brew install foo` if theres
no core formula with the same name, or with `brew install user/repo/foo` to
avoid conflicts.
Users can then install your formulae either with `brew install foo` if theres no core formula with the same name, or with `brew install user/repo/foo` to avoid conflicts.
## Maintaining a tap
A tap is just a Git repository so you dont have to do anything specific when
making modifications, apart from committing and pushing your changes.
A tap is just a Git repository so you dont have to do anything specific when making modifications, apart from committing and pushing your changes.
### Updating
Once your tap is installed, Homebrew will update it each time a user runs
`brew update`. Outdated formulae will be upgraded when a user runs
`brew upgrade`, like core formulae.
Once your tap is installed, Homebrew will update it each time a user runs `brew update`. Outdated formulae will be upgraded when a user runs `brew upgrade`, like core formulae.
## Casks
Casks can also be installed from a tap.
Casks can be included in taps with formulae, or in a tap with just casks.
Place any cask files you wish to make available in a `Casks` directory at the top level of your tap.
Casks can also be installed from a tap. Casks can be included in taps with formulae, or in a tap with just casks. Place any cask files you wish to make available in a `Casks` directory at the top level of your tap.
See [homebrew/cask](https://github.com/Homebrew/homebrew-cask) for an example of a tap with a `Casks` subdirectory.
### Naming
Unlike formulae, casks must have globally unique names to avoid clashes.
This can be achieved by e.g. prepending the cask name with your github username: `username-formula-name`.
Unlike formulae, casks must have globally unique names to avoid clashes. This can be achieved by e.g. prepending the cask name with your github username: `username-formula-name`.
## External commands
You can provide your tap users with custom `brew` commands by adding them in a
`cmd` subdirectory. [Read more on external commands](External-Commands.md).
You can provide your tap users with custom `brew` commands by adding them in a `cmd` subdirectory. [Read more on external commands](External-Commands.md).
See [homebrew/aliases](https://github.com/Homebrew/homebrew-aliases) for an
example of a tap with external commands.
See [homebrew/aliases](https://github.com/Homebrew/homebrew-aliases) for an example of a tap with external commands.
## Official Vendor Taps

View File

@ -1,6 +1,6 @@
# License Guidelines
We only accept formulae that use a [Debian Free Software Guidelines license](https://wiki.debian.org/DFSGLicenses) or are released into the public domain following [DFSG Guidelines on Public Domain software](https://wiki.debian.org/DFSGLicenses#Public_Domain).
We only accept formulae that use a [Debian Free Software Guidelines license](https://wiki.debian.org/DFSGLicenses) or are released into the public domain following [DFSG Guidelines on Public Domain software](https://wiki.debian.org/DFSGLicenses#Public_Domain) into `homebrew/core`.
## Specifying a License
@ -77,7 +77,7 @@ license any_of: [
The `HOMEBREW_FORBIDDEN_LICENSES` environment variable can be set to forbid installation of formulae that require or have dependencies that require certain licenses.
The `HOMEBREW_FORBIDDEN_LICENSES` should be set to a space separated list of licenses. Use `public_domain` to forbid installation of formulae with a `:public_domain` license.
The `HOMEBREW_FORBIDDEN_LICENSES` should be set to a space-separated list of licenses. Use `public_domain` to forbid installation of formulae with a `:public_domain` license.
For example, the following forbids installation of `MIT`, `Artistic-1.0` and `:public_domain` licenses:
@ -109,7 +109,7 @@ license any_of: ["MIT", "0BSD"]
export HOMEBREW_FORBIDDEN_LICENSES="Artistic-1.0+"
```
For GNU licenses (such as `GPL`, `LGPL`, `AGPL` and `GFDL`), use `-only` or `-or-later`. For example, the following would forbid `GPL-2.0`, `LGPL-2.1` and `LGPL-3.0` formulae from being installed, but would allow `GPL-3.0`
For GNU licenses (such as `GPL`, `LGPL`, `AGPL` and `GFDL`), use `-only` or `-or-later`. For example, the following would forbid `GPL-2.0`, `LGPL-2.1` and `LGPL-3.0` formulae from being installed, but would allow `GPL-3.0`:
```bash
export HOMEBREW_FORBIDDEN_LICENSES="GPL-2.0-only LGPL-2.1-or-later"

View File

@ -1,11 +1,11 @@
# Migrating A Formula To A Tap
# Migrating a Formula to a Tap
There are times when we may wish to migrate a formula from one tap into another tap. To do this:
1. Create a pull request to the new tap adding the formula file as-is from the original tap. Fix any test failures that may occur due to the stricter requirements for new formulae than existing formula (e.g. `brew audit --strict` must pass for that formula).
2. Create a pull request to the original tap deleting the formula file and add it to `tap_migrations.json` with a commit message like `gv: migrate to homebrew/core`.
1. Create a pull request on the new tap adding the formula file as-is from the original tap. Fix any test failures that may occur due to the stricter requirements for new formulae compared to existing formulae (e.g. `brew audit --strict` must pass for that formula).
2. Create a pull request on the original tap deleting the formula file and adding it to `tap_migrations.json` with a commit message like `gv: migrate to homebrew/core`.
3. Put a link for each pull request in the other pull request so the maintainers can merge them both at once.
Congratulations, you've moved a formula to a tap!
Congratulations, you've moved a formula to another tap!
For Homebrew maintainers, formulae should only ever be migrated into and within the Homebrew organisation (e.g. from Homebrew/core to Homebrew/cask, or from a third-party tap to Homebrew/core), and never out of it.
For Homebrew maintainers, formulae should only ever be migrated into and within the Homebrew organisation (e.g. from `homebrew/core` to `homebrew/cask`, or from a third-party tap to `homebrew/core`), and never out of it.

View File

@ -14,13 +14,11 @@ where `libexec` is the destination prefix (usually the `libexec` variable).
## Download URL
If the Node module is also available on the npm registry, we prefer npm hosted release tarballs over GitHub (or elsewhere) hosted source tarballs. The advantages of these tarballs are that they don't include the files from the `.npmignore` (such as tests) resulting in a smaller download size and that any possible transpilation step is already done (e.g. no need to compile CoffeeScript files as a build step).
If the Node module is also available on the npm registry, we prefer npm-hosted release tarballs over GitHub (or elsewhere) hosted source tarballs. The advantages of these tarballs are that they don't include the files from the `.npmignore` (such as tests) resulting in a smaller download size and that any possible transpilation step is already done (e.g. no need to compile CoffeeScript files as a build step).
The npm registry URLs usually have the format of:
```
https://registry.npmjs.org/<name>/-/<name>-<version>.tgz
```
https://registry.npmjs.org/<name>/-/<name>-<version>.tgz
Alternatively you could `curl` the JSON at `https://registry.npmjs.org/<name>` and look for the value of `versions[<version>].dist.tarball` for the correct tarball URL.
@ -32,7 +30,7 @@ Node modules which are compatible with the latest Node version should declare a
depends_on "node"
```
If your formula requires being executed with an older Node version you should use one of the versioned node formulae (e.g. `node@12`).
If your formula requires being executed with an older Node version you should use one of its versioned formulae (e.g. `node@12`).
### Special requirements for native addons
@ -42,7 +40,7 @@ If your Node module is a native addon or has a native addon somewhere in its dep
depends_on "python" => :build
```
Also note that such a formula would only be compatible with the same Node major version it originally was compiled with. This means that we need to revision every formula with a Node native addon with every major version bump of the `node` formula. To make sure we don't overlook your formula on a Node major version bump, write a meaningful test which would fail in such a case (invoked with an ABI-incompatible Node version).
Also note that such a formula would only be compatible with the same Node major version it originally was compiled with. This means that we need to revision every formula with a Node native addon with every major version bump of the `node` formula. To make sure we don't overlook your formula on a Node major version bump, write a meaningful test which would fail in such a case (being invoked with an ABI-incompatible Node version).
## Installation
@ -50,8 +48,8 @@ Node modules should be installed to `libexec`. This prevents the Node modules fr
In the following we distinguish between two types of Node modules installed using formulae:
* formulae for standard Node modules compatible with npm's global module format which should use [`std_npm_install_args`](#installing-global-style-modules-with-std_npm_install_args-to-libexec) (like [`azure-cli`](https://github.com/Homebrew/homebrew-core/blob/0f3b27d252b8112c744e0460d871cfe1def6b993/Formula/azure-cli.rb) or [`webpack`](https://github.com/Homebrew/homebrew-core/blob/6282879973d569962e63da7c81ac4623e1a8336b/Formula/webpack.rb))
* formulae where the `npm install` call is not the only required install step (e.g. need to also compile non-JavaScript sources) which have to use [`local_npm_install_args`](#installing-module-dependencies-locally-with-local_npm_install_args) (like [`elixirscript`](https://github.com/Homebrew/homebrew-core/blob/4bb491b7b246830aed57b97348a17e9401374978/Formula/elixirscript.rb) or [`grunt-cli`](https://github.com/Homebrew/homebrew-core/blob/93be1840908adb2f9ee8c48c66586ee6327480e3/Formula/grunt-cli.rb))
* formulae for standard Node modules compatible with npm's global module format which should use [`std_npm_install_args`](#installing-global-style-modules-with-std_npm_install_args-to-libexec) (like [`apollo-cli`](https://github.com/Homebrew/homebrew-core/blob/790c4298124d49823e5b9286d07519c1c1a9f773/Formula/apollo-cli.rb) or [`webpack`](https://github.com/Homebrew/homebrew-core/blob/6bb687199709b9cfed362efc9581e0ef24917acd/Formula/webpack.rb))
* formulae where the `npm install` call is not the only required install step (e.g. need to also compile non-JavaScript sources) which have to use [`local_npm_install_args`](#installing-module-dependencies-locally-with-local_npm_install_args) (like [`emscripten`](https://github.com/Homebrew/homebrew-core/blob/140d42bd9ada53cfd921abf964796dbf5bac1c3b/Formula/emscripten.rb) or [`grunt-cli`](https://github.com/Homebrew/homebrew-core/blob/0ab5d8e18f1dea2c4c57407a17f4aa4b8e985d76/Formula/grunt-cli.rb))
What both methods have in common is that they are setting the correct environment for using npm inside Homebrew and are returning the arguments for invoking `npm install` for their specific use cases. This includes fixing an important edge case with the npm cache (caused by Homebrew's redirection of `HOME` during the build and test process) by using our own custom `npm_cache` inside `HOMEBREW_CACHE`, which would otherwise result in very long build times and high disk space usage.
@ -69,7 +67,7 @@ In your formula's `install` method, simply `cd` to the top level of your Node mo
system "npm", "install", *Language::Node.std_npm_install_args(libexec)
```
This will install your Node module in npm's global module style with a custom prefix to `libexec`. All your modules' executables will be automatically resolved by npm into `libexec/bin` for you, which is not symlinked into Homebrew's prefix. We need to make sure these are installed. To do this we need to symlink all executables to `bin` with:
This will install your Node module in npm's global module style with a custom prefix to `libexec`. All your modules' executables will be automatically resolved by npm into `libexec/bin` for you, which are not symlinked into Homebrew's prefix. To make sure these are installed, we need to symlink all executables to `bin` with:
```ruby
bin.install_symlink Dir["#{libexec}/bin/*"]
@ -77,13 +75,13 @@ bin.install_symlink Dir["#{libexec}/bin/*"]
### Installing module dependencies locally with `local_npm_install_args`
In your formula's `install` method, do any installation steps which need to be done before the `npm install` step and then `cd` to the top level of the included Node module. Then, use `system` with `Language::Node.local_npm_install_args` to invoke `npm install` like:
In your formula's `install` method, do any installation steps which need to be done before the `npm install` step and then `cd` to the top level of the included Node module. Then, use `system` to invoke `npm install` with `Language::Node.local_npm_install_args` like:
```ruby
system "npm", "install", *Language::Node.local_npm_install_args
```
This will install all of your Node modules dependencies to your local build path. You can now continue with your build steps and take care of the installation into the Homebrew `prefix` on your own, following the [general Homebrew formula instructions](Formula-Cookbook.md).
This will install all of your Node modules' dependencies to your local build path. You can now continue with your build steps and handle the installation into the Homebrew prefix on your own, following the [general Homebrew formula instructions](Formula-Cookbook.md).
## Example

View File

@ -1,6 +1,7 @@
# Prose Style Guidelines
<!-- vale off -->
<!-- Disable vale linting for the whole of the style guide, because it contains deliberately bad examples. -->
# Prose Style Guidelines
This is a set of style and usage guidelines for Homebrew's prose documentation aimed at users, contributors, and maintainers (as opposed to executable computer code). It applies to documents like those in `docs` in the `Homebrew/brew` repository, announcement emails, and other communications with the Homebrew community.

View File

@ -10,25 +10,25 @@ Bindings are a special case of libraries that allow Python code to interact with
Homebrew is happy to accept applications that are built in Python, whether the apps are available from PyPI or not. Homebrew generally won't accept libraries that can be installed correctly with `pip install foo`. Bindings may be installed for packages that provide them, especially if equivalent functionality isn't available through pip.
Applications should unconditionally bundle all of their Python-language dependencies and libraries and should install any unsatisfied dependencies; these strategies are discussed in depth in the following sections.
Applications should unconditionally bundle all their Python-language dependencies and libraries and should install any unsatisfied dependencies; these strategies are discussed in depth in the following sections.
## Applications
### Python declarations
### Python declarations for applications
Formulae for apps that require Python 3 **should** declare an unconditional dependency on `"python@3.x"`. These apps **must** work with the current Homebrew Python 3.x formula.
Applications that are compatible with Python 2 **should** use the Apple-provided system Python in `/usr/bin` on systems that provide Python 2.7. No explicit Python dependency is needed since `/usr/bin` is always in `PATH` for Homebrew formulae.
### Installing
### Installing applications
Applications should be installed into a Python [virtualenv](https://virtualenv.pypa.io/en/stable/) environment rooted in `libexec`. This prevents the app's Python modules from contaminating the system site-packages and vice versa.
Applications should be installed into a Python [virtualenv](https://virtualenv.pypa.io/en/stable/) environment rooted in `libexec`. This prevents the app's Python modules from contaminating the system `site-packages` and vice versa.
All of the Python module dependencies of the application (and their dependencies, recursively) should be declared as `resource`s in the formula and installed into the virtualenv, as well. Each dependency should be explicitly specified; please do not rely on `setup.py` or `pip` to perform automatic dependency resolution, for the [reasons described here](Acceptable-Formulae.md#we-dont-like-install-scripts-that-download-unversioned-things).
All the Python module dependencies of the application (and their dependencies, recursively) should be declared as [`resource`](https://rubydoc.brew.sh/Formula#resource-class_method)s in the formula and installed into the virtualenv as well. Each dependency should be explicitly specified; please do not rely on `setup.py` or `pip` to perform automatic dependency resolution, for the [reasons described here](Acceptable-Formulae.md#we-dont-like-install-scripts-that-download-unversioned-things).
You can use `brew update-python-resources` to help you write resource stanzas. To use it, simply run `brew update-python-resources <formula>`. Sometimes, `brew update-python-resources` won't be able to automatically update the resources. If this happens, try running `brew update-python-resources --print-only <formula>` to print the resource stanzas instead of applying the changes directly to the file. You can then copy and paste resources as needed.
If using `brew update-python-resources` doesn't work, you can use [homebrew-pypi-poet](https://pypi.python.org/pypi/homebrew-pypi-poet) to help you write resource stanzas. To use it, set up a virtualenv and install your package and all its dependencies. Then, `pip install homebrew-pypi-poet` into the same virtualenv. Running `poet some_package` will generate the necessary resource stanzas. You can do this like:
If using `brew update-python-resources` doesn't work, you can use [homebrew-pypi-poet](https://github.com/tdsmith/homebrew-pypi-poet) to help you write resource stanzas. To use it, set up a virtualenv and install your package and all its dependencies. Then, `pip install homebrew-pypi-poet` into the same virtualenv. Running `poet some_package` will generate the necessary resource stanzas. You can do this like:
```sh
# Use a temporary directory for the virtual environment
@ -75,7 +75,7 @@ def install
end
```
### Example
### Example formula
Installing a formula with dependencies will look like this:
@ -86,13 +86,13 @@ class Foo < Formula
url "..."
resource "six" do
url "https://pypi.python.org/packages/source/s/six/six-1.9.0.tar.gz"
sha256 "e24052411fc4fbd1f672635537c3fc2330d9481b18c0317695b46259512c91d5"
url "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz"
sha256 "1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"
end
resource "parsedatetime" do
url "https://pypi.python.org/packages/source/p/parsedatetime/parsedatetime-1.4.tar.gz"
sha256 "09bfcd8f3c239c75e77b3ff05d782ab2c1aed0892f250ce2adf948d4308fe9dc"
url "https://files.pythonhosted.org/packages/a8/20/cb587f6672dbe585d101f590c3871d16e7aec5a576a1694997a3777312ac/parsedatetime-2.6.tar.gz"
sha256 "4cb368fbb18a0b7231f4d76119165451c8d2e35951455dfee97c62a87b04d455"
end
def install
@ -121,7 +121,7 @@ To add bindings for Python 3, please add `depends_on "python@3.x"` to work with
Build Python 2 bindings with the system Python by default (don't add an option) and they should be usable with any binary-compatible Python. If that isn't the case, it's an upstream bug; [here's some advice for resolving it](https://blog.tim-smith.us/2015/09/python-extension-modules-os-x/).
### Dependencies
### Dependencies for bindings
Bindings should follow the same advice for Python module dependencies as libraries; see below for more.
@ -147,39 +147,39 @@ Sometimes we have to edit a `Makefile` on-the-fly to use our prefix for the Pyth
## Libraries
### Python declarations
### Python declarations for libraries
Libraries built for Python 3 should include `depends_on "python@3.x"`, which will bottle against Homebrew's Python 3.x. Python 2.x libraries must function when they are installed against either the system Python or brewed Python.
Python 2 libraries need a `uses_from_macos "python@2"` declaration; they will be built with the system Python, but should still be usable with any other Python 2.7. If this is not the case, it's an upstream bug; [here's some advice for resolving it](https://blog.tim-smith.us/2015/09/python-extension-modules-os-x/).
Python 2 libraries need a `uses_from_macos "python@2"` declaration; they will be built with the system Python, but should still be usable with any other Python 2.7. If not, it's an upstream bug; [here's some advice for resolving it](https://blog.tim-smith.us/2015/09/python-extension-modules-os-x/).
### Installing
### Installing libraries
Libraries may be installed to `libexec` and added to `sys.path` by writing a `.pth` file (named like "homebrew-foo.pth") to the `prefix` site-packages. This simplifies the ensuing drama if `pip` is accidentally used to upgrade a Homebrew-installed package and prevents the accumulation of stale .pyc files in Homebrew's site-packages.
Libraries may be installed to `libexec` and added to `sys.path` by writing a `.pth` file (named like "homebrew-foo.pth") to the `prefix` site-packages. This simplifies the ensuing drama if pip is accidentally used to upgrade a Homebrew-installed package and prevents the accumulation of stale `.pyc` files in Homebrew's site-packages.
Most formulae presently just install to `prefix`.
### Dependencies
### Dependencies for libraries
The dependencies of libraries must be installed so that they are importable. To minimise the potential for linking conflicts, dependencies should be installed to `libexec/<vendor>` and added to `sys.path` by writing a second `.pth` file (named like "homebrew-foo-dependencies.pth") to the `prefix` site-packages.
Library dependencies must be installed so that they are importable. To minimise the potential for linking conflicts, dependencies should be installed to `libexec/<vendor>` and added to `sys.path` by writing a second `.pth` file (named like "homebrew-foo-dependencies.pth") to the `prefix` site-packages.
## Further down the rabbit hole
Additional commentary that explains why Homebrew does some of the things it does.
### setuptools vs. distutils vs. pip
### Setuptools vs. Distutils vs. pip
Distutils is a module in the Python standard library that provides developers a basic package management API. Setuptools is a module distributed outside the standard library that extends distutils. It is a convention that Python packages provide a `setup.py` that calls the `setup()` function from either distutils or setuptools.
Distutils is a module in the Python standard library that provides developers a basic package management API. Setuptools is a module distributed outside the standard library that extends Distutils. It is a convention that Python packages provide a `setup.py` that calls the `setup()` function from either Distutils or Setuptools.
Setuptools provides the `easy_install` command, which is an end-user package management tool that fetches and installs packages from PyPI, the Python Package Index. `pip` is another, newer end-user package management tool, which is also provided outside the standard library. While pip supplants `easy_install`, pip does not replace the other functionality of the setuptools module.
Setuptools provides the `easy_install` command, which is an end-user package management tool that fetches and installs packages from PyPI, the Python Package Index. `pip` is another, newer end-user package management tool, which is also provided outside the standard library. While pip supplants `easy_install`, it does not replace the other functionality of the Setuptools module.
Distutils and pip use a "flat" installation hierarchy that installs modules as individual files under site-packages while `easy_install` installs zipped eggs to site-packages instead.
Distutils and pip use a "flat" installation hierarchy that installs modules as individual files under `site-packages` while `easy_install` installs zipped eggs to `site-packages` instead.
Distribute (not to be confused with distutils) is an obsolete fork of setuptools. Distlib is a package maintained outside the standard library which is used by pip for some low-level packaging operations and is not relevant to most `setup.py` users.
Distribute (not to be confused with Distutils) is an obsolete fork of Setuptools. Distlib is a package maintained outside the standard library which is used by pip for some low-level packaging operations and is not relevant to most `setup.py` users.
### Running `setup.py`
In the event that a formula needs to interact with `setup.py` instead of calling `pip`, Homebrew provides a helper method, `Language::Python.setup_install_args`, which returns useful arguments for invoking `setup.py`. Your formula should use this instead of invoking `setup.py` explicitly. The syntax is:
For when a formula needs to interact with `setup.py` instead of calling `pip`, Homebrew provides the helper method `Language::Python.setup_install_args` which returns useful arguments for invoking `setup.py`. Your formula should use this instead of invoking `setup.py` explicitly. The syntax is:
```ruby
system Formula["python@3.x"].opt_bin/"python3", *Language::Python.setup_install_args(prefix)
@ -189,7 +189,7 @@ where `prefix` is the destination prefix (usually `libexec` or `prefix`).
### What is `--single-version-externally-managed`?
`--single-version-externally-managed` ("SVEM") is a setuptools-only [argument to `setup.py install`](https://setuptools.readthedocs.io/en/latest/setuptools.html?#install-run-easy-install-or-old-style-installation). The primary effect of SVEM is to use distutils to perform the install instead of using setuptools' `easy_install`.
`--single-version-externally-managed` ("SVEM") is a Setuptools-only [argument to `setup.py install`](https://setuptools.readthedocs.io/en/latest/setuptools.html?#install-run-easy-install-or-old-style-installation). The primary effect of SVEM is using Distutils to perform the install instead of Setuptools' `easy_install`.
`easy_install` does a few things that we need to avoid:
@ -197,17 +197,17 @@ where `prefix` is the destination prefix (usually `libexec` or `prefix`).
* upgrades dependencies in `sys.path` in-place
* writes `.pth` and `site.py` files which aren't useful for us and cause link conflicts
Setuptools requires that SVEM is used in conjunction with `--record`, which provides a list of files that can later be used to uninstall the package. We don't need or want this because Homebrew can manage uninstallation but since setuptools demands it we comply. The Homebrew convention is to call the record file "installed.txt".
Setuptools requires that SVEM be used in conjunction with `--record`, which provides a list of files that can later be used to uninstall the package. We don't need or want this because Homebrew can manage uninstallation, but since Setuptools demands it we comply. The Homebrew convention is to name the record file "installed.txt".
Detecting whether a `setup.py` uses `setup()` from setuptools or distutils is difficult, but we always need to pass this flag to setuptools-based scripts. `pip` faces the same problem that we do and forces `setup()` to use the setuptools version by loading a shim around `setup.py` that imports setuptools before doing anything else. Since setuptools monkey-patches distutils and replaces its `setup` function, this provides a single, consistent interface. We have borrowed this code and use it in `Language::Python.setup_install_args`.
Detecting whether a `setup.py` uses `setup()` from Setuptools or Distutils is difficult, but we always need to pass this flag to Setuptools-based scripts. `pip` faces the same problem that we do and forces `setup()` to use the Setuptools version by loading a shim around `setup.py` that imports Setuptools before doing anything else. Since Setuptools monkey-patches Distutils and replaces its `setup` function, this provides a single, consistent interface. We have borrowed this code and use it in `Language::Python.setup_install_args`.
### `--prefix` vs `--root`
`setup.py` accepts a slightly bewildering array of installation options. The correct switch for Homebrew is `--prefix`, which automatically sets the `--install-foo` family of options using sane POSIX-y values.
`setup.py` accepts a slightly bewildering array of installation options. The correct switch for Homebrew is `--prefix`, which automatically sets the `--install-foo` family of options with sane POSIX-y values.
`--root` [is used](https://mail.python.org/pipermail/distutils-sig/2010-November/017099.html) when installing into a prefix that will not become part of the final installation location of the files, like when building a .rpm or binary distribution. When using a `setup.py`-based setuptools, `--root` has the side effect of activating `--single-version-externally-managed`. It is not safe to use `--root` with an empty `--prefix` because the `root` is removed from paths when byte-compiling modules.
`--root` [is used](https://mail.python.org/pipermail/distutils-sig/2010-November/017099.html) when installing into a prefix that will not become part of the final installation location of the files, like when building a RPM or binary distribution. When using a `setup.py`-based Setuptools, `--root` has the side effect of activating `--single-version-externally-managed`. It is not safe to use `--root` with an empty `--prefix` because the `root` is removed from paths when byte-compiling modules.
It is probably safe to use `--prefix` with `--root=/`, which should work with either setuptools or distutils-based `setup.py`'s but is kinda ugly.
It is probably safe to use `--prefix` with `--root=/`, which should work with either Setuptools- or Distutils-based `setup.py`'s, but it's kinda ugly.
### `pip` vs. `setup.py`

View File

@ -24,7 +24,7 @@
- [External Commands](External-Commands.md)
- [Ruby Gems, Python Eggs and Perl Modules](Gems,-Eggs-and-Perl-Modules.md)
- [Python](Homebrew-and-Python.md)
- [How To Build Software Outside Homebrew With Homebrew `keg_only` dependencies](How-to-Build-Software-Outside-Homebrew-with-Homebrew-keg-only-Dependencies.md)
- [How to Build Software Outside Homebrew with Homebrew `keg_only` Dependencies](How-to-Build-Software-Outside-Homebrew-with-Homebrew-keg-only-Dependencies.md)
- [Xcode](Xcode.md)
- [Creating a Homebrew Issue](Creating-a-Homebrew-Issue.md)
@ -35,21 +35,21 @@
## Contributors
- [How To Open A Pull Request (and get it merged)](How-To-Open-a-Homebrew-Pull-Request.md)
- [How to Open a Pull Request (and get it merged)](How-To-Open-a-Homebrew-Pull-Request.md)
- [Formula Cookbook](Formula-Cookbook.md)
- [Cask Cookbook](Cask-Cookbook.md)
- [Acceptable Formulae](Acceptable-Formulae.md)
- [Acceptable Casks](Acceptable-Casks.md)
- [License Guidelines](License-Guidelines.md)
- [Formulae Versions](Versions.md)
- [Deprecating, Disabling, and Removing Formulae](Deprecating-Disabling-and-Removing-Formulae.md)
- [Deprecating, Disabling and Removing Formulae](Deprecating-Disabling-and-Removing-Formulae.md)
- [Node for Formula Authors](Node-for-Formula-Authors.md)
- [Python for Formula Authors](Python-for-Formula-Authors.md)
- [`brew livecheck`](Brew-Livecheck.md)
- [Migrating A Formula To A Tap](Migrating-A-Formula-To-A-Tap.md)
- [Rename A Formula](Rename-A-Formula.md)
- [Migrating a Formula to a Tap](Migrating-A-Formula-To-A-Tap.md)
- [Renaming a Formula](Rename-A-Formula.md)
- [Building Against Non-Homebrew Dependencies](Building-Against-Non-Homebrew-Dependencies.md)
- [How To Create (And Maintain) A Tap](How-to-Create-and-Maintain-a-Tap.md)
- [How to Create and Maintain a Tap](How-to-Create-and-Maintain-a-Tap.md)
- [Brew Test Bot](Brew-Test-Bot.md)
- [Diagram Guidelines](Diagram-Guidelines.md)
- [Prose Style Guidelines](Prose-Style-Guidelines.md)

View File

@ -1,11 +1,10 @@
# Renaming a Formula
Sometimes software and formulae need to be renamed. To rename a formula
you need to:
Sometimes software and formulae need to be renamed. To rename a formula you need to:
1. Rename the formula file and its class to a new formula. The new name must meet all the usual rules of formula naming. Fix any test failures that may occur due to the stricter requirements for new formulae than existing formulae (i.e. `brew audit --online --new-formula` must pass for that formula).
1. Rename the formula file and its class to a new formula name. The new name must meet all the usual rules of formula naming. Fix any test failures that may occur due to the stricter requirements for new formulae compared to existing formulae (e.g. `brew audit --strict` must pass for that formula).
2. Create a pull request to the corresponding tap deleting the old formula file, adding the new formula file, and adding it to `formula_renames.json` with a commit message like `newack: renamed from ack`. Use the canonical name (e.g. `ack` instead of `user/repo/ack`).
2. Create a pull request on the corresponding tap deleting the old formula file, adding the new formula file, and adding it to `formula_renames.json` with a commit message like `newack: renamed from ack`. Use the canonical name (e.g. `ack` instead of `user/repo/ack`).
A `formula_renames.json` example for a formula rename:

View File

@ -1,20 +1,14 @@
# Type Checking With Sorbet
The majority of the code in Homebrew is written in Ruby which is a dynamic
language. To avail the benefits of static type checking, we have set up
Sorbet in our codebase which provides the benefits of static type checking
to dynamic languages like Ruby.
The majority of the code in Homebrew is written in Ruby which is a dynamic language. To avail the benefits of static type checking, we have set up Sorbet in our codebase which provides the benefits of static type checking to dynamic languages like Ruby.
The [Sorbet Documentation] is a good place
to get started if you want to dive deeper into Sorbet and it's abilities.
The [Sorbet Documentation] is a good place to get started if you want to dive deeper into Sorbet and its abilities.
## Sorbet in the Homebrew Codebase
### Inline Type Annotations
To add type annotations to a class or module, we need to first extend it with
the `T::Sig` module (read this as `Type::Signature`). This adds the `sig`
method which is used to annotate method signatures. Here's a simple example:
To add type annotations to a class or module, we extend it with the `T::Sig` module (read this as `Type::Signature`). This adds the `sig` method which is used to annotate method signatures. Here's a simple example:
```ruby
class MyClass
@ -27,33 +21,20 @@ class MyClass
end
```
With `params`, we specify that we have a parameter `name` which must be a
`String` and with `returns`, we specify that this method always returns
a `String`.
With `params` we specify that there is a parameter `name` which must be a `String`, and with `returns` we specify that this method always returns a `String`.
For more information on how to express more complex types, refer to the
official documentation:
For more information on how to express more complex types, refer to the official documentation:
- [Method Signatures](https://sorbet.org/docs/sigs)
- [Class Types](https://sorbet.org/docs/class-types)
- [Nilable Types](https://sorbet.org/docs/nilable-types)
- [Union Types](https://sorbet.org/docs/union-types)
- [Method Signatures](https://sorbet.org/docs/sigs)
- [Class Types](https://sorbet.org/docs/class-types)
- [Nilable Types](https://sorbet.org/docs/nilable-types)
- [Union Types](https://sorbet.org/docs/union-types)
### Ruby Interface Files (`.rbi`)
RBI files help Sorbet learn about constants, ancestors and methods
defined in ways it doesnt understand natively. We can also create a
RBI file to help Sorbet understand dynamic definitions.
[RBI files](https://sorbet.org/docs/rbi) help Sorbet learn about constants, ancestors and methods defined in ways it doesnt understand natively. We can also create an RBI file to help Sorbet understand dynamic definitions.
Sometimes it is necessary to explicitly include the `Kernel` module in
order for Sorbet to know that methods such as `puts` are available in
a given context. This is mostly necessary for modules since they can
be used in both `BasicObject`s (which don't include `Kernel`) and
`Object`s (which include `Kernel` by default). In this case, it is
necessary to create an `.rbi` file ([example]) since re-including the
`Kernel` module in actual code can break things.
Read more about RBI files [here](https://sorbet.org/docs/rbi).
Sometimes it is necessary to explicitly include the `Kernel` module in order for Sorbet to know that methods such as `puts` are available in a given context. This is mostly necessary for modules since they can be used in both `BasicObject`s (which don't include `Kernel`) and `Object`s (which include `Kernel` by default). In this case, it is necessary to create an `.rbi` file ([example]) since re-including the `Kernel` module in actual code can break things.
[example]: https://github.com/Homebrew/brew/blob/61b79318ed089b5010501e2cbf163fd8e48e2dfc/Library/Homebrew/global.rbi
@ -61,69 +42,32 @@ Read more about RBI files [here](https://sorbet.org/docs/rbi).
[`Library/Homebrew/sorbet`]: https://github.com/Homebrew/brew/tree/master/Library/Homebrew/sorbet
- The `rbi` directory contains all Ruby Interface (`.rbi`) files
auto-generated by running `brew typecheck --update`:
- The `rbi` directory contains all Ruby Interface (`.rbi`) files auto-generated by running `brew typecheck --update`:
- RBI files for all gems are generated using
[Tapioca](https://github.com/Shopify/tapioca#tapioca).
- Definitions for dynamic code (i.e. meta-programming) are generated using
`srb rbi hidden-definitions`.
- RBI files for all gems are generated using [Tapioca](https://github.com/Shopify/tapioca#tapioca).
- Definitions for dynamic code (i.e. meta-programming) are generated using `srb rbi hidden-definitions`.
- Definitions for missing constants are generated using `srb rbi todo`.
- The `config` file is a newline-separated list of arguments to pass to
`srb tc`, the same as if theyd been passed at the command-line. Arguments
in the config file are always passed first, followed by arguments provided
on the command-line. We use it to ignore Gem directories which we do not
wish to type check.
- The `config` file is a newline-separated list of arguments to pass to `srb tc`, the same as if theyd been passed on the command line. Arguments in the config file are always passed first, followed by arguments provided on the command line. We use it to ignore Gem directories which we do not wish to type check.
- Every Ruby file in the codebase has a magic `# typed: <level>` comment at the
top, where `<level>` is one of [Sorbet's strictness levels], usually `false`,
`true` or `strict`. The `false` files only report errors related to the
syntax, constant resolution and correctness of the method signatures, but no
type errors. Our long-term goal is to move all `false` files to `true` and
start reporting type errors on those files as well. Therefore, when adding
new files, you should ideally mark it with `# typed: true` and work out any
resulting type errors.
- Every Ruby file in the codebase has a magic `# typed: <level>` comment at the top, where `<level>` is one of [Sorbet's strictness levels], usually `false`, `true` or `strict`. The `false` files only report errors related to the syntax, constant resolution and correctness of the method signatures, but no type errors. Our long-term goal is to move all `false` files to `true` and start reporting type errors on those files as well. Therefore, when adding new files, you should ideally mark it with `# typed: true` and work out any resulting type errors.
[Sorbet's strictness levels]: https://sorbet.org/docs/static#file-level-granularity-strictness-levels
[Sorbet's strictness levels]: https://sorbet.org/docs/static#file-level-granularity-strictness-levels
## Using `brew typecheck`
When run without any arguments, `brew typecheck`, will run considering the strictness levels
set in each of the individual Ruby files in the core Homebrew codebase. However, when
it is run on a specific file or directory, more errors may show up since Sorbet
cannot resolve constants defined outside the scope of the specified file. These
problems can be solved with RBI files. Currently `brew typecheck` provides `--quiet`, `--file`,
`--dir` and `--ignore` options but you can explore more options with `srb tc --help` and
passing them with `srb tc`.
When run without any arguments, `brew typecheck`, will run considering the strictness levels set in each of the individual Ruby files in the core Homebrew codebase. However, when it is run on a specific file or directory, more errors may show up since Sorbet cannot resolve constants defined outside the scope of the specified file. These problems can be solved with RBI files. Currently `brew typecheck` provides `--quiet`, `--file`, `--dir` and `--ignore` options but you can explore more options with `srb tc --help` and pass them with `srb tc`.
## Resolving Type Errors
Sorbet reports type errors along with an error reference code, which can be used
to look up more information on how to debug the error, or what causes the error in
the [Sorbet Documentation]. Here is how to debug some common type errors:
Sorbet reports type errors along with an error reference code, which can be used to look up more information on how to debug the error, or what causes the error in the [Sorbet Documentation]. Here is how to debug some common type errors:
- Using `T.reveal_type`. In files which are `true` or higher, if we wrap a variable
or method call in `T.reveal_type`, Sorbet will show us what type it thinks that
variable has in the output of `srb tc`. This is particularly useful when writing
[method signatures](https://sorbet.org/docs/sigs) and debugging. Make sure to
remove this line from your code before committing your changes, since this is
just a debugging tool.
- Using `T.reveal_type`: in files which are `true` or higher, by wrapping a variable or method call in `T.reveal_type`, Sorbet will show us what type it thinks that variable has in the output of `srb tc`. This is particularly useful when writing [method signatures](https://sorbet.org/docs/sigs) and debugging. Make sure to remove this line from your code before committing your changes, since this is just a debugging tool.
- One of the most frequent errors that we've encountered is: `7003: Method does not exist.`
Since Ruby is a very dynamic language, methods can be defined in ways Sorbet cannot
see statically. In such cases, check if the method exists at runtime, if not, then
Sorbet has caught a future bug! But, it is also possible that even though a method
exists at runtime, Sorbet cannot see it. In such cases, we use
[`.rbi` files](#ruby-interface-files-rbi).
- One of the most frequent errors that we've encountered is `7003: Method does not exist.` Since Ruby is a very dynamic language, methods can be defined in ways Sorbet cannot see statically. In such cases, check if the method exists at runtime; if not, then Sorbet has caught a future bug! But, it is also possible that even though a method exists at runtime, Sorbet cannot see it. In such cases, we use [`.rbi` files](#ruby-interface-files-rbi).
- Since Sorbet does not automatically assume that Kernel is to be included in Modules,
we may encounter many errors while trying to use methods like `puts`, `ohai`, `odebug` et cetera.
A simple workaround for this would be to add an extra `include Kernel` line in the
respective RBI file.
- Since Sorbet does not automatically assume that Kernel is to be included in Modules, we may encounter many errors while trying to use methods like `puts`, `ohai`, `odebug` etc. A simple workaround for this is to add an extra `include Kernel` line in the respective RBI file.
- The tips above are very generic and apply to lots of cases. For some common gotchas
when using Sorbet, refer to the [Sorbet Error Reference](https://sorbet.org/docs/error-reference)
and [FAQ](https://sorbet.org/docs/faq).
- The tips above are very generic and apply to lots of cases. For some common gotchas when using Sorbet, refer to the [Sorbet Error Reference](https://sorbet.org/docs/error-reference) and [FAQ](https://sorbet.org/docs/faq).
[Sorbet Documentation]: https://sorbet.org/docs/overview

View File

@ -1,26 +1,33 @@
# Versions
# Formulae Versions
[homebrew/core](https://github.com/homebrew/homebrew-core) supports multiple versions of formulae with a special naming format. For example, the formula for GCC 6 is named `gcc@6.rb` and begins with `class GccAT6 < Formula`.
[homebrew/core](https://github.com/homebrew/homebrew-core) supports multiple versions of formulae by using a special naming format. For example, the formula for GCC 6 is named `gcc@6.rb` and begins with `class GccAT6 < Formula`.
## Acceptable versioned formulae
Versioned formulae we include in [homebrew/core](https://github.com/homebrew/homebrew-core) must meet the following standards:
* Versioned software should build on all Homebrew's supported versions of macOS.
* Versioned software should build on all of Homebrew's supported versions of macOS.
* Versioned formulae should differ in major/minor (not patch) versions from the current stable release. This is because patch versions indicate bug or security updates, and we want to ensure you apply security updates.
* Unstable versions (alpha, beta, development versions) are not acceptable for versioned (or unversioned) formulae.
* Upstream should have a release branch for each formula version, and have an explicit policy of releasing security updates for each version when necessary. For example, [PHP 7.0 was not a supported version but PHP 7.2 was](https://php.net/supported-versions.php) in January 2020. By contrast, most software projects are structured to only release security updates for their latest versions, so their earlier versions are not eligible for versioning.
* Versioned formulae should share a codebase with the main formula. If the project is split into a different repository, we recommend creating a new formula (`formula2` rather than `formula@2` or `formula@1`).
* Formulae that depend on versioned formulae must not depend on the same formulae at two different versions twice in their recursive dependencies. For example, if you depend on `openssl@1.0` and `foo`, and `foo` depends on `openssl` then you must instead use `openssl`.
* Versioned formulae should only be linkable at the same time as their non-versioned counterpart if the upstream project provides support for it, e.g. using suffixed binaries. If this is not possible, use `keg_only :versioned_formula` to allow users to have multiple versions installed at once.
* Versioned formulae should only be linkable at the same time as their non-versioned counterpart if the upstream project provides support for it, e.g. by using suffixed binaries. If this is not possible, use `keg_only :versioned_formula` to allow users to have multiple versions installed at once.
* A `keg_only :versioned_formula` should not `post_install` anything in the `HOMEBREW_PREFIX` that conflicts with or duplicates the main counterpart (or other versioned formulae). For example, a `node@6` formula should not install its `npm` into `HOMEBREW_PREFIX` like the `node` formula does.
* Versioned formulae submitted should be expected to be used by a large number of people. If this ceases to be the case, they will be removed. We will aim not to remove those in the [top 3,000 `install_on_request` formulae](https://brew.sh/analytics/install-on-request/).
* Submitted versioned formulae should be expected to be used by a large number of people. If this ceases to be the case, they will be removed. We will aim not to remove those in the [top 3,000 `install_on_request` formulae](https://brew.sh/analytics/install-on-request/).
* Versioned formulae should not have `resource`s that require security updates. For example, a `node@6` formula should not have an `npm` resource but instead rely on the `npm` provided by the upstream tarball.
* Versioned formulae should be as similar as possible and sensible compared to the main formulae. Creating or updating a versioned formula should be a chance to ask questions of the main formula and vice versa, e.g. can some unused or useless options be removed or made default?
* No more than five versions of a formula (including the main one) will be supported at any given time, regardless of usage. When removing formulae that violate this, we will aim to do so based on usage and support status rather than age.
* Versioned formulae must be ABI stable for the lifetime of the version branch. Updates to the versioned formula must not introduce ABI incompatibilities or otherwise require dependents to be revision bumped. In practice, this means that their dependents should never need `revision` bumps to be rebuilt against newer versions. Version updates which violate this should be rejected and the formula be deprecated from that point onwards.
* Versioned formulae must be ABI-stable for the lifetime of the version branch. Updates to the versioned formula must not introduce ABI incompatibilities or otherwise require dependents to be revision bumped. In practice, this means that their dependents should never need `revision` bumps to be rebuilt against newer versions. Version updates which violate this should be rejected and the formula be deprecated from that point onwards.
Homebrew's versions should not be used to "pin" formulae to your personal requirements. You should instead create your own [tap](How-to-Create-and-Maintain-a-Tap.md) for formulae you or your organisation wish to control the versioning of, or those that do not meet the above standards. Software that has regular API or ABI breaking releases still needs to meet all the above requirements; that a `brew upgrade` has broken something for you is not an argument for us to add and maintain a formula for you.
Homebrew's versions should not be used to "pin" formulae to your personal requirements. You should instead [create your own tap](How-to-Create-and-Maintain-a-Tap.md) for formulae you or your organisation wish to control the versioning of, or those that do not meet the above standards. Software that has regular API or ABI breaking releases still needs to meet all the above requirements; that a `brew upgrade` has broken something for you is not an argument for us to add and maintain a formula for you.
If there is a formula that currently exists in the Homebrew/homebrew-core repository or has existed in the past (i.e. was migrated or deleted), you can recover it for your own use with the `brew extract` command. This will copy the desired version of the formula into a custom tap. For example, if your project depends on `automake` 1.12 instead of the most recent version, you can obtain the `automake` formula at version 1.12 by running `brew extract automake <YOUR_GITHUB_USER>/<YOUR_TAP_REPOSITORY_NAME> --version=1.12`. Formulae obtained this way may contain deprecated, disabled or removed Homebrew syntax (e.g. checksums may be `sha1` instead of `sha256`); the `brew extract` command does not edit or update formulae to meet current standards and style requirements.
If there is a formula that currently exists in the Homebrew/homebrew-core repository or has existed in the past (i.e. was migrated or deleted), you can recover it for your own use with the `brew extract` command. This will copy the desired version of the formula into a custom tap. For example, if your project depends on `automake` 1.12 instead of the most recent version, you can obtain the `automake` formula at version 1.12 by running:
```sh
brew extract automake --version=1.12 <YOUR_GITHUB_USER>/<YOUR_TAP_REPOSITORY_NAME>
```
Formulae obtained this way may contain deprecated, disabled or removed Homebrew syntax (e.g. checksums may be `sha1` instead of `sha256`); the `brew extract` command does not edit or update formulae to meet current standards and style requirements.
We may temporarily add versioned formulae for our own needs that do not meet these standards in [homebrew/core](https://github.com/homebrew/homebrew-core). The presence of a versioned formula there does not imply it will be maintained indefinitely or that we are willing to accept any more versions that do not meet the requirements above.