Compare commits

...

452 Commits
4.5.3 ... main

Author SHA1 Message Date
Ruoyu Zhong
23c491e5bc
Merge pull request #20247 from Homebrew/sorbet-files-update
sorbet: Update RBI files.
2025-07-13 14:51:13 +00:00
BrewTestBot
cc930ca089
sorbet: Update RBI files.
Autogenerated by the [sorbet](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/sorbet.yml) workflow.
2025-07-12 00:30:50 +00:00
Eric Knibbe
b631179579
Merge pull request #20246 from Homebrew/alias-symlink-names
aliases/aliases: fix naming of symlinks
2025-07-11 18:21:39 +00:00
Eric Knibbe
c1818fd099
aliases/aliases: fix naming of symlinks 2025-07-11 13:19:58 -04:00
Eric Knibbe
343748f601
Merge pull request #20242 from Homebrew/dependabot/pip/Library/Homebrew/formula-analytics/dependabot-e1daec460a
build(deps): bump the dependabot group across 1 directory with 3 updates
2025-07-11 16:51:52 +00:00
dependabot[bot]
4aee877f04
build(deps): bump the dependabot group across 1 directory with 3 updates
Bumps the dependabot group with 3 updates in the /Library/Homebrew/formula-analytics directory: [certifi](https://github.com/certifi/python-certifi), [influxdb3-python](https://github.com/InfluxCommunity/influxdb3-python) and [typing-extensions](https://github.com/python/typing_extensions).


Updates `certifi` from 2025.4.26 to 2025.6.15
- [Commits](https://github.com/certifi/python-certifi/compare/2025.04.26...2025.06.15)

Updates `influxdb3-python` from 0.13.0 to 0.14.0
- [Release notes](https://github.com/InfluxCommunity/influxdb3-python/releases)
- [Changelog](https://github.com/InfluxCommunity/influxdb3-python/blob/main/CHANGELOG.md)
- [Commits](https://github.com/InfluxCommunity/influxdb3-python/compare/v0.13.0...v0.14.0)

Updates `typing-extensions` from 4.13.2 to 4.14.1
- [Release notes](https://github.com/python/typing_extensions/releases)
- [Changelog](https://github.com/python/typing_extensions/blob/main/CHANGELOG.md)
- [Commits](https://github.com/python/typing_extensions/compare/4.13.2...4.14.1)

---
updated-dependencies:
- dependency-name: certifi
  dependency-version: 2025.6.15
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: dependabot
- dependency-name: influxdb3-python
  dependency-version: 0.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: dependabot
- dependency-name: typing-extensions
  dependency-version: 4.14.1
  dependency-type: indirect
  update-type: version-update:semver-minor
  dependency-group: dependabot
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-11 16:12:52 +00:00
Mike McQuaid
a7d986c6c2
Merge pull request #20243 from Homebrew/dependabot/pip/Library/Homebrew/formula-analytics/setuptools-80.9.0
build(deps): bump setuptools from 80.8.0 to 80.9.0 in /Library/Homebrew/formula-analytics
2025-07-11 15:56:09 +00:00
dependabot[bot]
837bb29607
build(deps): bump setuptools in /Library/Homebrew/formula-analytics
Bumps [setuptools](https://github.com/pypa/setuptools) from 80.8.0 to 80.9.0.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v80.8.0...v80.9.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-version: 80.9.0
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-11 15:36:54 +00:00
Mike McQuaid
11b3bd91c9
Merge pull request #20240 from Homebrew/sync-shared-config
Synchronize shared configuration
2025-07-11 15:11:55 +00:00
BrewTestBot
6b5d6c5333
dependabot.yml: update to match main configuration 2025-07-11 14:54:40 +00:00
Mike McQuaid
8856a609d6
Merge pull request #20239 from Homebrew/sync-shared-config
Synchronize shared configuration
2025-07-11 13:28:41 +00:00
Mike McQuaid
eec800149f
Merge pull request #20238 from Homebrew/fix_rubocop_fixture_style
`fixtures/rubocop@x.x.x.rbi`: fix style.
2025-07-11 13:17:54 +00:00
BrewTestBot
82914cafb1
dependabot.yml: update to match main configuration 2025-07-11 13:08:56 +00:00
Mike McQuaid
370ce002e9
Merge pull request #20237 from Homebrew/actionlint_skip_homebrew_brew
style: fix skipping actionlint checks on Homebrew/brew.
2025-07-11 13:06:52 +00:00
Issy Long
7f333ab6ec
Merge pull request #20235 from Homebrew/slash-not-plus-in-paths
rubocops/text: Prefer `lib/"string"` over `lib+"string"`
2025-07-11 12:56:54 +00:00
Mike McQuaid
607ffafd9f
fixtures/rubocop@x.x.x.rbi: fix style.
At least for me locally: `brew style` complains about this and
`brew style --fix` autocorrects it.
2025-07-11 13:54:51 +01:00
Mike McQuaid
26bb16e26d
style: fix skipping actionlint checks on Homebrew/brew.
If we're running `brew style` on Homebrew/brew: let's ensure that we
don't run the `actionlint` checks as they are handled by the dedicated
`actionlint.yml` workflow.
2025-07-11 13:51:59 +01:00
Mike McQuaid
36a4cb42ed
Merge pull request #20233 from Homebrew/zero_zero_zero_zero
Add ZeroZeroZeroZero cop
2025-07-11 12:44:23 +00:00
Issy Long
d4d1b4a22a
rubocops/text: Prefer lib/"string" over lib+"string"
- I found a few occurrences of this pattern from
  https://github.com/orgs/Homebrew/projects/5?pane=issue&itemId=97021840,
  that is an automated style request for:
  `core: use / instead of + operator in e.g. (lib+"lv").install "lv.hlp"`.
- Upon adding tests I realised that there's also the `prefix + "bin"`
  case that's already handled differently, so let's combine the handling
  given it's the same `+` that's wrong.
2025-07-11 13:41:58 +01:00
Mike McQuaid
3e0b0c1b32
Merge pull request #20232 from Homebrew/pathname_instance_variables
Improve some `Pathname` instance variable handling
2025-07-11 08:21:24 +00:00
Mike McQuaid
d57efd9ea2
Improve some Pathname instance variable handling
Will fix or at least partly address:
```
/home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/os/linux/elf.rb:225: warning: The class Pathname reached 8 shape variations, instance variables accesses will be slower and memory usage increased.
35
It is recommended to define instance variables in a consistent order, for instance by eagerly defining them all in the #initialize method.
```
2025-07-11 08:02:27 +00:00
Mike McQuaid
71bab462e1
Add ZeroZeroZeroZero cop
Add a new RuboCop to detect the use of 0.0.0.0 in formulae which
indicates binding to all network interfaces, internally or externally,
so is a bad default and potentially a security risk.

Co-authored-by: Issy Long <me@issylong.com>
2025-07-11 08:24:19 +01:00
Carlo Cabrera
5692ea6c17
Merge pull request #20236 from Homebrew/sync-shared-config
Synchronize shared configuration
2025-07-11 06:55:42 +00:00
BrewTestBot
8efb804e4e
actionlint.yml: update to match main configuration 2025-07-11 06:36:02 +00:00
Patrick Linnane
a65b9d0128
Merge pull request #20234 from Homebrew/sync-shared-config
Synchronize shared configuration
2025-07-10 17:25:05 +00:00
BrewTestBot
e4893037ae
dependabot.yml: update to match main configuration 2025-07-10 17:09:22 +00:00
Mike McQuaid
a2bf23ef70
Merge pull request #20224 from Homebrew/cask_dumper_old_tokens
Support Cask renames when installing/dumping
2025-07-10 13:54:26 +00:00
Carlo Cabrera
0b99d57621
Merge pull request #20226 from Homebrew/formula-loading-stdout
formulary: prevent formulae from printing to stdout while being loaded
2025-07-10 12:43:42 +00:00
Carlo Cabrera
69ce5edd14
formulary: improve style
Co-authored-by: Mike McQuaid <mike@mikemcquaid.com>
2025-07-10 20:27:52 +08:00
Mike McQuaid
b53f3b570c
Merge pull request #20228 from Paulchen5/use-github-secrets-in-workflow
Replace `github.token` by `secrets.GITHUB_TOKEN`
2025-07-10 08:32:40 +00:00
Mike McQuaid
5bc5d53a23
Merge pull request #20229 from Homebrew/attestation_opt_in
attestation: require explicit opt-in.
2025-07-10 08:24:48 +00:00
Mike McQuaid
17762fa77a
attestation: require explicit opt-in.
Work on this has stalled a bit and it slows things down so let's require
an explicit opt-in to use it.

While we're here, remove the silent/implicit opt-out for CI, too.
2025-07-10 09:10:08 +01:00
Mike McQuaid
e8bfa23877
Support Cask renames when installing/dumping
This adds support for Cask old tokens used for renames of Casks.

We'll now correctly check these at installation time to avoid repeatedly
installing renamed Casks and dump them in the Brewfile. We also use this
logic to avoid cleaning up renamed Casks.
2025-07-10 08:05:36 +00:00
Paulchen
b7b369270e
Replace github.token by secrets.GITHUB_TOKEN 2025-07-10 17:01:29 +09:00
Carlo Cabrera
d46d315cc1
Merge pull request #20227 from Homebrew/sync-shared-config
Synchronize shared configuration
2025-07-09 22:07:13 +00:00
BrewTestBot
455a461406
actionlint.yml: update to match main configuration 2025-07-09 21:53:17 +00:00
Carlo Cabrera
6141c6a181
formulary: prevent formulae from printing to stdout while being loaded
Formulae can execute arbitrary Ruby code when being loaded. In
particular, they can print to stdout with methods like `puts`. This can
break the parsing of output of commands like `brew info --json=v2`.

Let's fix that by capturing the output to stdout, and then printing
those messages to stderr instead (using `opoo` to try to discourage
formula authors from doing this).
2025-07-10 03:58:39 +08:00
Issy Long
ab3955209e
Merge pull request #20225 from Homebrew/rename-bundle-tests
Rename the `brew_{dumper,installer}_spec.rb` files
2025-07-09 17:42:23 +00:00
Issy Long
50c3181cdb
Rename the brew_{dumper,installer}_spec.rb files
- The classes were renamed in 990c1efc16aad71254ae89e0b7983eee97696c72,
  but I forgot to rename the test filenames.
2025-07-09 17:47:08 +01:00
Eric Knibbe
700d67a85e
Merge pull request #20220 from Homebrew/download_strategy-wanted-headers
download_strategy: only require content-disposition header
2025-07-07 17:52:52 +00:00
Eric Knibbe
0f2131484d
download_strategy: only require content-disposition header 2025-07-07 13:16:33 -04:00
Mike McQuaid
5ec756e0ca
Merge pull request #20193 from Homebrew/skinny-rubocop-rbi
Keep only the parts of `rubocop.rbi` that we actually use
2025-07-07 16:59:45 +00:00
Bo Anderson
d88a0e46fc
Merge pull request #20221 from Homebrew/shfmt-fix
style: run shfmt on real brew
2025-07-07 16:50:11 +00:00
Bo Anderson
2dfb8c0b76
style: run shfmt on real brew 2025-07-07 17:28:31 +01:00
Patrick Linnane
114d66082d
Merge pull request #20215 from Homebrew/sorbet-files-update
sorbet: Update RBI files.
2025-07-05 05:49:20 +00:00
BrewTestBot
d010adb903
sorbet: Update RBI files.
Autogenerated by the [sorbet](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/sorbet.yml) workflow.
2025-07-05 00:29:43 +00:00
Douglas Eichelberger
43b72d3633
Merge pull request #20213 from Homebrew/dug-20205
Exit non-zero when pinning uninstalled formula
2025-07-04 21:56:14 +00:00
Issy Long
1286a3676c
Merge pull request #20214 from Homebrew/the-old-brews-flag-needs-to-remain-for-backwards-compatibility
Retain the old `brew bundle --brews` flag for compatibility
2025-07-04 21:52:49 +00:00
Issy Long
ce8bf906c1
Retain the old brew bundle --brews flag for compatibility
https://github.com/Homebrew/brew/pull/20209#discussion_r2186099917
2025-07-04 22:02:59 +01:00
Douglas Eichelberger
e78cc286e0
Keep exiting zero on already pinned formulae 2025-07-04 13:55:12 -07:00
Douglas Eichelberger
f4bcda325a
Exit non-zero when pinning uninstalled formula 2025-07-04 13:28:54 -07:00
Issy Long
495b5bedde
Merge pull request #20209 from Homebrew/bundle-rename-brews-to-formulae
bundle: Rename "brews" to "formulae" for consistency
2025-07-04 20:21:38 +00:00
Issy Long
990c1efc16
bundle: Rename "brews" to "formulae" for consistency
- Homebrew Bundle referred to formulae as "brews". But it referred to
  casks as "casks" and taps as "taps".
- Let's use the same terminology everywhere.
- (I know that `brew "hello"` is the formula syntax in the Brewfile, so
  I'm not changing that (though would be up for it, in a backwards
  compatible manner), just making the code more consistent.)
2025-07-04 21:08:37 +01:00
Eric Knibbe
b57557dc3d
Merge pull request #20210 from Homebrew/formula-download-strategies
Formula-Cookbook: improve download strategy info
2025-07-04 19:25:40 +00:00
Eric Knibbe
bb372b2665
Formula-Cookbook: improve download strategy info 2025-07-04 15:12:32 -04:00
Patrick Linnane
727804bb08
Merge pull request #20206 from osalbahr/docs-update-dnf-commands
docs/Homebrew-on-Linux: update dnf5 syntax, centos/rhel section
2025-07-04 18:24:41 +00:00
Patrick Linnane
5c8fe3a339
Merge pull request #20212 from Homebrew/sponsors-maintainers-man-completions
Update manpage and completions.
2025-07-04 18:15:15 +00:00
BrewTestBot
37f1e48538
Update manpage and completions.
Autogenerated by the [sponsors-maintainers-man-completions](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/sponsors-maintainers-man-completions.yml) workflow.
2025-07-04 17:42:58 +00:00
Eric Knibbe
be6c62b1d9
Merge pull request #20211 from Homebrew/fix-brew-info
cmd/info: fix `brew info <formula>`
2025-07-04 17:23:47 +00:00
Eric Knibbe
a7471e449e
cmd/info: fix brew info <formula> 2025-07-04 10:33:11 -04:00
Issy Long
a36f8af593
Merge pull request #20208 from Homebrew/dependabot/github_actions/github-actions-384b59e5c3
build(deps): bump github/codeql-action from 3.29.0 to 3.29.2 in the github-actions group
2025-07-04 10:13:16 +00:00
dependabot[bot]
998470f4a5
build(deps): bump github/codeql-action in the github-actions group
Bumps the github-actions group with 1 update: [github/codeql-action](https://github.com/github/codeql-action).


Updates `github/codeql-action` from 3.29.0 to 3.29.2
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v3.29.0...181d5eefc20863364f96762470ba6f862bdef56b)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.29.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-04 08:59:13 +00:00
Osama Albahrani
4f677e72d4 docs/Homebrew-on-Linux: update dnf5 syntax, centos/rhel section
Tested on Fedora 42 and CentOS Stream/RHEL 10 (latest for all).

Note: Fedora 42 uses dnf5 while CentOS Stream/RHEL 10 use dnf4

See:
- https://github.com/Homebrew/install/pull/894
- 0fd28f83c8/install.sh (L1133)
2025-07-04 06:55:18 +03:00
Eric Knibbe
94606f343a
Merge pull request #20200 from Homebrew/consider-content-type
download_strategy: preserve cache upon text response
2025-07-04 02:18:45 +00:00
Eric Knibbe
eff4523074
download_strategy: preserve cache upon text response 2025-07-03 22:05:49 -04:00
Eric Knibbe
0b7c57af3b
Merge pull request #20204 from Homebrew/eval-all-check-env
cmd/dev-cmd: fetch `HOMEBREW_EVAL_ALL` for `--eval-all`
2025-07-04 02:05:22 +00:00
Issy Long
836d85277f
Keep only the parts of rubocop.rbi that we actually use
- This file was _massive_ - over 60k lines and we had to bump the file
  size limit for pushes to the repo!
- This was because by default Tapioca, when it encounters a
  `require "rubocop"` during RBI generation, loads all of the cops ever
  because they're all classes inside `RuboCop::Cop`.
- There wasn't an easy way to control this at Tapioca generation time
  (we tried), so now we parse the generated RBI file and delete classes
  and method definitions that we don't use.
- I regenerated the RBIs (`brew tc --update rubocop`) and added new
  things to the allowlist until Sorbet came back green.
- Now the file is ~7k lines and 240K - much better!
2025-07-04 00:27:12 +01:00
Eric Knibbe
f5c5d26173
cmd/dev-cmd: fetch HOMEBREW_EVAL_ALL for --eval-all 2025-07-03 12:59:12 -04:00
Carlo Cabrera
57024a9f2d
Merge pull request #20195 from tyuwags/ask-option-refactoring
Ask option refactoring
2025-07-03 12:28:46 +00:00
Issy Long
4b85b24531
Merge pull request #20201 from Homebrew/fix-dry-run-install
Fix "undefined method 'name' for an instance of FormulaInstaller"
2025-07-03 10:47:12 +00:00
Issy Long
c7af63488d
Be more explicit that we want the formula name 2025-07-03 11:29:50 +01:00
Thibaut Hérault
ea240e5aad
Update Library/Homebrew/reinstall.rb
Co-authored-by: Carlo Cabrera <github@carlo.cab>
2025-07-02 15:43:24 -04:00
Bevan Kay
23742f3500
Merge pull request #20203 from Homebrew/sync-shared-config
Synchronize shared configuration
2025-07-02 13:30:51 +00:00
BrewTestBot
09cec91b28
actionlint.yml: update to match main configuration 2025-07-02 08:10:35 +00:00
Eric Knibbe
ec9c0d65fd
Merge pull request #20202 from Homebrew/spdx-update
spdx: update license data.
2025-07-02 03:30:03 +00:00
BrewTestBot
2e963b2e06
spdx: update license data.
Autogenerated by [a scheduled GitHub Action](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/spdx.yml).
2025-07-02 00:17:54 +00:00
Issy Long
5310c5e730
Fix "undefined method 'name' for an instance of FormulaInstaller"
- Because `name` is not a method on `FormulaInstaller`, instead
  `formula` shows the name.
- Fixes issue 20199.

Before:

```
$ brew install -n hello
Error: undefined method 'name' for an instance of FormulaInstaller
Warning: Removed Sorbet lines from backtrace!
Rerun with `--verbose` to see the original backtrace
/opt/homebrew/Library/Homebrew/install.rb:330:in 'Array#map'
/opt/homebrew/Library/Homebrew/install.rb:330:in 'Homebrew::Install.install_formulae'
```

After:

```
$ brew install -n hello
==> Would install 1 formula:
hello
```
2025-07-01 22:25:22 +01:00
Eric Knibbe
8520539312
Merge pull request #20198 from Homebrew/determine-runner-arch
github_runner_matrix: fix skipped runner creation
2025-07-01 19:20:50 +00:00
Eric Knibbe
f92e961ff1
github_runner_matrix: fix skipped runner creation 2025-07-01 15:07:24 -04:00
Thibaut Hérault
a6aad3d12f
Update Library/Homebrew/upgrade.rb
Co-authored-by: Carlo Cabrera <github@carlo.cab>
2025-07-01 09:59:54 -04:00
thibhero
006d3779f3 returning early if upgradeable is blank
resolves #20197
2025-06-30 10:58:33 -04:00
thibhero
e3cc36a8b9 guard if keg or linked is nil 2025-06-30 10:57:41 -04:00
thibhero
c7f7ab5631 duplicate in ask_formulae 2025-06-29 23:29:18 -04:00
thibhero
c5036f3bba removing debugging symbols 2025-06-29 23:24:04 -04:00
thibhero
dfab4bbab2 removing formula previously updated 2025-06-29 23:18:38 -04:00
Issy Long
019a799fae
Merge pull request #20128 from Homebrew/some-bundle-files-werent-typed-at-all
Make the remaining `bundle` files `typed: true`
2025-06-29 23:10:59 +00:00
Douglas Eichelberger
bcab2ae500
Merge pull request #20192 from Homebrew/dug-refactor-exec
Refactor exec.rb type fixes
2025-06-29 11:59:27 -07:00
Douglas Eichelberger
fb01c0fa96
Update another overly narrow return type 2025-06-29 11:30:06 -07:00
Douglas Eichelberger
004c0a2a6c
Refactor exec.rb type fixes 2025-06-29 09:02:24 -07:00
Branch Vincent
52d66f206a
Merge pull request #20191 from branchvincent/maturin
extend/ENV/super: set `MATURIN_NO_INSTALL_RUST`
2025-06-28 20:09:44 +00:00
Branch Vincent
ba178a8f10
extend/ENV/super: set MATURIN_NO_INSTALL_RUST 2025-06-27 21:49:56 -07:00
Eric Knibbe
fe4f472c8d
Merge pull request #20187 from Homebrew/github-release-notes-link
dev-cmd/bump-formula-pr: release notes as proper html link
2025-06-28 00:14:45 +00:00
Bo Anderson
01c8e42ea8
Merge pull request #20190 from Homebrew/local-main-fix
cmd/update: ensure local branch moves to main
2025-06-27 23:52:58 +00:00
Issy Long
c3ec61b7cd
Merge pull request #20182 from Homebrew/some-bundle-files-werent-typed-at-all-but-now-some-are
Reapply "Make some of the `bundle` commands Sorbet `typed: true`"
2025-06-27 21:37:41 +00:00
Bo Anderson
98b7bc8d11
cmd/update: ensure local branch moves to main 2025-06-27 22:05:17 +01:00
Issy Long
a2e39c4814
Make Bundle::BrewDumper more Homebrew-y
- https://github.com/Homebrew/brew/pull/20182#discussion_r2170422499
2025-06-27 18:15:37 +01:00
Bo Anderson
4dabf8da16
Merge pull request #20186 from Homebrew/origin-head-fix
cmd/update: ensure we update remote main ref
2025-06-27 16:57:41 +00:00
Štefan Baebler
5627a90652
dev-cmd/bump-formula-pr: release notes as proper html link
The release notes link is not rendered as a proper hyperlink, this fixes it.

Few examples of PRs with unclickable links:
* https://github.com/Homebrew/homebrew-core/pull/228256
* https://github.com/Homebrew/homebrew-core/pull/228263
* https://github.com/Homebrew/homebrew-core/pull/228267
2025-06-27 18:52:43 +02:00
Bo Anderson
7f3f3c2d55
cmd/update: ensure we update remote main ref 2025-06-27 17:45:04 +01:00
Mike McQuaid
a83a71ab5f
Merge pull request #20185 from Homebrew/tier_doctor_issues
Provide more leeway to file Tier 2/3 issues.
2025-06-27 16:23:36 +00:00
Mike McQuaid
7019df7481
Provide more leeway to file Tier 2/3 issues.
Let's still continue to tell people to not file some issues but allow
them to file others.

While we're here, let's me a bit more chill with the language here.
2025-06-27 15:27:26 +01:00
Mike McQuaid
c9d3df2e54
Merge pull request #20176 from Homebrew/migrate_core_main
cmd/update: improve homebrew-core `main` migration.
2025-06-27 08:28:04 +00:00
Mike McQuaid
c8585134b4
Merge pull request #20171 from Homebrew/core_main
docs: homebrew-core's default branch is now `main`
2025-06-27 08:28:02 +00:00
Mike McQuaid
53bb328cbc
Merge pull request #20183 from tyuwags/correcting-Refine-ask‐option-dependency
Correcting refine ask option dependency
2025-06-27 08:05:34 +00:00
thibhero
e731b572f3 correcting rescue to use installer and not formula 2025-06-27 03:50:26 -04:00
Mike McQuaid
fbab2caec3
Merge pull request #20184 from Homebrew/fix_docs_ci
docs: fix HTML Proofer in CI
2025-06-27 07:34:16 +00:00
Mike McQuaid
e3e8ccef0a
docs: fix HTML Proofer in CI
- Add caching to make this build faster and less flaky.
- Skip the currently flaky URL.
- Cache external links for longer.
2025-06-27 08:09:24 +01:00
thibhero
f9dab1561a removing debugging symbol 2025-06-26 19:13:02 -04:00
thibhero
9e131d0794 correcting error of installation dependency
resolves #20181
2025-06-26 19:12:39 -04:00
Issy Long
5fed8f4210
Make the remaining Bundle file Sorbet typed: true 2025-06-26 23:21:54 +01:00
Issy Long
0d40f48e8d
Reapply "Make some of the bundle commands Sorbet typed: true"
- This reverts commit 68dbf12220f9a52ddf5ca5eb3aa1b356aa42da3a that was
  a revert of commit 68596ec720a50f44ae9c30c5806aa7f2d4bcc96f because I
  put the RBI file in the wrong place and Tapioca got rid of it, causing
  this week's release to be blocked.
2025-06-26 23:15:23 +01:00
Mike McQuaid
415c0de6b2
Merge pull request #20178 from tyuwags/upgrade-pin
upgrade pin nil value
2025-06-26 21:53:31 +00:00
thibhero
06cb0cd197 returning previously if there is no formulae to upgrade
resolves #20177
2025-06-26 13:06:57 -04:00
Mike McQuaid
4fd7c6fa8d
Merge pull request #20174 from Homebrew/remove-migrated-symlinks
cask/installer: remove migration symlinks on uninstall
2025-06-26 14:52:14 +00:00
Mike McQuaid
66c11afa7c
Merge pull request #20175 from Homebrew/migrate_brew_cask_main
cmd/update: improve Homebrew/brew and homebrew-cask `main` migration.
2025-06-26 14:49:34 +00:00
Eric Knibbe
29122c0008
cask/installer: remove migration symlinks on uninstall 2025-06-26 10:37:52 -04:00
Mike McQuaid
c86a5a1b74
Merge pull request #20156 from abitrolly/url-from-latest-release
create: detect URL from latest release if it isn't archive
2025-06-26 13:02:56 +00:00
Anatoli Babenia
3e36e98db3 create: detect URL from latest release if it isn't archive
Detects source archive for GitHub URL without version. Both releases
and tags share the same URL pattern for source archive

  https://github.com/Homebrew/brew/releases
  https://github.com/Homebrew/brew/tags
2025-06-26 15:07:51 +03:00
Mike McQuaid
aa596d3e6b
cmd/update: improve homebrew-core main migration.
Let's avoid people sticking on the master branch unnecessarily.
2025-06-26 12:13:48 +01:00
Mike McQuaid
f649587d51
cmd/update: improve Homebrew/brew main migration.
Let's avoid people sticking on the `master` branch unnecessarily.
2025-06-26 12:11:11 +01:00
Mike McQuaid
b87d2887fe
Merge pull request #20033 from tyuwags/master
Refine ask‐option dependency resolution and strengthen tests
2025-06-26 10:52:46 +00:00
Mike McQuaid
dfe8fde704
Merge pull request #20172 from Homebrew/cask_main
docs: homebrew-cask's default branch is now `main`
2025-06-26 10:37:05 +00:00
Mike McQuaid
db45e81d88
Merge pull request #20173 from Homebrew/named_args_old_tokens_warning
cli/named_args: don't warn about old tokens overlapping.
2025-06-25 16:38:07 +00:00
Mike McQuaid
c36389165c
cli/named_args: don't warn about old tokens overlapping.
This avoids e.g.

```
Warning: Treating angband as a formula.
For the cask, use homebrew/cask/angband-app or specify the `--cask` flag.
To silence this message, use the `--formula` flag.
```

when running `brew install angband`.
2025-06-25 17:24:35 +01:00
Mike McQuaid
f1e458a36a
Merge pull request #20117 from botantony/no_autobump
docs: add autobump related documentation
2025-06-25 15:27:51 +00:00
Mike McQuaid
505428e03b
docs/Formula-Cookbook: use autobumped terminology. 2025-06-25 15:42:24 +01:00
Mike McQuaid
9fa50e5e12
Merge pull request #20168 from tyuwags/json-update-migrator
updating json with `cask/migrator`
2025-06-25 14:41:41 +00:00
botantony
a85a9b84bb
rubocop.yml: add autobump_constants.rb
Signed-off-by: botantony <antonsm21@gmail.com>
2025-06-25 15:36:51 +02:00
botantony
0fb87af72c
autobump_constants: split NO_AUTOBUMP_REASONS_LIST
Signed-off-by: botantony <antonsm21@gmail.com>
2025-06-25 15:31:18 +02:00
Anton Melnikov
75146e032c
docs: suggestions from code review
Co-authored-by: Mike McQuaid <mike@mikemcquaid.com>
2025-06-25 15:30:06 +02:00
Mike McQuaid
b63ad37eeb
cask/migrator: tweak syntax. 2025-06-25 08:54:05 +01:00
Mike McQuaid
ec61b49ee9
docs: homebrew-cask's default branch is now main
Adjust documentation accordingly.
2025-06-25 08:50:36 +01:00
Mike McQuaid
e11952a2e0
docs: homebrew-core's default branch is now main
Adjust documentation accordingly.
2025-06-25 08:49:58 +01:00
Mike McQuaid
ca510da620
Merge pull request #20169 from boblail/lail/invalidate-download-cache-logging
download_strategy: Add logging when a cached download is being ignored
2025-06-25 07:44:04 +00:00
Bob Lail
048f58123f
download_strategy: Add logging when a cached download is being ignored 2025-06-25 08:32:02 +01:00
Rylan Polster
36ae1ee429
Merge pull request #20170 from Homebrew/spdx-update
spdx: update license data.
2025-06-25 00:56:15 +00:00
BrewTestBot
71d788e156
spdx: update license data.
Autogenerated by [a scheduled GitHub Action](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/spdx.yml).
2025-06-25 00:18:16 +00:00
Patrick Linnane
2c89b70f28
Merge pull request #20159 from Homebrew/paths_d_homebrew
package/scripts/postinstall: add Homebrew to PATH.
2025-06-24 20:27:16 +00:00
Patrick Linnane
f32f391fc4
Merge pull request #20165 from Homebrew/more_tab_types
tab, cask/tab: add more Sorbet types and signatures.
2025-06-24 20:27:11 +00:00
Patrick Linnane
f4491e0c8f
Merge pull request #20167 from Homebrew/update_report_display_descriptions
cmd/update-report: display descriptions for new formulae and casks.
2025-06-24 20:26:47 +00:00
thibhero
f34f1c4a33 updating json to add old_token when a migration is made 2025-06-24 12:03:41 -04:00
Mike McQuaid
28753ef002
cmd/update-report: display descriptions for new formulae and casks.
This parses Homebrew's API JSON data to display descriptions for new
formulae and casks if available.

While we're here also add tests for ReporterHub.
2025-06-24 16:59:24 +01:00
Mike McQuaid
3495ea576c
Merge pull request #20166 from Homebrew/sync-default-branches-force
workflows/sync-default-branches: force push instead of force-with-lease.
2025-06-24 15:29:14 +00:00
Mike McQuaid
b391d6f366
Merge branch 'main' into sync-default-branches-force 2025-06-24 15:58:51 +01:00
Mike McQuaid
f89387ac39
workflows/sync-default-branches: force push instead of force-with-lease.
Force-with-lease doesn't work as expected with a shallow clone.
2025-06-24 15:58:28 +01:00
Mike McQuaid
05c7b65f54
tab, cask/tab: add more Sorbet types and signatures.
I bailed before going all the way to `typed: strict` but this should at
least improve things and fix:

`Library/Homebrew/tab.rb:111: warning: The class Tab reached 8 shape variations, instance variables accesses will be slower and memory usage increased.`
2025-06-24 12:06:55 +01:00
Mike McQuaid
1ecd060b38
Merge pull request #20164 from Homebrew/more_master_to_main
Switch to using `main` as the default branch
2025-06-24 10:59:42 +00:00
Mike McQuaid
f83c5ee2ed
workflows/sync-default-branches: speed up with partial clone.
Let's avoid doing a full clone and instead use a partial clone and a
`git ls-remote` to get the target SHA and just push that without needing
 to fully fetch it.
2025-06-24 11:46:49 +01:00
Mike McQuaid
d661cffc1f
Switch to using main as the default branch
Homebrew/brew has moved to a `main` default branch so we can more move
references from `master` to `main`.
2025-06-24 11:14:57 +01:00
Mike McQuaid
e42084dc6f
Merge pull request #20163 from Homebrew/brew-doctor-xattr-linux-check
Remove redundant `xattr` doctor check on systems without quarantine support
2025-06-24 09:22:19 +00:00
Rylan Polster
426da94cc9
Remove redundant xattr doctor check on systems without quarantine support 2025-06-24 03:07:04 +00:00
Mike McQuaid
27b9bf2377
Merge pull request #20161 from Homebrew/sponsors-maintainers-man-completions
Update manpage and completions.
2025-06-23 16:06:13 +00:00
Mike McQuaid
2c16fe9184
Merge pull request #20160 from Homebrew/mcp_server_eof
mcp_server: fix EOF handling.
2025-06-23 16:04:29 +00:00
Mike McQuaid
818662352c
mcp_server: fix EOF handling.
We need to handle when `stdin` is closed but there's no interrupt
signal.

Without this, the server will be stuck an in infinite busy loop.
2025-06-23 16:50:39 +01:00
BrewTestBot
af14bcb69b
Update manpage and completions.
Autogenerated by the [sponsors-maintainers-man-completions](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/sponsors-maintainers-man-completions.yml) workflow.
2025-06-23 15:45:42 +00:00
Mike McQuaid
4759ca9430
Merge pull request #20134 from Homebrew/homebrew_core_cask_name_audit
audit: ensure that official formula and cask names don't conflict.
2025-06-23 15:33:00 +00:00
Mike McQuaid
55f65ec375
audit: ensure that official formula and cask names don't conflict.
Co-authored-by: Eric Knibbe <enk3@outlook.com>
2025-06-23 16:08:13 +01:00
Mike McQuaid
a9faa2cd8e
package/scripts/postinstall: add Homebrew to PATH.
This is automatic for `/usr/local/bin/brew` but let's do it manually
for `/opt/homebrew/bin/brew` too.
2025-06-23 15:16:49 +01:00
botantony
0dc48348af
docs: add autobump-related documentation
Signed-off-by: botantony <antonsm21@gmail.com>
2025-06-23 15:06:37 +02:00
Mike McQuaid
c19f08b3e8
Merge pull request #20158 from Homebrew/revert-20145-some-bundle-files-werent-typed-at-all-but-now-some-are
Revert "Make some of the `bundle` commands Sorbet `typed: true`"
2025-06-23 13:04:48 +00:00
Carlo Cabrera
d590e398fc
Merge pull request #20157 from Homebrew/shebang-regex
language/*: fix `*_SHEBANG_REGEX` anchors
2025-06-23 13:02:21 +00:00
Mike McQuaid
68dbf12220
Revert "Make some of the bundle commands Sorbet typed: true" 2025-06-23 13:52:35 +01:00
Carlo Cabrera
6a7416c296
language/*: fix *_SHEBANG_REGEX anchors
We should use `\A` to pick up shebangs at the start of files instead of
just anywhere in a given script.

See Homebrew/homebrew-core#227654 for an example where this can cause
problems.
2025-06-23 20:32:55 +08:00
Mike McQuaid
cfede01ea9
Merge pull request #20155 from Homebrew/core-caveats
rubocops/caveats: only apply dynamic logic check to core.
2025-06-23 08:17:08 +00:00
Mike McQuaid
984273be76
Merge pull request #20153 from Homebrew/brew-doctor-linux-cask-errors
Improve `brew doctor` warnings about `xattr` and cask quarantine
2025-06-23 08:07:30 +00:00
Mike McQuaid
afa5d50b36
rubocops/caveats: only apply dynamic logic check to core.
This doesn't really matter for non-API taps.
2025-06-23 08:58:34 +01:00
Mike McQuaid
a6b1d42488
Merge pull request #20154 from abitrolly/brew-audit-v-version
create: strip 'v' prefix from version
2025-06-23 07:30:03 +00:00
Eric Knibbe
2703f12875
Merge pull request #20150 from Homebrew/download_strategy-fossil
download_strategy: fossil now outputs `hash:`
2025-06-23 03:03:57 +00:00
Rylan Polster
2acd4e4293
Improve messaging with missing xattr 2025-06-22 18:59:52 +00:00
Eric Knibbe
8a4cac0238
download_strategy: fix cvs checkouts 2025-06-22 14:38:19 -04:00
Eric Knibbe
7e79232512
download_strategy: fossil now outputs hash: 2025-06-22 14:38:19 -04:00
Rylan Polster
12e5e24ce3
Improve brew doctor warnings about xattr and cask quarantine 2025-06-22 14:24:22 -04:00
Anatoli Babenia
84505c714d Fix brew style "Prefer double-quoted strings" 2025-06-22 18:05:47 +03:00
Anatoli Babenia
eca98d036c create: strip 'v' prefix from version
To fix subsequent `brew audit` error:

  * line 8, col 3: Version v0.38.1 should not have a leading 'v'
2025-06-22 17:41:00 +03:00
Rylan Polster
f238d3b494
Merge pull request #20151 from Homebrew/fix-doctor-linux
Fix `brew doctor` cask handling on Linux
2025-06-22 10:10:28 +00:00
Rylan Polster
44dcb58f9e
Merge pull request #20152 from Homebrew/extend-os-class-methods
Fix handling of class methods in `extend/os`
2025-06-22 02:20:18 +00:00
Rylan Polster
431d8f1ff7
Consistently use ClassMethods sub-module for prepending class methods 2025-06-21 21:40:57 -04:00
Rylan Polster
267afac198
Remove more monkey-patching in extend/os 2025-06-21 21:34:20 -04:00
Rylan Polster
508c8b606c
Fix DevelopmentTools::ld64_version on macOS 2025-06-21 21:13:38 -04:00
Rylan Polster
2a7fbd00a9
Fix Cask::Quarantine class methods on Linux 2025-06-21 21:07:08 -04:00
Rylan Polster
ff79015373
Fix Hardware::CPU::features on macOS 2025-06-21 21:01:44 -04:00
Rylan Polster
e1873d30d4
Run deprecated cask tap check on all systems 2025-06-21 13:59:58 -04:00
Rylan Polster
031160936f
Split out os-specific cask software version checks 2025-06-21 13:59:57 -04:00
thibhero
2d39c7feb5 making flow easier to understand 2025-06-20 16:41:32 -04:00
thibhero
f674a3ac03 comment 2025-06-20 12:59:15 -04:00
thibhero
a16129fc59 new line to make it easier to understand 2025-06-20 12:36:22 -04:00
thibhero
6d0a77fc79 fixing method refactoring 2025-06-20 12:32:46 -04:00
thibhero
7d7d04bdf5 Merge remote-tracking branch 'tyuwags/master' 2025-06-20 12:29:08 -04:00
thibhero
2fb6105f26 renaming variable 2025-06-20 12:29:02 -04:00
thibhero
90b697995f renaming parameter, method and struct to make it more understandable 2025-06-20 12:28:38 -04:00
thibhero
0db36b57c8 fetching tab and renaming variables 2025-06-20 12:25:55 -04:00
thibhero
052c0ae2cd adding parameter to fetch quietly if wanted 2025-06-20 12:25:12 -04:00
Thibaut Hérault
0800faf093
Update Library/Homebrew/upgrade.rb
Co-authored-by: Bo Anderson <mail@boanderson.me>
2025-06-20 11:10:36 -04:00
Thibaut Hérault
bcc7f0f796
Update Library/Homebrew/install.rb
Co-authored-by: Bo Anderson <mail@boanderson.me>
2025-06-20 11:10:18 -04:00
Mike McQuaid
dd04fb5ab6
Merge pull request #20146 from Homebrew/dependabot/github_actions/github-actions-348b342bd6
build(deps): bump docker/setup-buildx-action from 3.10.0 to 3.11.1 in the github-actions group
2025-06-20 12:33:42 +00:00
Mike McQuaid
d0a144520d
Merge pull request #20145 from Homebrew/some-bundle-files-werent-typed-at-all-but-now-some-are
Make some of the `bundle` commands Sorbet `typed: true`
2025-06-20 10:58:07 +00:00
dependabot[bot]
d961c4772a
build(deps): bump docker/setup-buildx-action in the github-actions group
Bumps the github-actions group with 1 update: [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action).


Updates `docker/setup-buildx-action` from 3.10.0 to 3.11.1
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](b5ca514318...e468171a9d)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-version: 3.11.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-20 08:44:06 +00:00
Issy Long
68596ec720
Make some of the bundle commands Sorbet typed: true
- The last remaining one is `exec` but that's a bit more involved
  (https://github.com/Homebrew/brew/pull/20128#discussion_r2156781591).
2025-06-20 10:11:35 +02:00
Mike McQuaid
9d357b57d1
Merge pull request #20135 from Homebrew/forbid_dynamic_caveats
rubocops/caveats: check for dynamic caveats.
2025-06-20 07:57:06 +00:00
Mike McQuaid
e6d4db8d6f
Merge pull request #20025 from abitrolly/new-detect-latest-release
formula_creator: detect GitHub version from latest release
2025-06-20 07:40:44 +00:00
Anatoli Babenia
dce285458e Add test for name override with GitHub URLs 2025-06-19 16:28:48 +03:00
Anatoli Babenia
cf2e20d586 Fix version reporting in odebug messages 2025-06-19 16:18:41 +03:00
Mike McQuaid
f77c9861de
rubocops/caveats: check for dynamic caveats.
This will avoid issues with the JSON API.
2025-06-19 10:13:32 +01:00
Mike McQuaid
2cd7a32660
formula_creator: improve code/test style. 2025-06-19 09:02:46 +01:00
Anatoli Babenia
3964186bec
formula_creator: fetch missing version from latest GitHub release 2025-06-19 09:02:36 +01:00
Mike McQuaid
9f5286f3d7
Merge pull request #20143 from Homebrew/dependabot/pip/Library/Homebrew/formula-analytics/urllib3-2.5.0
build(deps): bump urllib3 from 2.4.0 to 2.5.0 in /Library/Homebrew/formula-analytics
2025-06-19 07:40:29 +00:00
dependabot[bot]
6bfcd62c7c
build(deps): bump urllib3 in /Library/Homebrew/formula-analytics
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.4.0 to 2.5.0.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.4.0...2.5.0)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-version: 2.5.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-19 05:26:06 +00:00
Rylan Polster
4ce9faf294
Merge pull request #20142 from Homebrew/sorbet-files-update
sorbet: Update RBI files.
2025-06-19 02:10:16 +00:00
BrewTestBot
4c18ff443c
sorbet: Update RBI files.
Autogenerated by the [sorbet](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/sorbet.yml) workflow.
2025-06-19 00:30:14 +00:00
thibhero
19901b5332 refactoring style to resolve the last discussions 2025-06-18 16:05:19 -04:00
Mike McQuaid
99a8e3a288
Merge pull request #20141 from botantony/enable_no_autobump
tap: rely on new autobump list
2025-06-18 14:34:08 +00:00
Mike McQuaid
ccb3543c6c
Merge pull request #20126 from botantony/no_autobump_rubocops
rubocops: add `no_autobump!` rubocop
2025-06-18 14:33:37 +00:00
Mike McQuaid
62cff0e852
Merge pull request #20136 from abitrolly/newnew-detect-latest-release
formula_creator: test GitHub repo call for archive|releases URLs
2025-06-18 14:20:22 +00:00
botantony
aecdcd4840
rubocops: add no_autobump! rubocop
Signed-off-by: botantony <antonsm21@gmail.com>
2025-06-18 16:16:12 +02:00
botantony
d0345513e2
tap: rely on new autobump list
Signed-off-by: botantony <antonsm21@gmail.com>
2025-06-18 16:16:08 +02:00
Anatoli Babenia
f738fce3d9
formula_creator: test GitHub repo call for archive|releases URLs 2025-06-18 15:07:44 +01:00
Mike McQuaid
76470c0d8a
Merge pull request #20137 from Homebrew/cached-location-validation
download_strategy: fix caching of `:latest` downloads
2025-06-18 07:33:29 +00:00
Mike McQuaid
43a72a1a03
Merge pull request #20138 from Homebrew/rm-zap-messaging
cask/installer: remove confusing `zap` messaging
2025-06-18 07:32:47 +00:00
Patrick Linnane
989032b703
test/cask/reinstall_spec: remove confusing zap` messaging
Signed-off-by: Patrick Linnane <patrick@linnane.io>
2025-06-17 21:15:49 -07:00
Patrick Linnane
7da83ee19c
cask/installer: remove confusing zap messaging
Signed-off-by: Patrick Linnane <patrick@linnane.io>
2025-06-17 21:15:47 -07:00
thibhero
fe06e04e28 refactoring install.rb and reinstall.rb after removing Formula.installed 2025-06-17 21:12:47 -04:00
Thibaut Hérault
27a040cc32
Merge branch 'master' into master 2025-06-17 20:49:18 -04:00
thibhero
1b0e79121a brew style error 2025-06-17 20:36:47 -04:00
thibhero
ea7d441370 removing fixture 2025-06-17 20:21:41 -04:00
thibhero
fc18956eeb removing longer tests and putting back integration_test.rb 2025-06-17 20:21:32 -04:00
thibhero
971a8b40e6 refactoring as we can get dependants before installing 2025-06-17 19:21:17 -04:00
thibhero
8c203df671 trying to remove FormulaInstaller.installed to formulae 2025-06-17 19:20:43 -04:00
Rylan Polster
aeed5eb57a
Merge pull request #20139 from Homebrew/fix-type-mismatch-brew-info
Fix type mismatch in `brew info`
2025-06-17 21:53:47 +00:00
Rylan Polster
f71287c4a9
Fix type mismatch in brew info 2025-06-17 16:57:50 -04:00
Eric Knibbe
5ff58d2df0
download_strategy: fix caching of :latest downloads 2025-06-17 14:51:11 -04:00
Mike McQuaid
fb9d1c5a1c
Merge pull request #20133 from Homebrew/requirements
requirements: set `typed: strict`
2025-06-17 18:37:48 +00:00
Mike McQuaid
77321d6f8b
Merge pull request #20132 from Homebrew/dev-cmd
dev-cmd: set `typed: strict`
2025-06-17 18:37:03 +00:00
Mike McQuaid
e1fc5a2784
Merge pull request #20131 from Homebrew/debrew_strict
debrew: set `typed: strict`
2025-06-17 18:30:10 +00:00
Mike McQuaid
2916610699
Merge pull request #20130 from Homebrew/sorbet_cmd
cmd: set `typed: strict`
2025-06-17 18:29:23 +00:00
Mike McQuaid
9375fc21f4
requirements: set typed: strict 2025-06-17 16:34:59 +01:00
Mike McQuaid
ca1e08c7a8
dev-cmd: set typed: strict 2025-06-17 16:34:19 +01:00
Mike McQuaid
85c5f8f3a5
debrew: set typed: strict 2025-06-17 16:33:58 +01:00
Mike McQuaid
c4c66d41ef
cmd: set typed: strict 2025-06-17 16:33:16 +01:00
Mike McQuaid
3c30845240
Merge pull request #20116 from abitrolly/create-tests
Refactor `FormulaCreator` args and call `parse_url` automatically
2025-06-17 14:18:52 +00:00
Mike McQuaid
2ad0fed872
Merge pull request #20129 from Homebrew/fix_bump_sorbet
utils/github/api: fix Sorbet types.
2025-06-17 14:13:08 +00:00
Mike McQuaid
dfa79bf981
Merge pull request #20125 from Homebrew/cask_sorbet_strict
cask: move some files to strict Sorbet sigil.
2025-06-17 14:09:56 +00:00
Mike McQuaid
f2103c7138
utils/github/api: fix Sorbet types.
Let's not use `T.unsafe(nil)` but instead an empty hash.
2025-06-17 14:59:46 +01:00
Mike McQuaid
35407ab556
cask: move some files to strict Sorbet sigil. 2025-06-17 14:56:10 +01:00
Mike McQuaid
1f29f51654
dev-cmd/create: avoid duplicate presence check.
Co-authored-by: Anatoli Babenia <anatoli@rainforce.org>
2025-06-17 14:44:59 +01:00
Eric Knibbe
09eaf1495a
Merge pull request #20119 from Homebrew/audit-bundle-version
cask/audit: also check binary for minimum OS
2025-06-17 11:36:08 +00:00
Mike McQuaid
c5d091af21
Refactor/typecheck create and formula_creator 2025-06-17 11:44:15 +01:00
Mike McQuaid
768c10c6fb
Merge pull request #20124 from Homebrew/add-cask-config-rbi-compiler
Add Cask::Config RBI compiler
2025-06-17 10:32:59 +00:00
Anatoli Babenia
85d48da364
Refactor FormulaCreator args and call parse_url automatically
Co-authored-by: Mike McQuaid <mike@mikemcquaid.com>
2025-06-17 11:19:52 +01:00
Mike McQuaid
d7d8c61f00
Merge pull request #20121 from Homebrew/sorbet_strict_a
a*.rb: move to strict Sorbet sigil.
2025-06-17 10:05:27 +00:00
Mike McQuaid
7345607ca0
a*.rb: move to strict Sorbet sigil.
Co-authored-by: Rylan Polster <rslpolster@gmail.com>
2025-06-17 08:18:33 +01:00
Sam Ford
9c69859f99
Add Cask::Config RBI compiler
This is a naive attempt at creating an RBI compiler for the
`Cask::Config` class. `Config` contains methods like `appdir` that
are defined dynamically using the class's default values and Sorbet
doesn't understand that these methods exist or what their return
types are. This compiler works as expected and gets the job done but
I know basically nothing about Tapioca, so there may be a better way
of doing this.

For what it's worth, this isn't an issue right now but Sorbet will
surface an error once `Cask::DSL` is updated to `typed: strict` (i.e.,
`Method appdir does not exist on Cask::Config`). That's something
I've been working on and this compiler is intended as a way of
preemptively resolving that Sorbet error, so I can move forward with
the `Cask::DSL` type signature work.
2025-06-16 23:49:01 -04:00
Eric Knibbe
ab4acd655a
cask/audit: also check binary for minimum OS 2025-06-16 23:39:38 -04:00
Patrick Linnane
95f0e76154
Merge pull request #20123 from abitrolly/remove-vale-fixme
Remove `vale` FIXME
2025-06-16 19:24:14 +00:00
Anatoli Babenia
b5d4bc56fc Remove vale FIXME
https://github.com/errata-ai/vale/issues/818 is fixed a year ago
2025-06-16 21:39:39 +03:00
Mike McQuaid
e694e76857
Merge pull request #20120 from Homebrew/remove_alias_generic
Remove `alias generic_*` definitions in favour of using `super`
2025-06-16 14:11:20 +00:00
Mike McQuaid
9ac306e464
Remove alias generic_* definitions in favour of using super
This is the pattern we've been adopting for a while and it's a bit
cleaner. Let's remove all of the existing usage of the existing pattern
to avoid confusion when adopting the new one.
2025-06-16 08:10:08 +00:00
Mike McQuaid
b6167f6024
Merge pull request #20118 from Homebrew/sponsors-maintainers-man-completions
Update sponsors.
2025-06-16 07:40:51 +00:00
Mike McQuaid
ad28cc7cf5
Merge pull request #20108 from Homebrew/macos_version-upgrade-type-sigil
MacOSVersion: enable strong typing, expand tests
2025-06-16 07:37:02 +00:00
Mike McQuaid
62ca1323df
Merge pull request #20112 from Homebrew/add-newest-supported-env-var
Add HOMEBREW_MACOS_NEWEST_SUPPORTED env var
2025-06-16 07:28:44 +00:00
Mike McQuaid
b6f3b0439b
Merge pull request #20115 from abitrolly/fix-test-linking
Replace hardlinks with symlinks for `brew tests`
2025-06-16 07:28:41 +00:00
BrewTestBot
7656fee22d
Update sponsors.
Autogenerated by the [sponsors-maintainers-man-completions](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/sponsors-maintainers-man-completions.yml) workflow.
2025-06-16 00:09:15 +00:00
Sam Ford
ea57773327
MacOSVersion: expand test coverage
This adds tests to expand coverage of `MacOSVersion` to 100% for lines
and branches.
2025-06-15 09:02:42 -04:00
Sam Ford
00249bda44
MacOSVersion: enable strong typing 2025-06-15 09:02:41 -04:00
Anatoli Babenia
d2b6531f01 Replace hardlinks with symlinks for brew tests
Fixes https://github.com/Homebrew/brew/issues/20114
2025-06-15 14:08:04 +03:00
Sam Ford
764d2b2dcc
Add HOMEBREW_MACOS_NEWEST_SUPPORTED env var
We have a `HOMEBREW_MACOS_NEWEST_UNSUPPORTED` environment variable
and this is used in `MacOSVersion` to determine prerelease versions
but we don't have a way of easily determining the newest supported
macOS version.

`bump-cask-pr` contains logic that assumes the first key/value in
`MacOSVersion::SYMBOLS` is the newest macOS version but it recently
became clear that this is a prerelease version between WWDC and the
subsequent macOS release. Similarly, `dev-cmd/generate-cask-api.rb`
tries to compute the newest stable macOS version as
`HOMEBREW_MACOS_NEWEST_UNSUPPORTED.to_i - 1` and this will fail
if/when we update that variable to `"26"`, as the macOS version
before 26 is 15, not 25.

This adds a `HOMEBREW_MACOS_NEWEST_SUPPORTED` environment variable,
so we have a straightforward way of quickly identifying the newest
supported macOS version without having to make potentially unreliable
assumptions or do computations to identify the latest non-prerelease
`MacOSVersion` value. This also updates the two aforementioned areas
to use this environment variable to produce the newest stable macOS
version symbol in a more reliable way.
2025-06-14 18:45:25 -04:00
Mike McQuaid
6301c2d31f
Merge pull request #20110 from Homebrew/api-hashable-git-config
api_hashable: retain access to global gitconfig
2025-06-14 07:54:50 +00:00
Bo Anderson
82eaabf7fe
api_hashable: retain access to global gitconfig 2025-06-14 01:54:12 +01:00
Bevan Kay
f59624623c
Merge pull request #20109 from Homebrew/sponsors-maintainers-man-completions
Update sponsors.
2025-06-14 00:52:42 +00:00
BrewTestBot
4f072136d5
Update sponsors.
Autogenerated by the [sponsors-maintainers-man-completions](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/sponsors-maintainers-man-completions.yml) workflow.
2025-06-14 00:08:35 +00:00
Mike McQuaid
e3ae002054
Merge pull request #20107 from Homebrew/scheduled_issues
Open issues for failed scheduled workflows
2025-06-13 17:55:55 +00:00
Mike McQuaid
d2269c5b30
Open issues for failed scheduled workflows
I noticed recently the SBOM workflow was failing and had been for a long
time and we'd not noticed. I've added issues for the other workflows
that run on a schedule and fixed the updating state.

I've also renamed the SBOM workflow to `sbom.yml` to match what it does.

Co-authored-by: Rylan Polster <rslpolster@gmail.com>
2025-06-13 18:43:52 +01:00
Mike McQuaid
66621b56c9
Merge pull request #20104 from Homebrew/sync-shared-config
Synchronize shared configuration
2025-06-13 17:15:04 +00:00
Mike McQuaid
6fb115d342
Merge pull request #20099 from Homebrew/more_update_main_changes
cmd/update*: more fixes to allow migration from `master` to `main`.
2025-06-13 16:25:56 +00:00
Mike McQuaid
08eae94955
cmd/update*: more fixes to allow migration from master to main.
We're not migrating Homebrew/brew to `main` yet but this will allow us
to ensure we have a `brew update` ready in future when we're ready to do
this.
2025-06-13 17:13:51 +01:00
Mike McQuaid
dfd0cc8d85
Merge pull request #20098 from Homebrew/hide_main_branches
Hide `main` branches from `brew tap-info` and `brew info`
2025-06-13 16:11:23 +00:00
BrewTestBot
c15dec7821
zizmor.yml: update to match main configuration 2025-06-13 15:48:23 +00:00
BrewTestBot
cf2d4a5676
actionlint.yml: update to match main configuration 2025-06-13 15:48:23 +00:00
BrewTestBot
f154eb2812
homebrew-actions.yml: update to match main configuration 2025-06-13 15:48:23 +00:00
Mike McQuaid
1cdbc38802
Merge pull request #20103 from Homebrew/sync-default-branches
Add `sync-default-branches` workflow
2025-06-13 14:02:28 +00:00
Mike McQuaid
9494385745
Merge pull request #20102 from Homebrew/sorbet-files-update
sorbet: Update RBI files.
2025-06-13 13:35:16 +00:00
Mike McQuaid
3cb4ba8c26
Merge pull request #20101 from Homebrew/homebrew_actions_main
Use Homebrew/actions/*@main in Actions workflows
2025-06-13 13:33:52 +00:00
Mike McQuaid
a0d1e1d9d6
Add sync-default-branches workflow
This will allow us to migrate Homebrew/brew to `main` when we're ready
while preserving `master` as a branch with the same contents.

Until we're ready to migrate, this will keep a `main` branch updated
with `master`.
2025-06-13 14:24:18 +01:00
BrewTestBot
6105a241f8
sorbet: Update RBI files.
Autogenerated by the [sorbet](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/sorbet.yml) workflow.
2025-06-13 13:23:02 +00:00
Mike McQuaid
be6cee3006
Use Homebrew/actions/*@main in Actions workflows
We've migrated Homebrew/actions to use the `main` branch now so let's
update these references.
2025-06-13 14:22:09 +01:00
Mike McQuaid
cba6ecce92
Merge pull request #20100 from Homebrew/cask-initialize-yet-more-instance-variables
Cask: Initialize yet more instance variables
2025-06-13 12:53:37 +00:00
Sam Ford
4a4f7a541a
Cask: Initialize yet more instance variables
I previously added some instance variables in `Cask::DSL` to its
`initialize` method but I missed some last time, so we still see
warnings like `The class Cask::DSL reached 8 shape variations,
instance variables accesses will be slower and memory usage increased.
It is recommended to define instance variables in a consistent order,
for instance by eagerly defining them all in the #initialize method.`

This initializes more instance variables in `Cask` classes to resolve
other situations where this warning may occur. I've been testing this
for a while and haven't see any warnings with these changes but
there's always a chance that there's still more work to be done.
2025-06-13 08:32:56 -04:00
Mike McQuaid
af997ea2ad
Hide main branches from brew tap-info and brew info
These are basically as "default" as `master` now so we can hide them.
2025-06-13 12:09:02 +01:00
Mike McQuaid
e049ee3d3b
Merge pull request #20097 from Homebrew/dependabot/github_actions/github-actions-89d009b5d5
build(deps): bump the github-actions group with 3 updates
2025-06-13 10:51:48 +00:00
dependabot[bot]
c8213558ef
build(deps): bump the github-actions group with 3 updates
Bumps the github-actions group with 3 updates: [github/codeql-action](https://github.com/github/codeql-action), [ruby/setup-ruby](https://github.com/ruby/setup-ruby) and [actions/attest-build-provenance](https://github.com/actions/attest-build-provenance).


Updates `github/codeql-action` from 3.28.19 to 3.29.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](fca7ace96b...ce28f5bb42)

Updates `ruby/setup-ruby` from 1.244.0 to 1.245.0
- [Release notes](https://github.com/ruby/setup-ruby/releases)
- [Changelog](https://github.com/ruby/setup-ruby/blob/master/release.rb)
- [Commits](13e7a03dc3...a4effe49ee)

Updates `actions/attest-build-provenance` from 2.3.0 to 2.4.0
- [Release notes](https://github.com/actions/attest-build-provenance/releases)
- [Changelog](https://github.com/actions/attest-build-provenance/blob/main/RELEASE.md)
- [Commits](db473fddc0...e8998f9491)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.29.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: ruby/setup-ruby
  dependency-version: 1.245.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions/attest-build-provenance
  dependency-version: 2.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-13 08:22:08 +00:00
Mike McQuaid
5fc7a225c1
Merge pull request #20095 from Homebrew/fix-vscode-ruby-lsp-codespaces
Fix vscode ruby-lsp setup for GitHub codespaces
2025-06-13 07:59:10 +00:00
Rylan Polster
29e7229463
Merge pull request #20094 from Homebrew/remove-deprecated-vscode-sorbet-option
Remove deprecated vscode sorbet option
2025-06-13 06:16:13 +00:00
Rylan Polster
22dfe9267e
Fix vscode ruby-lsp setup for GitHub codespaces 2025-06-12 18:24:49 -04:00
Rylan Polster
35962a447d
Remove deprecated vscode sorbet option 2025-06-12 17:30:47 -04:00
Patrick Linnane
d428e832ee
Merge pull request #20093 from Homebrew/brew-mcp-settings
Add MCP server VS Code config
2025-06-12 20:48:08 +00:00
Patrick Linnane
ac6a7b476b
Add MCP server VS Code config
Signed-off-by: Patrick Linnane <patrick@linnane.io>
2025-06-12 10:58:21 -07:00
Rylan Polster
e66bb7ece5
Merge pull request #20092 from Homebrew/revert-20080-cask-variations-only-supported
Revert "Only generate cask variations for supported macOS configurations"
2025-06-12 16:43:59 +00:00
Mike McQuaid
ec539147a7
Merge pull request #20089 from Homebrew/revert-20079-fix-tests-only-files
Revert "Filter `brew tests` spec files appropriately for each OS"
2025-06-12 16:40:34 +00:00
Mike McQuaid
fca5630b23
Merge pull request #20091 from Homebrew/update-docs-workflow
Generate template API samples for `formulae.brew.sh` docs workflow
2025-06-12 16:40:30 +00:00
Rylan Polster
54b349bb89
Revert "Only generate cask variations for supported macOS configurations" 2025-06-12 11:53:01 -04:00
Mike McQuaid
f234423913
dev-cmd/tests: fix require ordering.
This needs to happen after `setup_environment!` so that
`HOMEBREW_TEST_GENERIC_OS` is set and `OS.linux?` and `OS.mac?` both
`return false`.
2025-06-12 16:43:50 +01:00
Mike McQuaid
9541ad8931
workflows/docs: remove comment. 2025-06-12 16:39:55 +01:00
Rylan Polster
577f01c30e
Generate template API samples for formulae.brew.sh docs workflow 2025-06-12 11:19:19 -04:00
Eric Knibbe
8063291f7c
Merge pull request #20090 from Lekensteyn/remove-force-auto-update-option
Remove unused --force-auto-update option
2025-06-12 13:51:36 +00:00
Mike McQuaid
1a5afaf739
Merge pull request #20082 from alex/strict-check-for-duplicate-prs
Add strict parameter to `GitHub::check_for_duplicate_pull_requests`
2025-06-12 13:23:17 +00:00
Mike McQuaid
50bdb40efb
Merge pull request #20080 from Homebrew/cask-variations-only-supported
Only generate cask variations for supported macOS configurations
2025-06-12 13:22:45 +00:00
Alex Gaynor
efa0c9554a fixes #19828 -- added a strict parameter to GitHub::check_for_duplicate_pull_requests 2025-06-12 08:45:16 -04:00
Mike McQuaid
d68b890d61
Merge pull request #20087 from Homebrew/bump-formula-pr-body-fix
dev-cmd/bump-formula-pr: handle null body
2025-06-12 12:17:17 +00:00
Peter Wu
770335f72e Remove unused --force-auto-update option
Remove the `brew tap --force-auto-update` option and the
`force_auto_update` configuration file option from Homebrew Bundles.

Fixes #19856
2025-06-12 14:16:12 +02:00
Bo Anderson
bf6f813492
dev-cmd/bump-formula-pr: handle null body 2025-06-12 04:48:15 +01:00
Eric Knibbe
a63baa62d2
Merge pull request #20086 from Homebrew/sync-shared-config
Synchronize shared configuration
2025-06-12 02:45:38 +00:00
thibhero
d525e25e99 resolving discussions 2025-06-11 22:41:22 -04:00
thibhero
fb5ddde5ad resolving discussions 2025-06-11 22:36:57 -04:00
thibhero
7e876e4681 resolving discussions 2025-06-11 22:35:00 -04:00
BrewTestBot
498ab9e4b7
homebrew-actions.yml: update to match main configuration 2025-06-12 02:23:28 +00:00
Eric Knibbe
bb0bb27591
Merge pull request #20081 from Homebrew/ignore-intel-only
cask/audit: skip caveats check for Intel-only casks
2025-06-12 02:13:30 +00:00
Rylan Polster
e5667cb5ae
Only generate cask variations for supported macOS configurations 2025-06-11 20:30:14 -04:00
Rylan Polster
7a806ac1bd
Merge pull request #20083 from Homebrew/sponsors-maintainers-man-completions
Update sponsors.
2025-06-12 00:20:42 +00:00
Rylan Polster
5831783a85
Merge pull request #20079 from Homebrew/fix-tests-only-files
Filter `brew tests` spec files appropriately for each OS
2025-06-12 00:15:21 +00:00
BrewTestBot
728440df3a
Update sponsors.
Autogenerated by the [sponsors-maintainers-man-completions](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/sponsors-maintainers-man-completions.yml) workflow.
2025-06-12 00:08:55 +00:00
Rylan Polster
e5495d097e
Add missing require 2025-06-11 19:56:37 -04:00
Rylan Polster
b242abfdf0
Fix cask API tests 2025-06-11 19:44:26 -04:00
Rylan Polster
ce72e34b19
Filter brew tests spec files appropriately for each OS 2025-06-11 15:59:21 -04:00
Eric Knibbe
689ff373d8
cask/audit: skip caveats check for Intel-only casks 2025-06-11 15:56:07 -04:00
Mike McQuaid
4e0e5782ec
Merge pull request #20078 from Homebrew/schema-update
data/schemas: update schema data.
2025-06-11 16:26:51 +00:00
Mike McQuaid
1857fe4670
Merge pull request #20077 from Homebrew/workflows_tweaks
Tweak GitHub Actions workflows
2025-06-11 15:51:47 +00:00
BrewTestBot
755353570d
data/schemas: update schema data.
Autogenerated by [a scheduled GitHub Action](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/schemas.yml).
2025-06-11 15:39:36 +00:00
Mike McQuaid
7bd8642bfc
Tweak GitHub Actions workflows
- prepare to use `main` instead of `master`.
- use synced `actionlint.yml` to simplify Homebrew/.github sync logic.
- fix some broken workflow PR opening logic.
2025-06-11 16:39:03 +01:00
Mike McQuaid
dffa42839c
Merge branch 'master' into master 2025-06-11 13:24:46 +01:00
Mike McQuaid
8aeb93ec98
Merge pull request #20073 from Homebrew/attempt_master_to_main_migration
cmd/update: attempt migration from `master` to `main` branch.
2025-06-11 07:51:00 +00:00
Mike McQuaid
837b28ba79
cmd/update: attempt migration from master to main branch.
This should allow any repositories that change from `master` to `main`
to be automatically migrated by `brew update` without requiring manual
intervention or displaying errors to the user.
2025-06-11 08:38:32 +01:00
Eric Knibbe
11f4d304ad
Merge pull request #20076 from Homebrew/sponsors-maintainers-man-completions
Update manpage and completions.
2025-06-10 21:22:07 +00:00
BrewTestBot
347b287967
Update manpage and completions.
Autogenerated by the [sponsors-maintainers-man-completions](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/sponsors-maintainers-man-completions.yml) workflow.
2025-06-10 21:00:09 +00:00
Eric Knibbe
721def31a5
Merge pull request #20075 from Homebrew/no-nested-depends_on
rubocops/cask/no_overrides: avoid nested `depends_on macos:`
2025-06-10 20:47:19 +00:00
Patrick Linnane
9540bfe5c4
Merge pull request #20074 from Homebrew/contributions_csv_output
dev-cmd/contributions: improve CSV output.
2025-06-10 20:47:11 +00:00
Eric Knibbe
ea8152757e
rubocops/cask/no_overrides: avoid nested depends_on macos: 2025-06-10 14:31:58 -04:00
Mike McQuaid
8d4395118c
dev-cmd/contributions: improve CSV output.
Output messages to stderr when CSV output is enabled.

This allows doing `brew contributions --csv > contributions.csv` to
save the output to a file.
2025-06-10 17:28:21 +01:00
Rylan Polster
324762b895
Merge pull request #20072 from Homebrew/sponsors-maintainers-man-completions
Update manpage and completions.
2025-06-10 16:02:06 +00:00
BrewTestBot
0af29dec14
Update manpage and completions.
Autogenerated by the [sponsors-maintainers-man-completions](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/sponsors-maintainers-man-completions.yml) workflow.
2025-06-10 15:45:47 +00:00
Mike McQuaid
144113318e
Merge pull request #20071 from Homebrew/brew_deps_output_warning
cmd/deps: add warning when not using runtime dependencies.
2025-06-10 15:41:25 +00:00
Mike McQuaid
724c10962e
Merge pull request #20070 from Homebrew/tests_default_api
tests: default to API mode enabled.
2025-06-10 15:32:45 +00:00
Mike McQuaid
d2f9677cde
cmd/deps: add warning when not using runtime dependencies.
This should provide clarify as to why the output may differ from a
formula's declared dependencies.
2025-06-10 15:55:39 +01:00
Mike McQuaid
e9f55a8f71
tests: default to API mode enabled.
While we're here, also add `brew tests --no-parallel` which I relied
on during testing.

Pretty much anywhere we rely on a stubbed formula on disk to work: we
need to disable the API.
2025-06-10 15:53:27 +01:00
Bo Anderson
3c9a7332d4
Merge pull request #20066 from Homebrew/sorbet-files-update
sorbet: Update RBI files.
2025-06-10 02:34:41 +00:00
BrewTestBot
c086bdcbba
sorbet: Update RBI files.
Autogenerated by the [sorbet](https://github.com/Homebrew/brew/blob/master/.github/workflows/sorbet.yml) workflow.
2025-06-10 00:29:54 +00:00
Bo Anderson
7b4ef99fed
Merge pull request #20062 from Homebrew/macos-26
Preliminary macOS 26 (Tahoe) support
2025-06-09 23:22:53 +00:00
Bo Anderson
b8e2cddbbd
Preliminary macOS 26 (Tahoe) support 2025-06-09 21:41:49 +01:00
Bo Anderson
ecd0d99001
Merge pull request #20063 from Homebrew/vendor-install-fail-fix
cmd/vendor-install: fix exit code handling for curl
2025-06-09 19:38:07 +00:00
Mike McQuaid
cfdc6fd3fe
Merge pull request #20061 from Homebrew/extend_cleanup
Cleanup `extend/` directory usage.
2025-06-09 19:37:14 +00:00
Bo Anderson
57ed94c421
cmd/vendor-install: fix exit code handling for curl 2025-06-09 19:59:41 +01:00
Mike McQuaid
dc71b7c8f6
Cleanup extend/ directory usage.
- move some things out of `extend` that don't really fit there e.g.
  `Module`s that are included but not doing any
  overriding/monkeypatching
- move some code into `extend/os` to fix all remaining
  `rubocop:todo Homebrew/MoveToExtendOS`s
- remove some unneeded `bundle` skipper code that doesn't really make
  sense given our current bottling strategy
- extract some `Pathname` extensions to `extend/pathname` for separate
  files
- move a `ENV` `Kernel` extension into `kernel.rb`
- `odeprecate` a seemingly unused backwards compatibility method
- move `readline_nonblock` from a monkeypatch to a
  `ReadlineNonblock.read` method as its only used in one place
- fix up a link in documentation
2025-06-09 19:06:16 +01:00
Mike McQuaid
8ebb2cd65b
Merge pull request #20060 from Homebrew/more_ci_tweaks
workflows/tests.yml: more CI tweaks.
2025-06-09 16:39:18 +00:00
Mike McQuaid
63abe0bebf
workflows/tests.yml: more CI tweaks.
- use `macos-15` for tap syntax, no reason to use (old) `macos-14`
- use `macos-latest` for all macOS jobs where we're only testing a
  single macOS and single Linux target
- add `test default formula` jobs for Linux `arm64`
- rename a few more jobs for consistency and clarity
2025-06-09 17:28:17 +01:00
Mike McQuaid
97bc7b1661
Merge pull request #20054 from Homebrew/remove_ci_warnings
Reduce Homebrew/brew CI warnings
2025-06-09 12:07:23 +00:00
Mike McQuaid
cc03340af3
Reduce Homebrew/brew CI warnings
- Remove a bunch of non-actionable/unnecessary noise in GitHub Actions
  CI.
- Limit number of threads used to generate analytics API data to avoid
  reproducible failures producing errors and requiring retries.
- Move to Debian Old Stable for testing non-system `glibc`.
- Remove unneeded core taps/updates.
- Improve naming of CI jobs to clarify purpose i.e. we're testing
  things work on Linux, not Ubuntu specifically.
- Remove dedicated non-online/non-generic Linux `brew tests` jobs from
  3 to 1.

Co-authored-by: Rylan Polster <rslpolster@gmail.com>
2025-06-09 12:47:22 +01:00
thibhero
32a53ab285 resolving error typecheck 2025-06-09 00:42:24 -04:00
thibhero
d39bded2f1 Merge branch 'refactor-install'
# Conflicts:
#	Library/Homebrew/test/cmd/upgrade_spec.rb
2025-06-09 00:35:40 -04:00
thibhero
aa47105d2a refactoring code 2025-06-09 00:14:16 -04:00
thibhero
a8638270f2 putting up to date install test 2025-06-08 12:35:10 -04:00
thibhero
8222b192ec updating upgrade to work 2025-06-08 12:34:56 -04:00
thibhero
a5251b2fb6 refactoring install 2025-06-08 12:34:24 -04:00
thibhero
fd159ed32c updating ask function 2025-06-08 11:32:21 -04:00
thibhero
628d265d7a updating test for upgrade 2025-06-08 11:31:51 -04:00
thibhero
27f7f282be refactoring homebrew upgrade for ask option 2025-06-08 11:31:40 -04:00
Rylan Polster
1f37a11b79
Merge pull request #20051 from Homebrew/internal-api-bare-minimum
Reduce the internal formula API to contain the bare minimum data
2025-06-06 16:45:40 +00:00
Mike McQuaid
fda164535e
Merge pull request #20059 from Homebrew/improve_caveats_completions
Improve completions (and elisp) output in caveats
2025-06-06 16:44:33 +00:00
Mike McQuaid
ff710f8191
Improve completions (and elisp) output in caveats
Instead of repeatedly outputting the same identical messages across
multiple packages and repeating them all for every package after they
were all installed: just output the identical messages in the final
caveats output instead.
2025-06-06 17:09:28 +01:00
Mike McQuaid
dd7b95439a
Merge pull request #20057 from Homebrew/cask_loader_error_handling
cask_loader: improve error handling.
2025-06-06 15:10:40 +00:00
Mike McQuaid
e7f667c198
cask_loader: improve error handling.
Handle weird edge cases where we try to read a cask from invalid paths.
2025-06-06 14:19:00 +01:00
Mike McQuaid
b23bc5e0fe
Merge pull request #20058 from Homebrew/dependabot/github_actions/github-actions-694872dfd1
build(deps): bump github/codeql-action from 3.28.18 to 3.28.19 in the github-actions group
2025-06-06 11:30:26 +00:00
dependabot[bot]
08e9a4365f
build(deps): bump github/codeql-action in the github-actions group
Bumps the github-actions group with 1 update: [github/codeql-action](https://github.com/github/codeql-action).


Updates `github/codeql-action` from 3.28.18 to 3.28.19
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](ff0a06e83c...fca7ace96b)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.28.19
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-06 08:33:23 +00:00
Rylan Polster
73b64390b3
Use existing Utils::Bottles::Collector#specification_for method 2025-06-05 12:38:15 -04:00
Rylan Polster
e83dc1cb3c
Fallback to older bottle hashes when viable 2025-06-05 11:32:47 -04:00
Eric Knibbe
0c4672a323
Merge pull request #20055 from Homebrew/cop-cask-url-verified
rubocops/cask/url: put keyword parameters on a new line
2025-06-05 15:32:32 +00:00
Mike McQuaid
1d2f045ecf
Merge pull request #20047 from Homebrew/brew_sh_profiles
`brew (bundle|) sh`: use user's configuration but override prompts.
2025-06-05 14:54:56 +00:00
Eric Knibbe
c75122c694
rubocops/cask/url: put keyword parameters on a new line 2025-06-05 10:53:34 -04:00
Mike McQuaid
5fe43ed3f2
brew (bundle|) sh: use user's configuration but override prompts.
This was more painful that I expected but will allow `brew bundle sh`
and `brew sh` to use the user's configuration but use our custom prompt
for Bash and ZSH.
2025-06-05 15:43:34 +01:00
Mike McQuaid
485f1abbee
Merge pull request #20053 from Homebrew/skip_zero_values
bin/brew: don't copy across zeroed env values.
2025-06-05 07:43:17 +00:00
Mike McQuaid
916c25ef18
bin/brew: don't copy across zeroed env values. 2025-06-05 08:33:08 +01:00
Rylan Polster
e47bc2fb86
Use hashes of arrays instead 2025-06-05 03:15:44 -04:00
Rylan Polster
b44ec56267
Reduce the internal formula API to contain the bare minimum data 2025-06-05 02:08:29 -04:00
Rylan Polster
0b67caf718
Merge pull request #20046 from Homebrew/internal-api-switch
Add undocumented `HOMEBREW_USE_INTERNAL_API` switch
2025-06-04 20:40:05 +00:00
Rylan Polster
71c8174136
Add undocumented HOMEBREW_USE_INTERNAL_API switch 2025-06-04 16:29:43 -04:00
Rylan Polster
6f8d31d698
Merge pull request #20048 from Homebrew/update-expat-version
os/mac/pkgconfig/15: update `expat` version to 2.7.1
2025-06-04 20:13:05 +00:00
Rylan Polster
da624601bb
os/mac/pkgconfig/15: update expat version 2025-06-04 15:46:41 -04:00
Mike McQuaid
68ef29fb5c
Merge pull request #20045 from Homebrew/fix-sharded-api
Fix sharded API structure to match existing API
2025-06-04 07:58:26 +00:00
Mike McQuaid
e825ceea0a
Merge pull request #20041 from Homebrew/mcp_server
Add `brew mcp-server`: a MCP server for Homebrew.
2025-06-04 07:58:01 +00:00
Eric Knibbe
ab1c3ed5f8
Merge pull request #20044 from Homebrew/show-env-var-associations
parser: show related environment variable in switch description
2025-06-04 01:11:58 +00:00
Rylan Polster
fa45209f09
Fix sharded API structure to match existing API 2025-06-03 16:58:47 -04:00
Eric Knibbe
3dc9e88542
parser: show related env var in switch description 2025-06-03 13:57:42 -04:00
Rylan Polster
317110f6f4
Merge pull request #20042 from Homebrew/refactor-bottle-tag-handling
Refactor `OnSystem` and `SimulateSystem` bottle tag handling
2025-06-03 16:22:53 +00:00
Rylan Polster
c03f70f1dc
Refactor OnSystem and SimulateSystem bottle tag handling 2025-06-03 11:57:17 -04:00
Mike McQuaid
21e3621132
Merge pull request #20040 from Homebrew/brew_sh_tests
test/cmd: add more shell tests.
2025-06-03 14:33:47 +00:00
Mike McQuaid
76c4eb60ee
test/cmd: add more shell tests.
This should help ensure that these don't regress.
2025-06-03 15:24:19 +01:00
Mike McQuaid
f9471f9591
Add brew mcp-server: a MCP server for Homebrew.
Add a new `brew mcp-server` command for a Model Context Protocol (MCP)
server for Homebrew. This integrates with AI/LLM tools like Claude,
Claude Code and Cursor.

It currently supports the calls needed/used by the MCP Inspector and
Cursor (where I've tested it).

It provides as `tools` the subcommands output by `brew help` but should
be fairly straightforward to add more in future.

It is implemented in a slightly strange way (a standalone Ruby command
called from a shell command) as MCP servers need a faster startup time
than a normal Homebrew Ruby command allows and fail if they don't get
it.

There are a few Ruby libraries available but, given how relatively
simplistic the implementation is, it didn't feel worthwhile to use and
vendor them.
2025-06-03 15:22:33 +01:00
Mike McQuaid
89739ac615
Merge pull request #20039 from Homebrew/sync-shared-config
Synchronize shared configuration
2025-06-03 08:23:41 +00:00
Mike McQuaid
29ffef482c
Merge pull request #20038 from Homebrew/shard-json-api
Shard JSON API by OS/Arch combination
2025-06-03 08:22:10 +00:00
BrewTestBot
175eb65073
dependabot.yml: update to match main configuration 2025-06-03 08:05:26 +00:00
Rylan Polster
0f03757e8f
Shard JSON API by OS/Arch combination 2025-06-02 23:06:02 -04:00
Mike McQuaid
a0c89e4a7f
Merge pull request #20037 from Homebrew/move_sudo_reset_timestamp
brew.sh: move sudo reset timestamp.
2025-06-03 01:27:47 +00:00
Mike McQuaid
7c5affa824
brew.sh: move sudo reset timestamp.
Let's move this from `bin/brew` to make things like e.g. `brew --prefix`
or `brew shellenv` not reset the sudo timestamp.

This is still in a place that ensures that e.g. no untrusted formula or
tap code has been run yet so should have no security implications but
provide mild usability improvements.
2025-06-02 15:09:27 +01:00
Mike McQuaid
d914a72122
Merge pull request #20030 from Homebrew/rubocop-messages
audits: quote and reword problem description text
2025-06-02 08:02:20 +00:00
thibhero
7c3281f51e Merge remote-tracking branch 'tyuwags/master' 2025-05-31 23:03:40 -04:00
thibhero
01ad6b53d3 double quotes for brew style 2025-05-31 23:02:01 -04:00
thibhero
ab3b2736b5 double quotes for brew style 2025-05-31 21:35:35 -04:00
Thibaut Hérault
326376ef44 Removing attributes from macOS 2025-06-01 03:25:16 +02:00
thibhero
b1c8567977 adding tarball parent for linux 2025-05-31 14:17:40 -04:00
thibhero
b0b29f9b53 updating name tarball for linux 2025-05-31 14:03:08 -04:00
thibhero
960b4343cc updating tarball to remove attributes from MacOS 2025-05-31 13:25:25 -04:00
thibhero
fbd13203d8 Merge remote-tracking branch 'tyuwags/master' 2025-05-31 12:55:49 -04:00
thibhero
19134b3005 making tests more robust with bottles to verify the whole hierarchy oh dependencies and dependants is upgraded as expected 2025-05-31 12:54:53 -04:00
thibhero
3f1341eb6a modifying ask function as it didn't find the whole hierarchy for parents 2025-05-31 12:53:38 -04:00
thibhero
3963af774a adding tarball for the different tests in upgrade_spec.rb and install_spec.rb 2025-05-31 12:52:34 -04:00
Eric Knibbe
cd6777fc73
audits: quote and reword problem description text 2025-05-30 23:49:26 -04:00
Bo Anderson
54c8b127ea
Merge pull request #20028 from Homebrew/sponsors-maintainers-man-completions
Update manpage and completions.
2025-05-31 02:23:19 +00:00
Mike McQuaid
bdbd80671a
Merge pull request #20026 from abitrolly/non-archive-fix
create: fix archive check if HTML starts with spaces
2025-05-30 16:49:09 +00:00
Mike McQuaid
e71b1473b8
formula_creator: tweak variable name 2025-05-30 14:55:50 +01:00
Mike McQuaid
8c6b3db1cd
Merge pull request #20029 from Homebrew/dependabot/github_actions/github-actions-4335f8aa65
build(deps): bump the github-actions group with 2 updates
2025-05-30 10:37:47 +00:00
dependabot[bot]
5805e9d597
build(deps): bump the github-actions group with 2 updates
Bumps the github-actions group with 2 updates: [docker/build-push-action](https://github.com/docker/build-push-action) and [actions/stale](https://github.com/actions/stale).


Updates `docker/build-push-action` from 6.17.0 to 6.18.0
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](1dc7386353...263435318d)

Updates `actions/stale` from 9.0.0 to 9.1.0
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](28ca103628...5bef64f19d)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: 6.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: actions/stale
  dependency-version: 9.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-30 08:29:10 +00:00
Anatoli Babenia
87e57368d4 create: explain file header length logic 2025-05-30 11:12:36 +03:00
Anatoli Babenia
d860fa1fa8 create: fix archive check if HTML starts with spaces 2025-05-30 11:12:36 +03:00
BrewTestBot
3c693459bd
Update manpage and completions.
Autogenerated by the [sponsors-maintainers-man-completions](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/sponsors-maintainers-man-completions.yml) workflow.
2025-05-30 07:36:42 +00:00
Mike McQuaid
e6377ed0c1
Merge pull request #19945 from botantony/cabal
dev-cmd/create: add `--cabal` switch
2025-05-30 07:24:37 +00:00
Bevan Kay
6278ac1801
Merge branch 'master' into cabal 2025-05-29 22:44:20 +10:00
Mike McQuaid
0cd1e6ca5b
Merge pull request #20024 from Homebrew/docs-livecheck-review
docs/Brew-Livecheck review
2025-05-29 07:49:41 +00:00
Eric Knibbe
493f2aa9f0
docs/Brew-Livecheck review 2025-05-28 13:53:38 -04:00
Mike McQuaid
f3c79353be
Merge pull request #20021 from botantony/no_autobump_constant
autobump_constants: add `:requires_manual_review` reason
2025-05-28 15:46:46 +00:00
botantony
9425734b4f
autobump_constants: add :requires_manual_review reason
Signed-off-by: botantony <antonsm21@gmail.com>
2025-05-27 21:48:58 +02:00
Bo Anderson
fe3783d711
Merge pull request #20018 from koddsson/fetch-repo-before-asserting-default-branch
tap: fix handling of `--repair` with no branches
2025-05-27 17:11:00 +00:00
Kristján Oddsson
972414cec7 add a T.must after fetching tap 2025-05-27 16:55:00 +00:00
Kristján Oddsson
7476f09672 format 2025-05-27 16:43:54 +00:00
Kristján Oddsson
0480411c6f
use conditional assignment operator
Co-authored-by: Bo Anderson <mail@boanderson.me>
2025-05-27 16:35:50 +00:00
Kristján Oddsson
24d9524bbd remove T.must to avoid full fetch 2025-05-27 16:01:35 +00:00
Kristján Oddsson
9e05995299 move git fetch before getting origin_branch_name 2025-05-27 14:54:57 +00:00
Patrick Linnane
0e14dd8d3a
Merge pull request #20013 from Homebrew/sponsors-maintainers-man-completions
Update manpage and completions.
2025-05-27 13:27:11 +00:00
Mike McQuaid
ff568c2179
Merge pull request #20016 from Homebrew/sync-shared-config
Synchronize shared configuration
2025-05-27 13:24:37 +00:00
Mike McQuaid
e6aed19670
Merge pull request #20015 from Homebrew/support-tiers-codeowners
docs/Support-Tiers: tweak wording, add CODEOWNERS.
2025-05-27 13:23:31 +00:00
BrewTestBot
8fe9691b13
Update manpage and completions.
Autogenerated by the [sponsors-maintainers-man-completions](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/sponsors-maintainers-man-completions.yml) workflow.
2025-05-27 14:14:59 +01:00
BrewTestBot
9d949f3f2f
stale-issues.yml: update to match main configuration 2025-05-27 14:14:45 +01:00
Mike McQuaid
214074cf02
docs/Support-Tiers: tweak wording, add CODEOWNERS.
Let's improve the wording of the Support Tiers document and add it to
a (new) CODEOWNERS file to ensure that I or the TSC review changes.
2025-05-27 14:14:05 +01:00
Mike McQuaid
600cb4544d
Merge pull request #20017 from Homebrew/release_fixes
workflows/pkg-installer: fix release upload.
2025-05-27 11:15:51 +00:00
Mike McQuaid
2131d70265
workflows/pkg-installer: fix release upload.
- Get the release tag from the installer path.
- Remove unnecessary `gh` installation.
- Remove failing test that I can't fix.
2025-05-27 11:47:00 +01:00
Mike McQuaid
171fba9c84
Merge pull request #20011 from Homebrew/revert-19946-SMillerDev-patch-1
Revert "feat: allow env for write_jar_script"
2025-05-26 16:28:31 +00:00
Mike McQuaid
1035024b83
Revert "feat: allow env for write_jar_script" 2025-05-26 17:19:48 +01:00
Sean Molenaar
f420f0f63d
Merge pull request #19946 from Homebrew/SMillerDev-patch-1
feat: allow env for write_jar_script
2025-05-26 14:36:15 +00:00
Sean Molenaar
81ea767ea3
Update Library/Homebrew/extend/pathname.rb 2025-05-26 21:17:05 +09:00
Bevan Kay
d416755560
Merge pull request #20005 from gibfahn/bump_write_only
bump-pr: respect --write-only flag and skip git operations
2025-05-26 08:41:55 +00:00
Mike McQuaid
a2894caceb
Merge pull request #20004 from Homebrew/formula-creator-ruby-rework
formula_creator: Update Ruby template
2025-05-26 07:41:51 +00:00
Mike McQuaid
3f15e0eef0
dev-cmd/bump-formula-pr: fix style. 2025-05-26 08:40:14 +01:00
Gibson Fahnestock
97acfb94ce
bump-pr: respect --write-only flag and skip git operations
The flag used to work well, but at some point started to run more and
more git actions. We use this to update formula and casks in other
homebrew taps, and it works well except for this issue.
2025-05-24 13:14:00 +01:00
Patrick Linnane
5ee4e609ac
formula_creator: Update Ruby template
Signed-off-by: Patrick Linnane <patrick@linnane.io>
2025-05-23 20:58:02 -07:00
botantony
92832c258c
dev-cmd/create: add --cabal switch
Signed-off-by: botantony <antonsm21@gmail.com>
2025-05-18 20:18:34 +02:00
Sean Molenaar
ca911fb446
feat: allow env for write_jar_script 2025-05-14 11:56:31 +02:00
435 changed files with 9036 additions and 59785 deletions

View File

@ -1,7 +1,7 @@
// For format details, see https://aka.ms/devcontainer.json. // For format details, see https://aka.ms/devcontainer.json.
{ {
"name": "Homebrew/brew", "name": "Homebrew/brew",
"image": "ghcr.io/homebrew/brew:master", "image": "ghcr.io/homebrew/brew:main",
"workspaceFolder": "/home/linuxbrew/.linuxbrew/Homebrew", "workspaceFolder": "/home/linuxbrew/.linuxbrew/Homebrew",
"workspaceMount": "source=${localWorkspaceFolder},target=/home/linuxbrew/.linuxbrew/Homebrew,type=bind,consistency=cached", "workspaceMount": "source=${localWorkspaceFolder},target=/home/linuxbrew/.linuxbrew/Homebrew,type=bind,consistency=cached",
"onCreateCommand": ".devcontainer/on-create-command.sh", "onCreateCommand": ".devcontainer/on-create-command.sh",

View File

@ -4,7 +4,7 @@ type: "Bug"
body: body:
- type: markdown - type: markdown
attributes: attributes:
value: Please note we will close your issue without comment if you do not correctly fill out the issue checklist below and provide ALL the requested information. If you repeatedly fail to use the issue template, we will block you from ever submitting issues to Homebrew again. value: Please note we may close your issue without comment if you do not fill out the issue checklist below and provide ALL the requested information (even if you consider them irrelevant). If you are unwilling to use the issue template, we may block you from ever submitting future issues to Homebrew.
- type: textarea - type: textarea
attributes: attributes:
render: shell render: shell
@ -16,10 +16,10 @@ body:
label: Verification label: Verification
description: Please verify that you've followed these steps. If you cannot truthfully check these boxes, open a discussion at https://github.com/orgs/Homebrew/discussions instead. description: Please verify that you've followed these steps. If you cannot truthfully check these boxes, open a discussion at https://github.com/orgs/Homebrew/discussions instead.
options: options:
- label: My "`brew doctor` output" above says `Your system is ready to brew.` and am still able to reproduce my issue.
required: true
- label: I ran `brew update` twice and am still able to reproduce my issue. - label: I ran `brew update` twice and am still able to reproduce my issue.
required: true required: true
- label: My "`brew doctor` output" above says `Your system is ready to brew` or a definitely unrelated `Tier` message.
required: true
- label: This issue's title and/or description do not reference a single formula e.g. `brew install wget`. If they do, open an issue at https://github.com/Homebrew/homebrew-core/issues/new/choose instead. - label: This issue's title and/or description do not reference a single formula e.g. `brew install wget`. If they do, open an issue at https://github.com/Homebrew/homebrew-core/issues/new/choose instead.
required: true required: true
- type: textarea - type: textarea

View File

@ -0,0 +1,7 @@
# This file is synced from the `.github` repository, do not modify it directly.
extensions:
- addsTo:
pack: codeql/actions-all
extensible: trustedActionsOwnerDataModel
data:
- ["Homebrew"]

178
.github/dependabot.yml vendored
View File

@ -1,90 +1,94 @@
# This file is synced from the `.github` repository, do not modify it directly.
---
version: 2 version: 2
updates: updates:
- package-ecosystem: github-actions - package-ecosystem: github-actions
directory: / directory: "/"
schedule: schedule:
interval: weekly interval: weekly
day: "friday" day: friday
time: "08:00" time: '08:00'
timezone: "Etc/UTC" timezone: Etc/UTC
allow: allow:
- dependency-type: all - dependency-type: all
groups: groups:
github-actions: dependabot:
patterns: patterns:
- "*" - "*"
cooldown:
default-days: 1
include:
- "*"
- package-ecosystem: bundler
directories:
- "/Library/Homebrew"
schedule:
interval: weekly
day: friday
time: '08:00'
timezone: Etc/UTC
allow:
- dependency-type: all
groups:
dependabot:
patterns:
- "*"
cooldown:
default-days: 1
semver-major-days: 14
semver-minor-days: 7
semver-patch-days: 1
include:
- "*"
- package-ecosystem: docker
directory: "/"
schedule:
interval: weekly
day: friday
time: '08:00'
timezone: Etc/UTC
allow:
- dependency-type: all
groups:
dependabot:
patterns:
- "*"
- package-ecosystem: devcontainers
directory: "/"
schedule:
interval: weekly
day: friday
time: '08:00'
timezone: Etc/UTC
allow:
- dependency-type: all
groups:
dependabot:
patterns:
- "*"
cooldown:
default-days: 1
include:
- "*"
- package-ecosystem: pip
directories:
- "/Library/Homebrew/formula-analytics/"
schedule:
interval: weekly
day: friday
time: '08:00'
timezone: Etc/UTC
allow:
- dependency-type: all
groups:
dependabot:
patterns:
- "*"
cooldown:
default-days: 1
semver-major-days: 14
semver-minor-days: 7
semver-patch-days: 1
include:
- "*"
- package-ecosystem: bundler
directories:
- /
- /Library/Homebrew
schedule:
interval: weekly
day: "friday"
time: "08:00"
timezone: "Etc/UTC"
allow:
- dependency-type: all
groups:
bundler:
patterns:
- "*"
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
day: "friday"
time: "08:00"
timezone: "Etc/UTC"
allow:
- dependency-type: all
groups:
npm:
patterns:
- "*"
- package-ecosystem: docker
directory: /
schedule:
interval: weekly
day: "friday"
time: "08:00"
timezone: "Etc/UTC"
allow:
- dependency-type: all
groups:
docker:
patterns:
- "*"
- package-ecosystem: devcontainers
directory: /
schedule:
interval: weekly
day: "friday"
time: "08:00"
timezone: "Etc/UTC"
allow:
- dependency-type: all
groups:
devcontainers:
patterns:
- "*"
- package-ecosystem: pip
directories:
- /
- /Library/Homebrew/formula-analytics/
schedule:
interval: weekly
day: "friday"
time: "08:00"
timezone: "Etc/UTC"
allow:
- dependency-type: all
groups:
pip:
patterns:
- "*"

View File

@ -1,18 +1,12 @@
name: actionlint # This file is synced from the `.github` repository, do not modify it directly.
name: Actionlint
on: on:
push: push:
branches: branches:
- main
- master - master
pull_request: pull_request:
paths:
- '.github/workflows/*.ya?ml'
- '.github/actionlint.yaml'
env:
HOMEBREW_DEVELOPER: 1
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_ENV_HINTS: 1
defaults: defaults:
run: run:
@ -22,16 +16,25 @@ concurrency:
group: "actionlint-${{ github.ref }}" group: "actionlint-${{ github.ref }}"
cancel-in-progress: ${{ github.event_name == 'pull_request' }} cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
HOMEBREW_DEVELOPER: 1
HOMEBREW_NO_AUTO_UPDATE: 1
HOMEBREW_NO_ENV_HINTS: 1
permissions: {} permissions: {}
jobs: jobs:
workflow_syntax: workflow_syntax:
if: github.repository_owner == 'Homebrew' if: github.repository_owner == 'Homebrew'
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: read
container:
image: ghcr.io/homebrew/ubuntu22.04:main
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: setup-homebrew id: setup-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: false core: false
cask: false cask: false
@ -40,31 +43,44 @@ jobs:
- name: Install tools - name: Install tools
run: brew install actionlint shellcheck zizmor run: brew install actionlint shellcheck zizmor
- name: Set up GITHUB_WORKSPACE - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- run: zizmor --format sarif . > results.sarif
env: env:
HOMEBREW_REPOSITORY: ${{ steps.setup-homebrew.outputs.repository-path }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Annotations work only relative to GITHUB_WORKSPACE
(shopt -s dotglob; rm -rf "${GITHUB_WORKSPACE:?}"/*; mv "${HOMEBREW_REPOSITORY:?}"/* "$GITHUB_WORKSPACE")
rmdir "$HOMEBREW_REPOSITORY"
ln -vs "$GITHUB_WORKSPACE" "$HOMEBREW_REPOSITORY"
echo "::add-matcher::.github/actionlint-matcher.json"
- run: |
# NOTE: exit code intentionally suppressed here
zizmor --format sarif . > results.sarif || true
- name: Upload SARIF file - name: Upload SARIF file
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
# We can't use the SARIF file when triggered by `merge_group` so we don't upload it.
if: always() && github.event_name != 'merge_group'
with: with:
name: results.sarif name: results.sarif
path: results.sarif path: results.sarif
- name: Set up actionlint
run: |
# In homebrew-core, setting `shell: /bin/bash` prevents shellcheck from running on
# those steps, so let's change them to `shell: bash` temporarily for better linting.
sed -i 's|shell: /bin/bash -x|shell: bash -x|' .github/workflows/*.y*ml
# In homebrew-core, the JSON matcher needs to be accessible to the container host.
cp "$(brew --repository)/.github/actionlint-matcher.json" "$HOME"
echo "::add-matcher::$HOME/actionlint-matcher.json"
- run: actionlint - run: actionlint
upload_sarif: upload_sarif:
needs: workflow_syntax needs: workflow_syntax
# We want to always upload this even if `actionlint` failed.
# This is only available on public repositories.
if: >
always() &&
!contains(fromJSON('["cancelled", "skipped"]'), needs.workflow_syntax.result) &&
!github.event.repository.private &&
github.event_name != 'merge_group'
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read contents: read
@ -77,7 +93,7 @@ jobs:
path: results.sarif path: results.sarif
- name: Upload SARIF file - name: Upload SARIF file
uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 uses: github/codeql-action/upload-sarif@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
with: with:
sarif_file: results.sarif sarif_file: results.sarif
category: zizmor category: zizmor

View File

@ -27,7 +27,7 @@ jobs:
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: false core: false
cask: false cask: false

View File

@ -3,10 +3,9 @@ name: "CodeQL"
on: on:
push: push:
branches: branches:
- main
- master - master
pull_request: pull_request:
branches:
- master
defaults: defaults:
run: run:
@ -28,7 +27,7 @@ jobs:
persist-credentials: false persist-credentials: false
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 uses: github/codeql-action/init@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2
with: with:
languages: ruby languages: ruby
config: | config: |
@ -36,4 +35,4 @@ jobs:
- Library/Homebrew/vendor - Library/Homebrew/vendor
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 uses: github/codeql-action/analyze@181d5eefc20863364f96762470ba6f862bdef56b # v3.29.2

View File

@ -4,6 +4,7 @@ on:
pull_request: pull_request:
push: push:
branches: branches:
- main
- master - master
merge_group: merge_group:
release: release:
@ -38,8 +39,8 @@ jobs:
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
- name: Fetch origin/master from Git - name: Fetch origin/HEAD from Git
run: git fetch origin master run: git fetch origin HEAD
- name: Determine build attributes - name: Determine build attributes
id: attributes id: attributes
@ -83,12 +84,16 @@ jobs:
) )
fi fi
elif [[ "${GITHUB_EVENT_NAME}" == "push" && elif [[ "${GITHUB_EVENT_NAME}" == "push" &&
"${GITHUB_REF}" == "refs/heads/master" && ("${GITHUB_REF}" == "refs/heads/master" || "${GITHUB_REF}" == "refs/heads/main") &&
"${version}" == "22.04" ]]; then "${version}" == "22.04" ]]; then
tags+=( tags+=(
"ghcr.io/homebrew/brew:main"
"ghcr.io/homebrew/brew:master" "ghcr.io/homebrew/brew:master"
"ghcr.io/homebrew/ubuntu${version}:main"
"ghcr.io/homebrew/ubuntu${version}:master" "ghcr.io/homebrew/ubuntu${version}:master"
"homebrew/brew:main"
"homebrew/brew:master" "homebrew/brew:master"
"homebrew/ubuntu${version}:main"
"homebrew/ubuntu${version}:master" "homebrew/ubuntu${version}:master"
) )
fi fi
@ -160,11 +165,11 @@ jobs:
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
- name: Fetch origin/master from Git - name: Fetch origin/HEAD from Git
run: git fetch origin master run: git fetch origin HEAD
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
with: with:
cache-binary: false cache-binary: false
@ -190,7 +195,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Build Docker image - name: Build Docker image
uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0 # v6.17.0 uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with: with:
context: . context: .
load: true load: true
@ -227,7 +232,7 @@ jobs:
- name: Deploy the Docker image by digest - name: Deploy the Docker image by digest
id: digest id: digest
if: fromJSON(steps.attributes.outputs.push) if: fromJSON(steps.attributes.outputs.push)
uses: docker/build-push-action@1dc73863535b631f98b2378be8619f83b136f4a0 # v6.17.0 uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with: with:
context: . context: .
cache-from: type=registry,ref=ghcr.io/homebrew/ubuntu${{ matrix.version }}:cache cache-from: type=registry,ref=ghcr.io/homebrew/ubuntu${{ matrix.version }}:cache
@ -263,7 +268,7 @@ jobs:
version: ${{ fromJSON(needs.generate-tags.outputs.matrix) }} version: ${{ fromJSON(needs.generate-tags.outputs.matrix) }}
steps: steps:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
with: with:
cache-binary: false cache-binary: false

View File

@ -24,7 +24,7 @@ jobs:
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: false core: false
cask: false cask: false
@ -52,7 +52,7 @@ jobs:
run: vale docs/ run: vale docs/
- name: Install Ruby - name: Install Ruby
uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0 uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # v1.245.0
with: with:
bundler-cache: true bundler-cache: true
working-directory: docs working-directory: docs
@ -67,7 +67,13 @@ jobs:
- name: Generate formulae.brew.sh API samples - name: Generate formulae.brew.sh API samples
if: github.repository == 'Homebrew/formulae.brew.sh' if: github.repository == 'Homebrew/formulae.brew.sh'
working-directory: docs working-directory: docs
run: ../script/generate-api-samples.rb run: ../script/generate-api-samples.rb --template
- name: Cache HTML Proofer
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
path: tmp/.htmlproofer
key: ${{ runner.os }}-htmlproofer
- name: Build the site and check for broken links - name: Build the site and check for broken links
working-directory: docs working-directory: docs

View File

@ -28,7 +28,7 @@ jobs:
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: false core: false
cask: false cask: false
@ -55,7 +55,7 @@ jobs:
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: false core: false
cask: false cask: false

View File

@ -43,7 +43,7 @@ jobs:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: false core: false
cask: false cask: false
@ -135,7 +135,7 @@ jobs:
fi fi
- name: Generate build provenance - name: Generate build provenance
uses: actions/attest-build-provenance@db473fddc028af60658334401dc6fa3ffd8669fd # v2.3.0 uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.4.0
with: with:
subject-path: Homebrew-${{ steps.homebrew-version.outputs.version }}.pkg subject-path: Homebrew-${{ steps.homebrew-version.outputs.version }}.pkg
@ -230,17 +230,15 @@ jobs:
--password "${PKG_APPLE_ID_APP_SPECIFIC_PASSWORD}" --password "${PKG_APPLE_ID_APP_SPECIFIC_PASSWORD}"
--wait --wait
- name: Install gh
run: brew install gh
- name: Upload installer to GitHub release - name: Upload installer to GitHub release
if: github.event_name == 'release' if: github.event_name == 'release'
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INSTALLER_PATH: ${{ needs.build.outputs.installer_path }} INSTALLER_PATH: ${{ needs.build.outputs.installer_path }}
run: gh release upload --repo Homebrew/brew run: |
"${GITHUB_REF//refs\/tags\//}" VERSION="${INSTALLER_PATH#Homebrew-}"
"${INSTALLER_PATH}" VERSION="${VERSION%.pkg}"
gh release upload --repo Homebrew/brew "${VERSION}" "${INSTALLER_PATH}"
issue: issue:
needs: [build, test, upload] needs: [build, test, upload]
@ -253,7 +251,7 @@ jobs:
issues: write issues: write
steps: steps:
- name: Open, update, or close pkg installer issue - name: Open, update, or close pkg installer issue
uses: Homebrew/actions/create-or-update-issue@master uses: Homebrew/actions/create-or-update-issue@main
with: with:
title: Failed to publish pkg installer title: Failed to publish pkg installer
body: > body: >
@ -261,7 +259,7 @@ jobs:
${{ github.ref_name }}. No pkg installer was uploaded to the GitHub ${{ github.ref_name }}. No pkg installer was uploaded to the GitHub
release. release.
labels: bug,release blocker labels: bug,release blocker
update-existing: ${{ contains(needs.*.result, 'failure') }} update-existing: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }}
close-existing: ${{ needs.upload.result == 'success' }} close-existing: ${{ needs.upload.result == 'success' }}
close-from-author: github-actions[bot] close-from-author: github-actions[bot]
close-comment: > close-comment: >

View File

@ -3,6 +3,7 @@ name: Ruby Documentation CI
on: on:
push: push:
branches: branches:
- main
- master - master
pull_request: pull_request:
@ -28,7 +29,7 @@ jobs:
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: false core: false
cask: false cask: false
@ -42,7 +43,7 @@ jobs:
persist-credentials: false persist-credentials: false
- name: Install Ruby - name: Install Ruby
uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0 uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # v1.245.0
with: with:
bundler-cache: true bundler-cache: true
working-directory: rubydoc working-directory: rubydoc

View File

@ -1,9 +1,10 @@
name: Update schema data name: Update SBOM schema
on: on:
push: push:
paths: paths:
- .github/workflows/schemas.yml - .github/workflows/sbom.yml
branches-ignore: branches-ignore:
- main
- master - master
schedule: schedule:
- cron: "0 0 * * *" - cron: "0 0 * * *"
@ -17,25 +18,25 @@ defaults:
shell: bash -xeuo pipefail {0} shell: bash -xeuo pipefail {0}
jobs: jobs:
spdx: sbom:
if: github.repository == 'Homebrew/brew' if: github.repository == 'Homebrew/brew'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: false core: false
cask: false cask: false
test-bot: false test-bot: false
- name: Configure Git user - name: Configure Git user
uses: Homebrew/actions/git-user-config@master uses: Homebrew/actions/git-user-config@main
with: with:
username: BrewTestBot username: BrewTestBot
- name: Set up commit signing - name: Set up commit signing
uses: Homebrew/actions/setup-commit-signing@master uses: Homebrew/actions/setup-commit-signing@main
with: with:
signing_key: ${{ secrets.BREWTESTBOT_SSH_SIGNING_KEY }} signing_key: ${{ secrets.BREWTESTBOT_SSH_SIGNING_KEY }}
@ -55,7 +56,7 @@ jobs:
git checkout "${BRANCH}" git checkout "${BRANCH}"
git checkout "Library/Homebrew/data/schemas" git checkout "Library/Homebrew/data/schemas"
else else
git checkout --no-track -B "${BRANCH}" origin/master git checkout --no-track -B "${BRANCH}" origin/HEAD
fi fi
# Intentionally tracking 2.3.x to match what we output in sbom.rb. 3.0 also doesn't have a JSON Schema. # Intentionally tracking 2.3.x to match what we output in sbom.rb. 3.0 also doesn't have a JSON Schema.
@ -67,9 +68,10 @@ jobs:
if ! git diff --exit-code Library/Homebrew/data/schemas if ! git diff --exit-code Library/Homebrew/data/schemas
then then
git add "Library/Homebrew/data/schemas" git add "Library/Homebrew/data/schemas"
git commit -m "data/schemas: update schema data." -m "Autogenerated by [a scheduled GitHub Action](https://github.com/Homebrew/brew/blob/master/.github/workflows/schemas.yml)." git commit -m "data/schemas: update schema data." -m "Autogenerated by [a scheduled GitHub Action](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/schemas.yml)."
echo "committed=true" >> "$GITHUB_OUTPUT" echo "committed=true" >> "$GITHUB_OUTPUT"
PULL_REQUEST_STATE="$(gh pr view --json=state | jq -r ".state")" PULL_REQUEST_STATE="$(gh pr view --json=state | jq -r ".state" || true)"
if [[ "${PULL_REQUEST_STATE}" != "OPEN" ]] if [[ "${PULL_REQUEST_STATE}" != "OPEN" ]]
then then
echo "pull_request=true" >> "$GITHUB_OUTPUT" echo "pull_request=true" >> "$GITHUB_OUTPUT"
@ -78,13 +80,13 @@ jobs:
- name: Push commits - name: Push commits
if: steps.update.outputs.committed == 'true' if: steps.update.outputs.committed == 'true'
uses: Homebrew/actions/git-try-push@master uses: Homebrew/actions/git-try-push@main
with: with:
token: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }} token: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }}
directory: ${{ steps.set-up-homebrew.outputs.repository-path }} directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
branch: ${{ steps.update.outputs.branch }} branch: ${{ steps.update.outputs.branch }}
force: true force: true
origin_branch: "master" origin_branch: "HEAD"
- name: Open a pull request - name: Open a pull request
if: steps.update.outputs.pull_request == 'true' if: steps.update.outputs.pull_request == 'true'
@ -92,3 +94,26 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }} GITHUB_TOKEN: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }}
working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }} working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
issue:
needs: sbom
if: always() && github.event_name == 'schedule'
runs-on: ubuntu-latest
env:
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
permissions:
# To create or update issues
issues: write
steps:
- name: Open, update, or close schema issue
uses: Homebrew/actions/create-or-update-issue@main
with:
title: Failed to update SBOM schema
body: >
The SBOM schema workflow [failed](${{ env.RUN_URL }}). No SBOM schema was updated.
labels: bug
update-existing: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }}
close-existing: ${{ needs.sbom.result == 'success' }}
close-from-author: github-actions[bot]
close-comment: >
The SBOM schema workflow [succeeded](${{ env.RUN_URL }}). Closing this issue.

View File

@ -10,6 +10,7 @@ on:
paths: paths:
- .github/workflows/sorbet.yml - .github/workflows/sorbet.yml
branches-ignore: branches-ignore:
- main
- master - master
schedule: schedule:
- cron: "0 0 * * *" - cron: "0 0 * * *"
@ -29,7 +30,7 @@ jobs:
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: false core: false
cask: false cask: false
@ -37,13 +38,13 @@ jobs:
- name: Configure Git user - name: Configure Git user
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
uses: Homebrew/actions/git-user-config@master uses: Homebrew/actions/git-user-config@main
with: with:
username: BrewTestBot username: BrewTestBot
- name: Set up commit signing - name: Set up commit signing
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
uses: Homebrew/actions/setup-commit-signing@master uses: Homebrew/actions/setup-commit-signing@main
with: with:
signing_key: ${{ secrets.BREWTESTBOT_SSH_SIGNING_KEY }} signing_key: ${{ secrets.BREWTESTBOT_SSH_SIGNING_KEY }}
@ -63,7 +64,7 @@ jobs:
git checkout "${BRANCH}" git checkout "${BRANCH}"
git checkout "Library/Homebrew/sorbet" git checkout "Library/Homebrew/sorbet"
else else
git checkout --no-track -B "${BRANCH}" origin/master git checkout --no-track -B "${BRANCH}" origin/HEAD
fi fi
fi fi
@ -80,17 +81,17 @@ jobs:
then then
git add "Library/Homebrew/sorbet" git add "Library/Homebrew/sorbet"
git commit -m "sorbet: Update RBI files." \ git commit -m "sorbet: Update RBI files." \
-m "Autogenerated by the [sorbet](https://github.com/Homebrew/brew/blob/master/.github/workflows/sorbet.yml) workflow." -m "Autogenerated by the [sorbet](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/sorbet.yml) workflow."
if ! git diff --stat --exit-code "Library/Homebrew" if ! git diff --stat --exit-code "Library/Homebrew"
then then
git add "Library/Homebrew/" git add "Library/Homebrew/"
git commit -m "sorbet: Autobump sigils via Spoom" \ git commit -m "sorbet: Autobump sigils via Spoom" \
-m "Autogenerated by the [sorbet](https://github.com/Homebrew/brew/blob/master/.github/workflows/sorbet.yml) workflow." -m "Autogenerated by the [sorbet](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/sorbet.yml) workflow."
fi fi
echo "committed=true" >> "$GITHUB_OUTPUT" echo "committed=true" >> "$GITHUB_OUTPUT"
PULL_REQUEST_STATE="$(gh pr view --json=state | jq -r ".state")" PULL_REQUEST_STATE="$(gh pr view --json=state | jq -r ".state" || true)"
if [[ "${PULL_REQUEST_STATE}" != "OPEN" ]] if [[ "${PULL_REQUEST_STATE}" != "OPEN" ]]
then then
echo "pull_request=true" >> "$GITHUB_OUTPUT" echo "pull_request=true" >> "$GITHUB_OUTPUT"
@ -99,13 +100,13 @@ jobs:
- name: Push commits - name: Push commits
if: steps.commit.outputs.committed == 'true' if: steps.commit.outputs.committed == 'true'
uses: Homebrew/actions/git-try-push@master uses: Homebrew/actions/git-try-push@main
with: with:
token: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }} token: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }}
directory: ${{ steps.set-up-homebrew.outputs.repository-path }} directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
branch: ${{ steps.update.outputs.branch }} branch: ${{ steps.update.outputs.branch }}
force: true force: true
origin_branch: "master" origin_branch: "HEAD"
- name: Open a pull request - name: Open a pull request
if: steps.commit.outputs.pull_request == 'true' if: steps.commit.outputs.pull_request == 'true'
@ -113,3 +114,26 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }} GITHUB_TOKEN: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }}
working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }} working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
issue:
needs: tapioca
if: always() && github.event_name == 'schedule'
runs-on: ubuntu-latest
env:
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
permissions:
# To create or update issues
issues: write
steps:
- name: Open, update, or close Sorbet issue
uses: Homebrew/actions/create-or-update-issue@main
with:
title: Failed to update RBI files
body: >
The Sorbet workflow [failed](${{ env.RUN_URL }}). No RBI files were updated.
labels: bug
update-existing: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }}
close-existing: ${{ needs.tapioca.result == 'success' }}
close-from-author: github-actions[bot]
close-comment: >
The Sorbet workflow [succeeded](${{ env.RUN_URL }}). Closing this issue.

View File

@ -4,6 +4,7 @@ on:
paths: paths:
- .github/workflows/spdx.yml - .github/workflows/spdx.yml
branches-ignore: branches-ignore:
- main
- master - master
schedule: schedule:
- cron: "0 0 * * *" - cron: "0 0 * * *"
@ -23,19 +24,19 @@ jobs:
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: false core: false
cask: false cask: false
test-bot: false test-bot: false
- name: Configure Git user - name: Configure Git user
uses: Homebrew/actions/git-user-config@master uses: Homebrew/actions/git-user-config@main
with: with:
username: BrewTestBot username: BrewTestBot
- name: Set up commit signing - name: Set up commit signing
uses: Homebrew/actions/setup-commit-signing@master uses: Homebrew/actions/setup-commit-signing@main
with: with:
signing_key: ${{ secrets.BREWTESTBOT_SSH_SIGNING_KEY }} signing_key: ${{ secrets.BREWTESTBOT_SSH_SIGNING_KEY }}
@ -55,15 +56,16 @@ jobs:
git checkout "${BRANCH}" git checkout "${BRANCH}"
git checkout "Library/Homebrew/data/spdx" git checkout "Library/Homebrew/data/spdx"
else else
git checkout --no-track -B "${BRANCH}" origin/master git checkout --no-track -B "${BRANCH}" origin/HEAD
fi fi
if brew update-license-data if brew update-license-data
then then
git add "Library/Homebrew/data/spdx" git add "Library/Homebrew/data/spdx"
git commit -m "spdx: update license data." -m "Autogenerated by [a scheduled GitHub Action](https://github.com/Homebrew/brew/blob/master/.github/workflows/spdx.yml)." git commit -m "spdx: update license data." -m "Autogenerated by [a scheduled GitHub Action](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/spdx.yml)."
echo "committed=true" >> "$GITHUB_OUTPUT" echo "committed=true" >> "$GITHUB_OUTPUT"
PULL_REQUEST_STATE="$(gh pr view --json=state | jq -r ".state")" PULL_REQUEST_STATE="$(gh pr view --json=state | jq -r ".state" || true)"
if [[ "${PULL_REQUEST_STATE}" != "OPEN" ]] if [[ "${PULL_REQUEST_STATE}" != "OPEN" ]]
then then
echo "pull_request=true" >> "$GITHUB_OUTPUT" echo "pull_request=true" >> "$GITHUB_OUTPUT"
@ -72,13 +74,13 @@ jobs:
- name: Push commits - name: Push commits
if: steps.update.outputs.committed == 'true' if: steps.update.outputs.committed == 'true'
uses: Homebrew/actions/git-try-push@master uses: Homebrew/actions/git-try-push@main
with: with:
token: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }} token: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }}
directory: ${{ steps.set-up-homebrew.outputs.repository-path }} directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
branch: ${{ steps.update.outputs.branch }} branch: ${{ steps.update.outputs.branch }}
force: true force: true
origin_branch: "master" origin_branch: "HEAD"
- name: Open a pull request - name: Open a pull request
if: steps.update.outputs.pull_request == 'true' if: steps.update.outputs.pull_request == 'true'
@ -86,3 +88,26 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }} GITHUB_TOKEN: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }}
working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }} working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
issue:
needs: spdx
if: always() && github.event_name == 'schedule'
runs-on: ubuntu-latest
env:
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
permissions:
# To create or update issues
issues: write
steps:
- name: Open, update, or close SPDX issue
uses: Homebrew/actions/create-or-update-issue@main
with:
title: Failed to update SPDX license data
body: >
The SPDX license data workflow [failed](${{ env.RUN_URL }}). No SPDX license data was updated.
labels: bug
update-existing: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }}
close-existing: ${{ needs.spdx.result == 'success' }}
close-from-author: github-actions[bot]
close-comment: >
The SPDX license data workflow [succeeded](${{ env.RUN_URL }}). Closing this issue.

View File

@ -3,6 +3,7 @@ name: Update sponsors, maintainers, manpage and completions
on: on:
push: push:
branches: branches:
- main
- master - master
paths: paths:
- .github/workflows/sponsors-maintainers-man-completions.yml - .github/workflows/sponsors-maintainers-man-completions.yml
@ -32,19 +33,19 @@ jobs:
steps: steps:
- name: Setup Homebrew - name: Setup Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: false core: false
cask: false cask: false
test-bot: false test-bot: false
- name: Configure Git user - name: Configure Git user
uses: Homebrew/actions/git-user-config@master uses: Homebrew/actions/git-user-config@main
with: with:
username: BrewTestBot username: BrewTestBot
- name: Set up commit signing - name: Set up commit signing
uses: Homebrew/actions/setup-commit-signing@master uses: Homebrew/actions/setup-commit-signing@main
with: with:
signing_key: ${{ secrets.BREWTESTBOT_SSH_SIGNING_KEY }} signing_key: ${{ secrets.BREWTESTBOT_SSH_SIGNING_KEY }}
@ -60,7 +61,7 @@ jobs:
run: | run: |
git fetch origin git fetch origin
if [[ -n "$GITHUB_REF_NAME" && "$GITHUB_REF_NAME" != "master" ]] if [[ -n "$GITHUB_REF_NAME" && "$GITHUB_REF_NAME" != "master" && "$GITHUB_REF_NAME" != "main" ]]
then then
BRANCH="$GITHUB_REF_NAME" BRANCH="$GITHUB_REF_NAME"
else else
@ -76,7 +77,7 @@ jobs:
"manpages/brew.1" \ "manpages/brew.1" \
"completions" "completions"
else else
git checkout --force --no-track -B "${BRANCH}" origin/master git checkout --force --no-track -B "${BRANCH}" origin/HEAD
fi fi
if brew update-sponsors if brew update-sponsors
@ -111,7 +112,7 @@ jobs:
if [[ -n "${COMMITTED-}" ]] if [[ -n "${COMMITTED-}" ]]
then then
echo "committed=true" >> "$GITHUB_OUTPUT" echo "committed=true" >> "$GITHUB_OUTPUT"
PULL_REQUEST_STATE="$(gh pr view --json=state | jq -r ".state")" PULL_REQUEST_STATE="$(gh pr view --json=state | jq -r ".state" || true)"
if [[ "${PULL_REQUEST_STATE}" != "OPEN" ]] if [[ "${PULL_REQUEST_STATE}" != "OPEN" ]]
then then
echo "pull_request=true" >> "$GITHUB_OUTPUT" echo "pull_request=true" >> "$GITHUB_OUTPUT"
@ -124,7 +125,7 @@ jobs:
- name: Push commits - name: Push commits
if: steps.update.outputs.committed == 'true' if: steps.update.outputs.committed == 'true'
uses: Homebrew/actions/git-try-push@master uses: Homebrew/actions/git-try-push@main
with: with:
token: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }} token: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }}
directory: ${{ steps.set-up-homebrew.outputs.repository-path }} directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
@ -137,3 +138,26 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }} GITHUB_TOKEN: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }}
working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }} working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
issue:
needs: updates
if: always() && github.event_name == 'schedule'
runs-on: ubuntu-latest
env:
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
permissions:
# To create or update issues
issues: write
steps:
- name: Open, update, or close sponsors, maintainers, manpage and completions issue
uses: Homebrew/actions/create-or-update-issue@main
with:
title: Failed to update sponsors, maintainers, manpage and completions
body: >
The sponsors, maintainers, manpage and completions workflow [failed](${{ env.RUN_URL }}). No sponsors, maintainers, manpage and completions were updated.
labels: bug
update-existing: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }}
close-existing: ${{ needs.updates.result == 'success' }}
close-from-author: github-actions[bot]
close-comment: >
The sponsors, maintainers, manpage and completions workflow [succeeded](${{ env.RUN_URL }}). Closing this issue.

View File

@ -0,0 +1,64 @@
name: Sync default branches
on:
push:
branches:
- main
- master
pull_request:
paths:
- .github/workflows/sync-default-branches.yml
permissions: {}
defaults:
run:
shell: bash -xeuo pipefail {0}
concurrency:
group: "sync-default-branches-${{ github.ref }}"
cancel-in-progress: true
jobs:
sync:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Configure Git user
uses: Homebrew/actions/git-user-config@main
with:
username: github-actions[bot]
- name: Determine source and target branches
id: branches
run: |
if [[ "${GITHUB_REF_NAME}" == "main" ]]; then
target="master"
source="main"
else
target="main"
source="master"
fi
echo "target=${target}" >> "$GITHUB_OUTPUT"
echo "source=${source}" >> "$GITHUB_OUTPUT"
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 1
persist-credentials: true
- name: Get target SHA
id: sha
run: |
TARGET_SHA=$(git ls-remote origin "refs/heads/${SOURCE_BRANCH}" | cut -f1)
echo "target=${TARGET_SHA}" >> "$GITHUB_OUTPUT"
env:
SOURCE_BRANCH: ${{ steps.branches.outputs.source }}
- name: Push target branch
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
run: git push origin "${TARGET_SHA}:refs/heads/${TARGET_BRANCH}" --force
env:
TARGET_SHA: ${{ steps.sha.outputs.target }}
TARGET_BRANCH: ${{ steps.branches.outputs.target }}

View File

@ -3,6 +3,7 @@ name: CI
on: on:
push: push:
branches: branches:
- main
- master - master
pull_request: pull_request:
merge_group: merge_group:
@ -32,7 +33,7 @@ jobs:
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: false core: false
cask: false cask: false
@ -80,11 +81,11 @@ jobs:
name: tap syntax name: tap syntax
needs: syntax needs: syntax
if: github.repository_owner == 'Homebrew' if: github.repository_owner == 'Homebrew'
runs-on: macos-14 runs-on: macos-15
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: true core: true
cask: true cask: true
@ -135,13 +136,13 @@ jobs:
if: github.repository_owner == 'Homebrew' && github.event_name != 'push' if: github.repository_owner == 'Homebrew' && github.event_name != 'push'
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: ghcr.io/homebrew/brew:master image: ghcr.io/homebrew/brew:main
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: true core: false
cask: false cask: false
test-bot: false test-bot: false
@ -162,7 +163,7 @@ jobs:
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: true core: true
cask: true cask: true
@ -185,14 +186,14 @@ jobs:
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: false core: false
cask: false cask: false
test-bot: false test-bot: false
- name: Configure Git user - name: Configure Git user
uses: Homebrew/actions/git-user-config@master uses: Homebrew/actions/git-user-config@main
with: with:
username: BrewTestBot username: BrewTestBot
@ -213,14 +214,14 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- name: update-test (Ubuntu) - name: update-test (Linux)
runs-on: ubuntu-latest runs-on: ubuntu-latest
- name: update-test (macOS) - name: update-test (macOS)
runs-on: macos-15 runs-on: macos-latest
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: false core: false
cask: false cask: false
@ -237,7 +238,6 @@ jobs:
name: ${{ matrix.name }} name: ${{ matrix.name }}
needs: syntax needs: syntax
runs-on: ${{ matrix.runs-on }} runs-on: ${{ matrix.runs-on }}
container: ${{ matrix.container }}
strategy: strategy:
matrix: matrix:
include: include:
@ -247,23 +247,16 @@ jobs:
- name: tests (generic OS) - name: tests (generic OS)
test-flags: --generic --coverage test-flags: --generic --coverage
runs-on: ubuntu-latest runs-on: ubuntu-latest
- name: tests (Ubuntu 24.04) - name: tests (Linux)
test-flags: --coverage test-flags: --coverage
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
- name: tests (Ubuntu 22.04) - name: tests (macOS)
test-flags: --coverage
runs-on: ubuntu-22.04
- name: tests (Ubuntu 20.04)
test-flags: --coverage
runs-on: ubuntu-latest
container: ghcr.io/homebrew/ubuntu20.04:latest
- name: tests (macOS 15 arm64)
test-flags: --coverage test-flags: --coverage
runs-on: macos-15 runs-on: macos-15
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
# We only test needs_homebrew_core tests on macOS because # We only test needs_homebrew_core tests on macOS because
# homebrew/core is not available by default on GitHub-hosted Ubuntu # homebrew/core is not available by default on GitHub-hosted Ubuntu
@ -349,7 +342,7 @@ jobs:
disable_search: true disable_search: true
token: ${{ secrets.CODECOV_TOKEN }} token: ${{ secrets.CODECOV_TOKEN }}
test-default-formula: test-bot:
name: ${{ matrix.name }} name: ${{ matrix.name }}
needs: syntax needs: syntax
if: github.repository_owner == 'Homebrew' && github.event_name != 'push' if: github.repository_owner == 'Homebrew' && github.event_name != 'push'
@ -358,36 +351,76 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- name: test default formula (Ubuntu 24.04) - name: test-bot (Linux arm64)
runs-on: ubuntu-latest runs-on: ubuntu-24.04-arm
container: ghcr.io/homebrew/ubuntu24.04:latest container: ghcr.io/homebrew/ubuntu24.04:latest
- name: test default formula (Ubuntu 22.04) - name: test-bot (Linux x86_64)
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: ghcr.io/homebrew/ubuntu22.04:master container: ghcr.io/homebrew/ubuntu22.04:main
- name: test default formula (Ubuntu 20.04) # Use Debian Old Stable for testing Homebrew's glibc support.
- name: test-bot (Linux Homebrew glibc)
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: ghcr.io/homebrew/ubuntu20.04:latest container: debian:oldstable
- name: test default formula (macOS 13 x86_64) - name: test-bot (macOS x86_64)
runs-on: macos-13 runs-on: macos-13
- name: test default formula (macOS 15 arm64) - name: test-bot (macOS arm64)
runs-on: macos-15 runs-on: macos-15
env: env:
HOMEBREW_TEST_BOT_ANALYTICS: 1 HOMEBREW_TEST_BOT_ANALYTICS: 1
HOMEBREW_ENFORCE_SBOM: 1 HOMEBREW_ENFORCE_SBOM: 1
steps: steps:
- name: Install Homebrew and Homebrew's dependencies
# All other images are built from our Homebrew Dockerfile.
# This is the only one that needs to be set up manually.
if: matrix.container == 'debian:oldstable'
run: |
# Slimmed down version from the Homebrew Dockerfile
apt-get update
apt-get install -y --no-install-recommends \
bzip2 \
ca-certificates \
curl \
file \
g++ \
git-core \
less \
locales \
make \
netbase \
patch \
procps \
sudo \
uuid-runtime \
tzdata
# Install Homebrew
mkdir -p /home/linuxbrew/.linuxbrew/bin
# Don't do shallow clone or it's unshallowed by "Set up Homebrew"
git clone https://github.com/Homebrew/brew.git /home/linuxbrew/.linuxbrew/Homebrew
cd /home/linuxbrew/.linuxbrew/bin
ln -s ../Homebrew/bin/brew brew
echo "/home/linuxbrew/.linuxbrew/bin" >>"$GITHUB_PATH"
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: true core: false
cask: false cask: false
test-bot: true test-bot: true
- run: brew test-bot --only-cleanup-before - run: brew test-bot --only-cleanup-before
- name: Setup environment variables - name: Setup environment variables
if: matrix.container == 'ghcr.io/homebrew/ubuntu20.04:latest' run: |
run: echo "HOMEBREW_GLIBC_TESTING=1" >> "$GITHUB_ENV" # Set enviroment variables to bypass `brew doctor` failures on Tier >=2 configurations
if [[ "${MATRIX_NAME}" == "test-bot (Linux arm64)" ]]; then
echo "HOMEBREW_ARM64_TESTING=1" >> "$GITHUB_ENV"
elif [[ "${MATRIX_NAME}" == "test-bot (Linux Homebrew glibc)" ]]; then
echo "HOMEBREW_GLIBC_TESTING=1" >> "$GITHUB_ENV"
fi
env:
MATRIX_NAME: ${{ matrix.name }}
- run: brew test-bot --only-setup - run: brew test-bot --only-setup
@ -395,7 +428,7 @@ jobs:
- run: brew test-bot --only-formulae --only-json-tab --test-default-formula - run: brew test-bot --only-formulae --only-json-tab --test-default-formula
test-brew-bundle-services: bundle-and-services:
name: ${{ matrix.name }} name: ${{ matrix.name }}
needs: syntax needs: syntax
if: github.repository_owner == 'Homebrew' && github.event_name != 'push' if: github.repository_owner == 'Homebrew' && github.event_name != 'push'
@ -403,16 +436,16 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- name: test brew bundle and brew services (Ubuntu) - name: bundle and services (Linux)
runs-on: ubuntu-latest runs-on: ubuntu-latest
- name: test brew bundle and brew services (macOS) - name: bundle and services (macOS)
runs-on: macos-15 runs-on: macos-latest
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: true core: false
cask: false cask: false
test-bot: false test-bot: false
@ -449,19 +482,22 @@ jobs:
brew services cleanup brew services cleanup
brew bundle cleanup --force brew bundle cleanup --force
test-analytics: analytics:
runs-on: ${{ matrix.os }} name: ${{ matrix.name }}
runs-on: ${{ matrix.runs-on }}
strategy: strategy:
matrix: matrix:
os: include:
- ubuntu-latest - name: analytics (Linux)
- macos-latest runs-on: ubuntu-latest
- name: analytics (macOS)
runs-on: macos-latest
needs: syntax needs: syntax
if: github.repository_owner == 'Homebrew' && github.event_name != 'push' if: github.repository_owner == 'Homebrew' && github.event_name != 'push'
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
- name: Setup Python - name: Setup Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0

View File

@ -9,6 +9,7 @@ on:
paths: paths:
- .github/workflows/vendor-gems.yml - .github/workflows/vendor-gems.yml
branches-ignore: branches-ignore:
- main
- master - master
workflow_dispatch: workflow_dispatch:
inputs: inputs:
@ -31,7 +32,7 @@ jobs:
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: false core: false
cask: false cask: false
@ -39,13 +40,13 @@ jobs:
- name: Configure Git user - name: Configure Git user
if: github.event_name == 'workflow_dispatch' if: github.event_name == 'workflow_dispatch'
uses: Homebrew/actions/git-user-config@master uses: Homebrew/actions/git-user-config@main
with: with:
username: BrewTestBot username: BrewTestBot
- name: Set up commit signing - name: Set up commit signing
if: github.event_name == 'workflow_dispatch' if: github.event_name == 'workflow_dispatch'
uses: Homebrew/actions/setup-commit-signing@master uses: Homebrew/actions/setup-commit-signing@main
with: with:
signing_key: ${{ secrets.BREWTESTBOT_SSH_SIGNING_KEY }} signing_key: ${{ secrets.BREWTESTBOT_SSH_SIGNING_KEY }}
@ -100,7 +101,7 @@ jobs:
- name: Push to pull request - name: Push to pull request
if: github.event_name == 'workflow_dispatch' if: github.event_name == 'workflow_dispatch'
uses: Homebrew/actions/git-try-push@master uses: Homebrew/actions/git-try-push@main
with: with:
token: ${{ steps.app-token.outputs.token }} token: ${{ steps.app-token.outputs.token }}
directory: ${{ steps.set-up-homebrew.outputs.repository-path }} directory: ${{ steps.set-up-homebrew.outputs.repository-path }}

View File

@ -19,7 +19,7 @@ jobs:
steps: steps:
- name: Set up Homebrew - name: Set up Homebrew
id: set-up-homebrew id: set-up-homebrew
uses: Homebrew/actions/setup-homebrew@master uses: Homebrew/actions/setup-homebrew@main
with: with:
core: false core: false
cask: false cask: false

1
.github/zizmor.yml vendored
View File

@ -1,3 +1,4 @@
# This file is synced from the `.github` repository, do not modify it directly.
rules: rules:
unpinned-uses: unpinned-uses:
config: config:

1
.gitignore vendored
View File

@ -164,6 +164,7 @@
!/completions !/completions
!/docs !/docs
!/manpages !/manpages
!/CODEOWNERS
# Unignore our packaging files # Unignore our packaging files
!/package !/package

11
.vscode/mcp.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"servers": {
"Homebrew": {
"type": "stdio",
"command": "brew",
"args": [
"mcp-server"
]
}
}
}

View File

@ -1,5 +1,12 @@
#!/bin/bash #!/bin/bash
HOMEBREW_PREFIX="$(cd "$(dirname "$0")"/../ && pwd)" if [[ -n "${BASH_SOURCE[0]}" ]]; then
SCRIPT_PATH="${BASH_SOURCE[0]}"
elif [[ -n "${ZSH_VERSION}" ]]; then
SCRIPT_PATH="${(%):-%x}"
else
SCRIPT_PATH="$0"
fi
HOMEBREW_PREFIX="$(cd "$(dirname "${SCRIPT_PATH}")"/../ && pwd)"
"${HOMEBREW_PREFIX}/bin/brew" install-bundler-gems --add-groups=style,typecheck,vscode >/dev/null 2>&1 "${HOMEBREW_PREFIX}/bin/brew" install-bundler-gems --add-groups=style,typecheck,vscode >/dev/null 2>&1

View File

@ -40,7 +40,6 @@
"id": "default", "id": "default",
"name": "Brew Typecheck", "name": "Brew Typecheck",
"description": "Default configuration", "description": "Default configuration",
"cwd": "${workspaceFolder}",
"command": [ "command": [
"./bin/brew", "./bin/brew",
"typecheck", "typecheck",

11
CODEOWNERS Normal file
View File

@ -0,0 +1,11 @@
# Note that the naming of this file is incorrect for our case: these people do not "own" the provided files but are
# people with write-access to this repository who wish to approve changes to these files.
#
# Their review is required to merge PRs that change these files.
#
# To be explicit: we will never accept changes to this file adding people from outside the Homebrew GitHub
# organisation. If you are not a Homebrew maintainer: you do not personally "own" or "maintain" any files.
#
# Note: @Homebrew/plc does not have write-access to this repository, and therefore cannot be listed in this file.
docs/Support-Tiers.md @Homebrew/tsc @MikeMcQuaid

View File

@ -304,7 +304,7 @@ Sorbet/StrictSigil:
- "Homebrew/utils/ruby_check_version_script.rb" # A standalone script. - "Homebrew/utils/ruby_check_version_script.rb" # A standalone script.
- "Homebrew/{standalone,startup}/*.rb" # These are loaded before sorbet-runtime - "Homebrew/{standalone,startup}/*.rb" # These are loaded before sorbet-runtime
- "Homebrew/test/**/*.rb" - "Homebrew/test/**/*.rb"
- "Homebrew/bundle/{brew_dumper,checker,commands/exec}.rb" # These aren't typed: true yet. - "Homebrew/bundle/{formula_dumper,checker,commands/exec}.rb" # These aren't typed: true yet.
Sorbet/TrueSigil: Sorbet/TrueSigil:
Enabled: true Enabled: true

View File

@ -25,6 +25,7 @@ Style/Documentation:
- Homebrew - Homebrew
Include: Include:
- abstract_command.rb - abstract_command.rb
- autobump_constants.rb
- cask/cask.rb - cask/cask.rb
- cask/dsl.rb - cask/dsl.rb
- cask/dsl/version.rb - cask/dsl/version.rb

View File

@ -39,12 +39,12 @@ class PATH
self self
end end
sig { params(block: T.proc.params(arg0: String).returns(T::Boolean)).returns(T.self_type) } sig { params(block: T.proc.params(arg0: String).returns(BasicObject)).returns(T.self_type) }
def select(&block) def select(&block)
self.class.new(@paths.select(&block)) self.class.new(@paths.select(&block))
end end
sig { params(block: T.proc.params(arg0: String).returns(T::Boolean)).returns(T.self_type) } sig { params(block: T.proc.params(arg0: String).returns(BasicObject)).returns(T.self_type) }
def reject(&block) def reject(&block)
self.class.new(@paths.reject(&block)) self.class.new(@paths.reject(&block))
end end

View File

@ -29,36 +29,36 @@ module Homebrew
Alias.new(name).remove Alias.new(name).remove
end end
sig { params(only: T::Array[String], block: T.proc.params(target: String, cmd: String).void).void } sig { params(only: T::Array[String], block: T.proc.params(name: String, command: String).void).void }
def self.each(only, &block) def self.each(only, &block)
Dir["#{HOMEBREW_ALIASES}/*"].each do |path| Dir["#{HOMEBREW_ALIASES}/*"].each do |path|
next if path.end_with? "~" # skip Emacs-like backup files next if path.end_with? "~" # skip Emacs-like backup files
next if File.directory?(path) next if File.directory?(path)
_shebang, _meta, *lines = File.readlines(path) _shebang, meta, *lines = File.readlines(path)
target = File.basename(path) name = T.must(meta)[/alias: brew (\S+)/, 1] || File.basename(path)
next if !only.empty? && only.exclude?(target) next if !only.empty? && only.exclude?(name)
lines.reject! { |line| line.start_with?("#") || line =~ /^\s*$/ } lines.reject! { |line| line.start_with?("#") || line =~ /^\s*$/ }
first_line = T.must(lines.first) first_line = T.must(lines.first)
cmd = first_line.chomp command = first_line.chomp
cmd.sub!(/ \$\*$/, "") command.sub!(/ \$\*$/, "")
if cmd.start_with? "brew " if command.start_with? "brew "
cmd.sub!(/^brew /, "") command.sub!(/^brew /, "")
else else
cmd = "!#{cmd}" command = "!#{command}"
end end
yield target, cmd if block.present? yield name, command if block.present?
end end
end end
sig { params(aliases: String).void } sig { params(aliases: String).void }
def self.show(*aliases) def self.show(*aliases)
each([*aliases]) do |target, cmd| each([*aliases]) do |name, command|
puts "brew alias #{target}='#{cmd}'" puts "brew alias #{name}='#{command}'"
existing_alias = Alias.new(target, cmd) existing_alias = Alias.new(name, command)
existing_alias.link unless existing_alias.symlink.exist? existing_alias.link unless existing_alias.symlink.exist?
end end
end end

View File

@ -1,4 +1,4 @@
# typed: true # rubocop:todo Sorbet/StrictSigil # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "api/analytics" require "api/analytics"
@ -11,10 +11,10 @@ module Homebrew
module API module API
extend Cachable extend Cachable
HOMEBREW_CACHE_API = (HOMEBREW_CACHE/"api").freeze HOMEBREW_CACHE_API = T.let((HOMEBREW_CACHE/"api").freeze, Pathname)
HOMEBREW_CACHE_API_SOURCE = (HOMEBREW_CACHE/"api-source").freeze HOMEBREW_CACHE_API_SOURCE = T.let((HOMEBREW_CACHE/"api-source").freeze, Pathname)
sig { params(endpoint: String).returns(Hash) } sig { params(endpoint: String).returns(T::Hash[String, T.untyped]) }
def self.fetch(endpoint) def self.fetch(endpoint)
return cache[endpoint] if cache.present? && cache.key?(endpoint) return cache[endpoint] if cache.present? && cache.key?(endpoint)
@ -33,7 +33,8 @@ module Homebrew
end end
sig { sig {
params(endpoint: String, target: Pathname, stale_seconds: Integer).returns([T.any(Array, Hash), T::Boolean]) params(endpoint: String, target: Pathname,
stale_seconds: Integer).returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
} }
def self.fetch_json_api_file(endpoint, target: HOMEBREW_CACHE_API/endpoint, def self.fetch_json_api_file(endpoint, target: HOMEBREW_CACHE_API/endpoint,
stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i) stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i)
@ -96,7 +97,8 @@ module Homebrew
mtime = insecure_download ? Time.new(1970, 1, 1) : Time.now mtime = insecure_download ? Time.new(1970, 1, 1) : Time.now
FileUtils.touch(target, mtime:) unless skip_download FileUtils.touch(target, mtime:) unless skip_download
JSON.parse(target.read(encoding: Encoding::UTF_8), freeze: true) # Can use `target.read` again when/if https://github.com/sorbet/sorbet/pull/8999 is merged/released.
JSON.parse(File.read(target, encoding: Encoding::UTF_8), freeze: true)
rescue JSON::ParserError rescue JSON::ParserError
target.unlink target.unlink
retry_count += 1 retry_count += 1
@ -122,14 +124,17 @@ module Homebrew
end end
end end
sig { params(json: Hash).returns(Hash) } sig {
def self.merge_variations(json) params(json: T::Hash[String, T.untyped],
bottle_tag: ::Utils::Bottles::Tag).returns(T::Hash[String, T.untyped])
}
def self.merge_variations(json, bottle_tag: T.unsafe(nil))
return json unless json.key?("variations") return json unless json.key?("variations")
bottle_tag = ::Utils::Bottles::Tag.new(system: Homebrew::SimulateSystem.current_os, bottle_tag ||= Homebrew::SimulateSystem.current_tag
arch: Homebrew::SimulateSystem.current_arch)
if (variation = json.dig("variations", bottle_tag.to_s).presence) if (variation = json.dig("variations", bottle_tag.to_s).presence) ||
(variation = json.dig("variations", bottle_tag.to_sym).presence)
json = json.merge(variation) json = json.merge(variation)
end end
@ -147,7 +152,10 @@ module Homebrew
false false
end end
sig { params(json_data: Hash).returns([T::Boolean, T.any(String, Array, Hash)]) } sig {
params(json_data: T::Hash[String, T.untyped])
.returns([T::Boolean, T.any(String, T::Array[T.untyped], T::Hash[String, T.untyped])])
}
private_class_method def self.verify_and_parse_jws(json_data) private_class_method def self.verify_and_parse_jws(json_data)
signatures = json_data["signatures"] signatures = json_data["signatures"]
homebrew_signature = signatures&.find { |sig| sig.dig("header", "kid") == "homebrew-1" } homebrew_signature = signatures&.find { |sig| sig.dig("header", "kid") == "homebrew-1" }

View File

@ -10,7 +10,6 @@ module Homebrew
def analytics_api_path def analytics_api_path
"analytics" "analytics"
end end
alias generic_analytics_api_path analytics_api_path
sig { params(category: String, days: T.any(Integer, String)).returns(T::Hash[String, T.untyped]) } sig { params(category: String, days: T.any(Integer, String)).returns(T::Hash[String, T.untyped]) }
def fetch(category, days) def fetch(category, days)

View File

@ -1,7 +1,7 @@
# typed: true # rubocop:todo Sorbet/StrictSigil # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "extend/cachable" require "cachable"
require "api/download" require "api/download"
module Homebrew module Homebrew
@ -12,9 +12,16 @@ module Homebrew
DEFAULT_API_FILENAME = "cask.jws.json" DEFAULT_API_FILENAME = "cask.jws.json"
sig { returns(String) }
def self.api_filename
return DEFAULT_API_FILENAME unless ENV.fetch("HOMEBREW_USE_INTERNAL_API", false)
"cask.#{SimulateSystem.current_tag}.jws.json"
end
private_class_method :cache private_class_method :cache
sig { params(token: String).returns(Hash) } sig { params(token: String).returns(T::Hash[String, T.untyped]) }
def self.fetch(token) def self.fetch(token)
Homebrew::API.fetch "cask/#{token}.json" Homebrew::API.fetch "cask/#{token}.json"
end end
@ -40,13 +47,14 @@ module Homebrew
.load(config: cask.config) .load(config: cask.config)
end end
sig { returns(Pathname) }
def self.cached_json_file_path def self.cached_json_file_path
HOMEBREW_CACHE_API/DEFAULT_API_FILENAME HOMEBREW_CACHE_API/api_filename
end end
sig { returns(T::Boolean) } sig { returns(T::Boolean) }
def self.download_and_cache_data! def self.download_and_cache_data!
json_casks, updated = Homebrew::API.fetch_json_api_file DEFAULT_API_FILENAME json_casks, updated = Homebrew::API.fetch_json_api_file api_filename
cache["renames"] = {} cache["renames"] = {}
cache["casks"] = json_casks.to_h do |json_cask| cache["casks"] = json_casks.to_h do |json_cask|
@ -63,7 +71,7 @@ module Homebrew
end end
private_class_method :download_and_cache_data! private_class_method :download_and_cache_data!
sig { returns(T::Hash[String, Hash]) } sig { returns(T::Hash[String, T::Hash[String, T.untyped]]) }
def self.all_casks def self.all_casks
unless cache.key?("casks") unless cache.key?("casks")
json_updated = download_and_cache_data! json_updated = download_and_cache_data!

View File

@ -1,7 +1,7 @@
# typed: strict # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "extend/cachable" require "cachable"
require "api/download" require "api/download"
module Homebrew module Homebrew
@ -12,6 +12,13 @@ module Homebrew
DEFAULT_API_FILENAME = "formula.jws.json" DEFAULT_API_FILENAME = "formula.jws.json"
sig { returns(String) }
def self.api_filename
return DEFAULT_API_FILENAME unless ENV.fetch("HOMEBREW_USE_INTERNAL_API", false)
"internal/formula.#{SimulateSystem.current_tag}.jws.json"
end
private_class_method :cache private_class_method :cache
sig { params(name: String).returns(T::Hash[String, T.untyped]) } sig { params(name: String).returns(T::Hash[String, T.untyped]) }
@ -42,12 +49,12 @@ module Homebrew
sig { returns(Pathname) } sig { returns(Pathname) }
def self.cached_json_file_path def self.cached_json_file_path
HOMEBREW_CACHE_API/DEFAULT_API_FILENAME HOMEBREW_CACHE_API/api_filename
end end
sig { returns(T::Boolean) } sig { returns(T::Boolean) }
def self.download_and_cache_data! def self.download_and_cache_data!
json_formulae, updated = Homebrew::API.fetch_json_api_file DEFAULT_API_FILENAME json_formulae, updated = Homebrew::API.fetch_json_api_file api_filename
cache["aliases"] = {} cache["aliases"] = {}
cache["renames"] = {} cache["renames"] = {}

View File

@ -1,22 +1,26 @@
# typed: true # rubocop:todo Sorbet/StrictSigil # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
# Used to substitute common paths with generic placeholders when generating JSON for the API. # Used to substitute common paths with generic placeholders when generating JSON for the API.
module APIHashable module APIHashable
sig { void }
def generating_hash! def generating_hash!
return if generating_hash? return if generating_hash?
# Apply monkeypatches for API generation # Apply monkeypatches for API generation
@old_homebrew_prefix = HOMEBREW_PREFIX @old_homebrew_prefix = T.let(HOMEBREW_PREFIX, T.nilable(Pathname))
@old_homebrew_cellar = HOMEBREW_CELLAR @old_homebrew_cellar = T.let(HOMEBREW_CELLAR, T.nilable(Pathname))
@old_home = Dir.home @old_home = T.let(Dir.home, T.nilable(String))
@old_git_config_global = T.let(ENV.fetch("GIT_CONFIG_GLOBAL", nil), T.nilable(String))
Object.send(:remove_const, :HOMEBREW_PREFIX) Object.send(:remove_const, :HOMEBREW_PREFIX)
Object.const_set(:HOMEBREW_PREFIX, Pathname.new(HOMEBREW_PREFIX_PLACEHOLDER)) Object.const_set(:HOMEBREW_PREFIX, Pathname.new(HOMEBREW_PREFIX_PLACEHOLDER))
ENV["HOME"] = HOMEBREW_HOME_PLACEHOLDER ENV["HOME"] = HOMEBREW_HOME_PLACEHOLDER
ENV["GIT_CONFIG_GLOBAL"] = File.join(@old_home, ".gitconfig")
@generating_hash = true @generating_hash = T.let(true, T.nilable(T::Boolean))
end end
sig { void }
def generated_hash! def generated_hash!
return unless generating_hash? return unless generating_hash?
@ -24,10 +28,12 @@ module APIHashable
Object.send(:remove_const, :HOMEBREW_PREFIX) Object.send(:remove_const, :HOMEBREW_PREFIX)
Object.const_set(:HOMEBREW_PREFIX, @old_homebrew_prefix) Object.const_set(:HOMEBREW_PREFIX, @old_homebrew_prefix)
ENV["HOME"] = @old_home ENV["HOME"] = @old_home
ENV["GIT_CONFIG_GLOBAL"] = @old_git_config_global
@generating_hash = false @generating_hash = false
end end
sig { returns(T::Boolean) }
def generating_hash? def generating_hash?
@generating_hash ||= false @generating_hash ||= false
@generating_hash == true @generating_hash == true

View File

@ -52,4 +52,4 @@ FORMULA_COMPONENT_PRECEDENCE_LIST = T.let([
[{ name: :caveats, type: :method_definition }], [{ name: :caveats, type: :method_definition }],
[{ name: :plist_options, type: :method_call }, { name: :plist, type: :method_definition }], [{ name: :plist_options, type: :method_call }, { name: :plist, type: :method_definition }],
[{ name: :test, type: :block_call }], [{ name: :test, type: :block_call }],
].freeze, T::Array[[{ name: Symbol, type: Symbol }]]) ].freeze, T::Array[T::Array[{ name: Symbol, type: Symbol }]])

View File

@ -64,12 +64,8 @@ module Homebrew
sig { returns(T::Boolean) } sig { returns(T::Boolean) }
def self.enabled? def self.enabled?
return false if Homebrew::EnvConfig.no_verify_attestations? return false if Homebrew::EnvConfig.no_verify_attestations?
return true if Homebrew::EnvConfig.verify_attestations?
return false if ENV.fetch("CI", false)
return false if OS.not_tier_one_configuration?
# Always check credentials last to avoid unnecessary credential extraction. Homebrew::EnvConfig.verify_attestations?
(Homebrew::EnvConfig.developer? || Homebrew::EnvConfig.devcmdrun?) && GitHub::API.credentials.present?
end end
# Returns a path to a suitable `gh` executable for attestation verification. # Returns a path to a suitable `gh` executable for attestation verification.

View File

@ -1,10 +1,15 @@
# typed: strict # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
# TODO: add more reasons here NO_AUTOBUMP_REASONS_INTERNAL = T.let({
extract_plist: "livecheck uses `:extract_plist` strategy",
latest_version: "`version` is set to `:latest`",
}.freeze, T::Hash[Symbol, String])
# The valid symbols for passing to `no_autobump!` in a `Formula` or `Cask`.
# @api public
NO_AUTOBUMP_REASONS_LIST = T.let({ NO_AUTOBUMP_REASONS_LIST = T.let({
incompatible_version_format: "incompatible version format", incompatible_version_format: "incompatible version format",
bumped_by_upstream: "bumped by upstream", bumped_by_upstream: "bumped by upstream",
extract_plist: "livecheck uses `:extract_plist` strategy", requires_manual_review: "a manual review of this package is required for inclusion in autobump",
latest_version: "`version` is set to `:latest`", }.merge(NO_AUTOBUMP_REASONS_INTERNAL).freeze, T::Hash[Symbol, String])
}.freeze, T::Hash[Symbol, String])

View File

@ -531,9 +531,9 @@ GIT_REVISION=$("${HOMEBREW_GIT}" -C "${HOMEBREW_REPOSITORY}" rev-parse HEAD 2>/d
if [[ -z "${GIT_REVISION}" ]] if [[ -z "${GIT_REVISION}" ]]
then then
read -r GIT_HEAD 2>/dev/null <"${HOMEBREW_REPOSITORY}/.git/HEAD" read -r GIT_HEAD 2>/dev/null <"${HOMEBREW_REPOSITORY}/.git/HEAD"
if [[ "${GIT_HEAD}" == "ref: refs/heads/master" ]] if [[ "${GIT_HEAD}" == "ref: refs/heads/main" ]]
then then
read -r GIT_REVISION 2>/dev/null <"${HOMEBREW_REPOSITORY}/.git/refs/heads/master" read -r GIT_REVISION 2>/dev/null <"${HOMEBREW_REPOSITORY}/.git/refs/heads/main"
elif [[ "${GIT_HEAD}" == "ref: refs/heads/stable" ]] elif [[ "${GIT_HEAD}" == "ref: refs/heads/stable" ]]
then then
read -r GIT_REVISION 2>/dev/null <"${HOMEBREW_REPOSITORY}/.git/refs/heads/stable" read -r GIT_REVISION 2>/dev/null <"${HOMEBREW_REPOSITORY}/.git/refs/heads/stable"
@ -600,6 +600,11 @@ case "$1" in
homebrew-version homebrew-version
exit 0 exit 0
;; ;;
mcp-server)
source "${HOMEBREW_LIBRARY}/Homebrew/cmd/mcp-server.sh"
homebrew-mcp-server "$@"
exit 0
;;
esac esac
# TODO: bump version when new macOS is released or announced and update references in: # TODO: bump version when new macOS is released or announced and update references in:
@ -609,6 +614,8 @@ esac
# and, if needed: # and, if needed:
# - MacOSVersion::SYMBOLS # - MacOSVersion::SYMBOLS
HOMEBREW_MACOS_NEWEST_UNSUPPORTED="16" HOMEBREW_MACOS_NEWEST_UNSUPPORTED="16"
# TODO: bump version when new macOS is released
HOMEBREW_MACOS_NEWEST_SUPPORTED="15"
# TODO: bump version when new macOS is released and update references in: # TODO: bump version when new macOS is released and update references in:
# - docs/Installation.md # - docs/Installation.md
# - HOMEBREW_MACOS_OLDEST_SUPPORTED in .github/workflows/pkg-installer.yml # - HOMEBREW_MACOS_OLDEST_SUPPORTED in .github/workflows/pkg-installer.yml
@ -836,6 +843,7 @@ export HOMEBREW_OS_VERSION
export HOMEBREW_MACOS_VERSION export HOMEBREW_MACOS_VERSION
export HOMEBREW_MACOS_VERSION_NUMERIC export HOMEBREW_MACOS_VERSION_NUMERIC
export HOMEBREW_MACOS_NEWEST_UNSUPPORTED export HOMEBREW_MACOS_NEWEST_UNSUPPORTED
export HOMEBREW_MACOS_NEWEST_SUPPORTED
export HOMEBREW_MACOS_OLDEST_SUPPORTED export HOMEBREW_MACOS_OLDEST_SUPPORTED
export HOMEBREW_MACOS_OLDEST_ALLOWED export HOMEBREW_MACOS_OLDEST_ALLOWED
export HOMEBREW_USER_AGENT export HOMEBREW_USER_AGENT
@ -1078,6 +1086,22 @@ else
export HOMEBREW_GITHUB_PACKAGES_AUTH="Bearer QQ==" export HOMEBREW_GITHUB_PACKAGES_AUTH="Bearer QQ=="
fi fi
# Avoid picking up any random `sudo` in `PATH`.
if [[ -x /usr/bin/sudo ]]
then
SUDO=/usr/bin/sudo
else
# Do this after ensuring we're using default Bash builtins.
SUDO="$(command -v sudo 2>/dev/null)"
fi
# Reset sudo timestamp to avoid running unauthorized sudo commands
if [[ -n "${SUDO}" ]]
then
"${SUDO}" --reset-timestamp 2>/dev/null || true
fi
unset SUDO
if [[ -n "${HOMEBREW_BASH_COMMAND}" ]] if [[ -n "${HOMEBREW_BASH_COMMAND}" ]]
then then
# source rather than executing directly to ensure the entire file is read into # source rather than executing directly to ensure the entire file is read into

View File

@ -130,6 +130,9 @@ module Homebrew
@formula_versions_from_env[formula_env_name] @formula_versions_from_env[formula_env_name]
end end
sig { void }
def prepend_pkgconf_path_if_needed!; end
sig { void } sig { void }
def reset! def reset!
@mas_installed = T.let(nil, T.nilable(T::Boolean)) @mas_installed = T.let(nil, T.nilable(T::Boolean))

View File

@ -1,7 +1,7 @@
# typed: true # rubocop:todo Sorbet/StrictSigil # typed: true # rubocop:todo Sorbet/StrictSigil
# frozen_string_literal: true # frozen_string_literal: true
require "bundle/brew_installer" require "bundle/formula_installer"
module Homebrew module Homebrew
module Bundle module Bundle
@ -11,7 +11,7 @@ module Homebrew
PACKAGE_TYPE_NAME = "Formula" PACKAGE_TYPE_NAME = "Formula"
def installed_and_up_to_date?(formula, no_upgrade: false) def installed_and_up_to_date?(formula, no_upgrade: false)
Homebrew::Bundle::BrewInstaller.formula_installed_and_up_to_date?(formula, no_upgrade:) Homebrew::Bundle::FormulaInstaller.formula_installed_and_up_to_date?(formula, no_upgrade:)
end end
end end
end end

View File

@ -24,8 +24,8 @@ module Homebrew
end end
def entry_to_formula(entry) def entry_to_formula(entry)
require "bundle/brew_installer" require "bundle/formula_installer"
Homebrew::Bundle::BrewInstaller.new(entry.name, entry.options) Homebrew::Bundle::FormulaInstaller.new(entry.name, entry.options)
end end
def formula_needs_to_start?(formula) def formula_needs_to_start?(formula)
@ -38,8 +38,8 @@ module Homebrew
end end
def lookup_old_name(service_name) def lookup_old_name(service_name)
require "bundle/brew_dumper" require "bundle/formula_dumper"
@old_names ||= Homebrew::Bundle::BrewDumper.formula_oldnames @old_names ||= Homebrew::Bundle::FormulaDumper.formula_oldnames
old_name = @old_names[service_name] old_name = @old_names[service_name]
old_name ||= @old_names[service_name.split("/").last] old_name ||= @old_names[service_name.split("/").last]
old_name old_name

View File

@ -8,6 +8,7 @@ module Homebrew
@casks = nil @casks = nil
@cask_names = nil @cask_names = nil
@cask_hash = nil @cask_hash = nil
@cask_oldnames = nil
end end
def self.cask_names def self.cask_names
@ -38,6 +39,25 @@ module Homebrew
end.join("\n") end.join("\n")
end end
def self.cask_oldnames
return @cask_oldnames if @cask_oldnames
@cask_oldnames = {}
casks.each do |c|
oldnames = c.old_tokens
next if oldnames.blank?
oldnames.each do |oldname|
@cask_oldnames[oldname] = c.full_name
if c.full_name.include? "/" # tap cask
tap_name = c.full_name.rpartition("/").first
@cask_oldnames["#{tap_name}/#{oldname}"] = c.full_name
end
end
end
@cask_oldnames
end
def self.formula_dependencies(cask_list) def self.formula_dependencies(cask_list)
return [] unless Bundle.cask_installed? return [] unless Bundle.cask_installed?
return [] if cask_list.blank? return [] if cask_list.blank?

View File

@ -87,12 +87,25 @@ module Homebrew
!cask_upgradable?(cask) !cask_upgradable?(cask)
end end
def self.cask_in_array?(cask, array)
return true if array.include?(cask)
return true if array.include?(cask.split("/").last)
require "bundle/cask_dumper"
old_names = Homebrew::Bundle::CaskDumper.cask_oldnames
old_name = old_names[cask]
old_name ||= old_names[cask.split("/").last]
return true if old_name && array.include?(old_name)
false
end
def self.cask_installed?(cask) def self.cask_installed?(cask)
installed_casks.include? cask cask_in_array?(cask, installed_casks)
end end
def self.cask_upgradable?(cask) def self.cask_upgradable?(cask)
outdated_casks.include? cask cask_in_array?(cask, outdated_casks)
end end
def self.installed_casks def self.installed_casks

View File

@ -1,4 +1,4 @@
# typed: false # rubocop:todo Sorbet/TrueSigil # typed: true
# frozen_string_literal: true # frozen_string_literal: true
module Homebrew module Homebrew
@ -23,7 +23,7 @@ module Homebrew
else else
"needs to be installed or updated." "needs to be installed or updated."
end end
"#{self.class::PACKAGE_TYPE_NAME} #{name} #{reason}" "#{self.class.const_get(:PACKAGE_TYPE_NAME)} #{name} #{reason}"
end end
def full_check(packages, no_upgrade:) def full_check(packages, no_upgrade:)
@ -33,7 +33,7 @@ module Homebrew
def checkable_entries(all_entries) def checkable_entries(all_entries)
require "bundle/skipper" require "bundle/skipper"
all_entries.select { |e| e.type == self.class::PACKAGE_TYPE } all_entries.select { |e| e.type == self.class.const_get(:PACKAGE_TYPE) }
.reject(&Bundle::Skipper.method(:skip?)) .reject(&Bundle::Skipper.method(:skip?))
end end
@ -139,14 +139,14 @@ module Homebrew
def self.reset! def self.reset!
require "bundle/cask_dumper" require "bundle/cask_dumper"
require "bundle/brew_dumper" require "bundle/formula_dumper"
require "bundle/mac_app_store_dumper" require "bundle/mac_app_store_dumper"
require "bundle/tap_dumper" require "bundle/tap_dumper"
require "bundle/brew_services" require "bundle/brew_services"
@dsl = nil @dsl = nil
Homebrew::Bundle::CaskDumper.reset! Homebrew::Bundle::CaskDumper.reset!
Homebrew::Bundle::BrewDumper.reset! Homebrew::Bundle::FormulaDumper.reset!
Homebrew::Bundle::MacAppStoreDumper.reset! Homebrew::Bundle::MacAppStoreDumper.reset!
Homebrew::Bundle::TapDumper.reset! Homebrew::Bundle::TapDumper.reset!
Homebrew::Bundle::BrewServices.reset! Homebrew::Bundle::BrewServices.reset!

View File

@ -1,4 +1,4 @@
# typed: true # rubocop:todo Sorbet/StrictSigil # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "bundle/adder" require "bundle/adder"
@ -7,6 +7,7 @@ module Homebrew
module Bundle module Bundle
module Commands module Commands
module Add module Add
sig { params(args: String, type: Symbol, global: T::Boolean, file: T.nilable(String)).void }
def self.run(*args, type:, global:, file:) def self.run(*args, type:, global:, file:)
Homebrew::Bundle::Adder.add(*args, type:, global:, file:) Homebrew::Bundle::Adder.add(*args, type:, global:, file:)
end end

View File

@ -10,7 +10,7 @@ module Homebrew
module Cleanup module Cleanup
def self.reset! def self.reset!
require "bundle/cask_dumper" require "bundle/cask_dumper"
require "bundle/brew_dumper" require "bundle/formula_dumper"
require "bundle/tap_dumper" require "bundle/tap_dumper"
require "bundle/vscode_extension_dumper" require "bundle/vscode_extension_dumper"
require "bundle/brew_services" require "bundle/brew_services"
@ -19,18 +19,18 @@ module Homebrew
@kept_casks = nil @kept_casks = nil
@kept_formulae = nil @kept_formulae = nil
Homebrew::Bundle::CaskDumper.reset! Homebrew::Bundle::CaskDumper.reset!
Homebrew::Bundle::BrewDumper.reset! Homebrew::Bundle::FormulaDumper.reset!
Homebrew::Bundle::TapDumper.reset! Homebrew::Bundle::TapDumper.reset!
Homebrew::Bundle::VscodeExtensionDumper.reset! Homebrew::Bundle::VscodeExtensionDumper.reset!
Homebrew::Bundle::BrewServices.reset! Homebrew::Bundle::BrewServices.reset!
end end
def self.run(global: false, file: nil, force: false, zap: false, dsl: nil, def self.run(global: false, file: nil, force: false, zap: false, dsl: nil,
brews: true, casks: true, taps: true, vscode: true) formulae: true, casks: true, taps: true, vscode: true)
@dsl ||= dsl @dsl ||= dsl
casks = casks ? casks_to_uninstall(global:, file:) : [] casks = casks ? casks_to_uninstall(global:, file:) : []
formulae = brews ? formulae_to_uninstall(global:, file:) : [] formulae = formulae ? formulae_to_uninstall(global:, file:) : []
taps = taps ? taps_to_untap(global:, file:) : [] taps = taps ? taps_to_untap(global:, file:) : []
vscode_extensions = vscode ? vscode_extensions_to_uninstall(global:, file:) : [] vscode_extensions = vscode ? vscode_extensions_to_uninstall(global:, file:) : []
if force if force
@ -101,11 +101,11 @@ module Homebrew
def self.formulae_to_uninstall(global: false, file: nil) def self.formulae_to_uninstall(global: false, file: nil)
kept_formulae = self.kept_formulae(global:, file:) kept_formulae = self.kept_formulae(global:, file:)
require "bundle/brew_dumper" require "bundle/formula_dumper"
require "bundle/brew_installer" require "bundle/formula_installer"
current_formulae = Homebrew::Bundle::BrewDumper.formulae current_formulae = Homebrew::Bundle::FormulaDumper.formulae
current_formulae.reject! do |f| current_formulae.reject! do |f|
Homebrew::Bundle::BrewInstaller.formula_in_array?(f[:full_name], kept_formulae) Homebrew::Bundle::FormulaInstaller.formula_in_array?(f[:full_name], kept_formulae)
end end
# Don't try to uninstall formulae with keepme references # Don't try to uninstall formulae with keepme references
@ -119,7 +119,7 @@ module Homebrew
private_class_method def self.kept_formulae(global: false, file: nil) private_class_method def self.kept_formulae(global: false, file: nil)
require "bundle/brewfile" require "bundle/brewfile"
require "bundle/brew_dumper" require "bundle/formula_dumper"
require "bundle/cask_dumper" require "bundle/cask_dumper"
@kept_formulae ||= begin @kept_formulae ||= begin
@ -128,12 +128,13 @@ module Homebrew
kept_formulae = @dsl.entries.select { |e| e.type == :brew }.map(&:name) kept_formulae = @dsl.entries.select { |e| e.type == :brew }.map(&:name)
kept_formulae += Homebrew::Bundle::CaskDumper.formula_dependencies(kept_casks) kept_formulae += Homebrew::Bundle::CaskDumper.formula_dependencies(kept_casks)
kept_formulae.map! do |f| kept_formulae.map! do |f|
Homebrew::Bundle::BrewDumper.formula_aliases[f] || Homebrew::Bundle::FormulaDumper.formula_aliases.fetch(
Homebrew::Bundle::BrewDumper.formula_oldnames[f] || f,
f Homebrew::Bundle::FormulaDumper.formula_oldnames.fetch(f, f),
)
end end
kept_formulae + recursive_dependencies(Homebrew::Bundle::BrewDumper.formulae, kept_formulae) kept_formulae + recursive_dependencies(Homebrew::Bundle::FormulaDumper.formulae, kept_formulae)
end end
end end
@ -142,7 +143,11 @@ module Homebrew
return @kept_casks if @kept_casks return @kept_casks if @kept_casks
@dsl ||= Brewfile.read(global:, file:) @dsl ||= Brewfile.read(global:, file:)
@kept_casks = @dsl.entries.select { |e| e.type == :cask }.map(&:name) kept_casks = @dsl.entries.select { |e| e.type == :cask }.flat_map(&:name)
kept_casks.map! do |c|
Homebrew::Bundle::CaskDumper.cask_oldnames.fetch(c, c)
end
@kept_casks = kept_casks
end end
private_class_method def self.recursive_dependencies(current_formulae, formulae_names, top_level: true) private_class_method def self.recursive_dependencies(current_formulae, formulae_names, top_level: true)

View File

@ -7,9 +7,10 @@ module Homebrew
module Bundle module Bundle
module Commands module Commands
module Dump module Dump
def self.run(global:, file:, describe:, force:, no_restart:, taps:, brews:, casks:, mas:, whalebrew:, vscode:) def self.run(global:, file:, describe:, force:, no_restart:, taps:, formulae:, casks:, mas:, whalebrew:,
vscode:)
Homebrew::Bundle::Dumper.dump_brewfile( Homebrew::Bundle::Dumper.dump_brewfile(
global:, file:, describe:, force:, no_restart:, taps:, brews:, casks:, mas:, whalebrew:, vscode:, global:, file:, describe:, force:, no_restart:, taps:, formulae:, casks:, mas:, whalebrew:, vscode:,
) )
end end
end end

View File

@ -1,4 +1,4 @@
# typed: false # rubocop:todo Sorbet/TrueSigil # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "English" require "English"
@ -13,6 +13,16 @@ module Homebrew
module Exec module Exec
PATH_LIKE_ENV_REGEX = /.+#{File::PATH_SEPARATOR}/ PATH_LIKE_ENV_REGEX = /.+#{File::PATH_SEPARATOR}/
sig {
params(
args: String,
global: T::Boolean,
file: T.nilable(String),
subcommand: String,
services: T::Boolean,
check: T::Boolean,
).void
}
def self.run(*args, global: false, file: nil, subcommand: "", services: false, check: false) def self.run(*args, global: false, file: nil, subcommand: "", services: false, check: false)
if check if check
require "bundle/commands/check" require "bundle/commands/check"
@ -25,9 +35,9 @@ module Homebrew
# Setup Homebrew's ENV extensions # Setup Homebrew's ENV extensions
ENV.activate_extensions! ENV.activate_extensions!
raise UsageError, "No command to execute was specified!" if args.blank?
command = args.first command = args.first
raise UsageError, "No command to execute was specified!" if command.blank?
require "bundle/brewfile" require "bundle/brewfile"
@dsl = Brewfile.read(global:, file:) @dsl = Brewfile.read(global:, file:)
@ -64,14 +74,8 @@ module Homebrew
ENV.prepend_path "PATH", Pathname.new(dep_root)/"shims" ENV.prepend_path "PATH", Pathname.new(dep_root)/"shims"
end end
# Setup pkg-config, if present, to help locate packages # Setup pkgconf, if needed, to help locate packages
# Only need this on Linux as Homebrew provides a shim on macOS Bundle.prepend_pkgconf_path_if_needed!
# TODO: use extend/OS here
# rubocop:todo Homebrew/MoveToExtendOS
if OS.linux? && (pkgconf = Formulary.factory("pkgconf")) && pkgconf.any_version_installed?
ENV.prepend_path "PATH", pkgconf.opt_bin.to_s
end
# rubocop:enable Homebrew/MoveToExtendOS
# For commands which aren't either absolute or relative # For commands which aren't either absolute or relative
# Add the command directory to PATH, since it may get blown away by superenv # Add the command directory to PATH, since it may get blown away by superenv
@ -170,12 +174,24 @@ module Homebrew
end end
end end
return return
elsif subcommand == "sh"
preferred_path = Utils::Shell.preferred_path(default: "/bin/bash")
notice = unless Homebrew::EnvConfig.no_env_hints?
<<~EOS
Your shell has been configured to use a build environment from your `Brewfile`.
This should help you build stuff.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
When done, type `exit`.
EOS
end
ENV["HOMEBREW_FORCE_API_AUTO_UPDATE"] = nil
args = [Utils::Shell.shell_with_prompt("brew bundle", preferred_path:, notice:)]
end end
if services if services
require "bundle/brew_services" require "bundle/brew_services"
exit_code = 0 exit_code = T.let(0, Integer)
run_services(@dsl.entries) do run_services(@dsl.entries) do
Kernel.system(*args) Kernel.system(*args)
if (system_exit_code = $CHILD_STATUS&.exitstatus) if (system_exit_code = $CHILD_STATUS&.exitstatus)
@ -193,7 +209,7 @@ module Homebrew
entries: T::Array[Homebrew::Bundle::Dsl::Entry], entries: T::Array[Homebrew::Bundle::Dsl::Entry],
_block: T.proc.params( _block: T.proc.params(
entry: Homebrew::Bundle::Dsl::Entry, entry: Homebrew::Bundle::Dsl::Entry,
info: T::Hash[String, T.anything], info: T::Hash[String, T.untyped],
service_file: Pathname, service_file: Pathname,
conflicting_services: T::Array[T::Hash[String, T.anything]], conflicting_services: T::Array[T::Hash[String, T.anything]],
).void, ).void,
@ -273,7 +289,7 @@ module Homebrew
map_service_info(entries) do |entry, info, service_file, conflicting_services| map_service_info(entries) do |entry, info, service_file, conflicting_services|
# Don't restart if already running this version # Don't restart if already running this version
loaded_file = Pathname.new(info["loaded_file"].to_s) loaded_file = Pathname.new(info["loaded_file"].to_s)
next if info["running"] && loaded_file&.file? && loaded_file&.realpath == service_file.realpath next if info["running"] && loaded_file.file? && loaded_file.realpath == service_file.realpath
if info["running"] && !Bundle::BrewServices.stop(info["name"], keep: true) if info["running"] && !Bundle::BrewServices.stop(info["name"], keep: true)
opoo "Failed to stop #{info["name"]} service" opoo "Failed to stop #{info["name"]} service"

View File

@ -8,11 +8,11 @@ module Homebrew
module Bundle module Bundle
module Commands module Commands
module List module List
def self.run(global:, file:, brews:, casks:, taps:, mas:, whalebrew:, vscode:) def self.run(global:, file:, formulae:, casks:, taps:, mas:, whalebrew:, vscode:)
parsed_entries = Brewfile.read(global:, file:).entries parsed_entries = Brewfile.read(global:, file:).entries
Homebrew::Bundle::Lister.list( Homebrew::Bundle::Lister.list(
parsed_entries, parsed_entries,
brews:, casks:, taps:, mas:, whalebrew:, vscode:, formulae:, casks:, taps:, mas:, whalebrew:, vscode:,
) )
end end
end end

View File

@ -13,9 +13,9 @@ module Homebrew
true true
end end
def self.build_brewfile(describe:, no_restart:, brews:, taps:, casks:, mas:, whalebrew:, vscode:) def self.build_brewfile(describe:, no_restart:, formulae:, taps:, casks:, mas:, whalebrew:, vscode:)
require "bundle/tap_dumper" require "bundle/tap_dumper"
require "bundle/brew_dumper" require "bundle/formula_dumper"
require "bundle/cask_dumper" require "bundle/cask_dumper"
require "bundle/mac_app_store_dumper" require "bundle/mac_app_store_dumper"
require "bundle/whalebrew_dumper" require "bundle/whalebrew_dumper"
@ -23,7 +23,7 @@ module Homebrew
content = [] content = []
content << TapDumper.dump if taps content << TapDumper.dump if taps
content << BrewDumper.dump(describe:, no_restart:) if brews content << FormulaDumper.dump(describe:, no_restart:) if formulae
content << CaskDumper.dump(describe:) if casks content << CaskDumper.dump(describe:) if casks
content << MacAppStoreDumper.dump if mas content << MacAppStoreDumper.dump if mas
content << WhalebrewDumper.dump if whalebrew content << WhalebrewDumper.dump if whalebrew
@ -31,11 +31,11 @@ module Homebrew
"#{content.reject(&:empty?).join("\n")}\n" "#{content.reject(&:empty?).join("\n")}\n"
end end
def self.dump_brewfile(global:, file:, describe:, force:, no_restart:, brews:, taps:, casks:, mas:, whalebrew:, def self.dump_brewfile(global:, file:, describe:, force:, no_restart:, formulae:, taps:, casks:, mas:,
vscode:) whalebrew:, vscode:)
path = brewfile_path(global:, file:) path = brewfile_path(global:, file:)
can_write_to_brewfile?(path, force:) can_write_to_brewfile?(path, force:)
content = build_brewfile(describe:, no_restart:, taps:, brews:, casks:, mas:, whalebrew:, vscode:) content = build_brewfile(describe:, no_restart:, taps:, formulae:, casks:, mas:, whalebrew:, vscode:)
write_file path, content write_file path, content
end end

View File

@ -1,4 +1,4 @@
# typed: false # rubocop:todo Sorbet/TrueSigil # typed: true
# frozen_string_literal: true # frozen_string_literal: true
require "json" require "json"
@ -7,10 +7,8 @@ require "tsort"
module Homebrew module Homebrew
module Bundle module Bundle
# TODO: refactor into multiple modules # TODO: refactor into multiple modules
module BrewDumper module FormulaDumper
module_function def self.reset!
def reset!
require "bundle/brew_services" require "bundle/brew_services"
Homebrew::Bundle::BrewServices.reset! Homebrew::Bundle::BrewServices.reset!
@ -21,14 +19,14 @@ module Homebrew
@formula_oldnames = nil @formula_oldnames = nil
end end
def formulae def self.formulae
return @formulae if @formulae return @formulae if @formulae
formulae_by_full_name formulae_by_full_name
@formulae @formulae
end end
def formulae_by_full_name(name = nil) def self.formulae_by_full_name(name = nil)
return @formulae_by_full_name[name] if name.present? && @formulae_by_full_name&.key?(name) return @formulae_by_full_name[name] if name.present? && @formulae_by_full_name&.key?(name)
require "formula" require "formula"
@ -51,11 +49,11 @@ module Homebrew
{} {}
end end
def formulae_by_name(name) def self.formulae_by_name(name)
formulae_by_full_name(name) || @formulae_by_name[name] formulae_by_full_name(name) || @formulae_by_name[name]
end end
def dump(describe: false, no_restart: false) def self.dump(describe: false, no_restart: false)
require "bundle/brew_services" require "bundle/brew_services"
requested_formula = formulae.select do |f| requested_formula = formulae.select do |f|
@ -77,7 +75,7 @@ module Homebrew
end.join("\n") end.join("\n")
end end
def formula_aliases def self.formula_aliases
return @formula_aliases if @formula_aliases return @formula_aliases if @formula_aliases
@formula_aliases = {} @formula_aliases = {}
@ -96,7 +94,7 @@ module Homebrew
@formula_aliases @formula_aliases
end end
def formula_oldnames def self.formula_oldnames
return @formula_oldnames if @formula_oldnames return @formula_oldnames if @formula_oldnames
@formula_oldnames = {} @formula_oldnames = {}
@ -115,7 +113,7 @@ module Homebrew
@formula_oldnames @formula_oldnames
end end
def add_formula(formula) private_class_method def self.add_formula(formula)
hash = formula_to_hash formula hash = formula_to_hash formula
@formulae_by_name[hash[:name]] = hash @formulae_by_name[hash[:name]] = hash
@ -123,9 +121,8 @@ module Homebrew
hash hash
end end
private_class_method :add_formula
def formula_to_hash(formula) private_class_method def self.formula_to_hash(formula)
keg = if formula.linked? keg = if formula.linked?
link = true if formula.keg_only? link = true if formula.keg_only?
formula.linked_keg formula.linked_keg
@ -185,17 +182,21 @@ module Homebrew
official_tap: formula.tap&.official? || false, official_tap: formula.tap&.official? || false,
} }
end end
private_class_method :formula_to_hash
class Topo < Hash class Topo < Hash
include TSort include TSort
def each_key(&block)
keys.each(&block)
end
alias tsort_each_node each_key alias tsort_each_node each_key
def tsort_each_child(node, &block) def tsort_each_child(node, &block)
fetch(node.downcase).sort.each(&block) fetch(node.downcase).sort.each(&block)
end end
end end
def sort!(formulae) private_class_method def self.sort!(formulae)
# Step 1: Sort by formula full name while putting tap formulae behind core formulae. # Step 1: Sort by formula full name while putting tap formulae behind core formulae.
# So we can have a nicer output. # So we can have a nicer output.
formulae = formulae.sort do |a, b| formulae = formulae.sort do |a, b|
@ -230,15 +231,14 @@ module Homebrew
odie <<~EOS odie <<~EOS
Formulae dependency graph sorting failed (likely due to a circular dependency): Formulae dependency graph sorting failed (likely due to a circular dependency):
#{cycle_first}: #{topo[cycle_first]} #{cycle_first}: #{topo[cycle_first] if topo}
#{cycle_last}: #{topo[cycle_last]} #{cycle_last}: #{topo[cycle_last] if topo}
Please run the following commands and try again: Please run the following commands and try again:
brew update brew update
brew uninstall --ignore-dependencies --force #{cycle_first} #{cycle_last} brew uninstall --ignore-dependencies --force #{cycle_first} #{cycle_last}
brew install #{cycle_first} #{cycle_last} brew install #{cycle_first} #{cycle_last}
EOS EOS
end end
private_class_method :sort!
end end
end end
end end

View File

@ -3,7 +3,7 @@
module Homebrew module Homebrew
module Bundle module Bundle
class BrewInstaller class FormulaInstaller
def self.reset! def self.reset!
@installed_formulae = nil @installed_formulae = nil
@outdated_formulae = nil @outdated_formulae = nil
@ -179,13 +179,13 @@ module Homebrew
return true if array.include?(formula) return true if array.include?(formula)
return true if array.include?(formula.split("/").last) return true if array.include?(formula.split("/").last)
require "bundle/brew_dumper" require "bundle/formula_dumper"
old_names = Homebrew::Bundle::BrewDumper.formula_oldnames old_names = Homebrew::Bundle::FormulaDumper.formula_oldnames
old_name = old_names[formula] old_name = old_names[formula]
old_name ||= old_names[formula.split("/").last] old_name ||= old_names[formula.split("/").last]
return true if old_name && array.include?(old_name) return true if old_name && array.include?(old_name)
resolved_full_name = Homebrew::Bundle::BrewDumper.formula_aliases[formula] resolved_full_name = Homebrew::Bundle::FormulaDumper.formula_aliases[formula]
return false unless resolved_full_name return false unless resolved_full_name
return true if array.include?(resolved_full_name) return true if array.include?(resolved_full_name)
return true if array.include?(resolved_full_name.split("/").last) return true if array.include?(resolved_full_name.split("/").last)
@ -219,14 +219,14 @@ module Homebrew
end end
def self.formulae def self.formulae
require "bundle/brew_dumper" require "bundle/formula_dumper"
Homebrew::Bundle::BrewDumper.formulae Homebrew::Bundle::FormulaDumper.formulae
end end
private private
def installed? def installed?
BrewInstaller.formula_installed?(@name) FormulaInstaller.formula_installed?(@name)
end end
def linked? def linked?
@ -242,7 +242,7 @@ module Homebrew
end end
def upgradable? def upgradable?
BrewInstaller.formula_upgradable?(@name) FormulaInstaller.formula_upgradable?(@name)
end end
def conflicts_with def conflicts_with
@ -250,8 +250,8 @@ module Homebrew
conflicts_with = Set.new conflicts_with = Set.new
conflicts_with += @conflicts_with_arg conflicts_with += @conflicts_with_arg
require "bundle/brew_dumper" require "bundle/formula_dumper"
if (formula = Homebrew::Bundle::BrewDumper.formulae_by_full_name(@full_name)) && if (formula = Homebrew::Bundle::FormulaDumper.formulae_by_full_name(@full_name)) &&
(formula_conflicts_with = formula[:conflicts_with]) (formula_conflicts_with = formula[:conflicts_with])
conflicts_with += formula_conflicts_with conflicts_with += formula_conflicts_with
end end
@ -262,7 +262,7 @@ module Homebrew
def resolve_conflicts!(verbose:) def resolve_conflicts!(verbose:)
conflicts_with.each do |conflict| conflicts_with.each do |conflict|
next unless BrewInstaller.formula_installed?(conflict) next unless FormulaInstaller.formula_installed?(conflict)
if verbose if verbose
puts <<~EOS puts <<~EOS
@ -293,7 +293,7 @@ module Homebrew
return false return false
end end
BrewInstaller.installed_formulae << @name FormulaInstaller.installed_formulae << @name
@changed = true @changed = true
true true
end end

View File

@ -2,7 +2,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require "bundle/dsl" require "bundle/dsl"
require "bundle/brew_installer" require "bundle/formula_installer"
require "bundle/cask_installer" require "bundle/cask_installer"
require "bundle/mac_app_store_installer" require "bundle/mac_app_store_installer"
require "bundle/whalebrew_installer" require "bundle/whalebrew_installer"
@ -27,8 +27,8 @@ module Homebrew
cls = case type cls = case type
when :brew when :brew
options = entry.options options = entry.options
verb = "Upgrading" if Homebrew::Bundle::BrewInstaller.formula_upgradable?(name) verb = "Upgrading" if Homebrew::Bundle::FormulaInstaller.formula_upgradable?(name)
Homebrew::Bundle::BrewInstaller Homebrew::Bundle::FormulaInstaller
when :cask when :cask
options = entry.options options = entry.options
verb = "Upgrading" if Homebrew::Bundle::CaskInstaller.cask_upgradable?(name) verb = "Upgrading" if Homebrew::Bundle::CaskInstaller.cask_upgradable?(name)

View File

@ -4,14 +4,14 @@
module Homebrew module Homebrew
module Bundle module Bundle
module Lister module Lister
def self.list(entries, brews:, casks:, taps:, mas:, whalebrew:, vscode:) def self.list(entries, formulae:, casks:, taps:, mas:, whalebrew:, vscode:)
entries.each do |entry| entries.each do |entry|
puts entry.name if show?(entry.type, brews:, casks:, taps:, mas:, whalebrew:, vscode:) puts entry.name if show?(entry.type, formulae:, casks:, taps:, mas:, whalebrew:, vscode:)
end end
end end
private_class_method def self.show?(type, brews:, casks:, taps:, mas:, whalebrew:, vscode:) private_class_method def self.show?(type, formulae:, casks:, taps:, mas:, whalebrew:, vscode:)
return true if brews && type == :brew return true if formulae && type == :brew
return true if casks && type == :cask return true if casks && type == :cask
return true if taps && type == :tap return true if taps && type == :tap
return true if mas && type == :mas return true if mas && type == :mas

View File

@ -9,21 +9,8 @@ module Homebrew
class << self class << self
sig { params(entry: Dsl::Entry, silent: T::Boolean).returns(T::Boolean) } sig { params(entry: Dsl::Entry, silent: T::Boolean).returns(T::Boolean) }
def skip?(entry, silent: false) def skip?(entry, silent: false)
require "bundle/brew_dumper" require "bundle/formula_dumper"
# TODO: use extend/OS here
# rubocop:todo Homebrew/MoveToExtendOS
if (Hardware::CPU.arm? || OS.linux?) &&
Homebrew.default_prefix? &&
entry.type == :brew && entry.name.exclude?("/") &&
(formula = BrewDumper.formulae_by_full_name(entry.name)) &&
formula[:official_tap] &&
!formula[:bottled]
reason = Hardware::CPU.arm? ? "Apple Silicon" : "Linux"
puts Formatter.warning "Skipping #{entry.name} (no bottle for #{reason})" unless silent
return true
end
# rubocop:enable Homebrew/MoveToExtendOS
return true if @failed_taps&.any? do |tap| return true if @failed_taps&.any? do |tap|
prefix = "#{tap}/" prefix = "#{tap}/"
entry.name.start_with?(prefix) || entry.options[:full_name]&.start_with?(prefix) entry.name.start_with?(prefix) || entry.options[:full_name]&.start_with?(prefix)

View File

@ -19,7 +19,6 @@ module Homebrew
puts "Installing #{name} tap. It is not currently installed." if verbose puts "Installing #{name} tap. It is not currently installed." if verbose
args = [] args = []
args << "--force" if force args << "--force" if force
args.append("--force-auto-update") if options[:force_auto_update]
success = if options[:clone_target] success = if options[:clone_target]
Bundle.brew("tap", name, options[:clone_target], *args, verbose:) Bundle.brew("tap", name, options[:clone_target], *args, verbose:)

View File

@ -139,7 +139,11 @@ module Cask
def initialize(cask, *dsl_args) def initialize(cask, *dsl_args)
@cask = cask @cask = cask
@dirmethod = nil
@dsl_args = dsl_args.deep_dup @dsl_args = dsl_args.deep_dup
@dsl_key = nil
@english_article = nil
@english_name = nil
end end
def config def config

View File

@ -41,7 +41,9 @@ module Cask
super super
target = target_hash[:target] target = target_hash[:target]
@source = nil
@source_string = source.to_s @source_string = source.to_s
@target = nil
@target_string = target.to_s @target_string = target.to_s
end end

View File

@ -1,9 +1,14 @@
# typed: true # rubocop:todo Sorbet/StrictSigil # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
module Cask module Cask
# Sorted set containing all cask artifacts. # Sorted set containing all cask artifacts.
class ArtifactSet < ::Set class ArtifactSet < ::Set
extend T::Generic
Elem = type_member(:out) { { fixed: Artifact::AbstractArtifact } }
sig { params(block: T.nilable(T.proc.params(arg0: Elem).returns(T.untyped))).void }
def each(&block) def each(&block)
return enum_for(T.must(__method__)) { size } unless block return enum_for(T.must(__method__)) { size } unless block
@ -11,6 +16,7 @@ module Cask
self self
end end
sig { returns(T::Array[Artifact::AbstractArtifact]) }
def to_a def to_a
super.sort super.sort
end end

View File

@ -27,7 +27,7 @@ module Cask
sig { sig {
params( params(
cask: ::Cask::Cask, download: T::Boolean, quarantine: T::Boolean, token_conflicts: T.nilable(T::Boolean), cask: ::Cask::Cask, download: T::Boolean, quarantine: T::Boolean,
online: T.nilable(T::Boolean), strict: T.nilable(T::Boolean), signing: T.nilable(T::Boolean), online: T.nilable(T::Boolean), strict: T.nilable(T::Boolean), signing: T.nilable(T::Boolean),
new_cask: T.nilable(T::Boolean), only: T::Array[String], except: T::Array[String] new_cask: T.nilable(T::Boolean), only: T::Array[String], except: T::Array[String]
).void ).void
@ -35,14 +35,13 @@ module Cask
def initialize( def initialize(
cask, cask,
download: false, quarantine: false, download: false, quarantine: false,
token_conflicts: nil, online: nil, strict: nil, signing: nil, online: nil, strict: nil, signing: nil,
new_cask: nil, only: [], except: [] new_cask: nil, only: [], except: []
) )
# `new_cask` implies `online`, `token_conflicts`, `strict` and `signing` # `new_cask` implies `online`, `strict` and `signing`
online = new_cask if online.nil? online = new_cask if online.nil?
strict = new_cask if strict.nil? strict = new_cask if strict.nil?
signing = new_cask if signing.nil? signing = new_cask if signing.nil?
token_conflicts = new_cask if token_conflicts.nil?
# `online` and `signing` imply `download` # `online` and `signing` imply `download`
download ||= online || signing download ||= online || signing
@ -53,7 +52,6 @@ module Cask
@strict = strict @strict = strict
@signing = signing @signing = signing
@new_cask = new_cask @new_cask = new_cask
@token_conflicts = token_conflicts
@only = only @only = only
@except = except @except = except
end end
@ -70,9 +68,6 @@ module Cask
sig { returns(T::Boolean) } sig { returns(T::Boolean) }
def strict? = !!@strict def strict? = !!@strict
sig { returns(T::Boolean) }
def token_conflicts? = !!@token_conflicts
sig { returns(::Cask::Audit) } sig { returns(::Cask::Audit) }
def run! def run!
only_audits = @only only_audits = @only
@ -430,15 +425,10 @@ module Cask
sig { void } sig { void }
def audit_token_conflicts def audit_token_conflicts
return unless token_conflicts?
Homebrew.with_no_api_env do Homebrew.with_no_api_env do
return unless core_formula_names.include?(cask.token) return unless core_formula_names.include?(cask.token)
add_error( add_error("cask token conflicts with an existing homebrew/core formula: #{Formatter.url(core_formula_url)}")
"possible duplicate, cask token conflicts with Homebrew core formula: #{Formatter.url(core_formula_url)}",
strict_only: true,
)
end end
end end
@ -653,11 +643,12 @@ module Cask
supports_arm = result.merged_output.include?("arm64") supports_arm = result.merged_output.include?("arm64")
mentions_rosetta = cask.caveats.include?("requires Rosetta 2") mentions_rosetta = cask.caveats.include?("requires Rosetta 2")
requires_intel = cask.depends_on.arch&.any? { |arch| arch[:type] == :intel }
if supports_arm && mentions_rosetta if supports_arm && mentions_rosetta
add_error "Artifacts do not require Rosetta 2 but the caveats say otherwise!", add_error "Artifacts do not require Rosetta 2 but the caveats say otherwise!",
location: url.location location: url.location
elsif !supports_arm && !mentions_rosetta elsif !supports_arm && !mentions_rosetta && !requires_intel
add_error "Artifacts require Rosetta 2 but this is not indicated by the caveats!", add_error "Artifacts require Rosetta 2 but this is not indicated by the caveats!",
location: url.location location: url.location
end end
@ -701,45 +692,53 @@ module Cask
return unless online? return unless online?
return unless strict? return unless strict?
odebug "Auditing minimum OS version" odebug "Auditing minimum macOS version"
plist_min_os = cask_plist_min_os bundle_min_os = cask_bundle_min_os
sparkle_min_os = livecheck_min_os sparkle_min_os = cask_sparkle_min_os
app_min_os = [bundle_min_os, sparkle_min_os].compact.max
debug_messages = [] debug_messages = []
debug_messages << "Plist #{plist_min_os}" if plist_min_os debug_messages << "from artifact: #{bundle_min_os.to_sym}" if bundle_min_os
debug_messages << "Sparkle #{sparkle_min_os}" if sparkle_min_os debug_messages << "from upstream: #{sparkle_min_os.to_sym}" if sparkle_min_os
odebug "Detected minimum OS version: #{debug_messages.join(" | ")}" unless debug_messages.empty? odebug "Detected minimum macOS: #{app_min_os.to_sym} (#{debug_messages.join(" | ")})" if app_min_os
min_os = [plist_min_os, sparkle_min_os].compact.max return if app_min_os.nil? || app_min_os <= HOMEBREW_MACOS_OLDEST_ALLOWED
return if min_os.nil? || min_os <= HOMEBREW_MACOS_OLDEST_ALLOWED
on_system_block_min_os = cask.on_system_block_min_os on_system_block_min_os = cask.on_system_block_min_os
cask_min_os = [on_system_block_min_os, cask.depends_on.macos&.minimum_version].compact.max depends_on_min_os = cask.depends_on.macos&.minimum_version
odebug "Declared minimum OS version: #{cask_min_os&.to_sym}"
return if cask_min_os&.to_sym == min_os.to_sym cask_min_os = [on_system_block_min_os, depends_on_min_os].compact.max
return if cask.on_system_blocks_exist? && debug_messages = []
OnSystem.arch_condition_met?(:arm) && debug_messages << "from on_system block: #{on_system_block_min_os.to_sym}" if on_system_block_min_os
if depends_on_min_os > HOMEBREW_MACOS_OLDEST_ALLOWED
debug_messages << "from depends_on stanza: #{depends_on_min_os.to_sym}"
end
odebug "Declared minimum macOS: #{cask_min_os.to_sym} (#{debug_messages.join(" | ").presence || "default"})"
return if cask_min_os.to_sym == app_min_os.to_sym
# ignore declared minimum OS < 11.x when auditing as ARM a cask with arch-specific artifacts
return if OnSystem.arch_condition_met?(:arm) &&
cask.on_system_blocks_exist? &&
cask_min_os.present? && cask_min_os.present? &&
cask_min_os < MacOSVersion.new("11") cask_min_os < MacOSVersion.new("11")
min_os_definition = if cask_min_os.present? min_os_definition = if cask_min_os > HOMEBREW_MACOS_OLDEST_ALLOWED
if on_system_block_min_os.present? && definition = if T.must(on_system_block_min_os.to_s <=> depends_on_min_os.to_s).positive?
on_system_block_min_os > cask.depends_on.macos&.minimum_version "an on_system block"
"a block with a minimum OS version of #{cask_min_os.to_sym.inspect}"
else else
cask_min_os.to_sym.inspect "a depends_on stanza"
end end
"#{definition} with a minimum macOS version of #{cask_min_os.to_sym.inspect}"
else else
"no minimum OS version" "no minimum macOS version"
end end
add_error "Upstream defined #{min_os.to_sym.inspect} as the minimum OS version " \ source = T.must(bundle_min_os.to_s <=> sparkle_min_os.to_s).positive? ? "Artifact" : "Upstream"
add_error "#{source} defined #{app_min_os.to_sym.inspect} as the minimum macOS version " \
"but the cask declared #{min_os_definition}", "but the cask declared #{min_os_definition}",
strict_only: true strict_only: true
end end
sig { returns(T.nilable(MacOSVersion)) } sig { returns(T.nilable(MacOSVersion)) }
def livecheck_min_os def cask_sparkle_min_os
return unless online? return unless online?
return unless cask.livecheck_defined? return unless cask.livecheck_defined?
return if cask.livecheck.strategy != :sparkle return if cask.livecheck.strategy != :sparkle
@ -772,10 +771,10 @@ module Cask
end end
sig { returns(T.nilable(MacOSVersion)) } sig { returns(T.nilable(MacOSVersion)) }
def cask_plist_min_os def cask_bundle_min_os
return unless online? return unless online?
plist_min_os = T.let(nil, T.untyped) min_os = T.let(nil, T.untyped)
@staged_path ||= cask.staged_path @staged_path ||= cask.staged_path
extract_artifacts do |artifacts, tmpdir| extract_artifacts do |artifacts, tmpdir|
@ -786,13 +785,33 @@ module Cask
next unless File.exist?(plist_path) next unless File.exist?(plist_path)
plist = system_command!("plutil", args: ["-convert", "xml1", "-o", "-", plist_path]).plist plist = system_command!("plutil", args: ["-convert", "xml1", "-o", "-", plist_path]).plist
plist_min_os = plist["LSMinimumSystemVersion"].presence min_os = plist["LSMinimumSystemVersion"].presence
break if plist_min_os break if min_os
next unless (main_binary = get_plist_main_binary(path))
next if !File.exist?(main_binary) || File.open(main_binary, "rb") { |f| f.read(2) == "#!" }
macho = MachO.open(main_binary)
min_os = case macho
when MachO::MachOFile
[
macho[:LC_VERSION_MIN_MACOSX].first&.version_string,
macho[:LC_BUILD_VERSION].first&.minos_string,
]
when MachO::FatFile
macho.machos.map do |slice|
[
slice[:LC_VERSION_MIN_MACOSX].first&.version_string,
slice[:LC_BUILD_VERSION].first&.minos_string,
]
end.flatten
end.compact.min
break if min_os
end end
end end
begin begin
MacOSVersion.new(plist_min_os).strip_patch MacOSVersion.new(min_os).strip_patch
rescue MacOSVersion::Error rescue MacOSVersion::Error
nil nil
end end

View File

@ -11,17 +11,17 @@ module Cask
params( params(
cask: ::Cask::Cask, audit_download: T::Boolean, audit_online: T.nilable(T::Boolean), cask: ::Cask::Cask, audit_download: T::Boolean, audit_online: T.nilable(T::Boolean),
audit_strict: T.nilable(T::Boolean), audit_signing: T.nilable(T::Boolean), audit_strict: T.nilable(T::Boolean), audit_signing: T.nilable(T::Boolean),
audit_token_conflicts: T.nilable(T::Boolean), audit_new_cask: T.nilable(T::Boolean), quarantine: T::Boolean, audit_new_cask: T.nilable(T::Boolean), quarantine: T::Boolean,
any_named_args: T::Boolean, language: T.nilable(String), only: T::Array[String], except: T::Array[String] any_named_args: T::Boolean, language: T.nilable(String), only: T::Array[String], except: T::Array[String]
).returns(T::Set[String]) ).returns(T::Set[String])
} }
def self.audit( def self.audit(
cask, audit_download: false, audit_online: nil, audit_strict: nil, audit_signing: nil, cask, audit_download: false, audit_online: nil, audit_strict: nil, audit_signing: nil,
audit_token_conflicts: nil, audit_new_cask: nil, quarantine: false, any_named_args: false, language: nil, audit_new_cask: nil, quarantine: false, any_named_args: false, language: nil,
only: [], except: [] only: [], except: []
) )
new( new(
cask, audit_download:, audit_online:, audit_strict:, audit_signing:, audit_token_conflicts:, cask, audit_download:, audit_online:, audit_strict:, audit_signing:,
audit_new_cask:, quarantine:, any_named_args:, language:, only:, except: audit_new_cask:, quarantine:, any_named_args:, language:, only:, except:
).audit ).audit
end end
@ -36,7 +36,7 @@ module Cask
params( params(
cask: ::Cask::Cask, audit_download: T::Boolean, audit_online: T.nilable(T::Boolean), cask: ::Cask::Cask, audit_download: T::Boolean, audit_online: T.nilable(T::Boolean),
audit_strict: T.nilable(T::Boolean), audit_signing: T.nilable(T::Boolean), audit_strict: T.nilable(T::Boolean), audit_signing: T.nilable(T::Boolean),
audit_token_conflicts: T.nilable(T::Boolean), audit_new_cask: T.nilable(T::Boolean), quarantine: T::Boolean, audit_new_cask: T.nilable(T::Boolean), quarantine: T::Boolean,
any_named_args: T::Boolean, language: T.nilable(String), only: T::Array[String], except: T::Array[String] any_named_args: T::Boolean, language: T.nilable(String), only: T::Array[String], except: T::Array[String]
).void ).void
} }
@ -46,7 +46,6 @@ module Cask
audit_online: nil, audit_online: nil,
audit_strict: nil, audit_strict: nil,
audit_signing: nil, audit_signing: nil,
audit_token_conflicts: nil,
audit_new_cask: nil, audit_new_cask: nil,
quarantine: false, quarantine: false,
any_named_args: false, any_named_args: false,
@ -61,7 +60,6 @@ module Cask
@audit_strict = audit_strict @audit_strict = audit_strict
@audit_signing = audit_signing @audit_signing = audit_signing
@quarantine = quarantine @quarantine = quarantine
@audit_token_conflicts = audit_token_conflicts
@any_named_args = any_named_args @any_named_args = any_named_args
@language = language @language = language
@only = only @only = only
@ -127,15 +125,14 @@ module Cask
def audit_cask_instance(cask) def audit_cask_instance(cask)
audit = Audit.new( audit = Audit.new(
cask, cask,
online: @audit_online, online: @audit_online,
strict: @audit_strict, strict: @audit_strict,
signing: @audit_signing, signing: @audit_signing,
new_cask: @audit_new_cask, new_cask: @audit_new_cask,
token_conflicts: @audit_token_conflicts, download: @audit_download,
download: @audit_download, quarantine: @quarantine,
quarantine: @quarantine, only: @only,
only: @only, except: @except,
except: @except,
) )
audit.run! audit.run!
end end

View File

@ -8,7 +8,7 @@ require "cask/dsl"
require "cask/metadata" require "cask/metadata"
require "cask/tab" require "cask/tab"
require "utils/bottles" require "utils/bottles"
require "extend/api_hashable" require "api_hashable"
module Cask module Cask
# An instance of a cask. # An instance of a cask.
@ -416,16 +416,14 @@ module Cask
if @dsl.on_system_blocks_exist? if @dsl.on_system_blocks_exist?
begin begin
OnSystem::ALL_OS_ARCH_COMBINATIONS.each do |os, arch| OnSystem::VALID_OS_ARCH_TAGS.each do |bottle_tag|
bottle_tag = ::Utils::Bottles::Tag.new(system: os, arch:)
next unless bottle_tag.valid_combination?
next if bottle_tag.linux? && @dsl.os.nil? next if bottle_tag.linux? && @dsl.os.nil?
next if bottle_tag.macos? && next if bottle_tag.macos? &&
depends_on.macos && depends_on.macos &&
!@dsl.depends_on_set_in_block? && !@dsl.depends_on_set_in_block? &&
!depends_on.macos.allows?(bottle_tag.to_macos_version) !depends_on.macos.allows?(bottle_tag.to_macos_version)
Homebrew::SimulateSystem.with(os:, arch:) do Homebrew::SimulateSystem.with_tag(bottle_tag) do
refresh refresh
to_h.each do |key, value| to_h.each do |key, value|

View File

@ -6,6 +6,7 @@ require "cask/cask"
require "uri" require "uri"
require "utils/curl" require "utils/curl"
require "extend/hash/keys" require "extend/hash/keys"
require "api"
module Cask module Cask
# Loads a cask from various sources. # Loads a cask from various sources.
@ -104,8 +105,8 @@ module Cask
return return
end end
return if %w[.rb .json].exclude?(path.extname)
return unless path.expand_path.exist? return unless path.expand_path.exist?
return if invalid_path?(path)
return if Homebrew::EnvConfig.forbid_packages_from_paths? && return if Homebrew::EnvConfig.forbid_packages_from_paths? &&
!path.realpath.to_s.start_with?("#{Caskroom.path}/", "#{HOMEBREW_LIBRARY}/Taps/") !path.realpath.to_s.start_with?("#{Caskroom.path}/", "#{HOMEBREW_LIBRARY}/Taps/")
@ -113,6 +114,14 @@ module Cask
new(path) new(path)
end end
sig { params(pathname: Pathname, valid_extnames: T::Array[String]).returns(T::Boolean) }
def self.invalid_path?(pathname, valid_extnames: %w[.rb .json])
return true if valid_extnames.exclude?(pathname.extname)
@invalid_basenames ||= %w[INSTALL_RECEIPT.json sbom.spdx.json].freeze
@invalid_basenames.include?(pathname.basename.to_s)
end
attr_reader :token, :path attr_reader :token, :path
sig { params(path: T.any(Pathname, String), token: String).void } sig { params(path: T.any(Pathname, String), token: String).void }
@ -135,8 +144,10 @@ module Cask
@content = path.read(encoding: "UTF-8") @content = path.read(encoding: "UTF-8")
@config = config @config = config
if path.extname == ".json" if !self.class.invalid_path?(path, valid_extnames: %w[.json]) &&
return FromAPILoader.new(token, from_json: JSON.parse(@content), path:).load(config:) (from_json = JSON.parse(@content).presence) &&
from_json.is_a?(Hash)
return FromAPILoader.new(token, from_json:, path:).load(config:)
end end
begin begin
@ -284,7 +295,7 @@ module Cask
sig { returns(Pathname) } sig { returns(Pathname) }
attr_reader :path attr_reader :path
sig { returns(T.nilable(Hash)) } sig { returns(T.nilable(T::Hash[String, T.untyped])) }
attr_reader :from_json attr_reader :from_json
sig { sig {
@ -306,7 +317,13 @@ module Cask
new("#{tap}/#{token}") new("#{tap}/#{token}")
end end
sig { params(token: String, from_json: Hash, path: T.nilable(Pathname)).void } sig {
params(
token: String,
from_json: T.nilable(T::Hash[String, T.untyped]),
path: T.nilable(Pathname),
).void
}
def initialize(token, from_json: T.unsafe(nil), path: nil) def initialize(token, from_json: T.unsafe(nil), path: nil)
@token = token.sub(%r{^homebrew/(?:homebrew-)?cask/}i, "") @token = token.sub(%r{^homebrew/(?:homebrew-)?cask/}i, "")
@sourcefile_path = path || Homebrew::API::Cask.cached_json_file_path @sourcefile_path = path || Homebrew::API::Cask.cached_json_file_path
@ -400,7 +417,7 @@ module Cask
container(**container_hash) container(**container_hash)
end end
json_cask[:artifacts].each do |artifact| json_cask[:artifacts]&.each do |artifact|
# convert generic string replacements into actual ones # convert generic string replacements into actual ones
artifact = cask.loader.from_h_gsubs(artifact, appdir) artifact = cask.loader.from_h_gsubs(artifact, appdir)
key = artifact.keys.first key = artifact.keys.first

View File

@ -26,7 +26,7 @@ require "cask/dsl/version"
require "cask/url" require "cask/url"
require "cask/utils" require "cask/utils"
require "extend/on_system" require "on_system"
module Cask module Cask
# Class representing the domain-specific language used for casks. # Class representing the domain-specific language used for casks.
@ -69,7 +69,6 @@ module Cask
].freeze ].freeze
DSL_METHODS = Set.new([ DSL_METHODS = Set.new([
:appcast,
:arch, :arch,
:artifacts, :artifacts,
:auto_updates, :auto_updates,
@ -123,15 +122,21 @@ module Cask
sig { params(cask: Cask).void } sig { params(cask: Cask).void }
def initialize(cask) def initialize(cask)
# NOTE: Variables set by `set_unique_stanza` must be initialized to `nil`. # NOTE: `:"@#{stanza}"` variables set by `set_unique_stanza` must be
@auto_updates = T.let(nil, T.nilable(T::Boolean)) # initialized to `nil`.
@arch = T.let(nil, T.nilable(String)) @arch = T.let(nil, T.nilable(String))
@arch_set_in_block = T.let(false, T::Boolean)
@artifacts = T.let(ArtifactSet.new, ArtifactSet) @artifacts = T.let(ArtifactSet.new, ArtifactSet)
@auto_updates = T.let(nil, T.nilable(T::Boolean))
@auto_updates_set_in_block = T.let(false, T::Boolean)
@autobump = T.let(true, T::Boolean)
@called_in_on_system_block = T.let(false, T::Boolean) @called_in_on_system_block = T.let(false, T::Boolean)
@cask = T.let(cask, Cask) @cask = T.let(cask, Cask)
@caveats = T.let(DSL::Caveats.new(cask), DSL::Caveats) @caveats = T.let(DSL::Caveats.new(cask), DSL::Caveats)
@conflicts_with = T.let(nil, T.nilable(DSL::ConflictsWith)) @conflicts_with = T.let(nil, T.nilable(DSL::ConflictsWith))
@conflicts_with_set_in_block = T.let(false, T::Boolean)
@container = T.let(nil, T.nilable(DSL::Container)) @container = T.let(nil, T.nilable(DSL::Container))
@container_set_in_block = T.let(false, T::Boolean)
@depends_on = T.let(DSL::DependsOn.new, DSL::DependsOn) @depends_on = T.let(DSL::DependsOn.new, DSL::DependsOn)
@depends_on_set_in_block = T.let(false, T::Boolean) @depends_on_set_in_block = T.let(false, T::Boolean)
@deprecated = T.let(false, T::Boolean) @deprecated = T.let(false, T::Boolean)
@ -140,27 +145,32 @@ module Cask
@deprecation_replacement_cask = T.let(nil, T.nilable(String)) @deprecation_replacement_cask = T.let(nil, T.nilable(String))
@deprecation_replacement_formula = T.let(nil, T.nilable(String)) @deprecation_replacement_formula = T.let(nil, T.nilable(String))
@desc = T.let(nil, T.nilable(String)) @desc = T.let(nil, T.nilable(String))
@desc_set_in_block = T.let(false, T::Boolean)
@disable_date = T.let(nil, T.nilable(Date)) @disable_date = T.let(nil, T.nilable(Date))
@disable_reason = T.let(nil, T.nilable(T.any(String, Symbol))) @disable_reason = T.let(nil, T.nilable(T.any(String, Symbol)))
@disable_replacement_cask = T.let(nil, T.nilable(String)) @disable_replacement_cask = T.let(nil, T.nilable(String))
@disable_replacement_formula = T.let(nil, T.nilable(String)) @disable_replacement_formula = T.let(nil, T.nilable(String))
@disabled = T.let(false, T::Boolean) @disabled = T.let(false, T::Boolean)
@homepage = T.let(nil, T.nilable(String)) @homepage = T.let(nil, T.nilable(String))
@homepage_set_in_block = T.let(false, T::Boolean)
@language_blocks = T.let({}, T::Hash[T::Array[String], Proc]) @language_blocks = T.let({}, T::Hash[T::Array[String], Proc])
@language_eval = T.let(nil, T.nilable(String)) @language_eval = T.let(nil, T.nilable(String))
@livecheck = T.let(Livecheck.new(cask), Livecheck) @livecheck = T.let(Livecheck.new(cask), Livecheck)
@livecheck_defined = T.let(false, T::Boolean) @livecheck_defined = T.let(false, T::Boolean)
@name = T.let([], T::Array[String]) @name = T.let([], T::Array[String])
@autobump = T.let(true, T::Boolean)
@no_autobump_defined = T.let(false, T::Boolean) @no_autobump_defined = T.let(false, T::Boolean)
@on_system_blocks_exist = T.let(false, T::Boolean) @on_system_blocks_exist = T.let(false, T::Boolean)
@os = T.let(nil, T.nilable(String))
@on_system_block_min_os = T.let(nil, T.nilable(MacOSVersion)) @on_system_block_min_os = T.let(nil, T.nilable(MacOSVersion))
@os = T.let(nil, T.nilable(String))
@os_set_in_block = T.let(false, T::Boolean)
@sha256 = T.let(nil, T.nilable(T.any(Checksum, Symbol))) @sha256 = T.let(nil, T.nilable(T.any(Checksum, Symbol)))
@sha256_set_in_block = T.let(false, T::Boolean)
@staged_path = T.let(nil, T.nilable(Pathname)) @staged_path = T.let(nil, T.nilable(Pathname))
@token = T.let(cask.token, String) @token = T.let(cask.token, String)
@url = T.let(nil, T.nilable(URL)) @url = T.let(nil, T.nilable(URL))
@url_set_in_block = T.let(false, T::Boolean)
@version = T.let(nil, T.nilable(DSL::Version)) @version = T.let(nil, T.nilable(DSL::Version))
@version_set_in_block = T.let(false, T::Boolean)
end end
sig { returns(T::Boolean) } sig { returns(T::Boolean) }
@ -216,7 +226,7 @@ module Cask
raise CaskInvalidError.new(cask, "'#{stanza}' stanza may only appear once.") raise CaskInvalidError.new(cask, "'#{stanza}' stanza may only appear once.")
end end
if instance_variable_defined?(:"@#{stanza}_set_in_block") && @called_in_on_system_block if instance_variable_get(:"@#{stanza}_set_in_block") && @called_in_on_system_block
raise CaskInvalidError.new(cask, "'#{stanza}' stanza may only be overridden once.") raise CaskInvalidError.new(cask, "'#{stanza}' stanza may only be overridden once.")
end end
end end
@ -476,7 +486,7 @@ module Cask
def add_implicit_macos_dependency def add_implicit_macos_dependency
return if (cask_depends_on = @depends_on).present? && cask_depends_on.macos.present? return if (cask_depends_on = @depends_on).present? && cask_depends_on.macos.present?
depends_on macos: ">= :#{MacOSVersion::SYMBOLS.key MacOSVersion::SYMBOLS.values.min}" depends_on macos: ">= #{MacOSVersion.new(HOMEBREW_MACOS_OLDEST_ALLOWED).to_sym.inspect}"
end end
# Declare conflicts that keep a cask from installing or working correctly. # Declare conflicts that keep a cask from installing or working correctly.

View File

@ -2,7 +2,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require "cask/utils" require "cask/utils"
require "extend/on_system" require "on_system"
module Cask module Cask
class DSL class DSL

View File

@ -52,16 +52,17 @@ module Cask
raise "Only a single 'depends_on macos' is allowed." if defined?(@macos) raise "Only a single 'depends_on macos' is allowed." if defined?(@macos)
# workaround for https://github.com/sorbet/sorbet/issues/6860 # workaround for https://github.com/sorbet/sorbet/issues/6860
first_arg = args.first&.to_s first_arg = args.first
first_arg_s = first_arg&.to_s
begin begin
@macos = if args.count > 1 @macos = if args.count > 1
MacOSRequirement.new([args], comparator: "==") MacOSRequirement.new([args], comparator: "==")
elsif MacOSVersion::SYMBOLS.key?(args.first) elsif first_arg.is_a?(Symbol) && MacOSVersion::SYMBOLS.key?(first_arg)
MacOSRequirement.new([args.first], comparator: "==") MacOSRequirement.new([args.first], comparator: "==")
elsif (md = /^\s*(?<comparator><|>|[=<>]=)\s*:(?<version>\S+)\s*$/.match(first_arg)) elsif (md = /^\s*(?<comparator><|>|[=<>]=)\s*:(?<version>\S+)\s*$/.match(first_arg_s))
MacOSRequirement.new([T.must(md[:version]).to_sym], comparator: md[:comparator]) MacOSRequirement.new([T.must(md[:version]).to_sym], comparator: md[:comparator])
elsif (md = /^\s*(?<comparator><|>|[=<>]=)\s*(?<version>\S+)\s*$/.match(first_arg)) elsif (md = /^\s*(?<comparator><|>|[=<>]=)\s*(?<version>\S+)\s*$/.match(first_arg_s))
MacOSRequirement.new([md[:version]], comparator: md[:comparator]) MacOSRequirement.new([md[:version]], comparator: md[:comparator])
# This is not duplicate of the first case: see `args.first` and a different comparator. # This is not duplicate of the first case: see `args.first` and a different comparator.
else # rubocop:disable Lint/DuplicateBranch else # rubocop:disable Lint/DuplicateBranch

View File

@ -4,6 +4,7 @@
require "formula_installer" require "formula_installer"
require "unpack_strategy" require "unpack_strategy"
require "utils/topological_hash" require "utils/topological_hash"
require "utils/analytics"
require "cask/config" require "cask/config"
require "cask/download" require "cask/download"
@ -149,7 +150,7 @@ module Cask
oh1 "Installing Cask #{Formatter.identifier(@cask)}" oh1 "Installing Cask #{Formatter.identifier(@cask)}"
# GitHub Actions globally disables Gatekeeper. # GitHub Actions globally disables Gatekeeper.
opoo "macOS's Gatekeeper has been disabled for this Cask" if !quarantine? && !GitHub::Actions.env_set? opoo_outside_github_actions "macOS's Gatekeeper has been disabled for this Cask" unless quarantine?
stage stage
@cask.config = @cask.default_config.merge(old_config) @cask.config = @cask.default_config.merge(old_config)
@ -303,6 +304,20 @@ on_request: true)
next if artifact.is_a?(Artifact::Binary) && !binaries? next if artifact.is_a?(Artifact::Binary) && !binaries?
artifact = T.cast(
artifact,
T.any(
Artifact::AbstractFlightBlock,
Artifact::Installer,
Artifact::KeyboardLayout,
Artifact::Mdimporter,
Artifact::Moved,
Artifact::Pkg,
Artifact::Qlplugin,
Artifact::Symlinked,
),
)
artifact.install_phase( artifact.install_phase(
command: @command, verbose: verbose?, adopt: adopt?, auto_updates: @cask.auto_updates, command: @command, verbose: verbose?, adopt: adopt?, auto_updates: @cask.auto_updates,
force: force?, predecessor: force: force?, predecessor:
@ -548,6 +563,18 @@ on_request: true)
artifacts.each do |artifact| artifacts.each do |artifact|
if artifact.respond_to?(:uninstall_phase) if artifact.respond_to?(:uninstall_phase)
artifact = T.cast(
artifact,
T.any(
Artifact::AbstractFlightBlock,
Artifact::KeyboardLayout,
Artifact::Moved,
Artifact::Qlplugin,
Artifact::Symlinked,
Artifact::Uninstall,
),
)
odebug "Uninstalling artifact of class #{artifact.class}" odebug "Uninstalling artifact of class #{artifact.class}"
artifact.uninstall_phase( artifact.uninstall_phase(
command: @command, command: @command,
@ -562,6 +589,8 @@ on_request: true)
next unless artifact.respond_to?(:post_uninstall_phase) next unless artifact.respond_to?(:post_uninstall_phase)
artifact = T.cast(artifact, Artifact::Uninstall)
odebug "Post-uninstalling artifact of class #{artifact.class}" odebug "Post-uninstalling artifact of class #{artifact.class}"
artifact.post_uninstall_phase( artifact.post_uninstall_phase(
command: @command, command: @command,
@ -575,7 +604,6 @@ on_request: true)
def zap def zap
load_installed_caskfile! load_installed_caskfile!
ohai "Implied `brew uninstall --cask #{@cask}`"
uninstall_artifacts uninstall_artifacts
if (zap_stanzas = @cask.artifacts.select { |a| a.is_a?(Artifact::Zap) }).empty? if (zap_stanzas = @cask.artifacts.select { |a| a.is_a?(Artifact::Zap) }).empty?
opoo "No zap stanza present for Cask '#{@cask}'" opoo "No zap stanza present for Cask '#{@cask}'"
@ -764,10 +792,10 @@ on_request: true)
if installed_caskfile&.exist? if installed_caskfile&.exist?
begin begin
@cask = CaskLoader.load(installed_caskfile) @cask = CaskLoader.load_from_installed_caskfile(installed_caskfile)
return return
rescue CaskInvalidError rescue CaskInvalidError, CaskUnavailableError
# could be caused by trying to load outdated caskfile # could be caused by trying to load outdated or deleted caskfile
end end
end end

View File

@ -5,10 +5,24 @@ require "tab"
module Cask module Cask
class Tab < ::AbstractTab class Tab < ::AbstractTab
attr_accessor :uninstall_flight_blocks, :uninstall_artifacts sig { returns(T.nilable(T::Boolean)) }
attr_accessor :uninstall_flight_blocks
sig { returns(T.nilable(T::Array[T.untyped])) }
attr_accessor :uninstall_artifacts
sig { params(attributes: T::Hash[String, T.untyped]).void }
def initialize(attributes = {})
@uninstall_flight_blocks = T.let(nil, T.nilable(T::Boolean))
@uninstall_artifacts = T.let(nil, T.nilable(T::Array[T.untyped]))
super
end
# Instantiates a {Tab} for a new installation of a cask. # Instantiates a {Tab} for a new installation of a cask.
def self.create(cask) sig { override.params(formula_or_cask: T.any(Formula, Cask)).returns(T.attached_class) }
def self.create(formula_or_cask)
cask = T.cast(formula_or_cask, Cask)
tab = super tab = super
tab.tabfile = cask.metadata_main_container_path/FILENAME tab.tabfile = cask.metadata_main_container_path/FILENAME
@ -23,6 +37,7 @@ module Cask
# Returns a {Tab} for an already installed cask, # Returns a {Tab} for an already installed cask,
# or a fake one if the cask is not installed. # or a fake one if the cask is not installed.
sig { params(cask: Cask).returns(T.attached_class) }
def self.for_cask(cask) def self.for_cask(cask)
path = cask.metadata_main_container_path/FILENAME path = cask.metadata_main_container_path/FILENAME
@ -40,6 +55,7 @@ module Cask
tab tab
end end
sig { returns(T.attached_class) }
def self.empty def self.empty
tab = super tab = super
tab.uninstall_flight_blocks = false tab.uninstall_flight_blocks = false
@ -76,10 +92,12 @@ module Cask
runtime_deps runtime_deps
end end
sig { returns(T.nilable(String)) }
def version def version
source["version"] source["version"]
end end
sig { params(_args: T.untyped).returns(String) }
def to_json(*_args) def to_json(*_args)
attributes = { attributes = {
"homebrew_version" => homebrew_version, "homebrew_version" => homebrew_version,
@ -98,6 +116,7 @@ module Cask
JSON.pretty_generate(attributes) JSON.pretty_generate(attributes)
end end
sig { returns(String) }
def to_s def to_s
s = ["Installed"] s = ["Installed"]
s << "using the formulae.brew.sh API" if loaded_from_api s << "using the formulae.brew.sh API" if loaded_from_api

View File

@ -11,11 +11,12 @@ module Cask
T.any(URI::Generic, String, [T.any(URI::Generic, String), T::Hash[Symbol, T.untyped]]) T.any(URI::Generic, String, [T.any(URI::Generic, String), T::Hash[Symbol, T.untyped]])
end end
# Methods for the `url` stanza.
class DSL class DSL
sig { returns(T.any(URI::Generic, String)) } sig { returns(T.any(URI::Generic, String)) }
attr_reader :uri attr_reader :uri
sig { returns(T.nilable(T::Array[String])) } sig { returns(T.nilable(T::Hash[T.any(Symbol, String), String])) }
attr_reader :revisions attr_reader :revisions
sig { returns(T.nilable(T::Boolean)) } sig { returns(T.nilable(T::Boolean)) }
@ -57,7 +58,7 @@ module Cask
# @api public # @api public
branch: T.nilable(String), branch: T.nilable(String),
# @api public # @api public
revisions: T.nilable(T::Array[String]), revisions: T.nilable(T::Hash[T.any(Symbol, String), String]),
# @api public # @api public
revision: T.nilable(String), revision: T.nilable(String),
# @api public # @api public
@ -87,7 +88,7 @@ module Cask
specs[:using] = @using = T.let(using, T.any(T::Class[AbstractDownloadStrategy], Symbol, NilClass)) specs[:using] = @using = T.let(using, T.any(T::Class[AbstractDownloadStrategy], Symbol, NilClass))
specs[:tag] = @tag = T.let(tag, T.nilable(String)) specs[:tag] = @tag = T.let(tag, T.nilable(String))
specs[:branch] = @branch = T.let(branch, T.nilable(String)) specs[:branch] = @branch = T.let(branch, T.nilable(String))
specs[:revisions] = @revisions = T.let(revisions, T.nilable(T::Array[String])) specs[:revisions] = @revisions = T.let(revisions, T.nilable(T::Hash[T.any(Symbol, String), String]))
specs[:revision] = @revision = T.let(revision, T.nilable(String)) specs[:revision] = @revision = T.let(revision, T.nilable(String))
specs[:trust_cert] = @trust_cert = T.let(trust_cert, T.nilable(T::Boolean)) specs[:trust_cert] = @trust_cert = T.let(trust_cert, T.nilable(T::Boolean))
specs[:cookies] = @cookies = T.let(cookies, T.nilable(T::Hash[String, String])) specs[:cookies] = @cookies = T.let(cookies, T.nilable(T::Hash[String, String]))
@ -101,6 +102,7 @@ module Cask
end end
end end
# Allow passing a block to the `url` stanza.
class BlockDSL class BlockDSL
# Allow accessing the URL associated with page contents. # Allow accessing the URL associated with page contents.
class PageWithURL < SimpleDelegator class PageWithURL < SimpleDelegator
@ -197,7 +199,7 @@ module Cask
using: T.any(T::Class[AbstractDownloadStrategy], Symbol, NilClass), using: T.any(T::Class[AbstractDownloadStrategy], Symbol, NilClass),
tag: T.nilable(String), tag: T.nilable(String),
branch: T.nilable(String), branch: T.nilable(String),
revisions: T.nilable(T::Array[String]), revisions: T.nilable(T::Hash[T.any(Symbol, String), String]),
revision: T.nilable(String), revision: T.nilable(String),
trust_cert: T.nilable(T::Boolean), trust_cert: T.nilable(T::Boolean),
cookies: T.nilable(T::Hash[String, String]), cookies: T.nilable(T::Hash[String, String]),

View File

@ -14,40 +14,54 @@ class Caveats
sig { params(formula: Formula).void } sig { params(formula: Formula).void }
def initialize(formula) def initialize(formula)
@formula = formula @formula = formula
@caveats = T.let(nil, T.nilable(String))
@completions_and_elisp = T.let(nil, T.nilable(T::Array[String]))
end end
sig { returns(String) } sig { returns(String) }
def caveats def caveats
caveats = [] @caveats ||= begin
build = formula.build caveats = []
begin build = formula.build
formula.build = Tab.for_formula(formula) begin
string = formula.caveats.to_s formula.build = Tab.for_formula(formula)
caveats << "#{string.chomp}\n" unless string.empty? string = formula.caveats.to_s
ensure caveats << "#{string.chomp}\n" unless string.empty?
formula.build = build ensure
formula.build = build
end
caveats << keg_only_text
caveats << service_caveats
caveats.compact.join("\n")
end end
caveats << keg_only_text
valid_shells = [:bash, :zsh, :fish, :pwsh].freeze
current_shell = Utils::Shell.preferred || Utils::Shell.parent
shells = if current_shell.present? &&
(shell_sym = current_shell.to_sym) &&
valid_shells.include?(shell_sym)
[shell_sym]
else
valid_shells
end
shells.each do |shell|
caveats << function_completion_caveats(shell)
end
caveats << service_caveats
caveats << elisp_caveats
caveats.compact.join("\n")
end end
delegate [:empty?, :to_s] => :caveats sig { returns(T::Boolean) }
def empty?
caveats.blank? && completions_and_elisp.blank?
end
delegate [:to_s] => :caveats
sig { returns(T::Array[String]) }
def completions_and_elisp
@completions_and_elisp ||= begin
valid_shells = [:bash, :zsh, :fish, :pwsh].freeze
current_shell = Utils::Shell.preferred || Utils::Shell.parent
shells = if current_shell.present? &&
(shell_sym = current_shell.to_sym) &&
valid_shells.include?(shell_sym)
[shell_sym]
else
valid_shells
end
completions_and_elisp = shells.map do |shell|
function_completion_caveats(shell)
end
completions_and_elisp << elisp_caveats
completions_and_elisp.compact
end
end
sig { params(skip_reason: T::Boolean).returns(T.nilable(String)) } sig { params(skip_reason: T::Boolean).returns(T.nilable(String)) }
def keg_only_text(skip_reason: false) def keg_only_text(skip_reason: false)

View File

@ -571,6 +571,7 @@ module Homebrew
end end
return unless available return unless available
return if Context.current.quiet? return if Context.current.quiet?
return if cask&.old_tokens&.include?(ref)
opoo package_conflicts_message(ref, loaded_type, cask) opoo package_conflicts_message(ref, loaded_type, cask)
end end

View File

@ -208,11 +208,15 @@ module Homebrew
return if global_switch return if global_switch
description = option_description(description, *names, hidden:) description = option_description(description, *names, hidden:)
process_option(*names, description, type: :switch, hidden:) unless disable env, counterpart = env
if env && @non_global_processed_options.any?
affix = counterpart ? " and `#{counterpart}` is passed." : "."
description += " Enabled by default if `$HOMEBREW_#{env.upcase}` is set#{affix}"
end
if replacement || disable if replacement || disable
description += " (#{disable ? "disabled" : "deprecated"}#{"; replaced by #{replacement}" if replacement})" description += " (#{disable ? "disabled" : "deprecated"}#{"; replaced by #{replacement}" if replacement})"
end end
process_option(*names, description, type: :switch, hidden:) unless disable
@parser.public_send(method, *names, *wrap_option_desc(description)) do |value| @parser.public_send(method, *names, *wrap_option_desc(description)) do |value|
# This odeprecated should stick around indefinitely. # This odeprecated should stick around indefinitely.

View File

@ -31,7 +31,7 @@ module Homebrew
sig { override.void } sig { override.void }
def run def run
ENV.activate_extensions! ENV.activate_extensions!
T.cast(ENV, Superenv).deps = args.named.to_formulae if superenv?(nil) ENV.deps = args.named.to_formulae if superenv?(nil)
ENV.setup_build_environment ENV.setup_build_environment
shell = if args.plain? shell = if args.plain?

View File

@ -73,11 +73,10 @@ module Homebrew
description: "`install` prints output from commands as they are run. " \ description: "`install` prints output from commands as they are run. " \
"`check` lists all missing dependencies." "`check` lists all missing dependencies."
switch "--no-upgrade", switch "--no-upgrade",
env: :bundle_no_upgrade,
description: "`install` does not run `brew upgrade` on outdated dependencies. " \ description: "`install` does not run `brew upgrade` on outdated dependencies. " \
"`check` does not check for outdated dependencies. " \ "`check` does not check for outdated dependencies. " \
"Note they may still be upgraded by `brew install` if needed. " \ "Note they may still be upgraded by `brew install` if needed.",
"This is enabled by default if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set." env: :bundle_no_upgrade
switch "--upgrade", switch "--upgrade",
description: "`install` runs `brew upgrade` on outdated dependencies, " \ description: "`install` runs `brew upgrade` on outdated dependencies, " \
"even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set." "even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set."
@ -87,21 +86,18 @@ module Homebrew
switch "--install", switch "--install",
description: "Run `install` before continuing to other operations e.g. `exec`." description: "Run `install` before continuing to other operations e.g. `exec`."
switch "--services", switch "--services",
env: :bundle_services, description: "Temporarily start services while running the `exec` or `sh` command.",
description: "Temporarily start services while running the `exec` or `sh` command. " \ env: :bundle_services
"This is enabled by default if `$HOMEBREW_BUNDLE_SERVICES` is set."
switch "-f", "--force", switch "-f", "--force",
description: "`install` runs with `--force`/`--overwrite`. " \ description: "`install` runs with `--force`/`--overwrite`. " \
"`dump` overwrites an existing `Brewfile`. " \ "`dump` overwrites an existing `Brewfile`. " \
"`cleanup` actually performs its cleanup operations." "`cleanup` actually performs its cleanup operations."
switch "--cleanup", switch "--cleanup",
env: :bundle_install_cleanup, description: "`install` performs cleanup operation, same as running `cleanup --force`.",
description: "`install` performs cleanup operation, same as running `cleanup --force`. " \ env: [:bundle_install_cleanup, "--global"]
"This is enabled by default if `$HOMEBREW_BUNDLE_INSTALL_CLEANUP` is set and " \
"`--global` is passed."
switch "--all", switch "--all",
description: "`list` all dependencies." description: "`list` all dependencies."
switch "--formula", "--brews", switch "--formula", "--formulae", "--brews",
description: "`list`, `dump` or `cleanup` Homebrew formula dependencies." description: "`list`, `dump` or `cleanup` Homebrew formula dependencies."
switch "--cask", "--casks", switch "--cask", "--casks",
description: "`list`, `dump` or `cleanup` Homebrew cask dependencies." description: "`list`, `dump` or `cleanup` Homebrew cask dependencies."
@ -114,14 +110,12 @@ module Homebrew
switch "--vscode", switch "--vscode",
description: "`list`, `dump` or `cleanup` VSCode (and forks/variants) extensions." description: "`list`, `dump` or `cleanup` VSCode (and forks/variants) extensions."
switch "--no-vscode", switch "--no-vscode",
env: :bundle_dump_no_vscode, description: "`dump` without VSCode (and forks/variants) extensions.",
description: "`dump` without VSCode (and forks/variants) extensions. " \ env: :bundle_dump_no_vscode
"This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set."
switch "--describe", switch "--describe",
env: :bundle_dump_describe,
description: "`dump` adds a description comment above each line, unless the " \ description: "`dump` adds a description comment above each line, unless the " \
"dependency does not have a description. " \ "dependency does not have a description.",
"This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_DESCRIBE` is set." env: :bundle_dump_describe
switch "--no-restart", switch "--no-restart",
description: "`dump` does not add `restart_service` to formula lines." description: "`dump` does not add `restart_service` to formula lines."
switch "--zap", switch "--zap",
@ -168,7 +162,7 @@ module Homebrew
zap = args.zap? zap = args.zap?
Homebrew::Bundle.upgrade_formulae = args.upgrade_formulae Homebrew::Bundle.upgrade_formulae = args.upgrade_formulae
no_type_args = !args.brews? && !args.casks? && !args.taps? && !args.mas? && !args.whalebrew? && !args.vscode? no_type_args = [args.formulae?, args.casks?, args.taps?, args.mas?, args.whalebrew?, args.vscode?].none?
if args.install? if args.install?
if [nil, "install", "upgrade"].include?(subcommand) if [nil, "install", "upgrade"].include?(subcommand)
@ -215,7 +209,7 @@ module Homebrew
describe: args.describe?, describe: args.describe?,
no_restart: args.no_restart?, no_restart: args.no_restart?,
taps: args.taps? || no_type_args, taps: args.taps? || no_type_args,
brews: args.brews? || no_type_args, formulae: args.formulae? || no_type_args,
casks: args.casks? || no_type_args, casks: args.casks? || no_type_args,
mas: args.mas? || no_type_args, mas: args.mas? || no_type_args,
whalebrew: args.whalebrew? || no_type_args, whalebrew: args.whalebrew? || no_type_args,
@ -228,7 +222,7 @@ module Homebrew
require "bundle/commands/cleanup" require "bundle/commands/cleanup"
Homebrew::Bundle::Commands::Cleanup.run( Homebrew::Bundle::Commands::Cleanup.run(
global:, file:, force:, zap:, global:, file:, force:, zap:,
brews: args.brews? || no_type_args, formulae: args.formulae? || no_type_args,
casks: args.casks? || no_type_args, casks: args.casks? || no_type_args,
taps: args.taps? || no_type_args, taps: args.taps? || no_type_args,
vscode: args.vscode? || no_type_args vscode: args.vscode? || no_type_args
@ -241,7 +235,7 @@ module Homebrew
Homebrew::Bundle::Commands::List.run( Homebrew::Bundle::Commands::List.run(
global:, global:,
file:, file:,
brews: args.brews? || args.all? || no_type_args, formulae: args.formulae? || args.all? || no_type_args,
casks: args.casks? || args.all?, casks: args.casks? || args.all?,
taps: args.taps? || args.all?, taps: args.taps? || args.all?,
mas: args.mas? || args.all?, mas: args.mas? || args.all?,
@ -249,9 +243,9 @@ module Homebrew
vscode: args.vscode? || args.all?, vscode: args.vscode? || args.all?,
) )
when "add", "remove" when "add", "remove"
# We intentionally omit the `s` from `brews`, `casks`, and `taps` for ease of handling later. # We intentionally omit the s from `brews`, `casks`, and `taps` for ease of handling later.
type_hash = { type_hash = {
brew: args.brews?, brew: args.formulae?,
cask: args.casks?, cask: args.casks?,
tap: args.taps?, tap: args.taps?,
mas: args.mas?, mas: args.mas?,
@ -282,17 +276,7 @@ module Homebrew
_subcommand, *named_args = args.named _subcommand, *named_args = args.named
named_args named_args
when "sh" when "sh"
preferred_path = Utils::Shell.preferred_path(default: "/bin/bash") ["sh"]
notice = unless Homebrew::EnvConfig.no_env_hints?
<<~EOS
Your shell has been configured to use a build environment from your `Brewfile`.
This should help you build stuff.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
When done, type `exit`.
EOS
end
ENV["HOMEBREW_FORCE_API_AUTO_UPDATE"] = nil
[Utils::Shell.shell_with_prompt("brew bundle", preferred_path:, notice:)]
when "env" when "env"
["env"] ["env"]
end end

View File

@ -18,8 +18,7 @@ module Homebrew
If any version of each formula argument is installed and no other options If any version of each formula argument is installed and no other options
are passed, this command displays their actual runtime dependencies (similar are passed, this command displays their actual runtime dependencies (similar
to `brew linkage`), which may differ from the current versions' stated to `brew linkage`), which may differ from a formula's declared dependencies.
dependencies if the installed versions are outdated.
*Note:* `--missing` and `--skip-recommended` have precedence over `--include-*`. *Note:* `--missing` and `--skip-recommended` have precedence over `--include-*`.
EOS EOS
@ -92,26 +91,50 @@ module Homebrew
raise UsageError, "`brew deps --arch=all` is not supported" if args.arch == "all" raise UsageError, "`brew deps --arch=all` is not supported" if args.arch == "all"
os, arch = T.must(args.os_arch_combinations.first) os, arch = T.must(args.os_arch_combinations.first)
all = args.eval_all? eval_all = args.eval_all?
Formulary.enable_factory_cache! Formulary.enable_factory_cache!
SimulateSystem.with(os:, arch:) do SimulateSystem.with(os:, arch:) do
recursive = !args.direct? @use_runtime_dependencies = true
installed = args.installed? || dependents(args.named.to_formulae_and_casks).all?(&:any_version_installed?)
@use_runtime_dependencies = installed && recursive && installed = args.installed? || dependents(args.named.to_formulae_and_casks).all?(&:any_version_installed?)
!args.tree? && unless installed
!args.graph? && not_using_runtime_dependencies_reason = if args.installed?
!args.HEAD? && "not all the named formulae were installed"
!args.include_implicit? && else
!args.include_build? && "`--installed` was not passed"
!args.include_test? && end
!args.include_optional? &&
!args.skip_recommended? && @use_runtime_dependencies = false
!args.missing? && end
args.os.nil? &&
args.arch.nil? %w[direct tree graph HEAD skip_recommended missing
include_implicit include_build include_test include_optional].each do |arg|
next unless args.public_send("#{arg}?")
not_using_runtime_dependencies_reason = "--#{arg.tr("_", "-")} was passed"
@use_runtime_dependencies = false
end
%w[os arch].each do |arg|
next if args.public_send(arg).nil?
not_using_runtime_dependencies_reason = "--#{arg.tr("_", "-")} was passed"
@use_runtime_dependencies = false
end
if !@use_runtime_dependencies && !Homebrew::EnvConfig.no_env_hints?
opoo <<~EOS
`brew deps` is not the actual runtime dependencies because #{not_using_runtime_dependencies_reason}!
This means dependencies may differ from a formula's declared dependencies.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
EOS
end
recursive = !args.direct?
if args.tree? || args.graph? if args.tree? || args.graph?
dependents = if args.named.present? dependents = if args.named.present?
@ -141,9 +164,9 @@ module Homebrew
puts_deps_tree(dependents, recursive:) puts_deps_tree(dependents, recursive:)
return return
elsif all elsif eval_all
puts_deps(sorted_dependents( puts_deps(sorted_dependents(
Formula.all(eval_all: args.eval_all?) + Cask::Cask.all(eval_all: args.eval_all?), Formula.all(eval_all:) + Cask::Cask.all(eval_all:),
), recursive:) ), recursive:)
return return
elsif !args.no_named? && args.for_each? elsif !args.no_named? && args.for_each?

View File

@ -25,7 +25,8 @@ module Homebrew
"it is interpreted as a regular expression." "it is interpreted as a regular expression."
switch "--eval-all", switch "--eval-all",
description: "Evaluate all available formulae and casks, whether installed or not, to search their " \ description: "Evaluate all available formulae and casks, whether installed or not, to search their " \
"descriptions. Implied if `$HOMEBREW_EVAL_ALL` is set." "descriptions.",
env: :eval_all
switch "--formula", "--formulae", switch "--formula", "--formulae",
description: "Treat all named arguments as formulae." description: "Treat all named arguments as formulae."
switch "--cask", "--casks", switch "--cask", "--casks",
@ -47,7 +48,7 @@ module Homebrew
end end
if search_type.present? if search_type.present?
if !args.eval_all? && !Homebrew::EnvConfig.eval_all? && Homebrew::EnvConfig.no_install_from_api? if !args.eval_all? && Homebrew::EnvConfig.no_install_from_api?
raise UsageError, "`brew desc --search` needs `--eval-all` passed or `$HOMEBREW_EVAL_ALL` set!" raise UsageError, "`brew desc --search` needs `--eval-all` passed or `$HOMEBREW_EVAL_ALL` set!"
end end

View File

@ -9,7 +9,7 @@ module Homebrew
cmd_args do cmd_args do
description <<~EOS description <<~EOS
Control Homebrew's developer mode. When developer mode is enabled, Control Homebrew's developer mode. When developer mode is enabled,
`brew update` will update Homebrew to the latest commit on the `master` `brew update` will update Homebrew to the latest commit on the `main`
branch instead of the latest stable version along with some other behaviour changes. branch instead of the latest stable version along with some other behaviour changes.
`brew developer` [`state`]: `brew developer` [`state`]:
@ -38,7 +38,7 @@ module Homebrew
puts "However, `brew update` will update to the latest stable tag because " \ puts "However, `brew update` will update to the latest stable tag because " \
"#{Tty.bold}HOMEBREW_UPDATE_TO_TAG#{Tty.reset} is set." "#{Tty.bold}HOMEBREW_UPDATE_TO_TAG#{Tty.reset} is set."
else else
puts "`brew update` will update to the latest commit on the `master` branch." puts "`brew update` will update to the latest commit on the `main` branch."
end end
else else
puts "`brew update` will update to the latest stable tag." puts "`brew update` will update to the latest stable tag."

View File

@ -1,4 +1,4 @@
# typed: true # rubocop:todo Sorbet/StrictSigil # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
@ -6,6 +6,7 @@ require "formula"
require "fetch" require "fetch"
require "cask/download" require "cask/download"
require "retryable_download" require "retryable_download"
require "download_queue"
module Homebrew module Homebrew
module Cmd module Cmd
@ -69,15 +70,16 @@ module Homebrew
named_args [:formula, :cask], min: 1 named_args [:formula, :cask], min: 1
end end
sig { returns(Integer) }
def concurrency def concurrency
@concurrency ||= args.concurrency&.to_i || 1 @concurrency ||= T.let(args.concurrency&.to_i || 1, T.nilable(Integer))
end end
sig { returns(DownloadQueue) }
def download_queue def download_queue
@download_queue ||= begin @download_queue ||= T.let(begin
require "download_queue"
DownloadQueue.new(concurrency) DownloadQueue.new(concurrency)
end end, T.nilable(DownloadQueue))
end end
class Spinner class Spinner
@ -96,8 +98,8 @@ module Homebrew
sig { void } sig { void }
def initialize def initialize
@start = Time.now @start = T.let(Time.now, Time)
@i = 0 @i = T.let(0, Integer)
end end
sig { returns(String) } sig { returns(String) }
@ -136,7 +138,7 @@ module Homebrew
bucket.each do |formula_or_cask| bucket.each do |formula_or_cask|
case formula_or_cask case formula_or_cask
when Formula when Formula
formula = T.cast(formula_or_cask, Formula) formula = formula_or_cask
ref = formula.loaded_from_api? ? formula.full_name : formula.path ref = formula.loaded_from_api? ? formula.full_name : formula.path
os_arch_combinations.each do |os, arch| os_arch_combinations.each do |os, arch|
@ -189,7 +191,9 @@ module Homebrew
next if fetched_bottle next if fetched_bottle
fetch_downloadable(formula.resource) if (resource = formula.resource)
fetch_downloadable(resource)
end
formula.resources.each do |r| formula.resources.each do |r|
fetch_downloadable(r) fetch_downloadable(r)
@ -231,7 +235,7 @@ module Homebrew
end end
else else
spinner = Spinner.new spinner = Spinner.new
remaining_downloads = downloads.dup remaining_downloads = downloads.dup.to_a
previous_pending_line_count = 0 previous_pending_line_count = 0
begin begin
@ -332,10 +336,13 @@ module Homebrew
private private
sig { returns(T::Hash[T.any(Resource, Bottle, Cask::Download), Concurrent::Promises::Future]) }
def downloads def downloads
@downloads ||= {} @downloads ||= T.let({}, T.nilable(T::Hash[T.any(Resource, Bottle, Cask::Download),
Concurrent::Promises::Future]))
end end
sig { params(downloadable: T.any(Resource, Bottle, Cask::Download)).void }
def fetch_downloadable(downloadable) def fetch_downloadable(downloadable)
downloads[downloadable] ||= begin downloads[downloadable] ||= begin
tries = args.retry? ? {} : { tries: 1 } tries = args.retry? ? {} : { tries: 1 }

View File

@ -1,4 +1,4 @@
# typed: true # rubocop:todo Sorbet/StrictSigil # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
@ -18,7 +18,7 @@ module Homebrew
class Info < AbstractCommand class Info < AbstractCommand
VALID_DAYS = %w[30 90 365].freeze VALID_DAYS = %w[30 90 365].freeze
VALID_FORMULA_CATEGORIES = %w[install install-on-request build-error].freeze VALID_FORMULA_CATEGORIES = %w[install install-on-request build-error].freeze
VALID_CATEGORIES = (VALID_FORMULA_CATEGORIES + %w[cask-install os-version]).freeze VALID_CATEGORIES = T.let((VALID_FORMULA_CATEGORIES + %w[cask-install os-version]).freeze, T::Array[String])
cmd_args do cmd_args do
description <<~EOS description <<~EOS
@ -57,7 +57,7 @@ module Homebrew
switch "--eval-all", switch "--eval-all",
depends_on: "--json", depends_on: "--json",
description: "Evaluate all available formulae and casks, whether installed or not, to print their " \ description: "Evaluate all available formulae and casks, whether installed or not, to print their " \
"JSON. Implied if `$HOMEBREW_EVAL_ALL` is set." "JSON."
switch "--variations", switch "--variations",
depends_on: "--json", depends_on: "--json",
description: "Include the variations hash in each formula's JSON output." description: "Include the variations hash in each formula's JSON output."
@ -96,14 +96,15 @@ module Homebrew
end end
print_analytics print_analytics
elsif args.json elsif (json = args.json)
all = args.eval_all? print_json(json, args.eval_all?)
print_json(all)
elsif args.github? elsif args.github?
raise FormulaOrCaskUnspecifiedError if args.no_named? raise FormulaOrCaskUnspecifiedError if args.no_named?
exec_browser(*args.named.to_formulae_and_casks.map { |f| github_info(f) }) exec_browser(*args.named.to_formulae_and_casks.map do |formula_keg_or_cask|
formula_or_cask = T.cast(formula_keg_or_cask, T.any(Formula, Cask::Cask))
github_info(formula_or_cask)
end)
elsif args.no_named? elsif args.no_named?
print_statistics print_statistics
else else
@ -111,6 +112,7 @@ module Homebrew
end end
end end
sig { params(remote: String, path: String).returns(String) }
def github_remote_path(remote, path) def github_remote_path(remote, path)
if remote =~ %r{^(?:https?://|git(?:@|://))github\.com[:/](.+)/(.+?)(?:\.git)?$} if remote =~ %r{^(?:https?://|git(?:@|://))github\.com[:/](.+)/(.+?)(?:\.git)?$}
"https://github.com/#{Regexp.last_match(1)}/#{Regexp.last_match(2)}/blob/HEAD/#{path}" "https://github.com/#{Regexp.last_match(1)}/#{Regexp.last_match(2)}/blob/HEAD/#{path}"
@ -175,6 +177,7 @@ module Homebrew
end end
end end
sig { params(version: T.any(T::Boolean, String)).returns(Symbol) }
def json_version(version) def json_version(version)
version_hash = { version_hash = {
true => :default, true => :default,
@ -187,16 +190,16 @@ module Homebrew
version_hash[version] version_hash[version]
end end
sig { params(all: T::Boolean).void } sig { params(json: T.any(T::Boolean, String), eval_all: T::Boolean).void }
def print_json(all) def print_json(json, eval_all)
raise FormulaOrCaskUnspecifiedError if !(all || args.installed?) && args.no_named? raise FormulaOrCaskUnspecifiedError if !(eval_all || args.installed?) && args.no_named?
json = case json_version(args.json) json = case json_version(json)
when :v1, :default when :v1, :default
raise UsageError, "Cannot specify `--cask` when using `--json=v1`!" if args.cask? raise UsageError, "Cannot specify `--cask` when using `--json=v1`!" if args.cask?
formulae = if all formulae = if eval_all
Formula.all(eval_all: args.eval_all?).sort Formula.all(eval_all:).sort
elsif args.installed? elsif args.installed?
Formula.installed.sort Formula.installed.sort
else else
@ -210,10 +213,10 @@ module Homebrew
end end
when :v2 when :v2
formulae, casks = T.let( formulae, casks = T.let(
if all if eval_all
[ [
Formula.all(eval_all: args.eval_all?).sort, Formula.all(eval_all:).sort,
Cask::Cask.all(eval_all: args.eval_all?).sort_by(&:full_name), Cask::Cask.all(eval_all:).sort_by(&:full_name),
] ]
elsif args.installed? elsif args.installed?
[Formula.installed.sort, Cask::Caskroom.casks.sort_by(&:full_name)] [Formula.installed.sort, Cask::Caskroom.casks.sort_by(&:full_name)]
@ -240,25 +243,31 @@ module Homebrew
puts JSON.pretty_generate(json) puts JSON.pretty_generate(json)
end end
sig { params(formula_or_cask: T.any(Formula, Cask::Cask)).returns(String) }
def github_info(formula_or_cask) def github_info(formula_or_cask)
return formula_or_cask.path if formula_or_cask.tap.blank? || formula_or_cask.tap.remote.blank?
path = case formula_or_cask path = case formula_or_cask
when Formula when Formula
formula = formula_or_cask formula = formula_or_cask
formula.path.relative_path_from(T.must(formula.tap).path) tap = formula.tap
return formula.path.to_s if tap.blank? || tap.remote.blank?
formula.path.relative_path_from(tap.path)
when Cask::Cask when Cask::Cask
cask = formula_or_cask cask = formula_or_cask
tap = cask.tap
return cask.sourcefile_path.to_s if tap.blank? || tap.remote.blank?
if cask.sourcefile_path.blank? || cask.sourcefile_path.extname != ".rb" if cask.sourcefile_path.blank? || cask.sourcefile_path.extname != ".rb"
return "#{cask.tap.default_remote}/blob/HEAD/#{cask.tap.relative_cask_path(cask.token)}" return "#{tap.default_remote}/blob/HEAD/#{tap.relative_cask_path(cask.token)}"
end end
cask.sourcefile_path.relative_path_from(cask.tap.path) cask.sourcefile_path.relative_path_from(tap.path)
end end
github_remote_path(formula_or_cask.tap.remote, path) github_remote_path(tap.remote, path.to_s)
end end
sig { params(formula: Formula).void }
def info_formula(formula) def info_formula(formula)
specs = [] specs = []
@ -356,6 +365,7 @@ module Homebrew
Utils::Analytics.formula_output(formula, args:) Utils::Analytics.formula_output(formula, args:)
end end
sig { params(dependencies: T::Array[Dependency]).returns(String) }
def decorate_dependencies(dependencies) def decorate_dependencies(dependencies)
deps_status = dependencies.map do |dep| deps_status = dependencies.map do |dep|
if dep.satisfied?([]) if dep.satisfied?([])
@ -367,6 +377,7 @@ module Homebrew
deps_status.join(", ") deps_status.join(", ")
end end
sig { params(requirements: T::Array[Requirement]).returns(String) }
def decorate_requirements(requirements) def decorate_requirements(requirements)
req_status = requirements.map do |req| req_status = requirements.map do |req|
req_s = req.display_s req_s = req.display_s
@ -375,12 +386,14 @@ module Homebrew
req_status.join(", ") req_status.join(", ")
end end
sig { params(dep: Dependency).returns(String) }
def dep_display_s(dep) def dep_display_s(dep)
return dep.name if dep.option_tags.empty? return dep.name if dep.option_tags.empty?
"#{dep.name} #{dep.option_tags.map { |o| "--#{o}" }.join(" ")}" "#{dep.name} #{dep.option_tags.map { |o| "--#{o}" }.join(" ")}"
end end
sig { params(cask: Cask::Cask).void }
def info_cask(cask) def info_cask(cask)
require "cask/info" require "cask/info"

View File

@ -33,8 +33,8 @@ module Homebrew
description: "If brewing fails, open an interactive debugging session with access to IRB " \ description: "If brewing fails, open an interactive debugging session with access to IRB " \
"or a shell inside the temporary build directory." "or a shell inside the temporary build directory."
switch "--display-times", switch "--display-times",
env: :display_install_times, description: "Print install times for each package at the end of the run.",
description: "Print install times for each package at the end of the run." env: :display_install_times
switch "-f", "--force", switch "-f", "--force",
description: "Install formulae without checking for previously installed keg-only or " \ description: "Install formulae without checking for previously installed keg-only or " \
"non-migrated versions. When installing casks, overwrite existing files " \ "non-migrated versions. When installing casks, overwrite existing files " \
@ -44,9 +44,9 @@ module Homebrew
switch "-n", "--dry-run", switch "-n", "--dry-run",
description: "Show what would be installed, but do not actually install anything." description: "Show what would be installed, but do not actually install anything."
switch "--ask", switch "--ask",
env: :ask,
description: "Ask for confirmation before downloading and installing formulae. " \ description: "Ask for confirmation before downloading and installing formulae. " \
"Print bottles and dependencies download size and install size." "Print download and install sizes of bottles and dependencies.",
env: :ask
[ [
[:switch, "--formula", "--formulae", { [:switch, "--formula", "--formulae", {
description: "Treat all named arguments as formulae.", description: "Treat all named arguments as formulae.",
@ -310,9 +310,7 @@ module Homebrew
Install.perform_preinstall_checks_once Install.perform_preinstall_checks_once
Install.check_cc_argv(args.cc) Install.check_cc_argv(args.cc)
Install.ask_formulae(installed_formulae, args: args) if args.ask? formulae_installer = Install.formula_installers(
Install.install_formulae(
installed_formulae, installed_formulae,
installed_on_request: !args.as_dependency?, installed_on_request: !args.as_dependency?,
installed_as_dependency: args.as_dependency?, installed_as_dependency: args.as_dependency?,
@ -338,9 +336,10 @@ module Homebrew
skip_link: args.skip_link?, skip_link: args.skip_link?,
) )
Upgrade.check_installed_dependents( dependants = Upgrade.dependants(
installed_formulae, installed_formulae,
flags: args.flags_only, flags: args.flags_only,
ask: args.ask?,
installed_on_request: !args.as_dependency?, installed_on_request: !args.as_dependency?,
force_bottle: args.force_bottle?, force_bottle: args.force_bottle?,
build_from_source_formulae: args.build_from_source_formulae, build_from_source_formulae: args.build_from_source_formulae,
@ -354,6 +353,28 @@ module Homebrew
dry_run: args.dry_run?, dry_run: args.dry_run?,
) )
# Main block: if asking the user is enabled, show dependency and size information.
Install.ask_formulae(formulae_installer, dependants, args: args) if args.ask?
Install.install_formulae(formulae_installer,
dry_run: args.dry_run?,
verbose: args.verbose?)
Upgrade.upgrade_dependents(
dependants, installed_formulae,
flags: args.flags_only,
dry_run: args.dry_run?,
force_bottle: args.force_bottle?,
build_from_source_formulae: args.build_from_source_formulae,
interactive: args.interactive?,
keep_tmp: args.keep_tmp?,
debug_symbols: args.debug_symbols?,
force: args.force?,
debug: args.debug?,
quiet: args.quiet?,
verbose: args.verbose?
)
Cleanup.periodic_clean!(dry_run: args.dry_run?) Cleanup.periodic_clean!(dry_run: args.dry_run?)
Homebrew.messages.display_messages(display_times: args.display_times?) Homebrew.messages.display_messages(display_times: args.display_times?)

View File

@ -0,0 +1,23 @@
# typed: strong
# frozen_string_literal: true
require "abstract_command"
require "shell_command"
module Homebrew
module Cmd
class McpServerCmd < AbstractCommand
# This is a shell command as MCP servers need a faster startup time
# than a normal Homebrew Ruby command allows.
include ShellCommand
cmd_args do
description <<~EOS
Starts the Homebrew MCP (Model Context Protocol) server.
EOS
switch "-d", "--debug", description: "Enable debug logging to stderr."
switch "--ping", description: "Start the server, act as if receiving a ping and then exit.", hidden: true
end
end
end
end

View File

@ -0,0 +1,14 @@
# Documentation defined in Library/Homebrew/cmd/mcp-server.rb
# This is a shell command as MCP servers need a faster startup time
# than a normal Homebrew Ruby command allows.
# HOMEBREW_LIBRARY is set by brew.sh
# HOMEBREW_BREW_FILE is set by extend/ENV/super.rb
# shellcheck disable=SC2154
homebrew-mcp-server() {
source "${HOMEBREW_LIBRARY}/Homebrew/utils/ruby.sh"
setup-ruby-path
export HOMEBREW_VERSION
"${HOMEBREW_RUBY_PATH}" "-r${HOMEBREW_LIBRARY}/Homebrew/mcp_server.rb" -e "Homebrew::McpServer.new.run" "$@"
}

View File

@ -18,7 +18,8 @@ module Homebrew
description: "Show options for formulae that are currently installed." description: "Show options for formulae that are currently installed."
switch "--eval-all", switch "--eval-all",
description: "Evaluate all available formulae and casks, whether installed or not, to show their " \ description: "Evaluate all available formulae and casks, whether installed or not, to show their " \
"options." "options.",
env: :eval_all
flag "--command=", flag "--command=",
description: "Show options for the specified <command>." description: "Show options for the specified <command>."
@ -29,10 +30,10 @@ module Homebrew
sig { override.void } sig { override.void }
def run def run
all = args.eval_all? eval_all = args.eval_all?
if all if eval_all
puts_options(Formula.all(eval_all: args.eval_all?).sort) puts_options(Formula.all(eval_all:).sort)
elsif args.installed? elsif args.installed?
puts_options(Formula.installed.sort) puts_options(Formula.installed.sort)
elsif args.command.present? elsif args.command.present?

View File

@ -32,12 +32,10 @@ module Homebrew
"formula is outdated. Otherwise, the repository's HEAD will only be checked for " \ "formula is outdated. Otherwise, the repository's HEAD will only be checked for " \
"updates when a new stable or development version has been released." "updates when a new stable or development version has been released."
switch "-g", "--greedy", switch "-g", "--greedy",
env: :upgrade_greedy, description: "Also include outdated casks with `auto_updates true` or `version :latest`.",
description: "Also include outdated casks with `auto_updates true` or `version :latest`." env: :upgrade_greedy
switch "--greedy-latest", switch "--greedy-latest",
description: "Also include outdated casks including those with `version :latest`." description: "Also include outdated casks including those with `version :latest`."
switch "--greedy-auto-updates", switch "--greedy-auto-updates",
description: "Also include outdated casks including those with `auto_updates true`." description: "Also include outdated casks including those with `auto_updates true`."

View File

@ -25,7 +25,7 @@ module Homebrew
if f.pinned? if f.pinned?
opoo "#{f.name} already pinned" opoo "#{f.name} already pinned"
elsif !f.pinnable? elsif !f.pinnable?
onoe "#{f.name} not installed" ofail "#{f.name} not installed"
else else
f.pin f.pin
end end

View File

@ -24,8 +24,8 @@ module Homebrew
switch "--syntax", switch "--syntax",
description: "Syntax-check all of Homebrew's Ruby files (if no <tap> is passed)." description: "Syntax-check all of Homebrew's Ruby files (if no <tap> is passed)."
switch "--eval-all", switch "--eval-all",
description: "Evaluate all available formulae and casks, whether installed or not. " \ description: "Evaluate all available formulae and casks, whether installed or not.",
"Implied if `$HOMEBREW_EVAL_ALL` is set." env: :eval_all
switch "--no-simulate", switch "--no-simulate",
description: "Don't simulate other system configurations when checking formulae and casks." description: "Don't simulate other system configurations when checking formulae and casks."
@ -49,7 +49,7 @@ module Homebrew
options[:os_arch_combinations] = args.os_arch_combinations if args.os || args.arch options[:os_arch_combinations] = args.os_arch_combinations if args.os || args.arch
taps = if args.no_named? taps = if args.no_named?
if !args.eval_all? && !Homebrew::EnvConfig.eval_all? unless args.eval_all?
raise UsageError, "`brew readall` needs a tap or `--eval-all` passed or `$HOMEBREW_EVAL_ALL` set!" raise UsageError, "`brew readall` needs a tap or `--eval-all` passed or `$HOMEBREW_EVAL_ALL` set!"
end end

View File

@ -32,8 +32,8 @@ module Homebrew
description: "If brewing fails, open an interactive debugging session with access to IRB " \ description: "If brewing fails, open an interactive debugging session with access to IRB " \
"or a shell inside the temporary build directory." "or a shell inside the temporary build directory."
switch "--display-times", switch "--display-times",
env: :display_install_times, description: "Print install times for each package at the end of the run.",
description: "Print install times for each package at the end of the run." env: :display_install_times
switch "-f", "--force", switch "-f", "--force",
description: "Install without checking for previously installed keg-only or " \ description: "Install without checking for previously installed keg-only or " \
"non-migrated versions." "non-migrated versions."
@ -41,7 +41,7 @@ module Homebrew
description: "Print the verification and post-install steps." description: "Print the verification and post-install steps."
switch "--ask", switch "--ask",
description: "Ask for confirmation before downloading and upgrading formulae. " \ description: "Ask for confirmation before downloading and upgrading formulae. " \
"Print bottles and dependencies download size, install and net install size.", "Print download, install and net install sizes of bottles and dependencies.",
env: :ask env: :ask
[ [
[:switch, "--formula", "--formulae", { description: "Treat all named arguments as formulae." }], [:switch, "--formula", "--formulae", { description: "Treat all named arguments as formulae." }],
@ -130,16 +130,13 @@ module Homebrew
unless formulae.empty? unless formulae.empty?
Install.perform_preinstall_checks_once Install.perform_preinstall_checks_once
# If asking the user is enabled, show dependency and size information. install_context = formulae.map do |formula|
Install.ask_formulae(formulae, args: args) if args.ask?
formulae.each do |formula|
if formula.pinned? if formula.pinned?
onoe "#{formula.full_name} is pinned. You must unpin it to reinstall." onoe "#{formula.full_name} is pinned. You must unpin it to reinstall."
next next
end end
Migrator.migrate_if_needed(formula, force: args.force?) Migrator.migrate_if_needed(formula, force: args.force?)
Homebrew::Reinstall.reinstall_formula( Homebrew::Reinstall.build_install_context(
formula, formula,
flags: args.flags_only, flags: args.flags_only,
force_bottle: args.force_bottle?, force_bottle: args.force_bottle?,
@ -153,12 +150,12 @@ module Homebrew
verbose: args.verbose?, verbose: args.verbose?,
git: args.git?, git: args.git?,
) )
Cleanup.install_formula_clean!(formula)
end end
Upgrade.check_installed_dependents( dependants = Upgrade.dependants(
formulae, formulae,
flags: args.flags_only, flags: args.flags_only,
ask: args.ask?,
force_bottle: args.force_bottle?, force_bottle: args.force_bottle?,
build_from_source_formulae: args.build_from_source_formulae, build_from_source_formulae: args.build_from_source_formulae,
interactive: args.interactive?, interactive: args.interactive?,
@ -169,6 +166,43 @@ module Homebrew
quiet: args.quiet?, quiet: args.quiet?,
verbose: args.verbose?, verbose: args.verbose?,
) )
formulae_installer = install_context.map(&:formula_installer)
# Main block: if asking the user is enabled, show dependency and size information.
Install.ask_formulae(formulae_installer, dependants, args: args) if args.ask?
install_context.each do |f|
Homebrew::Reinstall.reinstall_formula(
f,
flags: args.flags_only,
force_bottle: args.force_bottle?,
build_from_source_formulae: args.build_from_source_formulae,
interactive: args.interactive?,
keep_tmp: args.keep_tmp?,
debug_symbols: args.debug_symbols?,
force: args.force?,
debug: args.debug?,
quiet: args.quiet?,
verbose: args.verbose?,
git: args.git?,
)
Cleanup.install_formula_clean!(f.formula)
end
Upgrade.upgrade_dependents(
dependants, formulae,
flags: args.flags_only,
force_bottle: args.force_bottle?,
build_from_source_formulae: args.build_from_source_formulae,
interactive: args.interactive?,
keep_tmp: args.keep_tmp?,
debug_symbols: args.debug_symbols?,
force: args.force?,
debug: args.debug?,
quiet: args.quiet?,
verbose: args.verbose?
)
end end
if casks.any? if casks.any?

View File

@ -40,7 +40,8 @@ module Homebrew
switch "--eval-all", switch "--eval-all",
depends_on: "--desc", depends_on: "--desc",
description: "Evaluate all available formulae and casks, whether installed or not, to search their " \ description: "Evaluate all available formulae and casks, whether installed or not, to search their " \
"descriptions. Implied if `$HOMEBREW_EVAL_ALL` is set." "descriptions.",
env: :eval_all
switch "--pull-request", switch "--pull-request",
description: "Search for GitHub pull requests containing <text>." description: "Search for GitHub pull requests containing <text>."
switch "--open", switch "--open",
@ -70,7 +71,7 @@ module Homebrew
string_or_regex = Search.query_regexp(query) string_or_regex = Search.query_regexp(query)
if args.desc? if args.desc?
if !args.eval_all? && !Homebrew::EnvConfig.eval_all? && Homebrew::EnvConfig.no_install_from_api? if !args.eval_all? && Homebrew::EnvConfig.no_install_from_api?
raise UsageError, "`brew search --desc` needs `--eval-all` passed or `$HOMEBREW_EVAL_ALL` set!" raise UsageError, "`brew search --desc` needs `--eval-all` passed or `$HOMEBREW_EVAL_ALL` set!"
end end

View File

@ -13,18 +13,20 @@ module Homebrew
description <<~EOS description <<~EOS
Valid shells: bash|csh|fish|pwsh|sh|tcsh|zsh Valid shells: bash|csh|fish|pwsh|sh|tcsh|zsh
Print export statements. When run in a shell, this installation of Homebrew will be added to your `PATH`, `MANPATH`, and `INFOPATH`. Print export statements. When run in a shell, this installation of Homebrew will be added to your
`$PATH`, `$MANPATH`, and `$INFOPATH`.
The variables `$HOMEBREW_PREFIX`, `$HOMEBREW_CELLAR` and `$HOMEBREW_REPOSITORY` are also exported to avoid The variables `$HOMEBREW_PREFIX`, `$HOMEBREW_CELLAR` and `$HOMEBREW_REPOSITORY` are also exported to avoid
querying them multiple times. querying them multiple times.
To help guarantee idempotence, this command produces no output when Homebrew's `bin` and `sbin` directories To help guarantee idempotence, this command produces no output when Homebrew's `bin` and `sbin` directories
are first and second respectively in your `PATH`. Consider adding evaluation of this command's output to are first and second respectively in your `$PATH`. Consider adding evaluation of this command's output to
your dotfiles (e.g. `~/.bash_profile` or ~/.zprofile` on macOS and ~/.bashrc` or ~/.zshrc` on Linux) with: your dotfiles (e.g. `~/.bash_profile` or ~/.zprofile` on macOS and ~/.bashrc` or ~/.zshrc` on Linux) with:
`eval "$(brew shellenv)"` `eval "$(brew shellenv)"`
The shell can be specified explicitly with a supported shell name parameter. Unknown shells will output The shell can be specified explicitly with a supported shell name parameter. Unknown shells will output
POSIX exports. POSIX exports.
EOS EOS
named_args :shell named_args :shell
end end
end end

View File

@ -63,6 +63,8 @@ module Homebrew
puts info puts info
else else
info = "" info = ""
default_branches = %w[main master].freeze
taps.each_with_index do |tap, i| taps.each_with_index do |tap, i|
puts unless i.zero? puts unless i.zero?
info = "#{tap}: " info = "#{tap}: "
@ -79,7 +81,7 @@ module Homebrew
info += "\norigin: #{tap.remote}" if tap.remote != tap.default_remote info += "\norigin: #{tap.remote}" if tap.remote != tap.default_remote
info += "\nHEAD: #{tap.git_head || "(none)"}" info += "\nHEAD: #{tap.git_head || "(none)"}"
info += "\nlast commit: #{tap.git_last_commit || "never"}" info += "\nlast commit: #{tap.git_last_commit || "never"}"
info += "\nbranch: #{tap.git_branch || "(none)"}" if tap.git_branch != "master" info += "\nbranch: #{tap.git_branch || "(none)"}" if default_branches.exclude?(tap.git_branch)
else else
info += "Not installed" info += "Not installed"
end end

View File

@ -33,16 +33,14 @@ module Homebrew
"integration.", "integration.",
replacement: false, replacement: false,
disable: true disable: true
switch "--[no-]force-auto-update",
hidden: true
switch "--custom-remote", switch "--custom-remote",
description: "Install or change a tap with a custom remote. Useful for mirrors." description: "Install or change a tap with a custom remote. Useful for mirrors."
switch "--repair", switch "--repair",
description: "Add missing symlinks to tap manpages and shell completions. Correct git remote " \ description: "Add missing symlinks to tap manpages and shell completions. Correct git remote " \
"refs for any taps where upstream HEAD branch has been renamed." "refs for any taps where upstream HEAD branch has been renamed."
switch "--eval-all", switch "--eval-all",
description: "Evaluate all the formulae, casks and aliases in the new tap to check validity. " \ description: "Evaluate all formulae, casks and aliases in the new tap to check their validity.",
"Implied if `$HOMEBREW_EVAL_ALL` is set." env: :eval_all
switch "-f", "--force", switch "-f", "--force",
description: "Force install core taps even under API mode." description: "Force install core taps even under API mode."
@ -64,7 +62,7 @@ module Homebrew
tap.install clone_target: args.named.second, tap.install clone_target: args.named.second,
custom_remote: args.custom_remote?, custom_remote: args.custom_remote?,
quiet: args.quiet?, quiet: args.quiet?,
verify: args.eval_all? || Homebrew::EnvConfig.eval_all?, verify: args.eval_all?,
force: args.force? force: args.force?
rescue Tap::InvalidNameError, TapRemoteMismatchError, TapNoCustomRemoteError => e rescue Tap::InvalidNameError, TapRemoteMismatchError, TapNoCustomRemoteError => e
odie e odie e

View File

@ -1,4 +1,4 @@
# typed: true # rubocop:todo Sorbet/StrictSigil # typed: strict
# frozen_string_literal: true # frozen_string_literal: true
require "abstract_command" require "abstract_command"
@ -39,13 +39,15 @@ module Homebrew
private private
sig { void }
def auto_update_header def auto_update_header
@auto_update_header ||= begin @auto_update_header ||= T.let(begin
ohai "Auto-updated Homebrew!" if args.auto_update? ohai "Auto-updated Homebrew!" if args.auto_update?
true true
end end, T.nilable(T::Boolean))
end end
sig { void }
def output_update_report def output_update_report
# Run `brew update` (again) if we've got a linuxbrew-core CoreTap # Run `brew update` (again) if we've got a linuxbrew-core CoreTap
if CoreTap.instance.installed? && CoreTap.instance.linuxbrew_core? && if CoreTap.instance.installed? && CoreTap.instance.linuxbrew_core? &&
@ -293,14 +295,17 @@ module Homebrew
EOS EOS
end end
sig { returns(String) }
def no_changes_message def no_changes_message
"No changes to formulae or casks." "No changes to formulae or casks."
end end
sig { params(revision: String).returns(String) }
def shorten_revision(revision) def shorten_revision(revision)
Utils.popen_read("git", "-C", HOMEBREW_REPOSITORY, "rev-parse", "--short", revision).chomp Utils.popen_read("git", "-C", HOMEBREW_REPOSITORY, "rev-parse", "--short", revision).chomp
end end
sig { void }
def tap_or_untap_core_taps_if_necessary def tap_or_untap_core_taps_if_necessary
return if ENV["HOMEBREW_UPDATE_TEST"] return if ENV["HOMEBREW_UPDATE_TEST"]
@ -320,10 +325,11 @@ module Homebrew
return if (HOMEBREW_PREFIX/".homebrewdocker").exist? return if (HOMEBREW_PREFIX/".homebrewdocker").exist?
tap_output_header_printed = T.let(false, T::Boolean) tap_output_header_printed = T.let(false, T::Boolean)
default_branches = %w[main master].freeze
[CoreTap.instance, CoreCaskTap.instance].each do |tap| [CoreTap.instance, CoreCaskTap.instance].each do |tap|
next unless tap.installed? next unless tap.installed?
if tap.git_branch == "master" && if default_branches.include?(tap.git_branch) &&
(Date.parse(T.must(tap.git_repository.last_commit_date)) <= Date.today.prev_month) (Date.parse(T.must(tap.git_repository.last_commit_date)) <= Date.today.prev_month)
ohai "#{tap.name} is old and unneeded, untapping to save space..." ohai "#{tap.name} is old and unneeded, untapping to save space..."
tap.uninstall tap.uninstall
@ -339,6 +345,7 @@ module Homebrew
end end
end end
sig { params(repository: Pathname).void }
def link_completions_manpages_and_docs(repository = HOMEBREW_REPOSITORY) def link_completions_manpages_and_docs(repository = HOMEBREW_REPOSITORY)
command = "brew update" command = "brew update"
Utils::Link.link_completions(repository, command) Utils::Link.link_completions(repository, command)
@ -351,10 +358,12 @@ module Homebrew
EOS EOS
end end
sig { void }
def migrate_gcc_dependents_if_needed def migrate_gcc_dependents_if_needed
# do nothing # do nothing
end end
sig { void }
def analytics_message def analytics_message
return if Utils::Analytics.messages_displayed? return if Utils::Analytics.messages_displayed?
return if Utils::Analytics.no_message_output? return if Utils::Analytics.no_message_output?
@ -384,6 +393,7 @@ module Homebrew
Utils::Analytics.messages_displayed! if $stdout.tty? Utils::Analytics.messages_displayed! if $stdout.tty?
end end
sig { void }
def donation_message def donation_message
return if Settings.read("donationmessage") == "true" return if Settings.read("donationmessage") == "true"
@ -394,6 +404,7 @@ module Homebrew
Settings.write "donationmessage", true if $stdout.tty? Settings.write "donationmessage", true if $stdout.tty?
end end
sig { void }
def install_from_api_message def install_from_api_message
return if Settings.read("installfromapimessage") == "true" return if Settings.read("installfromapimessage") == "true"
@ -418,30 +429,38 @@ require "extend/os/cmd/update-report"
class Reporter class Reporter
class ReporterRevisionUnsetError < RuntimeError class ReporterRevisionUnsetError < RuntimeError
sig { params(var_name: String).void }
def initialize(var_name) def initialize(var_name)
super "#{var_name} is unset!" super "#{var_name} is unset!"
end end
end end
sig {
params(tap: Tap, api_names_txt: T.nilable(Pathname), api_names_before_txt: T.nilable(Pathname),
api_dir_prefix: T.nilable(Pathname)).void
}
def initialize(tap, api_names_txt: nil, api_names_before_txt: nil, api_dir_prefix: nil) def initialize(tap, api_names_txt: nil, api_names_before_txt: nil, api_dir_prefix: nil)
@tap = tap @tap = tap
# This is slightly involved/weird but all the #report logic is shared so it's worth it. # This is slightly involved/weird but all the #report logic is shared so it's worth it.
if installed_from_api?(api_names_txt, api_names_before_txt, api_dir_prefix) if installed_from_api?(api_names_txt, api_names_before_txt, api_dir_prefix)
@api_names_txt = api_names_txt @api_names_txt = T.let(api_names_txt, T.nilable(Pathname))
@api_names_before_txt = api_names_before_txt @api_names_before_txt = T.let(api_names_before_txt, T.nilable(Pathname))
@api_dir_prefix = api_dir_prefix @api_dir_prefix = T.let(api_dir_prefix, T.nilable(Pathname))
else else
initial_revision_var = "HOMEBREW_UPDATE_BEFORE#{tap.repository_var_suffix}" initial_revision_var = "HOMEBREW_UPDATE_BEFORE#{tap.repository_var_suffix}"
@initial_revision = ENV[initial_revision_var].to_s @initial_revision = T.let(ENV[initial_revision_var].to_s, String)
raise ReporterRevisionUnsetError, initial_revision_var if @initial_revision.empty? raise ReporterRevisionUnsetError, initial_revision_var if @initial_revision.empty?
current_revision_var = "HOMEBREW_UPDATE_AFTER#{tap.repository_var_suffix}" current_revision_var = "HOMEBREW_UPDATE_AFTER#{tap.repository_var_suffix}"
@current_revision = ENV[current_revision_var].to_s @current_revision = T.let(ENV[current_revision_var].to_s, String)
raise ReporterRevisionUnsetError, current_revision_var if @current_revision.empty? raise ReporterRevisionUnsetError, current_revision_var if @current_revision.empty?
end end
@report = T.let(nil, T.nilable(T::Hash[Symbol, T::Array[String]]))
end end
sig { params(auto_update: T::Boolean).returns(T::Hash[Symbol, T::Array[String]]) }
def report(auto_update: false) def report(auto_update: false)
return @report if @report return @report if @report
@ -482,9 +501,9 @@ class Reporter
case status case status
when "A", "D" when "A", "D"
full_name = tap.formula_file_to_name(src) full_name = tap.formula_file_to_name(src)
name = full_name.split("/").last name = T.must(full_name.split("/").last)
new_tap = tap.tap_migrations[name] new_tap = tap.tap_migrations[name]
@report[status.to_sym] << full_name unless new_tap @report[T.must(status).to_sym] << full_name unless new_tap
when "M" when "M"
name = tap.formula_file_to_name(src) name = tap.formula_file_to_name(src)
@ -584,6 +603,7 @@ class Reporter
@report @report
end end
sig { returns(T::Boolean) }
def updated? def updated?
if installed_from_api? if installed_from_api?
diff.present? diff.present?
@ -592,9 +612,10 @@ class Reporter
end end
end end
sig { void }
def migrate_tap_migration def migrate_tap_migration
(report[:D] + report[:DC]).each do |full_name| (Array(report[:D]) + Array(report[:DC])).each do |full_name|
name = full_name.split("/").last name = T.must(full_name.split("/").last)
new_tap_name = tap.tap_migrations[name] new_tap_name = tap.tap_migrations[name]
next if new_tap_name.nil? # skip if not in tap_migrations list. next if new_tap_name.nil? # skip if not in tap_migrations list.
@ -609,7 +630,7 @@ class Reporter
end end
# This means it is a cask # This means it is a cask
if report[:DC].include? full_name if Array(report[:DC]).include? full_name
next unless (HOMEBREW_PREFIX/"Caskroom"/new_name).exist? next unless (HOMEBREW_PREFIX/"Caskroom"/new_name).exist?
new_tap = Tap.fetch(new_tap_name) new_tap = Tap.fetch(new_tap_name)
@ -675,12 +696,14 @@ class Reporter
end end
end end
sig { void }
def migrate_cask_rename def migrate_cask_rename
Cask::Caskroom.casks.each do |cask| Cask::Caskroom.casks.each do |cask|
Cask::Migrator.migrate_if_needed(cask) Cask::Migrator.migrate_if_needed(cask)
end end
end end
sig { params(force: T::Boolean, verbose: T::Boolean).void }
def migrate_formula_rename(force:, verbose:) def migrate_formula_rename(force:, verbose:)
Formula.installed.each do |formula| Formula.installed.each do |formula|
next unless Migrator.needs_migration?(formula) next unless Migrator.needs_migration?(formula)
@ -704,14 +727,36 @@ class Reporter
private private
attr_reader :tap, :initial_revision, :current_revision, :api_names_txt, :api_names_before_txt, :api_dir_prefix sig { returns(Tap) }
attr_reader :tap
sig { returns(String) }
attr_reader :initial_revision
sig { returns(String) }
attr_reader :current_revision
sig { returns(T.nilable(Pathname)) }
attr_reader :api_names_txt
sig { returns(T.nilable(Pathname)) }
attr_reader :api_names_before_txt
sig { returns(T.nilable(Pathname)) }
attr_reader :api_dir_prefix
sig {
params(api_names_txt: T.nilable(Pathname), api_names_before_txt: T.nilable(Pathname),
api_dir_prefix: T.nilable(Pathname)).returns(T::Boolean)
}
def installed_from_api?(api_names_txt = @api_names_txt, api_names_before_txt = @api_names_before_txt, def installed_from_api?(api_names_txt = @api_names_txt, api_names_before_txt = @api_names_before_txt,
api_dir_prefix = @api_dir_prefix) api_dir_prefix = @api_dir_prefix)
!api_names_txt.nil? && !api_names_before_txt.nil? && !api_dir_prefix.nil? !api_names_txt.nil? && !api_names_before_txt.nil? && !api_dir_prefix.nil?
end end
sig { returns(String) }
def diff def diff
@diff ||= T.let(nil, T.nilable(String))
@diff ||= if installed_from_api? @diff ||= if installed_from_api?
# Hack `git diff` output with regexes to look like `git diff-tree` output. # Hack `git diff` output with regexes to look like `git diff-tree` output.
# Yes, I know this is a bit filthy but it saves duplicating the #report logic. # Yes, I know this is a bit filthy but it saves duplicating the #report logic.
@ -719,12 +764,14 @@ class Reporter
header_regex = /^(---|\+\+\+) / header_regex = /^(---|\+\+\+) /
add_delete_characters = ["+", "-"].freeze add_delete_characters = ["+", "-"].freeze
api_dir_prefix_basename = T.must(api_dir_prefix).basename
diff_output.lines.filter_map do |line| diff_output.lines.filter_map do |line|
next if line.match?(header_regex) next if line.match?(header_regex)
next unless add_delete_characters.include?(line[0]) next unless add_delete_characters.include?(line[0])
line.sub(/^\+/, "A #{api_dir_prefix.basename}/") line.sub(/^\+/, "A #{api_dir_prefix_basename}/")
.sub(/^-/, "D #{api_dir_prefix.basename}/") .sub(/^-/, "D #{api_dir_prefix_basename}/")
.sub(/$/, ".rb") .sub(/$/, ".rb")
.chomp .chomp
end.join("\n") end.join("\n")
@ -738,28 +785,33 @@ class Reporter
end end
class ReporterHub class ReporterHub
sig { returns(T::Array[Reporter]) }
attr_reader :reporters attr_reader :reporters
sig { void } sig { void }
def initialize def initialize
@hash = {} @hash = T.let({}, T::Hash[Symbol, T::Array[String]])
@reporters = [] @reporters = T.let([], T::Array[Reporter])
end end
sig { params(key: Symbol).returns(T::Array[String]) }
def select_formula_or_cask(key) def select_formula_or_cask(key)
@hash.fetch(key, []) @hash.fetch(key, [])
end end
sig { params(reporter: Reporter, auto_update: T::Boolean).void }
def add(reporter, auto_update: false) def add(reporter, auto_update: false)
@reporters << reporter @reporters << reporter
report = reporter.report(auto_update:).delete_if { |_k, v| v.empty? } report = reporter.report(auto_update:).delete_if { |_k, v| v.empty? }
@hash.update(report) { |_key, oldval, newval| oldval.concat(newval) } @hash.update(report) { |_key, oldval, newval| oldval.concat(newval) }
end end
sig { returns(T::Boolean) }
def empty? def empty?
@hash.empty? @hash.empty?
end end
sig { params(auto_update: T::Boolean).void }
def dump(auto_update: false) def dump(auto_update: false)
unless Homebrew::EnvConfig.no_update_report_new? unless Homebrew::EnvConfig.no_update_report_new?
dump_new_formula_report dump_new_formula_report
@ -814,22 +866,41 @@ class ReporterHub
private private
sig { void }
def dump_new_formula_report def dump_new_formula_report
formulae = select_formula_or_cask(:A).sort.reject { |name| installed?(name) } formulae = select_formula_or_cask(:A).sort.reject { |name| installed?(name) }
return if formulae.blank?
output_dump_formula_or_cask_report "New Formulae", formulae ohai "New Formulae"
formulae.each do |formula|
if (desc = description(formula))
puts "#{formula}: #{desc}"
else
puts formula
end
end
end end
sig { void }
def dump_new_cask_report def dump_new_cask_report
return if Homebrew::SimulateSystem.simulating_or_running_on_linux? return unless Cask::Caskroom.any_casks_installed?
casks = select_formula_or_cask(:AC).sort.filter_map do |name| casks = select_formula_or_cask(:AC).sort.filter_map do |name|
name.split("/").last unless cask_installed?(name) name.split("/").last unless cask_installed?(name)
end end
return if casks.blank?
output_dump_formula_or_cask_report "New Casks", casks ohai "New Casks"
casks.each do |cask|
if (desc = cask_description(cask))
puts "#{cask}: #{desc}"
else
puts cask
end
end
end end
sig { void }
def dump_deleted_formula_report def dump_deleted_formula_report
formulae = select_formula_or_cask(:D).sort.filter_map do |name| formulae = select_formula_or_cask(:D).sort.filter_map do |name|
pretty_uninstalled(name) if installed?(name) pretty_uninstalled(name) if installed?(name)
@ -838,40 +909,84 @@ class ReporterHub
output_dump_formula_or_cask_report "Deleted Installed Formulae", formulae output_dump_formula_or_cask_report "Deleted Installed Formulae", formulae
end end
sig { void }
def dump_deleted_cask_report def dump_deleted_cask_report
return if Homebrew::SimulateSystem.simulating_or_running_on_linux? return if Homebrew::SimulateSystem.simulating_or_running_on_linux?
casks = select_formula_or_cask(:DC).sort.filter_map do |name| casks = select_formula_or_cask(:DC).sort.filter_map do |name|
name = name.split("/").last name = T.must(name.split("/").last)
pretty_uninstalled(name) if cask_installed?(name) pretty_uninstalled(name) if cask_installed?(name)
end end
output_dump_formula_or_cask_report "Deleted Installed Casks", casks output_dump_formula_or_cask_report "Deleted Installed Casks", casks
end end
sig { params(title: String, formulae_or_casks: T::Array[String]).void }
def output_dump_formula_or_cask_report(title, formulae_or_casks) def output_dump_formula_or_cask_report(title, formulae_or_casks)
return if formulae_or_casks.blank? return if formulae_or_casks.blank?
ohai title, Formatter.columns(formulae_or_casks.sort) ohai title, Formatter.columns(formulae_or_casks.sort)
end end
sig { params(formula: String).returns(T::Boolean) }
def installed?(formula) def installed?(formula)
(HOMEBREW_CELLAR/formula.split("/").last).directory? (HOMEBREW_CELLAR/formula.split("/").last).directory?
end end
sig { params(formula: String).returns(T::Boolean) }
def outdated?(formula) def outdated?(formula)
Formula[formula].outdated? Formula[formula].outdated?
rescue FormulaUnavailableError rescue FormulaUnavailableError
false false
end end
sig { params(cask: String).returns(T::Boolean) }
def cask_installed?(cask) def cask_installed?(cask)
(Cask::Caskroom.path/cask).directory? (Cask::Caskroom.path/cask).directory?
end end
sig { params(cask: String).returns(T::Boolean) }
def cask_outdated?(cask) def cask_outdated?(cask)
Cask::CaskLoader.load(cask).outdated? Cask::CaskLoader.load(cask).outdated?
rescue Cask::CaskError rescue Cask::CaskError
false false
end end
sig { returns(T::Array[T.untyped]) }
def all_formula_json
return @all_formula_json if @all_formula_json
@all_formula_json = T.let(nil, T.nilable(T::Array[T.untyped]))
all_formula_json, = Homebrew::API.fetch_json_api_file "formula.jws.json"
all_formula_json = T.cast(all_formula_json, T::Array[T.untyped])
@all_formula_json = all_formula_json
end
sig { returns(T::Array[T.untyped]) }
def all_cask_json
return @all_cask_json if @all_cask_json
@all_cask_json = T.let(nil, T.nilable(T::Array[T.untyped]))
all_cask_json, = Homebrew::API.fetch_json_api_file "cask.jws.json"
all_cask_json = T.cast(all_cask_json, T::Array[T.untyped])
@all_cask_json = all_cask_json
end
sig { params(formula: String).returns(T.nilable(String)) }
def description(formula)
return if Homebrew::EnvConfig.no_install_from_api?
all_formula_json.find { |f| f["name"] == formula }
&.fetch("desc", nil)
&.presence
end
sig { params(cask: String).returns(T.nilable(String)) }
def cask_description(cask)
return if Homebrew::EnvConfig.no_install_from_api?
all_cask_json.find { |f| f["token"] == cask }
&.fetch("desc", nil)
&.presence
end
end end

View File

@ -54,9 +54,10 @@ git_init_if_necessary() {
fi fi
git config remote.origin.url "${HOMEBREW_BREW_GIT_REMOTE}" git config remote.origin.url "${HOMEBREW_BREW_GIT_REMOTE}"
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
git config fetch.prune true
git fetch --force --tags origin git fetch --force --tags origin
git remote set-head origin --auto >/dev/null git remote set-head origin --auto >/dev/null
git reset --hard origin/master git reset --hard origin/HEAD
SKIP_FETCH_BREW_REPOSITORY=1 SKIP_FETCH_BREW_REPOSITORY=1
set +e set +e
trap - EXIT trap - EXIT
@ -77,9 +78,10 @@ git_init_if_necessary() {
fi fi
git config remote.origin.url "${HOMEBREW_CORE_GIT_REMOTE}" git config remote.origin.url "${HOMEBREW_CORE_GIT_REMOTE}"
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
git fetch --force origin refs/heads/master:refs/remotes/origin/master git config fetch.prune true
git fetch --force origin
git remote set-head origin --auto >/dev/null git remote set-head origin --auto >/dev/null
git reset --hard origin/master git reset --hard origin/HEAD
SKIP_FETCH_CORE_REPOSITORY=1 SKIP_FETCH_CORE_REPOSITORY=1
set +e set +e
trap - EXIT trap - EXIT
@ -110,7 +112,7 @@ upstream_branch() {
upstream_branch="$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null)" upstream_branch="$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null)"
fi fi
upstream_branch="${upstream_branch#refs/remotes/origin/}" upstream_branch="${upstream_branch#refs/remotes/origin/}"
[[ -z "${upstream_branch}" ]] && upstream_branch="master" [[ -z "${upstream_branch}" ]] && upstream_branch="main"
echo "${upstream_branch}" echo "${upstream_branch}"
} }
@ -242,7 +244,7 @@ merge_or_rebase() {
Could not 'git stash' in ${DIR}! Could not 'git stash' in ${DIR}!
Please stash/commit manually if you need to keep your changes or, if not, run: Please stash/commit manually if you need to keep your changes or, if not, run:
cd ${DIR} cd ${DIR}
git reset --hard origin/master git reset --hard origin/HEAD
EOS EOS
fi fi
git reset --hard "${QUIET_ARGS[@]}" git reset --hard "${QUIET_ARGS[@]}"
@ -250,6 +252,14 @@ EOS
fi fi
INITIAL_BRANCH="$(git symbolic-ref --short HEAD 2>/dev/null)" INITIAL_BRANCH="$(git symbolic-ref --short HEAD 2>/dev/null)"
MAIN_MIGRATION_REQUIRED=
if [[ "${INITIAL_BRANCH}" == "master" &&
("${DIR}" == "${HOMEBREW_REPOSITORY}" || "${DIR}" == "${HOMEBREW_CORE_REPOSITORY}" || "${DIR}" == "${HOMEBREW_CASK_REPOSITORY}") ]]
then
# Migrate master to main for Homebrew/brew, homebrew-core or homebrew-cask
MAIN_MIGRATION_REQUIRED="1"
fi
if [[ -n "${UPSTREAM_TAG}" ]] || if [[ -n "${UPSTREAM_TAG}" ]] ||
[[ "${INITIAL_BRANCH}" != "${UPSTREAM_BRANCH}" && -n "${INITIAL_BRANCH}" ]] [[ "${INITIAL_BRANCH}" != "${UPSTREAM_BRANCH}" && -n "${INITIAL_BRANCH}" ]]
then then
@ -260,10 +270,12 @@ EOS
then then
git checkout --force "${UPSTREAM_BRANCH}" "${QUIET_ARGS[@]}" git checkout --force "${UPSTREAM_BRANCH}" "${QUIET_ARGS[@]}"
else else
if [[ -n "${UPSTREAM_TAG}" && "${UPSTREAM_BRANCH}" != "master" ]] && if [[ -n "${UPSTREAM_TAG}" && "${UPSTREAM_BRANCH}" != "master" && "${UPSTREAM_BRANCH}" != "main" ]] &&
[[ "${INITIAL_BRANCH}" != "master" ]] [[ "${INITIAL_BRANCH}" != "master" && "${INITIAL_BRANCH}" != "main" ]]
then then
git branch --force "master" "origin/master" "${QUIET_ARGS[@]}" local detected_upstream_branch
detected_upstream_branch="$(upstream_branch)"
git branch --force "${detected_upstream_branch}" "origin/${detected_upstream_branch}" "${QUIET_ARGS[@]}"
fi fi
git checkout --force -B "${UPSTREAM_BRANCH}" "${REMOTE_REF}" "${QUIET_ARGS[@]}" git checkout --force -B "${UPSTREAM_BRANCH}" "${REMOTE_REF}" "${QUIET_ARGS[@]}"
@ -313,7 +325,7 @@ EOS
if [[ -n "${HOMEBREW_NO_UPDATE_CLEANUP}" ]] if [[ -n "${HOMEBREW_NO_UPDATE_CLEANUP}" ]]
then then
if [[ "${INITIAL_BRANCH}" != "${UPSTREAM_BRANCH}" && -n "${INITIAL_BRANCH}" ]] && if [[ -z "${MAIN_MIGRATION_REQUIRED}" && "${INITIAL_BRANCH}" != "${UPSTREAM_BRANCH}" && -n "${INITIAL_BRANCH}" ]] &&
[[ ! "${INITIAL_BRANCH}" =~ ^v[0-9]+\.[0-9]+\.[0-9]|stable$ ]] [[ ! "${INITIAL_BRANCH}" =~ ^v[0-9]+\.[0-9]+\.[0-9]|stable$ ]]
then then
git checkout "${INITIAL_BRANCH}" "${QUIET_ARGS[@]}" git checkout "${INITIAL_BRANCH}" "${QUIET_ARGS[@]}"
@ -324,6 +336,11 @@ EOS
pop_stash_message pop_stash_message
fi fi
if [[ -n "${MAIN_MIGRATION_REQUIRED}" && -n "$(git config branch.main.remote 2>/dev/null || true)" ]]
then
git branch -d "${QUIET_ARGS[@]}" master
fi
trap - SIGINT trap - SIGINT
} }
@ -541,7 +558,8 @@ EOS
echo "HOMEBREW_CORE_GIT_REMOTE set: using ${HOMEBREW_CORE_GIT_REMOTE} as the Homebrew/homebrew-core Git remote." echo "HOMEBREW_CORE_GIT_REMOTE set: using ${HOMEBREW_CORE_GIT_REMOTE} as the Homebrew/homebrew-core Git remote."
git remote set-url origin "${HOMEBREW_CORE_GIT_REMOTE}" git remote set-url origin "${HOMEBREW_CORE_GIT_REMOTE}"
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
git fetch --force origin refs/heads/master:refs/remotes/origin/master git config fetch.prune true
git fetch --force origin
SKIP_FETCH_CORE_REPOSITORY=1 SKIP_FETCH_CORE_REPOSITORY=1
fi fi
@ -642,9 +660,9 @@ EOS
UPDATING_MESSAGE_SHOWN=1 UPDATING_MESSAGE_SHOWN=1
fi fi
# The upstream repository's default branch may not be master; # The upstream repository's default branch may not be main or master;
# check refs/remotes/origin/HEAD to see what the default # check refs/remotes/origin/HEAD to see what the default
# origin branch name is, and use that. If not set, fall back to "master". # origin branch name is, and use that. If not set, fall back to "main".
# the refspec ensures that the default upstream branch gets updated # the refspec ensures that the default upstream branch gets updated
( (
UPSTREAM_REPOSITORY_URL="$(git config remote.origin.url)" UPSTREAM_REPOSITORY_URL="$(git config remote.origin.url)"
@ -664,6 +682,16 @@ EOS
UPSTREAM_REPOSITORY_TOKEN="${BASH_REMATCH[1]#*:}" UPSTREAM_REPOSITORY_TOKEN="${BASH_REMATCH[1]#*:}"
fi fi
MAIN_MIGRATION_REQUIRED=
if [[ "${UPSTREAM_BRANCH_DIR}" == "master" &&
("${DIR}" == "${HOMEBREW_REPOSITORY}" || "${DIR}" == "${HOMEBREW_CORE_REPOSITORY}" || "${DIR}" == "${HOMEBREW_CASK_REPOSITORY}") ]]
then
# Migrate master to main for Homebrew/brew, homebrew-core or homebrew-cask
MAIN_MIGRATION_REQUIRED=1
UPSTREAM_BRANCH_DIR="main"
declare UPSTREAM_BRANCH"${TAP_VAR}"="main"
fi
if [[ -n "${UPSTREAM_REPOSITORY}" ]] if [[ -n "${UPSTREAM_REPOSITORY}" ]]
then then
# UPSTREAM_REPOSITORY_TOKEN is parsed (if exists) from UPSTREAM_REPOSITORY_URL # UPSTREAM_REPOSITORY_TOKEN is parsed (if exists) from UPSTREAM_REPOSITORY_URL
@ -725,32 +753,59 @@ EOS
local tmp_failure_file="${DIR}/.git/TMP_FETCH_FAILURES" local tmp_failure_file="${DIR}/.git/TMP_FETCH_FAILURES"
rm -f "${tmp_failure_file}" rm -f "${tmp_failure_file}"
if [[ -n "${HOMEBREW_UPDATE_AUTO}" ]] if ! git fetch --tags --force "${QUIET_ARGS[@]}" origin \
"refs/heads/${UPSTREAM_BRANCH_DIR}:refs/remotes/origin/${UPSTREAM_BRANCH_DIR}" 2>>"${tmp_failure_file}"
then then
git fetch --tags --force "${QUIET_ARGS[@]}" origin \ if [[ -f "${tmp_failure_file}" ]]
"refs/heads/${UPSTREAM_BRANCH_DIR}:refs/remotes/origin/${UPSTREAM_BRANCH_DIR}" 2>/dev/null
else
# Capture stderr to tmp_failure_file
if ! git fetch --tags --force "${QUIET_ARGS[@]}" origin \
"refs/heads/${UPSTREAM_BRANCH_DIR}:refs/remotes/origin/${UPSTREAM_BRANCH_DIR}" 2>>"${tmp_failure_file}"
then then
# Reprint fetch errors to stderr local git_errors
[[ -f "${tmp_failure_file}" ]] && cat "${tmp_failure_file}" 1>&2 git_errors="$(cat "${tmp_failure_file}")"
# Attempt migration from master to main branch.
if [[ "${UPSTREAM_SHA_HTTP_CODE}" == "404" ]] if [[ "${git_errors}" == "fatal: couldn't find remote ref refs/heads/master" ]]
then then
TAP="${DIR#"${HOMEBREW_LIBRARY}"/Taps/}" if git fetch --tags --force "${QUIET_ARGS[@]}" origin \
echo "${TAP} does not exist! Run \`brew untap ${TAP}\` to remove it." >>"${update_failed_file}" "refs/heads/main:refs/remotes/origin/main" 2>>"${tmp_failure_file}"
else
echo "Fetching ${DIR} failed!" >>"${update_failed_file}"
if [[ -f "${tmp_failure_file}" ]] &&
[[ "$(cat "${tmp_failure_file}")" == "fatal: couldn't find remote ref refs/heads/${UPSTREAM_BRANCH_DIR}" ]]
then then
echo "${DIR}" >>"${missing_remote_ref_dirs_file}" rm -f "${DIR}/.git/refs/remotes/origin/HEAD" "${DIR}/.git/refs/remotes/origin/master"
UPSTREAM_BRANCH_DIR="$(upstream_branch)"
declare UPSTREAM_BRANCH"${TAP_VAR}"="${UPSTREAM_BRANCH_DIR}"
git branch -m master main "${QUIET_ARGS[@]}"
git branch -u origin/main main "${QUIET_ARGS[@]}"
rm -f "${tmp_failure_file}"
exit
fi fi
fi fi
rm -f "${tmp_failure_file}"
fi fi
# Don't output errors if HOMEBREW_UPDATE_AUTO is set.
if [[ -n "${HOMEBREW_UPDATE_AUTO}" ]]
then
exit
fi
# Reprint fetch errors to stderr
[[ -n "${git_errors}" ]] && echo "${git_errors}" 1>&2
if [[ "${UPSTREAM_SHA_HTTP_CODE}" == "404" ]]
then
TAP="${DIR#"${HOMEBREW_LIBRARY}"/Taps/}"
echo "${TAP} does not exist! Run \`brew untap ${TAP}\` to remove it." >>"${update_failed_file}"
else
echo "Fetching ${DIR} failed!" >>"${update_failed_file}"
if [[ -f "${tmp_failure_file}" ]] &&
[[ "$(cat "${tmp_failure_file}")" == "fatal: couldn't find remote ref refs/heads/${UPSTREAM_BRANCH_DIR}" ]]
then
echo "${DIR}" >>"${missing_remote_ref_dirs_file}"
fi
fi
fi
if [[ -n "${MAIN_MIGRATION_REQUIRED}" ]]
then
git remote set-head origin --auto >/dev/null
fi fi
rm -f "${tmp_failure_file}" rm -f "${tmp_failure_file}"

View File

@ -29,8 +29,8 @@ module Homebrew
description: "If brewing fails, open an interactive debugging session with access to IRB " \ description: "If brewing fails, open an interactive debugging session with access to IRB " \
"or a shell inside the temporary build directory." "or a shell inside the temporary build directory."
switch "--display-times", switch "--display-times",
env: :display_install_times, description: "Print install times for each package at the end of the run.",
description: "Print install times for each package at the end of the run." env: :display_install_times
switch "-f", "--force", switch "-f", "--force",
description: "Install formulae without checking for previously installed keg-only or " \ description: "Install formulae without checking for previously installed keg-only or " \
"non-migrated versions. When installing casks, overwrite existing files " \ "non-migrated versions. When installing casks, overwrite existing files " \
@ -41,7 +41,7 @@ module Homebrew
description: "Show what would be upgraded, but do not actually upgrade anything." description: "Show what would be upgraded, but do not actually upgrade anything."
switch "--ask", switch "--ask",
description: "Ask for confirmation before downloading and upgrading formulae. " \ description: "Ask for confirmation before downloading and upgrading formulae. " \
"Print bottles and dependencies download size, install and net install size.", "Print download, install and net install sizes of bottles and dependencies.",
env: :ask env: :ask
[ [
[:switch, "--formula", "--formulae", { [:switch, "--formula", "--formulae", {
@ -220,10 +220,7 @@ module Homebrew
Install.perform_preinstall_checks_once Install.perform_preinstall_checks_once
# Main block: if asking the user is enabled, show dependency and size information. formulae_installer = Upgrade.formula_installers(
Install.ask_formulae(formulae_to_install, args: args) if args.ask?
Upgrade.upgrade_formulae(
formulae_to_install, formulae_to_install,
flags: args.flags_only, flags: args.flags_only,
dry_run: args.dry_run?, dry_run: args.dry_run?,
@ -239,10 +236,35 @@ module Homebrew
verbose: args.verbose?, verbose: args.verbose?,
) )
Upgrade.check_installed_dependents( return false if formulae_installer.blank?
dependants = Upgrade.dependants(
formulae_to_install, formulae_to_install,
flags: args.flags_only, flags: args.flags_only,
dry_run: args.dry_run?, dry_run: args.dry_run?,
ask: args.ask?,
force_bottle: args.force_bottle?,
build_from_source_formulae: args.build_from_source_formulae,
interactive: args.interactive?,
keep_tmp: args.keep_tmp?,
debug_symbols: args.debug_symbols?,
force: args.force?,
debug: args.debug?,
quiet: args.quiet?,
verbose: args.verbose?,
)
# Main block: if asking the user is enabled, show dependency and size information.
Install.ask_formulae(formulae_installer, dependants, args: args) if args.ask?
Upgrade.upgrade_formulae(formulae_installer,
dry_run: args.dry_run?,
verbose: args.verbose?)
Upgrade.upgrade_dependents(
dependants, formulae_to_install,
flags: args.flags_only,
dry_run: args.dry_run?,
force_bottle: args.force_bottle?, force_bottle: args.force_bottle?,
build_from_source_formulae: args.build_from_source_formulae, build_from_source_formulae: args.build_from_source_formulae,
interactive: args.interactive?, interactive: args.interactive?,
@ -251,7 +273,7 @@ module Homebrew
force: args.force?, force: args.force?,
debug: args.debug?, debug: args.debug?,
quiet: args.quiet?, quiet: args.quiet?,
verbose: args.verbose?, verbose: args.verbose?
) )
true true

View File

@ -36,7 +36,8 @@ module Homebrew
description: "Only list formulae and casks that are not currently installed." description: "Only list formulae and casks that are not currently installed."
switch "--eval-all", switch "--eval-all",
description: "Evaluate all available formulae and casks, whether installed or not, to show " \ description: "Evaluate all available formulae and casks, whether installed or not, to show " \
"their dependents." "their dependents.",
env: :eval_all
switch "--include-implicit", switch "--include-implicit",
description: "Include formulae that have <formula> as an implicit dependency for " \ description: "Include formulae that have <formula> as an implicit dependency for " \
"downloading and unpacking source files." "downloading and unpacking source files."
@ -119,17 +120,17 @@ module Homebrew
deps deps
else else
all = args.eval_all? eval_all = args.eval_all?
if !args.installed? && !(all || Homebrew::EnvConfig.eval_all?) if !args.installed? && !eval_all
raise UsageError, "`brew uses` needs `--installed` or `--eval-all` passed or `$HOMEBREW_EVAL_ALL` set!" raise UsageError, "`brew uses` needs `--installed` or `--eval-all` passed or `$HOMEBREW_EVAL_ALL` set!"
end end
if show_formulae_and_casks || args.formula? if show_formulae_and_casks || args.formula?
deps += args.installed? ? Formula.installed : Formula.all(eval_all: args.eval_all?) deps += args.installed? ? Formula.installed : Formula.all(eval_all:)
end end
if show_formulae_and_casks || args.cask? if show_formulae_and_casks || args.cask?
deps += args.installed? ? Cask::Caskroom.casks : Cask::Cask.all(eval_all: args.eval_all?) deps += args.installed? ? Cask::Caskroom.casks : Cask::Cask.all(eval_all:)
end end
if args.missing? if args.missing?

View File

@ -101,6 +101,7 @@ fetch() {
local first_try=1 local first_try=1
local vendor_locations local vendor_locations
local temporary_path local temporary_path
local curl_exit_code=0
curl_args=() curl_args=()
@ -149,19 +150,27 @@ fetch() {
# HOMEBREW_CURL is set by brew.sh (and isn't misspelt here) # HOMEBREW_CURL is set by brew.sh (and isn't misspelt here)
# shellcheck disable=SC2153 # shellcheck disable=SC2153
"${HOMEBREW_CURL}" "${curl_args[@]}" -C - "${url}" -o "${temporary_path}" "${HOMEBREW_CURL}" "${curl_args[@]}" -C - "${url}" -o "${temporary_path}"
if [[ $? -eq 33 ]] curl_exit_code="$?"
if [[ "${curl_exit_code}" -eq 33 ]]
then then
[[ -n "${HOMEBREW_QUIET}" ]] || echo "Trying a full download" >&2 [[ -n "${HOMEBREW_QUIET}" ]] || echo "Trying a full download" >&2
rm -f "${temporary_path}" rm -f "${temporary_path}"
"${HOMEBREW_CURL}" "${curl_args[@]}" "${url}" -o "${temporary_path}" "${HOMEBREW_CURL}" "${curl_args[@]}" "${url}" -o "${temporary_path}"
curl_exit_code="$?"
fi fi
else else
"${HOMEBREW_CURL}" "${curl_args[@]}" "${url}" -o "${temporary_path}" "${HOMEBREW_CURL}" "${curl_args[@]}" "${url}" -o "${temporary_path}"
curl_exit_code="$?"
fi fi
[[ -f "${temporary_path}" ]] && break [[ -f "${temporary_path}" ]] && break
done done
if [[ "${curl_exit_code}" -ne 0 ]]
then
rm -f "${temporary_path}"
fi
if [[ ! -f "${temporary_path}" ]] if [[ ! -f "${temporary_path}" ]]
then then
vendor_locations="$(printf " - %s\n" "${VENDOR_URLs[@]}")" vendor_locations="$(printf " - %s\n" "${VENDOR_URLs[@]}")"

View File

@ -1,12 +1,12 @@
{ {
"$schema" : "https://json-schema.org/draft/2019-09/schema", "$schema" : "https://json-schema.org/draft/2019-09/schema",
"$id" : "http://spdx.org/rdf/terms/2.3", "$id" : "http://spdx.org/rdf/terms/2.3",
"title" : "SPDX 2.3", "title" : "SPDX 2.3.1-dev",
"type" : "object", "type" : "object",
"properties" : { "properties" : {
"$schema": { "$schema": {
"type": "string", "type": "string",
"description": "Reference the SPDX 2.3 JSON schema." "description": "Reference the SPDX 2.3.1 JSON schema."
}, },
"SPDXID" : { "SPDXID" : {
"type" : "string", "type" : "string",
@ -90,7 +90,7 @@
"enum" : [ "SHA1", "BLAKE3", "SHA3-384", "SHA256", "SHA384", "BLAKE2b-512", "BLAKE2b-256", "SHA3-512", "MD2", "ADLER32", "MD4", "SHA3-256", "BLAKE2b-384", "SHA512", "MD6", "MD5", "SHA224" ] "enum" : [ "SHA1", "BLAKE3", "SHA3-384", "SHA256", "SHA384", "BLAKE2b-512", "BLAKE2b-256", "SHA3-512", "MD2", "ADLER32", "MD4", "SHA3-256", "BLAKE2b-384", "SHA512", "MD6", "MD5", "SHA224" ]
}, },
"checksumValue" : { "checksumValue" : {
"description" : "The checksumValue property provides a lower case hexidecimal encoded digest value produced using a specific algorithm.", "description" : "The checksumValue property provides a lower case hexadecimal encoded digest value produced using a specific algorithm.",
"type" : "string" "type" : "string"
} }
}, },
@ -270,10 +270,10 @@
} }
}, },
"attributionTexts" : { "attributionTexts" : {
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.", "description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConcluded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
"type" : "array", "type" : "array",
"items" : { "items" : {
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.", "description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConcluded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
"type" : "string" "type" : "string"
} }
}, },
@ -293,7 +293,7 @@
"enum" : [ "SHA1", "BLAKE3", "SHA3-384", "SHA256", "SHA384", "BLAKE2b-512", "BLAKE2b-256", "SHA3-512", "MD2", "ADLER32", "MD4", "SHA3-256", "BLAKE2b-384", "SHA512", "MD6", "MD5", "SHA224" ] "enum" : [ "SHA1", "BLAKE3", "SHA3-384", "SHA256", "SHA384", "BLAKE2b-512", "BLAKE2b-256", "SHA3-512", "MD2", "ADLER32", "MD4", "SHA3-256", "BLAKE2b-384", "SHA512", "MD6", "MD5", "SHA224" ]
}, },
"checksumValue" : { "checksumValue" : {
"description" : "The checksumValue property provides a lower case hexidecimal encoded digest value produced using a specific algorithm.", "description" : "The checksumValue property provides a lower case hexadecimal encoded digest value produced using a specific algorithm.",
"type" : "string" "type" : "string"
} }
}, },
@ -375,10 +375,10 @@
"type" : "string" "type" : "string"
}, },
"licenseInfoFromFiles" : { "licenseInfoFromFiles" : {
"description" : "The licensing information that was discovered directly within the package. There will be an instance of this property for each distinct value of alllicenseInfoInFile properties of all files contained in the package.\n\nIf the licenseInfoFromFiles field is not present for a package and filesAnalyzed property for that same package is true or omitted, it implies an equivalent meaning to NOASSERTION.", "description" : "The licensing information that was discovered directly within the package. There will be an instance of this property for each distinct value of all licenseInfoInFile properties of all files contained in the package.\n\nIf the licenseInfoFromFiles field is not present for a package and filesAnalyzed property for that same package is true or omitted, it implies an equivalent meaning to NOASSERTION.",
"type" : "array", "type" : "array",
"items" : { "items" : {
"description" : "License expression for licenseInfoFromFiles. See SPDX Annex D for the license expression syntax. The licensing information that was discovered directly within the package. There will be an instance of this property for each distinct value of alllicenseInfoInFile properties of all files contained in the package.\n\nIf the licenseInfoFromFiles field is not present for a package and filesAnalyzed property for that same package is true or omitted, it implies an equivalent meaning to NOASSERTION.", "description" : "License expression for licenseInfoFromFiles. See SPDX Annex D for the license expression syntax. The licensing information that was discovered directly within the package. There will be an instance of this property for each distinct value of all licenseInfoInFile properties of all files contained in the package.\n\nIf the licenseInfoFromFiles field is not present for a package and filesAnalyzed property for that same package is true or omitted, it implies an equivalent meaning to NOASSERTION.",
"type" : "string" "type" : "string"
} }
}, },
@ -417,7 +417,7 @@
"primaryPackagePurpose" : { "primaryPackagePurpose" : {
"description" : "This field provides information about the primary purpose of the identified package. Package Purpose is intrinsic to how the package is being used rather than the content of the package.", "description" : "This field provides information about the primary purpose of the identified package. Package Purpose is intrinsic to how the package is being used rather than the content of the package.",
"type" : "string", "type" : "string",
"enum" : [ "OTHER", "INSTALL", "ARCHIVE", "FIRMWARE", "APPLICATION", "FRAMEWORK", "LIBRARY", "CONTAINER", "SOURCE", "DEVICE", "OPERATING_SYSTEM", "FILE" ] "enum" : [ "OTHER", "INSTALL", "ARCHIVE", "FIRMWARE", "APPLICATION", "FRAMEWORK", "LIBRARY", "CONTAINER", "SOURCE", "DEVICE", "OPERATING-SYSTEM", "FILE" ]
}, },
"releaseDate" : { "releaseDate" : {
"description" : "This field provides a place for recording the date the package was released.", "description" : "This field provides a place for recording the date the package was released.",
@ -494,10 +494,10 @@
} }
}, },
"attributionTexts" : { "attributionTexts" : {
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.", "description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConcluded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
"type" : "array", "type" : "array",
"items" : { "items" : {
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.", "description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConcluded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
"type" : "string" "type" : "string"
} }
}, },
@ -514,7 +514,7 @@
"enum" : [ "SHA1", "BLAKE3", "SHA3-384", "SHA256", "SHA384", "BLAKE2b-512", "BLAKE2b-256", "SHA3-512", "MD2", "ADLER32", "MD4", "SHA3-256", "BLAKE2b-384", "SHA512", "MD6", "MD5", "SHA224" ] "enum" : [ "SHA1", "BLAKE3", "SHA3-384", "SHA256", "SHA384", "BLAKE2b-512", "BLAKE2b-256", "SHA3-512", "MD2", "ADLER32", "MD4", "SHA3-256", "BLAKE2b-384", "SHA512", "MD6", "MD5", "SHA224" ]
}, },
"checksumValue" : { "checksumValue" : {
"description" : "The checksumValue property provides a lower case hexidecimal encoded digest value produced using a specific algorithm.", "description" : "The checksumValue property provides a lower case hexadecimal encoded digest value produced using a specific algorithm.",
"type" : "string" "type" : "string"
} }
}, },
@ -624,10 +624,10 @@
} }
}, },
"attributionTexts" : { "attributionTexts" : {
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.", "description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConcluded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
"type" : "array", "type" : "array",
"items" : { "items" : {
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.", "description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConcluded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
"type" : "string" "type" : "string"
} }
}, },
@ -709,7 +709,7 @@
} }
}, },
"snippetFromFile" : { "snippetFromFile" : {
"description" : "SPDX ID for File. File containing the SPDX element (e.g. the file contaning a snippet).", "description" : "SPDX ID for File. File containing the SPDX element (e.g. the file containing a snippet).",
"type" : "string" "type" : "string"
} }
}, },

View File

@ -1,11 +1,11 @@
{ {
"licenseListVersion": "3.26.0", "licenseListVersion": "3.27.0",
"exceptions": [ "exceptions": [
{ {
"reference": "https://spdx.org/licenses/389-exception.html", "reference": "https://spdx.org/licenses/389-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/389-exception.json", "detailsUrl": "https://spdx.org/licenses/389-exception.json",
"referenceNumber": 54, "referenceNumber": 36,
"name": "389 Directory Server Exception", "name": "389 Directory Server Exception",
"licenseExceptionId": "389-exception", "licenseExceptionId": "389-exception",
"seeAlso": [ "seeAlso": [
@ -17,7 +17,7 @@
"reference": "https://spdx.org/licenses/Asterisk-exception.html", "reference": "https://spdx.org/licenses/Asterisk-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Asterisk-exception.json", "detailsUrl": "https://spdx.org/licenses/Asterisk-exception.json",
"referenceNumber": 25, "referenceNumber": 16,
"name": "Asterisk exception", "name": "Asterisk exception",
"licenseExceptionId": "Asterisk-exception", "licenseExceptionId": "Asterisk-exception",
"seeAlso": [ "seeAlso": [
@ -29,7 +29,7 @@
"reference": "https://spdx.org/licenses/Asterisk-linking-protocols-exception.html", "reference": "https://spdx.org/licenses/Asterisk-linking-protocols-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Asterisk-linking-protocols-exception.json", "detailsUrl": "https://spdx.org/licenses/Asterisk-linking-protocols-exception.json",
"referenceNumber": 42, "referenceNumber": 22,
"name": "Asterisk linking protocols exception", "name": "Asterisk linking protocols exception",
"licenseExceptionId": "Asterisk-linking-protocols-exception", "licenseExceptionId": "Asterisk-linking-protocols-exception",
"seeAlso": [ "seeAlso": [
@ -40,7 +40,7 @@
"reference": "https://spdx.org/licenses/Autoconf-exception-2.0.html", "reference": "https://spdx.org/licenses/Autoconf-exception-2.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Autoconf-exception-2.0.json", "detailsUrl": "https://spdx.org/licenses/Autoconf-exception-2.0.json",
"referenceNumber": 17, "referenceNumber": 2,
"name": "Autoconf exception 2.0", "name": "Autoconf exception 2.0",
"licenseExceptionId": "Autoconf-exception-2.0", "licenseExceptionId": "Autoconf-exception-2.0",
"seeAlso": [ "seeAlso": [
@ -52,7 +52,7 @@
"reference": "https://spdx.org/licenses/Autoconf-exception-3.0.html", "reference": "https://spdx.org/licenses/Autoconf-exception-3.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Autoconf-exception-3.0.json", "detailsUrl": "https://spdx.org/licenses/Autoconf-exception-3.0.json",
"referenceNumber": 20, "referenceNumber": 51,
"name": "Autoconf exception 3.0", "name": "Autoconf exception 3.0",
"licenseExceptionId": "Autoconf-exception-3.0", "licenseExceptionId": "Autoconf-exception-3.0",
"seeAlso": [ "seeAlso": [
@ -63,7 +63,7 @@
"reference": "https://spdx.org/licenses/Autoconf-exception-generic.html", "reference": "https://spdx.org/licenses/Autoconf-exception-generic.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Autoconf-exception-generic.json", "detailsUrl": "https://spdx.org/licenses/Autoconf-exception-generic.json",
"referenceNumber": 66, "referenceNumber": 73,
"name": "Autoconf generic exception", "name": "Autoconf generic exception",
"licenseExceptionId": "Autoconf-exception-generic", "licenseExceptionId": "Autoconf-exception-generic",
"seeAlso": [ "seeAlso": [
@ -77,7 +77,7 @@
"reference": "https://spdx.org/licenses/Autoconf-exception-generic-3.0.html", "reference": "https://spdx.org/licenses/Autoconf-exception-generic-3.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Autoconf-exception-generic-3.0.json", "detailsUrl": "https://spdx.org/licenses/Autoconf-exception-generic-3.0.json",
"referenceNumber": 16, "referenceNumber": 40,
"name": "Autoconf generic exception for GPL-3.0", "name": "Autoconf generic exception for GPL-3.0",
"licenseExceptionId": "Autoconf-exception-generic-3.0", "licenseExceptionId": "Autoconf-exception-generic-3.0",
"seeAlso": [ "seeAlso": [
@ -88,7 +88,7 @@
"reference": "https://spdx.org/licenses/Autoconf-exception-macro.html", "reference": "https://spdx.org/licenses/Autoconf-exception-macro.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Autoconf-exception-macro.json", "detailsUrl": "https://spdx.org/licenses/Autoconf-exception-macro.json",
"referenceNumber": 41, "referenceNumber": 63,
"name": "Autoconf macro exception", "name": "Autoconf macro exception",
"licenseExceptionId": "Autoconf-exception-macro", "licenseExceptionId": "Autoconf-exception-macro",
"seeAlso": [ "seeAlso": [
@ -101,7 +101,7 @@
"reference": "https://spdx.org/licenses/Bison-exception-1.24.html", "reference": "https://spdx.org/licenses/Bison-exception-1.24.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Bison-exception-1.24.json", "detailsUrl": "https://spdx.org/licenses/Bison-exception-1.24.json",
"referenceNumber": 34, "referenceNumber": 56,
"name": "Bison exception 1.24", "name": "Bison exception 1.24",
"licenseExceptionId": "Bison-exception-1.24", "licenseExceptionId": "Bison-exception-1.24",
"seeAlso": [ "seeAlso": [
@ -112,7 +112,7 @@
"reference": "https://spdx.org/licenses/Bison-exception-2.2.html", "reference": "https://spdx.org/licenses/Bison-exception-2.2.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Bison-exception-2.2.json", "detailsUrl": "https://spdx.org/licenses/Bison-exception-2.2.json",
"referenceNumber": 50, "referenceNumber": 28,
"name": "Bison exception 2.2", "name": "Bison exception 2.2",
"licenseExceptionId": "Bison-exception-2.2", "licenseExceptionId": "Bison-exception-2.2",
"seeAlso": [ "seeAlso": [
@ -123,7 +123,7 @@
"reference": "https://spdx.org/licenses/Bootloader-exception.html", "reference": "https://spdx.org/licenses/Bootloader-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Bootloader-exception.json", "detailsUrl": "https://spdx.org/licenses/Bootloader-exception.json",
"referenceNumber": 67, "referenceNumber": 65,
"name": "Bootloader Distribution Exception", "name": "Bootloader Distribution Exception",
"licenseExceptionId": "Bootloader-exception", "licenseExceptionId": "Bootloader-exception",
"seeAlso": [ "seeAlso": [
@ -134,7 +134,7 @@
"reference": "https://spdx.org/licenses/CGAL-linking-exception.html", "reference": "https://spdx.org/licenses/CGAL-linking-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/CGAL-linking-exception.json", "detailsUrl": "https://spdx.org/licenses/CGAL-linking-exception.json",
"referenceNumber": 43, "referenceNumber": 74,
"name": "CGAL Linking Exception", "name": "CGAL Linking Exception",
"licenseExceptionId": "CGAL-linking-exception", "licenseExceptionId": "CGAL-linking-exception",
"seeAlso": [ "seeAlso": [
@ -146,7 +146,7 @@
"reference": "https://spdx.org/licenses/Classpath-exception-2.0.html", "reference": "https://spdx.org/licenses/Classpath-exception-2.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Classpath-exception-2.0.json", "detailsUrl": "https://spdx.org/licenses/Classpath-exception-2.0.json",
"referenceNumber": 69, "referenceNumber": 67,
"name": "Classpath exception 2.0", "name": "Classpath exception 2.0",
"licenseExceptionId": "Classpath-exception-2.0", "licenseExceptionId": "Classpath-exception-2.0",
"seeAlso": [ "seeAlso": [
@ -158,7 +158,7 @@
"reference": "https://spdx.org/licenses/CLISP-exception-2.0.html", "reference": "https://spdx.org/licenses/CLISP-exception-2.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/CLISP-exception-2.0.json", "detailsUrl": "https://spdx.org/licenses/CLISP-exception-2.0.json",
"referenceNumber": 1, "referenceNumber": 10,
"name": "CLISP exception 2.0", "name": "CLISP exception 2.0",
"licenseExceptionId": "CLISP-exception-2.0", "licenseExceptionId": "CLISP-exception-2.0",
"seeAlso": [ "seeAlso": [
@ -169,7 +169,7 @@
"reference": "https://spdx.org/licenses/cryptsetup-OpenSSL-exception.html", "reference": "https://spdx.org/licenses/cryptsetup-OpenSSL-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/cryptsetup-OpenSSL-exception.json", "detailsUrl": "https://spdx.org/licenses/cryptsetup-OpenSSL-exception.json",
"referenceNumber": 53, "referenceNumber": 46,
"name": "cryptsetup OpenSSL exception", "name": "cryptsetup OpenSSL exception",
"licenseExceptionId": "cryptsetup-OpenSSL-exception", "licenseExceptionId": "cryptsetup-OpenSSL-exception",
"seeAlso": [ "seeAlso": [
@ -177,14 +177,26 @@
"https://gitlab.nic.cz/datovka/datovka/-/blob/develop/COPYING", "https://gitlab.nic.cz/datovka/datovka/-/blob/develop/COPYING",
"https://github.com/nbs-system/naxsi/blob/951123ad456bdf5ac94e8d8819342fe3d49bc002/naxsi_src/naxsi_raw.c", "https://github.com/nbs-system/naxsi/blob/951123ad456bdf5ac94e8d8819342fe3d49bc002/naxsi_src/naxsi_raw.c",
"http://web.mit.edu/jgross/arch/amd64_deb60/bin/mosh", "http://web.mit.edu/jgross/arch/amd64_deb60/bin/mosh",
"https://sourceforge.net/p/linux-ima/ima-evm-utils/ci/master/tree/src/evmctl.c#l30" "https://sourceforge.net/p/linux-ima/ima-evm-utils/ci/master/tree/src/evmctl.c#l30",
"https://github.com/ocaml-omake/omake/blob/master/LICENSE.OMake#L20"
]
},
{
"reference": "https://spdx.org/licenses/Digia-Qt-LGPL-exception-1.1.html",
"isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Digia-Qt-LGPL-exception-1.1.json",
"referenceNumber": 48,
"name": "Digia Qt LGPL Exception version 1.1",
"licenseExceptionId": "Digia-Qt-LGPL-exception-1.1",
"seeAlso": [
"https://src.fedoraproject.org/rpms/qtlockedfile/blob/rawhide/f/LGPL_EXCEPTION"
] ]
}, },
{ {
"reference": "https://spdx.org/licenses/DigiRule-FOSS-exception.html", "reference": "https://spdx.org/licenses/DigiRule-FOSS-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/DigiRule-FOSS-exception.json", "detailsUrl": "https://spdx.org/licenses/DigiRule-FOSS-exception.json",
"referenceNumber": 13, "referenceNumber": 53,
"name": "DigiRule FOSS License Exception", "name": "DigiRule FOSS License Exception",
"licenseExceptionId": "DigiRule-FOSS-exception", "licenseExceptionId": "DigiRule-FOSS-exception",
"seeAlso": [ "seeAlso": [
@ -195,7 +207,7 @@
"reference": "https://spdx.org/licenses/eCos-exception-2.0.html", "reference": "https://spdx.org/licenses/eCos-exception-2.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/eCos-exception-2.0.json", "detailsUrl": "https://spdx.org/licenses/eCos-exception-2.0.json",
"referenceNumber": 58, "referenceNumber": 61,
"name": "eCos exception 2.0", "name": "eCos exception 2.0",
"licenseExceptionId": "eCos-exception-2.0", "licenseExceptionId": "eCos-exception-2.0",
"seeAlso": [ "seeAlso": [
@ -206,7 +218,7 @@
"reference": "https://spdx.org/licenses/erlang-otp-linking-exception.html", "reference": "https://spdx.org/licenses/erlang-otp-linking-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/erlang-otp-linking-exception.json", "detailsUrl": "https://spdx.org/licenses/erlang-otp-linking-exception.json",
"referenceNumber": 38, "referenceNumber": 13,
"name": "Erlang/OTP Linking Exception", "name": "Erlang/OTP Linking Exception",
"licenseExceptionId": "erlang-otp-linking-exception", "licenseExceptionId": "erlang-otp-linking-exception",
"seeAlso": [ "seeAlso": [
@ -219,7 +231,7 @@
"reference": "https://spdx.org/licenses/Fawkes-Runtime-exception.html", "reference": "https://spdx.org/licenses/Fawkes-Runtime-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Fawkes-Runtime-exception.json", "detailsUrl": "https://spdx.org/licenses/Fawkes-Runtime-exception.json",
"referenceNumber": 12, "referenceNumber": 21,
"name": "Fawkes Runtime Exception", "name": "Fawkes Runtime Exception",
"licenseExceptionId": "Fawkes-Runtime-exception", "licenseExceptionId": "Fawkes-Runtime-exception",
"seeAlso": [ "seeAlso": [
@ -230,7 +242,7 @@
"reference": "https://spdx.org/licenses/FLTK-exception.html", "reference": "https://spdx.org/licenses/FLTK-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/FLTK-exception.json", "detailsUrl": "https://spdx.org/licenses/FLTK-exception.json",
"referenceNumber": 8, "referenceNumber": 66,
"name": "FLTK exception", "name": "FLTK exception",
"licenseExceptionId": "FLTK-exception", "licenseExceptionId": "FLTK-exception",
"seeAlso": [ "seeAlso": [
@ -241,7 +253,7 @@
"reference": "https://spdx.org/licenses/fmt-exception.html", "reference": "https://spdx.org/licenses/fmt-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/fmt-exception.json", "detailsUrl": "https://spdx.org/licenses/fmt-exception.json",
"referenceNumber": 2, "referenceNumber": 77,
"name": "fmt exception", "name": "fmt exception",
"licenseExceptionId": "fmt-exception", "licenseExceptionId": "fmt-exception",
"seeAlso": [ "seeAlso": [
@ -253,7 +265,7 @@
"reference": "https://spdx.org/licenses/Font-exception-2.0.html", "reference": "https://spdx.org/licenses/Font-exception-2.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Font-exception-2.0.json", "detailsUrl": "https://spdx.org/licenses/Font-exception-2.0.json",
"referenceNumber": 59, "referenceNumber": 35,
"name": "Font exception 2.0", "name": "Font exception 2.0",
"licenseExceptionId": "Font-exception-2.0", "licenseExceptionId": "Font-exception-2.0",
"seeAlso": [ "seeAlso": [
@ -264,7 +276,7 @@
"reference": "https://spdx.org/licenses/freertos-exception-2.0.html", "reference": "https://spdx.org/licenses/freertos-exception-2.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/freertos-exception-2.0.json", "detailsUrl": "https://spdx.org/licenses/freertos-exception-2.0.json",
"referenceNumber": 37, "referenceNumber": 23,
"name": "FreeRTOS Exception 2.0", "name": "FreeRTOS Exception 2.0",
"licenseExceptionId": "freertos-exception-2.0", "licenseExceptionId": "freertos-exception-2.0",
"seeAlso": [ "seeAlso": [
@ -275,7 +287,7 @@
"reference": "https://spdx.org/licenses/GCC-exception-2.0.html", "reference": "https://spdx.org/licenses/GCC-exception-2.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/GCC-exception-2.0.json", "detailsUrl": "https://spdx.org/licenses/GCC-exception-2.0.json",
"referenceNumber": 27, "referenceNumber": 14,
"name": "GCC Runtime Library exception 2.0", "name": "GCC Runtime Library exception 2.0",
"licenseExceptionId": "GCC-exception-2.0", "licenseExceptionId": "GCC-exception-2.0",
"seeAlso": [ "seeAlso": [
@ -287,7 +299,7 @@
"reference": "https://spdx.org/licenses/GCC-exception-2.0-note.html", "reference": "https://spdx.org/licenses/GCC-exception-2.0-note.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/GCC-exception-2.0-note.json", "detailsUrl": "https://spdx.org/licenses/GCC-exception-2.0-note.json",
"referenceNumber": 47, "referenceNumber": 20,
"name": "GCC Runtime Library exception 2.0 - note variant", "name": "GCC Runtime Library exception 2.0 - note variant",
"licenseExceptionId": "GCC-exception-2.0-note", "licenseExceptionId": "GCC-exception-2.0-note",
"seeAlso": [ "seeAlso": [
@ -298,7 +310,7 @@
"reference": "https://spdx.org/licenses/GCC-exception-3.1.html", "reference": "https://spdx.org/licenses/GCC-exception-3.1.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/GCC-exception-3.1.json", "detailsUrl": "https://spdx.org/licenses/GCC-exception-3.1.json",
"referenceNumber": 65, "referenceNumber": 25,
"name": "GCC Runtime Library exception 3.1", "name": "GCC Runtime Library exception 3.1",
"licenseExceptionId": "GCC-exception-3.1", "licenseExceptionId": "GCC-exception-3.1",
"seeAlso": [ "seeAlso": [
@ -309,7 +321,7 @@
"reference": "https://spdx.org/licenses/Gmsh-exception.html", "reference": "https://spdx.org/licenses/Gmsh-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Gmsh-exception.json", "detailsUrl": "https://spdx.org/licenses/Gmsh-exception.json",
"referenceNumber": 24, "referenceNumber": 26,
"name": "Gmsh exception", "name": "Gmsh exception",
"licenseExceptionId": "Gmsh-exception", "licenseExceptionId": "Gmsh-exception",
"seeAlso": [ "seeAlso": [
@ -320,7 +332,7 @@
"reference": "https://spdx.org/licenses/GNAT-exception.html", "reference": "https://spdx.org/licenses/GNAT-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/GNAT-exception.json", "detailsUrl": "https://spdx.org/licenses/GNAT-exception.json",
"referenceNumber": 14, "referenceNumber": 69,
"name": "GNAT exception", "name": "GNAT exception",
"licenseExceptionId": "GNAT-exception", "licenseExceptionId": "GNAT-exception",
"seeAlso": [ "seeAlso": [
@ -331,7 +343,7 @@
"reference": "https://spdx.org/licenses/GNOME-examples-exception.html", "reference": "https://spdx.org/licenses/GNOME-examples-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/GNOME-examples-exception.json", "detailsUrl": "https://spdx.org/licenses/GNOME-examples-exception.json",
"referenceNumber": 19, "referenceNumber": 76,
"name": "GNOME examples exception", "name": "GNOME examples exception",
"licenseExceptionId": "GNOME-examples-exception", "licenseExceptionId": "GNOME-examples-exception",
"seeAlso": [ "seeAlso": [
@ -343,7 +355,7 @@
"reference": "https://spdx.org/licenses/GNU-compiler-exception.html", "reference": "https://spdx.org/licenses/GNU-compiler-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/GNU-compiler-exception.json", "detailsUrl": "https://spdx.org/licenses/GNU-compiler-exception.json",
"referenceNumber": 57, "referenceNumber": 58,
"name": "GNU Compiler Exception", "name": "GNU Compiler Exception",
"licenseExceptionId": "GNU-compiler-exception", "licenseExceptionId": "GNU-compiler-exception",
"seeAlso": [ "seeAlso": [
@ -354,7 +366,7 @@
"reference": "https://spdx.org/licenses/gnu-javamail-exception.html", "reference": "https://spdx.org/licenses/gnu-javamail-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/gnu-javamail-exception.json", "detailsUrl": "https://spdx.org/licenses/gnu-javamail-exception.json",
"referenceNumber": 63, "referenceNumber": 64,
"name": "GNU JavaMail exception", "name": "GNU JavaMail exception",
"licenseExceptionId": "gnu-javamail-exception", "licenseExceptionId": "gnu-javamail-exception",
"seeAlso": [ "seeAlso": [
@ -365,7 +377,7 @@
"reference": "https://spdx.org/licenses/GPL-3.0-389-ds-base-exception.html", "reference": "https://spdx.org/licenses/GPL-3.0-389-ds-base-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/GPL-3.0-389-ds-base-exception.json", "detailsUrl": "https://spdx.org/licenses/GPL-3.0-389-ds-base-exception.json",
"referenceNumber": 64, "referenceNumber": 18,
"name": "GPL-3.0 389 DS Base Exception", "name": "GPL-3.0 389 DS Base Exception",
"licenseExceptionId": "GPL-3.0-389-ds-base-exception", "licenseExceptionId": "GPL-3.0-389-ds-base-exception",
"seeAlso": [] "seeAlso": []
@ -374,7 +386,7 @@
"reference": "https://spdx.org/licenses/GPL-3.0-interface-exception.html", "reference": "https://spdx.org/licenses/GPL-3.0-interface-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/GPL-3.0-interface-exception.json", "detailsUrl": "https://spdx.org/licenses/GPL-3.0-interface-exception.json",
"referenceNumber": 44, "referenceNumber": 78,
"name": "GPL-3.0 Interface Exception", "name": "GPL-3.0 Interface Exception",
"licenseExceptionId": "GPL-3.0-interface-exception", "licenseExceptionId": "GPL-3.0-interface-exception",
"seeAlso": [ "seeAlso": [
@ -385,7 +397,7 @@
"reference": "https://spdx.org/licenses/GPL-3.0-linking-exception.html", "reference": "https://spdx.org/licenses/GPL-3.0-linking-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/GPL-3.0-linking-exception.json", "detailsUrl": "https://spdx.org/licenses/GPL-3.0-linking-exception.json",
"referenceNumber": 10, "referenceNumber": 68,
"name": "GPL-3.0 Linking Exception", "name": "GPL-3.0 Linking Exception",
"licenseExceptionId": "GPL-3.0-linking-exception", "licenseExceptionId": "GPL-3.0-linking-exception",
"seeAlso": [ "seeAlso": [
@ -396,7 +408,7 @@
"reference": "https://spdx.org/licenses/GPL-3.0-linking-source-exception.html", "reference": "https://spdx.org/licenses/GPL-3.0-linking-source-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/GPL-3.0-linking-source-exception.json", "detailsUrl": "https://spdx.org/licenses/GPL-3.0-linking-source-exception.json",
"referenceNumber": 71, "referenceNumber": 62,
"name": "GPL-3.0 Linking Exception (with Corresponding Source)", "name": "GPL-3.0 Linking Exception (with Corresponding Source)",
"licenseExceptionId": "GPL-3.0-linking-source-exception", "licenseExceptionId": "GPL-3.0-linking-source-exception",
"seeAlso": [ "seeAlso": [
@ -408,7 +420,7 @@
"reference": "https://spdx.org/licenses/GPL-CC-1.0.html", "reference": "https://spdx.org/licenses/GPL-CC-1.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/GPL-CC-1.0.json", "detailsUrl": "https://spdx.org/licenses/GPL-CC-1.0.json",
"referenceNumber": 18, "referenceNumber": 33,
"name": "GPL Cooperation Commitment 1.0", "name": "GPL Cooperation Commitment 1.0",
"licenseExceptionId": "GPL-CC-1.0", "licenseExceptionId": "GPL-CC-1.0",
"seeAlso": [ "seeAlso": [
@ -420,7 +432,7 @@
"reference": "https://spdx.org/licenses/GStreamer-exception-2005.html", "reference": "https://spdx.org/licenses/GStreamer-exception-2005.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/GStreamer-exception-2005.json", "detailsUrl": "https://spdx.org/licenses/GStreamer-exception-2005.json",
"referenceNumber": 72, "referenceNumber": 4,
"name": "GStreamer Exception (2005)", "name": "GStreamer Exception (2005)",
"licenseExceptionId": "GStreamer-exception-2005", "licenseExceptionId": "GStreamer-exception-2005",
"seeAlso": [ "seeAlso": [
@ -431,7 +443,7 @@
"reference": "https://spdx.org/licenses/GStreamer-exception-2008.html", "reference": "https://spdx.org/licenses/GStreamer-exception-2008.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/GStreamer-exception-2008.json", "detailsUrl": "https://spdx.org/licenses/GStreamer-exception-2008.json",
"referenceNumber": 6, "referenceNumber": 41,
"name": "GStreamer Exception (2008)", "name": "GStreamer Exception (2008)",
"licenseExceptionId": "GStreamer-exception-2008", "licenseExceptionId": "GStreamer-exception-2008",
"seeAlso": [ "seeAlso": [
@ -442,7 +454,7 @@
"reference": "https://spdx.org/licenses/harbour-exception.html", "reference": "https://spdx.org/licenses/harbour-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/harbour-exception.json", "detailsUrl": "https://spdx.org/licenses/harbour-exception.json",
"referenceNumber": 7, "referenceNumber": 59,
"name": "harbour exception", "name": "harbour exception",
"licenseExceptionId": "harbour-exception", "licenseExceptionId": "harbour-exception",
"seeAlso": [ "seeAlso": [
@ -453,7 +465,7 @@
"reference": "https://spdx.org/licenses/i2p-gpl-java-exception.html", "reference": "https://spdx.org/licenses/i2p-gpl-java-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/i2p-gpl-java-exception.json", "detailsUrl": "https://spdx.org/licenses/i2p-gpl-java-exception.json",
"referenceNumber": 40, "referenceNumber": 9,
"name": "i2p GPL+Java Exception", "name": "i2p GPL+Java Exception",
"licenseExceptionId": "i2p-gpl-java-exception", "licenseExceptionId": "i2p-gpl-java-exception",
"seeAlso": [ "seeAlso": [
@ -464,7 +476,7 @@
"reference": "https://spdx.org/licenses/Independent-modules-exception.html", "reference": "https://spdx.org/licenses/Independent-modules-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Independent-modules-exception.json", "detailsUrl": "https://spdx.org/licenses/Independent-modules-exception.json",
"referenceNumber": 61, "referenceNumber": 45,
"name": "Independent Module Linking exception", "name": "Independent Module Linking exception",
"licenseExceptionId": "Independent-modules-exception", "licenseExceptionId": "Independent-modules-exception",
"seeAlso": [ "seeAlso": [
@ -475,7 +487,7 @@
"reference": "https://spdx.org/licenses/KiCad-libraries-exception.html", "reference": "https://spdx.org/licenses/KiCad-libraries-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/KiCad-libraries-exception.json", "detailsUrl": "https://spdx.org/licenses/KiCad-libraries-exception.json",
"referenceNumber": 68, "referenceNumber": 44,
"name": "KiCad Libraries Exception", "name": "KiCad Libraries Exception",
"licenseExceptionId": "KiCad-libraries-exception", "licenseExceptionId": "KiCad-libraries-exception",
"seeAlso": [ "seeAlso": [
@ -486,7 +498,7 @@
"reference": "https://spdx.org/licenses/LGPL-3.0-linking-exception.html", "reference": "https://spdx.org/licenses/LGPL-3.0-linking-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/LGPL-3.0-linking-exception.json", "detailsUrl": "https://spdx.org/licenses/LGPL-3.0-linking-exception.json",
"referenceNumber": 33, "referenceNumber": 32,
"name": "LGPL-3.0 Linking Exception", "name": "LGPL-3.0 Linking Exception",
"licenseExceptionId": "LGPL-3.0-linking-exception", "licenseExceptionId": "LGPL-3.0-linking-exception",
"seeAlso": [ "seeAlso": [
@ -499,7 +511,7 @@
"reference": "https://spdx.org/licenses/libpri-OpenH323-exception.html", "reference": "https://spdx.org/licenses/libpri-OpenH323-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/libpri-OpenH323-exception.json", "detailsUrl": "https://spdx.org/licenses/libpri-OpenH323-exception.json",
"referenceNumber": 55, "referenceNumber": 19,
"name": "libpri OpenH323 exception", "name": "libpri OpenH323 exception",
"licenseExceptionId": "libpri-OpenH323-exception", "licenseExceptionId": "libpri-OpenH323-exception",
"seeAlso": [ "seeAlso": [
@ -510,7 +522,7 @@
"reference": "https://spdx.org/licenses/Libtool-exception.html", "reference": "https://spdx.org/licenses/Libtool-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Libtool-exception.json", "detailsUrl": "https://spdx.org/licenses/Libtool-exception.json",
"referenceNumber": 15, "referenceNumber": 71,
"name": "Libtool Exception", "name": "Libtool Exception",
"licenseExceptionId": "Libtool-exception", "licenseExceptionId": "Libtool-exception",
"seeAlso": [ "seeAlso": [
@ -522,7 +534,7 @@
"reference": "https://spdx.org/licenses/Linux-syscall-note.html", "reference": "https://spdx.org/licenses/Linux-syscall-note.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Linux-syscall-note.json", "detailsUrl": "https://spdx.org/licenses/Linux-syscall-note.json",
"referenceNumber": 22, "referenceNumber": 37,
"name": "Linux Syscall Note", "name": "Linux Syscall Note",
"licenseExceptionId": "Linux-syscall-note", "licenseExceptionId": "Linux-syscall-note",
"seeAlso": [ "seeAlso": [
@ -533,7 +545,7 @@
"reference": "https://spdx.org/licenses/LLGPL.html", "reference": "https://spdx.org/licenses/LLGPL.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/LLGPL.json", "detailsUrl": "https://spdx.org/licenses/LLGPL.json",
"referenceNumber": 3, "referenceNumber": 24,
"name": "LLGPL Preamble", "name": "LLGPL Preamble",
"licenseExceptionId": "LLGPL", "licenseExceptionId": "LLGPL",
"seeAlso": [ "seeAlso": [
@ -544,7 +556,7 @@
"reference": "https://spdx.org/licenses/LLVM-exception.html", "reference": "https://spdx.org/licenses/LLVM-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/LLVM-exception.json", "detailsUrl": "https://spdx.org/licenses/LLVM-exception.json",
"referenceNumber": 74, "referenceNumber": 72,
"name": "LLVM Exception", "name": "LLVM Exception",
"licenseExceptionId": "LLVM-exception", "licenseExceptionId": "LLVM-exception",
"seeAlso": [ "seeAlso": [
@ -555,7 +567,7 @@
"reference": "https://spdx.org/licenses/LZMA-exception.html", "reference": "https://spdx.org/licenses/LZMA-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/LZMA-exception.json", "detailsUrl": "https://spdx.org/licenses/LZMA-exception.json",
"referenceNumber": 32, "referenceNumber": 30,
"name": "LZMA exception", "name": "LZMA exception",
"licenseExceptionId": "LZMA-exception", "licenseExceptionId": "LZMA-exception",
"seeAlso": [ "seeAlso": [
@ -566,7 +578,7 @@
"reference": "https://spdx.org/licenses/mif-exception.html", "reference": "https://spdx.org/licenses/mif-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/mif-exception.json", "detailsUrl": "https://spdx.org/licenses/mif-exception.json",
"referenceNumber": 75, "referenceNumber": 29,
"name": "Macros and Inline Functions Exception", "name": "Macros and Inline Functions Exception",
"licenseExceptionId": "mif-exception", "licenseExceptionId": "mif-exception",
"seeAlso": [ "seeAlso": [
@ -579,7 +591,7 @@
"reference": "https://spdx.org/licenses/mxml-exception.html", "reference": "https://spdx.org/licenses/mxml-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/mxml-exception.json", "detailsUrl": "https://spdx.org/licenses/mxml-exception.json",
"referenceNumber": 21, "referenceNumber": 38,
"name": "mxml Exception", "name": "mxml Exception",
"licenseExceptionId": "mxml-exception", "licenseExceptionId": "mxml-exception",
"seeAlso": [ "seeAlso": [
@ -591,7 +603,7 @@
"reference": "https://spdx.org/licenses/Nokia-Qt-exception-1.1.html", "reference": "https://spdx.org/licenses/Nokia-Qt-exception-1.1.html",
"isDeprecatedLicenseId": true, "isDeprecatedLicenseId": true,
"detailsUrl": "https://spdx.org/licenses/Nokia-Qt-exception-1.1.json", "detailsUrl": "https://spdx.org/licenses/Nokia-Qt-exception-1.1.json",
"referenceNumber": 51, "referenceNumber": 47,
"name": "Nokia Qt LGPL exception 1.1", "name": "Nokia Qt LGPL exception 1.1",
"licenseExceptionId": "Nokia-Qt-exception-1.1", "licenseExceptionId": "Nokia-Qt-exception-1.1",
"seeAlso": [ "seeAlso": [
@ -602,7 +614,7 @@
"reference": "https://spdx.org/licenses/OCaml-LGPL-linking-exception.html", "reference": "https://spdx.org/licenses/OCaml-LGPL-linking-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/OCaml-LGPL-linking-exception.json", "detailsUrl": "https://spdx.org/licenses/OCaml-LGPL-linking-exception.json",
"referenceNumber": 35, "referenceNumber": 42,
"name": "OCaml LGPL Linking Exception", "name": "OCaml LGPL Linking Exception",
"licenseExceptionId": "OCaml-LGPL-linking-exception", "licenseExceptionId": "OCaml-LGPL-linking-exception",
"seeAlso": [ "seeAlso": [
@ -613,7 +625,7 @@
"reference": "https://spdx.org/licenses/OCCT-exception-1.0.html", "reference": "https://spdx.org/licenses/OCCT-exception-1.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/OCCT-exception-1.0.json", "detailsUrl": "https://spdx.org/licenses/OCCT-exception-1.0.json",
"referenceNumber": 70, "referenceNumber": 17,
"name": "Open CASCADE Exception 1.0", "name": "Open CASCADE Exception 1.0",
"licenseExceptionId": "OCCT-exception-1.0", "licenseExceptionId": "OCCT-exception-1.0",
"seeAlso": [ "seeAlso": [
@ -624,7 +636,7 @@
"reference": "https://spdx.org/licenses/OpenJDK-assembly-exception-1.0.html", "reference": "https://spdx.org/licenses/OpenJDK-assembly-exception-1.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/OpenJDK-assembly-exception-1.0.json", "detailsUrl": "https://spdx.org/licenses/OpenJDK-assembly-exception-1.0.json",
"referenceNumber": 77, "referenceNumber": 11,
"name": "OpenJDK Assembly exception 1.0", "name": "OpenJDK Assembly exception 1.0",
"licenseExceptionId": "OpenJDK-assembly-exception-1.0", "licenseExceptionId": "OpenJDK-assembly-exception-1.0",
"seeAlso": [ "seeAlso": [
@ -635,7 +647,7 @@
"reference": "https://spdx.org/licenses/openvpn-openssl-exception.html", "reference": "https://spdx.org/licenses/openvpn-openssl-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/openvpn-openssl-exception.json", "detailsUrl": "https://spdx.org/licenses/openvpn-openssl-exception.json",
"referenceNumber": 9, "referenceNumber": 3,
"name": "OpenVPN OpenSSL Exception", "name": "OpenVPN OpenSSL Exception",
"licenseExceptionId": "openvpn-openssl-exception", "licenseExceptionId": "openvpn-openssl-exception",
"seeAlso": [ "seeAlso": [
@ -647,18 +659,29 @@
"reference": "https://spdx.org/licenses/PCRE2-exception.html", "reference": "https://spdx.org/licenses/PCRE2-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/PCRE2-exception.json", "detailsUrl": "https://spdx.org/licenses/PCRE2-exception.json",
"referenceNumber": 76, "referenceNumber": 12,
"name": "PCRE2 exception", "name": "PCRE2 exception",
"licenseExceptionId": "PCRE2-exception", "licenseExceptionId": "PCRE2-exception",
"seeAlso": [ "seeAlso": [
"https://www.pcre.org/licence.txt" "https://www.pcre.org/licence.txt"
] ]
}, },
{
"reference": "https://spdx.org/licenses/polyparse-exception.html",
"isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/polyparse-exception.json",
"referenceNumber": 54,
"name": "Polyparse Exception",
"licenseExceptionId": "polyparse-exception",
"seeAlso": [
"https://hackage.haskell.org/package/polyparse-1.13/src/COPYRIGHT"
]
},
{ {
"reference": "https://spdx.org/licenses/PS-or-PDF-font-exception-20170817.html", "reference": "https://spdx.org/licenses/PS-or-PDF-font-exception-20170817.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/PS-or-PDF-font-exception-20170817.json", "detailsUrl": "https://spdx.org/licenses/PS-or-PDF-font-exception-20170817.json",
"referenceNumber": 4, "referenceNumber": 43,
"name": "PS/PDF font exception (2017-08-17)", "name": "PS/PDF font exception (2017-08-17)",
"licenseExceptionId": "PS-or-PDF-font-exception-20170817", "licenseExceptionId": "PS-or-PDF-font-exception-20170817",
"seeAlso": [ "seeAlso": [
@ -669,7 +692,7 @@
"reference": "https://spdx.org/licenses/QPL-1.0-INRIA-2004-exception.html", "reference": "https://spdx.org/licenses/QPL-1.0-INRIA-2004-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/QPL-1.0-INRIA-2004-exception.json", "detailsUrl": "https://spdx.org/licenses/QPL-1.0-INRIA-2004-exception.json",
"referenceNumber": 48, "referenceNumber": 50,
"name": "INRIA QPL 1.0 2004 variant exception", "name": "INRIA QPL 1.0 2004 variant exception",
"licenseExceptionId": "QPL-1.0-INRIA-2004-exception", "licenseExceptionId": "QPL-1.0-INRIA-2004-exception",
"seeAlso": [ "seeAlso": [
@ -681,7 +704,7 @@
"reference": "https://spdx.org/licenses/Qt-GPL-exception-1.0.html", "reference": "https://spdx.org/licenses/Qt-GPL-exception-1.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Qt-GPL-exception-1.0.json", "detailsUrl": "https://spdx.org/licenses/Qt-GPL-exception-1.0.json",
"referenceNumber": 45, "referenceNumber": 34,
"name": "Qt GPL exception 1.0", "name": "Qt GPL exception 1.0",
"licenseExceptionId": "Qt-GPL-exception-1.0", "licenseExceptionId": "Qt-GPL-exception-1.0",
"seeAlso": [ "seeAlso": [
@ -692,7 +715,7 @@
"reference": "https://spdx.org/licenses/Qt-LGPL-exception-1.1.html", "reference": "https://spdx.org/licenses/Qt-LGPL-exception-1.1.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Qt-LGPL-exception-1.1.json", "detailsUrl": "https://spdx.org/licenses/Qt-LGPL-exception-1.1.json",
"referenceNumber": 73, "referenceNumber": 39,
"name": "Qt LGPL exception 1.1", "name": "Qt LGPL exception 1.1",
"licenseExceptionId": "Qt-LGPL-exception-1.1", "licenseExceptionId": "Qt-LGPL-exception-1.1",
"seeAlso": [ "seeAlso": [
@ -703,7 +726,7 @@
"reference": "https://spdx.org/licenses/Qwt-exception-1.0.html", "reference": "https://spdx.org/licenses/Qwt-exception-1.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Qwt-exception-1.0.json", "detailsUrl": "https://spdx.org/licenses/Qwt-exception-1.0.json",
"referenceNumber": 11, "referenceNumber": 79,
"name": "Qwt exception 1.0", "name": "Qwt exception 1.0",
"licenseExceptionId": "Qwt-exception-1.0", "licenseExceptionId": "Qwt-exception-1.0",
"seeAlso": [ "seeAlso": [
@ -714,7 +737,7 @@
"reference": "https://spdx.org/licenses/romic-exception.html", "reference": "https://spdx.org/licenses/romic-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/romic-exception.json", "detailsUrl": "https://spdx.org/licenses/romic-exception.json",
"referenceNumber": 28, "referenceNumber": 6,
"name": "Romic Exception", "name": "Romic Exception",
"licenseExceptionId": "romic-exception", "licenseExceptionId": "romic-exception",
"seeAlso": [ "seeAlso": [
@ -730,7 +753,7 @@
"reference": "https://spdx.org/licenses/RRDtool-FLOSS-exception-2.0.html", "reference": "https://spdx.org/licenses/RRDtool-FLOSS-exception-2.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/RRDtool-FLOSS-exception-2.0.json", "detailsUrl": "https://spdx.org/licenses/RRDtool-FLOSS-exception-2.0.json",
"referenceNumber": 29, "referenceNumber": 7,
"name": "RRDtool FLOSS exception 2.0", "name": "RRDtool FLOSS exception 2.0",
"licenseExceptionId": "RRDtool-FLOSS-exception-2.0", "licenseExceptionId": "RRDtool-FLOSS-exception-2.0",
"seeAlso": [ "seeAlso": [
@ -742,7 +765,7 @@
"reference": "https://spdx.org/licenses/SANE-exception.html", "reference": "https://spdx.org/licenses/SANE-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/SANE-exception.json", "detailsUrl": "https://spdx.org/licenses/SANE-exception.json",
"referenceNumber": 26, "referenceNumber": 27,
"name": "SANE Exception", "name": "SANE Exception",
"licenseExceptionId": "SANE-exception", "licenseExceptionId": "SANE-exception",
"seeAlso": [ "seeAlso": [
@ -755,7 +778,7 @@
"reference": "https://spdx.org/licenses/SHL-2.0.html", "reference": "https://spdx.org/licenses/SHL-2.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/SHL-2.0.json", "detailsUrl": "https://spdx.org/licenses/SHL-2.0.json",
"referenceNumber": 30, "referenceNumber": 5,
"name": "Solderpad Hardware License v2.0", "name": "Solderpad Hardware License v2.0",
"licenseExceptionId": "SHL-2.0", "licenseExceptionId": "SHL-2.0",
"seeAlso": [ "seeAlso": [
@ -766,7 +789,7 @@
"reference": "https://spdx.org/licenses/SHL-2.1.html", "reference": "https://spdx.org/licenses/SHL-2.1.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/SHL-2.1.json", "detailsUrl": "https://spdx.org/licenses/SHL-2.1.json",
"referenceNumber": 36, "referenceNumber": 1,
"name": "Solderpad Hardware License v2.1", "name": "Solderpad Hardware License v2.1",
"licenseExceptionId": "SHL-2.1", "licenseExceptionId": "SHL-2.1",
"seeAlso": [ "seeAlso": [
@ -777,7 +800,7 @@
"reference": "https://spdx.org/licenses/stunnel-exception.html", "reference": "https://spdx.org/licenses/stunnel-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/stunnel-exception.json", "detailsUrl": "https://spdx.org/licenses/stunnel-exception.json",
"referenceNumber": 60, "referenceNumber": 49,
"name": "stunnel Exception", "name": "stunnel Exception",
"licenseExceptionId": "stunnel-exception", "licenseExceptionId": "stunnel-exception",
"seeAlso": [ "seeAlso": [
@ -788,7 +811,7 @@
"reference": "https://spdx.org/licenses/SWI-exception.html", "reference": "https://spdx.org/licenses/SWI-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/SWI-exception.json", "detailsUrl": "https://spdx.org/licenses/SWI-exception.json",
"referenceNumber": 46, "referenceNumber": 15,
"name": "SWI exception", "name": "SWI exception",
"licenseExceptionId": "SWI-exception", "licenseExceptionId": "SWI-exception",
"seeAlso": [ "seeAlso": [
@ -799,7 +822,7 @@
"reference": "https://spdx.org/licenses/Swift-exception.html", "reference": "https://spdx.org/licenses/Swift-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Swift-exception.json", "detailsUrl": "https://spdx.org/licenses/Swift-exception.json",
"referenceNumber": 56, "referenceNumber": 52,
"name": "Swift Exception", "name": "Swift Exception",
"licenseExceptionId": "Swift-exception", "licenseExceptionId": "Swift-exception",
"seeAlso": [ "seeAlso": [
@ -811,7 +834,7 @@
"reference": "https://spdx.org/licenses/Texinfo-exception.html", "reference": "https://spdx.org/licenses/Texinfo-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Texinfo-exception.json", "detailsUrl": "https://spdx.org/licenses/Texinfo-exception.json",
"referenceNumber": 62, "referenceNumber": 60,
"name": "Texinfo exception", "name": "Texinfo exception",
"licenseExceptionId": "Texinfo-exception", "licenseExceptionId": "Texinfo-exception",
"seeAlso": [ "seeAlso": [
@ -822,7 +845,7 @@
"reference": "https://spdx.org/licenses/u-boot-exception-2.0.html", "reference": "https://spdx.org/licenses/u-boot-exception-2.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/u-boot-exception-2.0.json", "detailsUrl": "https://spdx.org/licenses/u-boot-exception-2.0.json",
"referenceNumber": 5, "referenceNumber": 8,
"name": "U-Boot exception 2.0", "name": "U-Boot exception 2.0",
"licenseExceptionId": "u-boot-exception-2.0", "licenseExceptionId": "u-boot-exception-2.0",
"seeAlso": [ "seeAlso": [
@ -833,7 +856,7 @@
"reference": "https://spdx.org/licenses/UBDL-exception.html", "reference": "https://spdx.org/licenses/UBDL-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/UBDL-exception.json", "detailsUrl": "https://spdx.org/licenses/UBDL-exception.json",
"referenceNumber": 23, "referenceNumber": 75,
"name": "Unmodified Binary Distribution exception", "name": "Unmodified Binary Distribution exception",
"licenseExceptionId": "UBDL-exception", "licenseExceptionId": "UBDL-exception",
"seeAlso": [ "seeAlso": [
@ -844,7 +867,7 @@
"reference": "https://spdx.org/licenses/Universal-FOSS-exception-1.0.html", "reference": "https://spdx.org/licenses/Universal-FOSS-exception-1.0.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/Universal-FOSS-exception-1.0.json", "detailsUrl": "https://spdx.org/licenses/Universal-FOSS-exception-1.0.json",
"referenceNumber": 52, "referenceNumber": 70,
"name": "Universal FOSS Exception, Version 1.0", "name": "Universal FOSS Exception, Version 1.0",
"licenseExceptionId": "Universal-FOSS-exception-1.0", "licenseExceptionId": "Universal-FOSS-exception-1.0",
"seeAlso": [ "seeAlso": [
@ -855,7 +878,7 @@
"reference": "https://spdx.org/licenses/vsftpd-openssl-exception.html", "reference": "https://spdx.org/licenses/vsftpd-openssl-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/vsftpd-openssl-exception.json", "detailsUrl": "https://spdx.org/licenses/vsftpd-openssl-exception.json",
"referenceNumber": 39, "referenceNumber": 55,
"name": "vsftpd OpenSSL exception", "name": "vsftpd OpenSSL exception",
"licenseExceptionId": "vsftpd-openssl-exception", "licenseExceptionId": "vsftpd-openssl-exception",
"seeAlso": [ "seeAlso": [
@ -868,7 +891,7 @@
"reference": "https://spdx.org/licenses/WxWindows-exception-3.1.html", "reference": "https://spdx.org/licenses/WxWindows-exception-3.1.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/WxWindows-exception-3.1.json", "detailsUrl": "https://spdx.org/licenses/WxWindows-exception-3.1.json",
"referenceNumber": 49, "referenceNumber": 31,
"name": "WxWindows Library Exception 3.1", "name": "WxWindows Library Exception 3.1",
"licenseExceptionId": "WxWindows-exception-3.1", "licenseExceptionId": "WxWindows-exception-3.1",
"seeAlso": [ "seeAlso": [
@ -879,7 +902,7 @@
"reference": "https://spdx.org/licenses/x11vnc-openssl-exception.html", "reference": "https://spdx.org/licenses/x11vnc-openssl-exception.html",
"isDeprecatedLicenseId": false, "isDeprecatedLicenseId": false,
"detailsUrl": "https://spdx.org/licenses/x11vnc-openssl-exception.json", "detailsUrl": "https://spdx.org/licenses/x11vnc-openssl-exception.json",
"referenceNumber": 31, "referenceNumber": 57,
"name": "x11vnc OpenSSL Exception", "name": "x11vnc OpenSSL Exception",
"licenseExceptionId": "x11vnc-openssl-exception", "licenseExceptionId": "x11vnc-openssl-exception",
"seeAlso": [ "seeAlso": [
@ -887,5 +910,5 @@
] ]
} }
], ],
"releaseDate": "2024-12-30T00:00:00Z" "releaseDate": "2025-07-01T00:00:00Z"
} }

Some files were not shown because too many files have changed in this diff Show More