Merge remote-tracking branch 'origin/main' into stricter-brew-wrappers
This commit is contained in:
commit
145c65d811
21
.github/copilot-instructions.md
vendored
21
.github/copilot-instructions.md
vendored
@ -9,15 +9,19 @@ Please follow these guidelines when contributing:
|
||||
### Required Before Each Commit
|
||||
|
||||
- Run `brew typecheck` to verify types are declared correctly using Sorbet.
|
||||
Individual files/directories cannot be checked.
|
||||
`brew typecheck` is fast enough to just be run globally every time.
|
||||
- Run `brew style --fix` to lint code formatting using RuboCop.
|
||||
Individual files can be checked/fixed by passing them as arguments.
|
||||
Individual files can be checked/fixed by passing them as arguments e.g. `brew style --fix Library/Homebrew/cmd/reinstall.rb``
|
||||
- Run `brew tests --online` to ensure that RSpec unit tests are passing (although some online tests may be flaky so can be ignored if they pass on a rerun).
|
||||
Individual test files can be passed with `--only` e.g. to test `Library/Homebrew/cmd/reinstall.rb` with `Library/Homebrew/test/cmd/reinstall_spec.rb` run `brew tests --only=cmd/reinstall`.
|
||||
|
||||
### Development Flow
|
||||
|
||||
- Write new code (using Sorbet `sig` type signatures and `typed: strict` files whenever possible)
|
||||
- Write new tests (avoid more than one `:integration_test` per file for speed)
|
||||
- Write new code (using Sorbet `sig` type signatures and `typed: strict` for new files, but never for RSpec/test/`*_spec.rb` files)
|
||||
- Write new tests (avoid more than one `:integration_test` per file for speed).
|
||||
Use only one `expect` assertion per test.
|
||||
- Keep comments minimal; prefer self-documenting code through strings, variable names, etc. over more comments.
|
||||
|
||||
## Repository Structure
|
||||
|
||||
@ -34,7 +38,10 @@ Please follow these guidelines when contributing:
|
||||
|
||||
## Key Guidelines
|
||||
|
||||
1. Follow Ruby best practices and idiomatic patterns
|
||||
2. Maintain existing code structure and organisation
|
||||
3. Write unit tests for new functionality. Use one assertion per test where possible.
|
||||
4. Document public APIs and complex logic. Suggest changes to the `docs/` folder when appropriate
|
||||
1. Follow Ruby and Bash best practices and idiomatic patterns.
|
||||
2. Maintain existing code structure and organisation.
|
||||
3. Write unit tests for new functionality.
|
||||
4. Document public APIs and complex logic.
|
||||
5. Suggest changes to the `docs/` folder when appropriate
|
||||
6. Follow software principles such as DRY and YAGNI.
|
||||
7. Keep diffs as minimal as possible.
|
||||
|
||||
22
.github/dependabot.yml
vendored
22
.github/dependabot.yml
vendored
@ -17,13 +17,6 @@ updates:
|
||||
- "*"
|
||||
allow:
|
||||
- dependency-type: all
|
||||
cooldown:
|
||||
default-days: 1
|
||||
semver-major-days: 14
|
||||
semver-minor-days: 7
|
||||
semver-patch-days: 1
|
||||
include:
|
||||
- "*"
|
||||
- package-ecosystem: devcontainers
|
||||
directory: "/"
|
||||
multi-ecosystem-group: all
|
||||
@ -31,10 +24,6 @@ updates:
|
||||
- "*"
|
||||
allow:
|
||||
- dependency-type: all
|
||||
cooldown:
|
||||
default-days: 1
|
||||
include:
|
||||
- "*"
|
||||
- package-ecosystem: docker
|
||||
directory: "/"
|
||||
multi-ecosystem-group: all
|
||||
@ -49,10 +38,6 @@ updates:
|
||||
- "*"
|
||||
allow:
|
||||
- dependency-type: all
|
||||
cooldown:
|
||||
default-days: 1
|
||||
include:
|
||||
- "*"
|
||||
- package-ecosystem: pip
|
||||
directories:
|
||||
- "/Library/Homebrew/formula-analytics/"
|
||||
@ -61,11 +46,4 @@ updates:
|
||||
- "*"
|
||||
allow:
|
||||
- dependency-type: all
|
||||
cooldown:
|
||||
default-days: 1
|
||||
semver-major-days: 14
|
||||
semver-minor-days: 7
|
||||
semver-patch-days: 1
|
||||
include:
|
||||
- "*"
|
||||
|
||||
|
||||
6
.github/workflows/actionlint.yml
vendored
6
.github/workflows/actionlint.yml
vendored
@ -43,7 +43,7 @@ jobs:
|
||||
- name: Install tools
|
||||
run: brew install actionlint shellcheck zizmor
|
||||
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@ -87,13 +87,13 @@ jobs:
|
||||
security-events: write
|
||||
steps:
|
||||
- name: Download SARIF file
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
|
||||
with:
|
||||
name: results.sarif
|
||||
path: results.sarif
|
||||
|
||||
- name: Upload SARIF file
|
||||
uses: github/codeql-action/upload-sarif@51f77329afa6477de8c49fc9c7046c15b9a4e79d # v3.29.5
|
||||
uses: github/codeql-action/upload-sarif@df559355d593797519d70b90fc8edd5db049e7a2 # v3.29.9
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
category: zizmor
|
||||
|
||||
2
.github/workflows/autogenerated-files.yml
vendored
2
.github/workflows/autogenerated-files.yml
vendored
@ -34,7 +34,7 @@ jobs:
|
||||
test-bot: true
|
||||
|
||||
- name: Cache Bundler RubyGems
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
with:
|
||||
path: ${{ steps.set-up-homebrew.outputs.gems-path }}
|
||||
key: ${{ runner.os }}-rubygems-${{ steps.set-up-homebrew.outputs.gems-hash }}
|
||||
|
||||
6
.github/workflows/codeql-analysis.yml
vendored
6
.github/workflows/codeql-analysis.yml
vendored
@ -22,12 +22,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@4e828ff8d448a8a6e532957b1811f387a63867e8 # v3.29.4
|
||||
uses: github/codeql-action/init@df559355d593797519d70b90fc8edd5db049e7a2 # v3.29.9
|
||||
with:
|
||||
languages: ruby
|
||||
config: |
|
||||
@ -35,4 +35,4 @@ jobs:
|
||||
- Library/Homebrew/vendor
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@4e828ff8d448a8a6e532957b1811f387a63867e8 # v3.29.4
|
||||
uses: github/codeql-action/analyze@df559355d593797519d70b90fc8edd5db049e7a2 # v3.29.9
|
||||
|
||||
14
.github/workflows/docker.yml
vendored
14
.github/workflows/docker.yml
vendored
@ -34,7 +34,7 @@ jobs:
|
||||
merge: ${{ steps.attributes.outputs.merge }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
@ -160,7 +160,7 @@ jobs:
|
||||
arch: "arm64"
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
@ -188,7 +188,7 @@ jobs:
|
||||
echo "push=$(jq --raw-output "${filter}" <<<"${PUSH}")" >>"${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Log in to GitHub Packages (github-actions[bot])
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
|
||||
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: github-actions[bot]
|
||||
@ -223,7 +223,7 @@ jobs:
|
||||
|
||||
- name: Log in to GitHub Packages (BrewTestBot)
|
||||
if: fromJSON(steps.attributes.outputs.push)
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
|
||||
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: BrewTestBot
|
||||
@ -273,20 +273,20 @@ jobs:
|
||||
cache-binary: false
|
||||
|
||||
- name: Download Docker image digests
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
|
||||
with:
|
||||
path: ${{ runner.temp }}/digests
|
||||
pattern: digest-${{ matrix.version }}-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
|
||||
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
|
||||
with:
|
||||
username: brewtestbot
|
||||
password: ${{ secrets.HOMEBREW_BREW_DOCKER_TOKEN }}
|
||||
|
||||
- name: Log in to GitHub Packages (BrewTestBot)
|
||||
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
|
||||
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: BrewTestBot
|
||||
|
||||
6
.github/workflows/docs.yml
vendored
6
.github/workflows/docs.yml
vendored
@ -31,7 +31,7 @@ jobs:
|
||||
test-bot: false
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
@ -52,7 +52,7 @@ jobs:
|
||||
run: vale docs/
|
||||
|
||||
- name: Install Ruby
|
||||
uses: ruby/setup-ruby@472790540115ce5bd69d399a020189a8c87d641f # v1.247.0
|
||||
uses: ruby/setup-ruby@829114fc20da43a41d27359103ec7a63020954d4 # v1.255.0
|
||||
with:
|
||||
bundler-cache: true
|
||||
working-directory: docs
|
||||
@ -70,7 +70,7 @@ jobs:
|
||||
run: ../script/generate-api-samples.rb --template
|
||||
|
||||
- name: Cache HTML Proofer
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
with:
|
||||
path: tmp/.htmlproofer
|
||||
key: ${{ runner.os }}-htmlproofer
|
||||
|
||||
6
.github/workflows/pkg-installer.yml
vendored
6
.github/workflows/pkg-installer.yml
vendored
@ -81,7 +81,7 @@ jobs:
|
||||
run: rm -f "${RUNNER_TEMP}/${TEMPORARY_CERTIFICATE_FILE}"
|
||||
|
||||
- name: Checkout another Homebrew to brew subdirectory
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
path: brew
|
||||
fetch-depth: 0
|
||||
@ -162,7 +162,7 @@ jobs:
|
||||
name: macos-15-arm64
|
||||
steps:
|
||||
- name: Download installer from GitHub Actions
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
|
||||
with:
|
||||
name: "${{ needs.build.outputs.installer_path }}"
|
||||
|
||||
@ -215,7 +215,7 @@ jobs:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Download installer from GitHub Actions
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
||||
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
|
||||
with:
|
||||
name: "${{ needs.build.outputs.installer_path }}"
|
||||
|
||||
|
||||
4
.github/workflows/rubydoc.yml
vendored
4
.github/workflows/rubydoc.yml
vendored
@ -36,14 +36,14 @@ jobs:
|
||||
test-bot: false
|
||||
|
||||
- name: Checkout Homebrew/rubydoc.brew.sh
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
repository: Homebrew/rubydoc.brew.sh
|
||||
path: rubydoc
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Ruby
|
||||
uses: ruby/setup-ruby@472790540115ce5bd69d399a020189a8c87d641f # v1.247.0
|
||||
uses: ruby/setup-ruby@829114fc20da43a41d27359103ec7a63020954d4 # v1.255.0
|
||||
with:
|
||||
bundler-cache: true
|
||||
working-directory: rubydoc
|
||||
|
||||
@ -50,7 +50,7 @@ jobs:
|
||||
signing_key: ${{ secrets.BREWTESTBOT_SSH_SIGNING_KEY }}
|
||||
|
||||
- name: Cache Bundler RubyGems
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
with:
|
||||
path: ${{ steps.set-up-homebrew.outputs.gems-path }}
|
||||
key: ${{ runner.os }}-rubygems-${{ steps.set-up-homebrew.outputs.gems-hash }}
|
||||
|
||||
2
.github/workflows/sync-default-branches.yml
vendored
2
.github/workflows/sync-default-branches.yml
vendored
@ -43,7 +43,7 @@ jobs:
|
||||
echo "target=${target}" >> "$GITHUB_OUTPUT"
|
||||
echo "source=${source}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
fetch-depth: 1
|
||||
persist-credentials: true
|
||||
|
||||
14
.github/workflows/tests.yml
vendored
14
.github/workflows/tests.yml
vendored
@ -40,7 +40,7 @@ jobs:
|
||||
test-bot: false
|
||||
|
||||
- name: Cache Bundler RubyGems
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
with:
|
||||
path: ${{ steps.set-up-homebrew.outputs.gems-path }}
|
||||
key: ${{ runner.os }}-rubygems-syntax-${{ steps.set-up-homebrew.outputs.gems-hash }}
|
||||
@ -53,7 +53,7 @@ jobs:
|
||||
run: brew install shellcheck shfmt
|
||||
|
||||
- name: Cache style cache
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
with:
|
||||
path: ~/.cache/Homebrew/style
|
||||
key: syntax-style-cache-${{ github.sha }}
|
||||
@ -92,7 +92,7 @@ jobs:
|
||||
test-bot: true
|
||||
|
||||
- name: Cache Bundler RubyGems
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
with:
|
||||
path: ${{ steps.set-up-homebrew.outputs.gems-path }}
|
||||
key: ${{ runner.os }}-rubygems-tap-syntax-${{ steps.set-up-homebrew.outputs.gems-hash }}
|
||||
@ -102,7 +102,7 @@ jobs:
|
||||
run: brew install-bundler-gems --groups=style
|
||||
|
||||
- name: Cache style cache
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
with:
|
||||
path: ~/.cache/Homebrew/style
|
||||
key: tap-syntax-style-cache-${{ github.sha }}
|
||||
@ -266,7 +266,7 @@ jobs:
|
||||
test-bot: false
|
||||
|
||||
- name: Cache Bundler RubyGems
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
with:
|
||||
path: ${{ steps.set-up-homebrew.outputs.gems-path }}
|
||||
key: ${{ matrix.runs-on }}-tests-rubygems-${{ steps.set-up-homebrew.outputs.gems-hash }}
|
||||
@ -281,7 +281,7 @@ jobs:
|
||||
run: mkdir tests
|
||||
|
||||
- name: Cache parallel tests log
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
with:
|
||||
path: tests
|
||||
key: ${{ runner.os }}-${{ matrix.test-flags }}-parallel_runtime_rspec-${{ github.sha }}
|
||||
@ -505,7 +505,7 @@ jobs:
|
||||
|
||||
- name: Cache Homebrew Bundler RubyGems
|
||||
id: cache
|
||||
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
|
||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||
with:
|
||||
path: ${{ steps.set-up-homebrew.outputs.gems-path }}
|
||||
key: ${{ runner.os }}-rubygems-${{ steps.set-up-homebrew.outputs.gems-hash }}
|
||||
|
||||
2
.github/workflows/vendor-gems.yml
vendored
2
.github/workflows/vendor-gems.yml
vendored
@ -92,7 +92,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Generate push token
|
||||
uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
|
||||
uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
|
||||
id: app-token
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
with:
|
||||
|
||||
@ -96,6 +96,11 @@ Layout/ArgumentAlignment:
|
||||
Layout/CaseIndentation:
|
||||
EnforcedStyle: end
|
||||
|
||||
# currently bugged and as relevant/urgent in taps:
|
||||
# https://github.com/rubocop/rubocop/issues/14443
|
||||
Layout/EmptyLinesAfterModuleInclusion:
|
||||
Enabled: false
|
||||
|
||||
# significantly less indentation involved; more consistent
|
||||
Layout/FirstArrayElementIndentation:
|
||||
EnforcedStyle: consistent
|
||||
|
||||
@ -17,7 +17,7 @@ GEM
|
||||
bindata (~> 2)
|
||||
erubi (1.13.1)
|
||||
hana (1.3.7)
|
||||
json (2.13.0)
|
||||
json (2.13.2)
|
||||
json_schemer (2.4.0)
|
||||
bigdecimal
|
||||
hana (~> 1.3)
|
||||
@ -32,7 +32,7 @@ GEM
|
||||
minitest (5.25.5)
|
||||
netrc (0.11.0)
|
||||
parallel (1.27.0)
|
||||
parallel_tests (5.3.1)
|
||||
parallel_tests (5.4.0)
|
||||
parallel
|
||||
parser (3.3.9.0)
|
||||
ast (~> 2.4.1)
|
||||
@ -55,7 +55,7 @@ GEM
|
||||
logger
|
||||
prism (>= 1.3.0)
|
||||
redcarpet (3.6.1)
|
||||
regexp_parser (2.10.0)
|
||||
regexp_parser (2.11.2)
|
||||
require-hooks (0.2.2)
|
||||
rexml (3.4.1)
|
||||
rspec (3.13.1)
|
||||
@ -79,7 +79,7 @@ GEM
|
||||
rspec-support (3.13.4)
|
||||
rspec_junit_formatter (0.6.0)
|
||||
rspec-core (>= 2, < 4, != 2.12.0)
|
||||
rubocop (1.78.0)
|
||||
rubocop (1.79.2)
|
||||
json (~> 2.3)
|
||||
language_server-protocol (~> 3.17.0.2)
|
||||
lint_roller (~> 1.1.0)
|
||||
@ -87,7 +87,7 @@ GEM
|
||||
parser (>= 3.3.0.2)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 2.9.3, < 3.0)
|
||||
rubocop-ast (>= 1.45.1, < 2.0)
|
||||
rubocop-ast (>= 1.46.0, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 2.4.0, < 4.0)
|
||||
rubocop-ast (1.46.0)
|
||||
@ -106,7 +106,7 @@ GEM
|
||||
rubocop-sorbet (0.10.5)
|
||||
lint_roller
|
||||
rubocop (>= 1.75.2)
|
||||
ruby-lsp (0.25.0)
|
||||
ruby-lsp (0.26.1)
|
||||
language_server-protocol (~> 3.17.0)
|
||||
prism (>= 1.2, < 2.0)
|
||||
rbs (>= 3, < 5)
|
||||
@ -118,22 +118,22 @@ GEM
|
||||
docile (~> 1.1)
|
||||
simplecov-html (~> 0.11)
|
||||
simplecov_json_formatter (~> 0.1)
|
||||
simplecov-cobertura (2.1.0)
|
||||
simplecov-cobertura (3.0.0)
|
||||
rexml
|
||||
simplecov (~> 0.19)
|
||||
simplecov-html (0.13.2)
|
||||
simplecov_json_formatter (0.1.4)
|
||||
simpleidn (0.2.3)
|
||||
sorbet (0.5.12357)
|
||||
sorbet-static (= 0.5.12357)
|
||||
sorbet-runtime (0.5.12357)
|
||||
sorbet-static (0.5.12357-aarch64-linux)
|
||||
sorbet-static (0.5.12357-universal-darwin)
|
||||
sorbet-static (0.5.12357-x86_64-linux)
|
||||
sorbet-static-and-runtime (0.5.12357)
|
||||
sorbet (= 0.5.12357)
|
||||
sorbet-runtime (= 0.5.12357)
|
||||
spoom (1.7.5)
|
||||
sorbet (0.5.12401)
|
||||
sorbet-static (= 0.5.12401)
|
||||
sorbet-runtime (0.5.12401)
|
||||
sorbet-static (0.5.12401-aarch64-linux)
|
||||
sorbet-static (0.5.12401-universal-darwin)
|
||||
sorbet-static (0.5.12401-x86_64-linux)
|
||||
sorbet-static-and-runtime (0.5.12401)
|
||||
sorbet (= 0.5.12401)
|
||||
sorbet-runtime (= 0.5.12401)
|
||||
spoom (1.7.6)
|
||||
erubi (>= 1.10.0)
|
||||
prism (>= 0.28.0)
|
||||
rbi (>= 0.3.3)
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
require "api/analytics"
|
||||
require "api/cask"
|
||||
require "api/formula"
|
||||
require "api/internal"
|
||||
require "base64"
|
||||
|
||||
module Homebrew
|
||||
@ -26,7 +27,7 @@ module Homebrew
|
||||
api_url = "#{HOMEBREW_API_DEFAULT_DOMAIN}/#{endpoint}"
|
||||
output = Utils::Curl.curl_output("--fail", api_url)
|
||||
end
|
||||
raise ArgumentError, "No file found at #{Tty.underline}#{api_url}#{Tty.reset}" unless output.success?
|
||||
raise ArgumentError, "No file found at: #{Tty.underline}#{api_url}#{Tty.reset}" unless output.success?
|
||||
|
||||
cache[endpoint] = JSON.parse(output.stdout, freeze: true)
|
||||
rescue JSON::ParserError
|
||||
@ -151,6 +152,30 @@ module Homebrew
|
||||
json.except("variations")
|
||||
end
|
||||
|
||||
sig { params(download_queue: T.nilable(DownloadQueue), stale_seconds: Integer).void }
|
||||
def self.fetch_api_files!(download_queue: nil, stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i)
|
||||
if Homebrew::EnvConfig.use_internal_api?
|
||||
Homebrew::API::Internal.fetch_formula_api!(download_queue:, stale_seconds:)
|
||||
Homebrew::API::Internal.fetch_cask_api!(download_queue:, stale_seconds:)
|
||||
else
|
||||
Homebrew::API::Formula.fetch_api!(download_queue:, stale_seconds:)
|
||||
Homebrew::API::Formula.fetch_tap_migrations!(download_queue:, stale_seconds:)
|
||||
Homebrew::API::Cask.fetch_api!(download_queue:, stale_seconds:)
|
||||
Homebrew::API::Cask.fetch_tap_migrations!(download_queue:, stale_seconds:)
|
||||
end
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def self.write_names_and_aliases
|
||||
if Homebrew::EnvConfig.use_internal_api?
|
||||
Homebrew::API::Internal.write_formula_names_and_aliases
|
||||
Homebrew::API::Internal.write_cask_names
|
||||
else
|
||||
Homebrew::API::Formula.write_names_and_aliases
|
||||
Homebrew::API::Cask.write_names
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(names: T::Array[String], type: String, regenerate: T::Boolean).returns(T::Boolean) }
|
||||
def self.write_names_file!(names, type, regenerate:)
|
||||
names_path = HOMEBREW_CACHE_API/"#{type}_names.txt"
|
||||
@ -162,6 +187,20 @@ module Homebrew
|
||||
false
|
||||
end
|
||||
|
||||
sig { params(aliases: T::Hash[String, String], type: String, regenerate: T::Boolean).returns(T::Boolean) }
|
||||
def self.write_aliases_file!(aliases, type, regenerate:)
|
||||
aliases_path = HOMEBREW_CACHE_API/"#{type}_aliases.txt"
|
||||
if !aliases_path.exist? || regenerate
|
||||
aliases_text = aliases.map do |alias_name, real_name|
|
||||
"#{alias_name}|#{real_name}"
|
||||
end
|
||||
aliases_path.write(aliases_text.join("\n"))
|
||||
return true
|
||||
end
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
sig {
|
||||
params(json_data: T::Hash[String, T.untyped])
|
||||
.returns([T::Boolean, T.any(String, T::Array[T.untyped], T::Hash[String, T.untyped])])
|
||||
@ -202,6 +241,69 @@ module Homebrew
|
||||
|
||||
Tap.fetch(org, repo)
|
||||
end
|
||||
|
||||
sig { returns(T::Array[String]) }
|
||||
def self.formula_names
|
||||
if Homebrew::EnvConfig.use_internal_api?
|
||||
Homebrew::API::Internal.formula_arrays.keys
|
||||
else
|
||||
Homebrew::API::Formula.all_formulae.keys
|
||||
end
|
||||
end
|
||||
|
||||
sig { returns(T::Hash[String, String]) }
|
||||
def self.formula_aliases
|
||||
if Homebrew::EnvConfig.use_internal_api?
|
||||
Homebrew::API::Internal.formula_aliases
|
||||
else
|
||||
Homebrew::API::Formula.all_aliases
|
||||
end
|
||||
end
|
||||
|
||||
sig { returns(T::Hash[String, String]) }
|
||||
def self.formula_renames
|
||||
if Homebrew::EnvConfig.use_internal_api?
|
||||
Homebrew::API::Internal.formula_renames
|
||||
else
|
||||
Homebrew::API::Formula.all_renames
|
||||
end
|
||||
end
|
||||
|
||||
sig { returns(T::Hash[String, String]) }
|
||||
def self.formula_tap_migrations
|
||||
if Homebrew::EnvConfig.use_internal_api?
|
||||
Homebrew::API::Internal.formula_tap_migrations
|
||||
else
|
||||
Homebrew::API::Formula.tap_migrations
|
||||
end
|
||||
end
|
||||
|
||||
sig { returns(T::Array[String]) }
|
||||
def self.cask_tokens
|
||||
if Homebrew::EnvConfig.use_internal_api?
|
||||
Homebrew::API::Internal.cask_hashes.keys
|
||||
else
|
||||
Homebrew::API::Cask.all_casks.keys
|
||||
end
|
||||
end
|
||||
|
||||
sig { returns(T::Hash[String, String]) }
|
||||
def self.cask_renames
|
||||
if Homebrew::EnvConfig.use_internal_api?
|
||||
Homebrew::API::Internal.cask_renames
|
||||
else
|
||||
Homebrew::API::Cask.all_renames
|
||||
end
|
||||
end
|
||||
|
||||
sig { returns(T::Hash[String, String]) }
|
||||
def self.cask_tap_migrations
|
||||
if Homebrew::EnvConfig.use_internal_api?
|
||||
Homebrew::API::Internal.cask_tap_migrations
|
||||
else
|
||||
Homebrew::API::Cask.tap_migrations
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(block: T.proc.returns(T.untyped)).returns(T.untyped) }
|
||||
|
||||
@ -14,18 +14,25 @@ module Homebrew
|
||||
|
||||
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
|
||||
|
||||
sig { params(token: String).returns(T::Hash[String, T.untyped]) }
|
||||
def self.fetch(token)
|
||||
Homebrew::API.fetch "cask/#{token}.json"
|
||||
sig { params(name: String).returns(T::Hash[String, T.untyped]) }
|
||||
def self.cask_json(name)
|
||||
fetch_cask_json! name if !cache.key?("cask_json") || !cache.fetch("cask_json").key?(name)
|
||||
|
||||
cache.fetch("cask_json").fetch(name)
|
||||
end
|
||||
|
||||
sig { params(name: String, download_queue: T.nilable(DownloadQueue)).void }
|
||||
def self.fetch_cask_json!(name, download_queue: nil)
|
||||
endpoint = "cask/#{name}.json"
|
||||
json_cask, updated = Homebrew::API.fetch_json_api_file endpoint, download_queue: download_queue
|
||||
return if download_queue
|
||||
|
||||
json_cask = JSON.parse((HOMEBREW_CACHE_API/endpoint).read) unless updated
|
||||
|
||||
cache["cask_json"] ||= {}
|
||||
cache["cask_json"][name] = json_cask
|
||||
end
|
||||
|
||||
sig { params(cask: ::Cask::Cask, download_queue: T.nilable(Homebrew::DownloadQueue)).returns(Homebrew::API::SourceDownload) }
|
||||
@ -64,7 +71,7 @@ module Homebrew
|
||||
|
||||
sig { returns(Pathname) }
|
||||
def self.cached_json_file_path
|
||||
HOMEBREW_CACHE_API/api_filename
|
||||
HOMEBREW_CACHE_API/DEFAULT_API_FILENAME
|
||||
end
|
||||
|
||||
sig {
|
||||
@ -72,7 +79,7 @@ module Homebrew
|
||||
.returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
|
||||
}
|
||||
def self.fetch_api!(download_queue: nil, stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i)
|
||||
Homebrew::API.fetch_json_api_file api_filename, stale_seconds:, download_queue:
|
||||
Homebrew::API.fetch_json_api_file DEFAULT_API_FILENAME, stale_seconds:, download_queue:
|
||||
end
|
||||
|
||||
sig {
|
||||
|
||||
@ -14,18 +14,25 @@ module Homebrew
|
||||
|
||||
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
|
||||
|
||||
sig { params(name: String).returns(T::Hash[String, T.untyped]) }
|
||||
def self.fetch(name)
|
||||
Homebrew::API.fetch "formula/#{name}.json"
|
||||
def self.formula_json(name)
|
||||
fetch_formula_json! name if !cache.key?("formula_json") || !cache.fetch("formula_json").key?(name)
|
||||
|
||||
cache.fetch("formula_json").fetch(name)
|
||||
end
|
||||
|
||||
sig { params(name: String, download_queue: T.nilable(DownloadQueue)).void }
|
||||
def self.fetch_formula_json!(name, download_queue: nil)
|
||||
endpoint = "formula/#{name}.json"
|
||||
json_formula, updated = Homebrew::API.fetch_json_api_file endpoint, download_queue: download_queue
|
||||
return if download_queue
|
||||
|
||||
json_formula = JSON.parse((HOMEBREW_CACHE_API/endpoint).read) unless updated
|
||||
|
||||
cache["formula_json"] ||= {}
|
||||
cache["formula_json"][name] = json_formula
|
||||
end
|
||||
|
||||
sig { params(formula: ::Formula, download_queue: T.nilable(Homebrew::DownloadQueue)).returns(Homebrew::API::SourceDownload) }
|
||||
@ -63,7 +70,7 @@ module Homebrew
|
||||
|
||||
sig { returns(Pathname) }
|
||||
def self.cached_json_file_path
|
||||
HOMEBREW_CACHE_API/api_filename
|
||||
HOMEBREW_CACHE_API/DEFAULT_API_FILENAME
|
||||
end
|
||||
|
||||
sig {
|
||||
@ -71,7 +78,7 @@ module Homebrew
|
||||
.returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
|
||||
}
|
||||
def self.fetch_api!(download_queue: nil, stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i)
|
||||
Homebrew::API.fetch_json_api_file api_filename, stale_seconds:, download_queue:
|
||||
Homebrew::API.fetch_json_api_file DEFAULT_API_FILENAME, stale_seconds:, download_queue:
|
||||
end
|
||||
|
||||
sig {
|
||||
@ -147,13 +154,8 @@ module Homebrew
|
||||
def self.write_names_and_aliases(regenerate: false)
|
||||
download_and_cache_data! unless cache.key?("formulae")
|
||||
|
||||
return unless Homebrew::API.write_names_file!(all_formulae.keys, "formula", regenerate:)
|
||||
|
||||
(HOMEBREW_CACHE_API/"formula_aliases.txt").open("w") do |file|
|
||||
all_aliases.each do |alias_name, real_name|
|
||||
file.puts "#{alias_name}|#{real_name}"
|
||||
end
|
||||
end
|
||||
Homebrew::API.write_names_file!(all_formulae.keys, "formula", regenerate:)
|
||||
Homebrew::API.write_aliases_file!(all_aliases, "formula", regenerate:)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
177
Library/Homebrew/api/internal.rb
Normal file
177
Library/Homebrew/api/internal.rb
Normal file
@ -0,0 +1,177 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "cachable"
|
||||
require "api"
|
||||
require "api/source_download"
|
||||
require "download_queue"
|
||||
require "formula_stub"
|
||||
|
||||
module Homebrew
|
||||
module API
|
||||
# Helper functions for using the JSON internal API.
|
||||
module Internal
|
||||
extend Cachable
|
||||
|
||||
private_class_method :cache
|
||||
|
||||
sig { returns(String) }
|
||||
def self.formula_endpoint
|
||||
"internal/formula.#{SimulateSystem.current_tag}.jws.json"
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def self.cask_endpoint
|
||||
"internal/cask.#{SimulateSystem.current_tag}.jws.json"
|
||||
end
|
||||
|
||||
sig { params(name: String).returns(Homebrew::FormulaStub) }
|
||||
def self.formula_stub(name)
|
||||
return cache["formula_stubs"][name] if cache.key?("formula_stubs") && cache["formula_stubs"].key?(name)
|
||||
|
||||
stub_array = formula_arrays[name]
|
||||
raise "No formula stub found for #{name}" unless stub_array
|
||||
|
||||
stub = Homebrew::FormulaStub.new(
|
||||
name: name,
|
||||
pkg_version: PkgVersion.parse(stub_array[0]),
|
||||
rebuild: stub_array[1],
|
||||
sha256: stub_array[2],
|
||||
)
|
||||
|
||||
cache["formula_stubs"] ||= {}
|
||||
cache["formula_stubs"][name] = stub
|
||||
|
||||
stub
|
||||
end
|
||||
|
||||
sig {
|
||||
params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: Integer)
|
||||
.returns([T::Hash[String, T.untyped], T::Boolean])
|
||||
}
|
||||
def self.fetch_formula_api!(download_queue: nil, stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i)
|
||||
json_contents, updated = (Homebrew::API.fetch_json_api_file formula_endpoint, stale_seconds:, download_queue:)
|
||||
[T.cast(json_contents, T::Hash[String, T.untyped]), updated]
|
||||
end
|
||||
|
||||
sig {
|
||||
params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: Integer)
|
||||
.returns([T::Hash[String, T.untyped], T::Boolean])
|
||||
}
|
||||
def self.fetch_cask_api!(download_queue: nil, stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i)
|
||||
json_contents, updated = (Homebrew::API.fetch_json_api_file cask_endpoint, stale_seconds:, download_queue:)
|
||||
[T.cast(json_contents, T::Hash[String, T.untyped]), updated]
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def self.download_and_cache_formula_data!
|
||||
json_contents, updated = fetch_formula_api!
|
||||
cache["formula_stubs"] = {}
|
||||
cache["formula_aliases"] = json_contents["aliases"]
|
||||
cache["formula_renames"] = json_contents["renames"]
|
||||
cache["formula_tap_migrations"] = json_contents["tap_migrations"]
|
||||
cache["formula_arrays"] = json_contents["formulae"]
|
||||
|
||||
updated
|
||||
end
|
||||
private_class_method :download_and_cache_formula_data!
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def self.download_and_cache_cask_data!
|
||||
json_contents, updated = fetch_cask_api!
|
||||
cache["cask_stubs"] = {}
|
||||
cache["cask_renames"] = json_contents["renames"]
|
||||
cache["cask_tap_migrations"] = json_contents["tap_migrations"]
|
||||
cache["cask_hashes"] = json_contents["casks"]
|
||||
|
||||
updated
|
||||
end
|
||||
private_class_method :download_and_cache_cask_data!
|
||||
|
||||
sig { params(regenerate: T::Boolean).void }
|
||||
def self.write_formula_names_and_aliases(regenerate: false)
|
||||
download_and_cache_formula_data! unless cache.key?("formula_arrays")
|
||||
|
||||
Homebrew::API.write_names_file!(formula_arrays.keys, "formula", regenerate:)
|
||||
Homebrew::API.write_aliases_file!(formula_aliases, "formula", regenerate:)
|
||||
end
|
||||
|
||||
sig { params(regenerate: T::Boolean).void }
|
||||
def self.write_cask_names(regenerate: false)
|
||||
download_and_cache_cask_data! unless cache.key?("cask_hashes")
|
||||
|
||||
Homebrew::API.write_names_file!(cask_hashes.keys, "cask", regenerate:)
|
||||
end
|
||||
|
||||
sig { returns(T::Hash[String, [String, Integer, T.nilable(String)]]) }
|
||||
def self.formula_arrays
|
||||
unless cache.key?("formula_arrays")
|
||||
updated = download_and_cache_formula_data!
|
||||
write_formula_names_and_aliases(regenerate: updated)
|
||||
end
|
||||
|
||||
cache["formula_arrays"]
|
||||
end
|
||||
|
||||
sig { returns(T::Hash[String, String]) }
|
||||
def self.formula_aliases
|
||||
unless cache.key?("formula_aliases")
|
||||
updated = download_and_cache_formula_data!
|
||||
write_formula_names_and_aliases(regenerate: updated)
|
||||
end
|
||||
|
||||
cache["formula_aliases"]
|
||||
end
|
||||
|
||||
sig { returns(T::Hash[String, String]) }
|
||||
def self.formula_renames
|
||||
unless cache.key?("formula_renames")
|
||||
updated = download_and_cache_formula_data!
|
||||
write_formula_names_and_aliases(regenerate: updated)
|
||||
end
|
||||
|
||||
cache["formula_renames"]
|
||||
end
|
||||
|
||||
sig { returns(T::Hash[String, String]) }
|
||||
def self.formula_tap_migrations
|
||||
unless cache.key?("formula_tap_migrations")
|
||||
updated = download_and_cache_formula_data!
|
||||
write_formula_names_and_aliases(regenerate: updated)
|
||||
end
|
||||
|
||||
cache["formula_tap_migrations"]
|
||||
end
|
||||
|
||||
sig { returns(T::Hash[String, T::Hash[String, T.untyped]]) }
|
||||
def self.cask_hashes
|
||||
unless cache.key?("cask_hashes")
|
||||
updated = download_and_cache_cask_data!
|
||||
write_cask_names(regenerate: updated)
|
||||
end
|
||||
|
||||
cache["cask_hashes"]
|
||||
end
|
||||
|
||||
sig { returns(T::Hash[String, String]) }
|
||||
def self.cask_renames
|
||||
unless cache.key?("cask_renames")
|
||||
updated = download_and_cache_cask_data!
|
||||
write_cask_names(regenerate: updated)
|
||||
end
|
||||
|
||||
cache["cask_renames"]
|
||||
end
|
||||
|
||||
sig { returns(T::Hash[String, String]) }
|
||||
def self.cask_tap_migrations
|
||||
unless cache.key?("cask_tap_migrations")
|
||||
updated = download_and_cache_cask_data!
|
||||
write_cask_names(regenerate: updated)
|
||||
end
|
||||
|
||||
cache["cask_tap_migrations"]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -4,18 +4,27 @@
|
||||
class BottleSpecification
|
||||
RELOCATABLE_CELLARS = [:any, :any_skip_relocation].freeze
|
||||
|
||||
sig { returns(T.nilable(Tap)) }
|
||||
attr_accessor :tap
|
||||
attr_reader :collector, :root_url_specs, :repository
|
||||
|
||||
attr_reader :collector
|
||||
|
||||
sig { returns(T::Hash[String, T.untyped]) }
|
||||
attr_reader :root_url_specs
|
||||
|
||||
sig { returns(String) }
|
||||
attr_reader :repository
|
||||
|
||||
sig { void }
|
||||
def initialize
|
||||
@rebuild = 0
|
||||
@repository = Homebrew::DEFAULT_REPOSITORY
|
||||
@collector = Utils::Bottles::Collector.new
|
||||
@root_url_specs = {}
|
||||
@rebuild = T.let(0, Integer)
|
||||
@repository = T.let(Homebrew::DEFAULT_REPOSITORY, String)
|
||||
@collector = T.let(Utils::Bottles::Collector.new, Utils::Bottles::Collector)
|
||||
@root_url_specs = T.let({}, T::Hash[String, T.untyped])
|
||||
@root_url = T.let(nil, T.nilable(String))
|
||||
end
|
||||
|
||||
sig { params(val: Integer).returns(T.nilable(Integer)) }
|
||||
sig { params(val: Integer).returns(Integer) }
|
||||
def rebuild(val = T.unsafe(nil))
|
||||
val.nil? ? @rebuild : @rebuild = val
|
||||
end
|
||||
|
||||
@ -95,10 +95,7 @@ begin
|
||||
require "api/cask"
|
||||
download_queue = Homebrew::DownloadQueue.new
|
||||
stale_seconds = 86400 # 1 day
|
||||
Homebrew::API::Formula.fetch_api!(download_queue:, stale_seconds:)
|
||||
Homebrew::API::Formula.fetch_tap_migrations!(download_queue:, stale_seconds:)
|
||||
Homebrew::API::Cask.fetch_api!(download_queue:, stale_seconds:)
|
||||
Homebrew::API::Cask.fetch_tap_migrations!(download_queue:, stale_seconds:)
|
||||
Homebrew::API.fetch_api_files!(download_queue:, stale_seconds:)
|
||||
begin
|
||||
download_queue.fetch
|
||||
ensure
|
||||
|
||||
@ -678,8 +678,8 @@ else
|
||||
then
|
||||
message="Please update your system curl or set HOMEBREW_CURL_PATH to a newer version.
|
||||
Minimum required version: ${HOMEBREW_MINIMUM_CURL_VERSION}
|
||||
Your curl version: ${curl_name_and_version##* }
|
||||
Your curl executable: $(type -p "${HOMEBREW_CURL}")"
|
||||
Your curl version: ${curl_name_and_version##* }
|
||||
Your curl executable: $(type -p "${HOMEBREW_CURL}")"
|
||||
|
||||
if [[ -z ${HOMEBREW_CURL_PATH} ]]
|
||||
then
|
||||
@ -706,8 +706,8 @@ Your curl executable: $(type -p "${HOMEBREW_CURL}")"
|
||||
then
|
||||
message="Please update your system Git or set HOMEBREW_GIT_PATH to a newer version.
|
||||
Minimum required version: ${HOMEBREW_MINIMUM_GIT_VERSION}
|
||||
Your Git version: ${major}.${minor}.${micro}.${build}
|
||||
Your Git executable: $(unset git && type -p "${HOMEBREW_GIT}")"
|
||||
Your Git version: ${major}.${minor}.${micro}.${build}
|
||||
Your Git executable: $(unset git && type -p "${HOMEBREW_GIT}")"
|
||||
if [[ -z ${HOMEBREW_GIT_PATH} ]]
|
||||
then
|
||||
HOMEBREW_FORCE_BREWED_GIT="1"
|
||||
@ -1067,6 +1067,9 @@ then
|
||||
fi
|
||||
unset SUDO
|
||||
|
||||
# Remove internal variables
|
||||
unset HOMEBREW_INTERNAL_ALLOW_PACKAGES_FROM_PATHS
|
||||
|
||||
if [[ -n "${HOMEBREW_BASH_COMMAND}" ]]
|
||||
then
|
||||
# source rather than executing directly to ensure the entire file is read into
|
||||
|
||||
@ -227,7 +227,10 @@ class Build
|
||||
end
|
||||
|
||||
begin
|
||||
ENV.delete("HOMEBREW_FORBID_PACKAGES_FROM_PATHS")
|
||||
# Undocumented opt-out for internal use.
|
||||
# We need to allow formulae from paths here due to how we pass them through.
|
||||
ENV["HOMEBREW_INTERNAL_ALLOW_PACKAGES_FROM_PATHS"] = "1"
|
||||
|
||||
args = Homebrew::Cmd::InstallCmd.new.args
|
||||
Context.current = args.context
|
||||
|
||||
@ -268,7 +271,7 @@ rescue Exception => e # rubocop:disable Lint/RescueException
|
||||
error_hash["output"] = e.output
|
||||
end
|
||||
|
||||
error_pipe.puts error_hash.to_json
|
||||
error_pipe.close
|
||||
error_pipe&.puts error_hash.to_json
|
||||
error_pipe&.close
|
||||
exit! 1
|
||||
end
|
||||
|
||||
@ -8,6 +8,7 @@ module Cask
|
||||
# Abstract superclass for all artifacts.
|
||||
class AbstractArtifact
|
||||
extend T::Helpers
|
||||
|
||||
abstract!
|
||||
|
||||
include Comparable
|
||||
|
||||
@ -389,7 +389,7 @@ module Cask
|
||||
end
|
||||
|
||||
def uninstall_pkgutil(*pkgs, command: nil, **_)
|
||||
ohai "Uninstalling packages with sudo; the password may be necessary:"
|
||||
ohai "Uninstalling packages with `sudo` (which may request your password)..."
|
||||
pkgs.each do |regex|
|
||||
::Cask::Pkg.all_matching(regex, command).each do |pkg|
|
||||
puts pkg.package_id
|
||||
|
||||
@ -35,7 +35,7 @@ module Cask
|
||||
private
|
||||
|
||||
def run_installer(command: nil, verbose: false, **_options)
|
||||
ohai "Running installer for #{cask} with sudo; the password may be necessary."
|
||||
ohai "Running installer for #{cask} with `sudo` (which may request your password)..."
|
||||
unless path.exist?
|
||||
pkg = path.relative_path_from(cask.staged_path)
|
||||
pkgs = Pathname.glob(cask.staged_path/"**"/"*.pkg").map { |path| path.relative_path_from(cask.staged_path) }
|
||||
|
||||
@ -56,6 +56,9 @@ module Cask
|
||||
(target.realpath == source.realpath || target.realpath.to_s.start_with?("#{cask.caskroom_path}/"))
|
||||
opoo "#{message}; overwriting."
|
||||
Utils.gain_permissions_remove(target, command:)
|
||||
elsif (formula = conflicting_formula)
|
||||
opoo "#{message} from formula #{formula}; skipping link."
|
||||
return
|
||||
else
|
||||
raise CaskError, "#{message}."
|
||||
end
|
||||
@ -69,11 +72,32 @@ module Cask
|
||||
return unless target.symlink?
|
||||
|
||||
ohai "Unlinking #{self.class.english_name} '#{target}'"
|
||||
|
||||
if (formula = conflicting_formula)
|
||||
odebug "#{target} is from formula #{formula}; skipping unlink."
|
||||
return
|
||||
end
|
||||
|
||||
Utils.gain_permissions_remove(target, command:)
|
||||
end
|
||||
|
||||
sig { params(command: T.class_of(SystemCommand)).void }
|
||||
def create_filesystem_link(command); end
|
||||
|
||||
# Check if the target file is a symlink that originates from a formula
|
||||
# with the same name as this cask, indicating a potential conflict
|
||||
sig { returns(T.nilable(String)) }
|
||||
def conflicting_formula
|
||||
if target.symlink? && target.exist? &&
|
||||
(match = target.realpath.to_s.match(%r{^#{HOMEBREW_CELLAR}/(?<formula>[^/]+)/}o))
|
||||
match[:formula]
|
||||
end
|
||||
rescue => e
|
||||
# If we can't determine the realpath or any other error occurs,
|
||||
# don't treat it as a conflicting formula file
|
||||
odebug "Error checking for conflicting formula file: #{e}"
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
|
||||
require "cask/denylist"
|
||||
require "cask/download"
|
||||
require "cask/installer"
|
||||
require "cask/quarantine"
|
||||
require "digest"
|
||||
require "livecheck/livecheck"
|
||||
require "source_location"
|
||||
@ -498,20 +500,32 @@ module Cask
|
||||
return if url.nil?
|
||||
|
||||
return if !cask.tap.official? && !signing?
|
||||
return if cask.deprecated? && cask.deprecation_reason != :unsigned
|
||||
return if cask.deprecated? && cask.deprecation_reason != :fails_gatekeeper_check
|
||||
|
||||
unless Quarantine.available?
|
||||
odebug "Quarantine support is not available, skipping signing audit"
|
||||
return
|
||||
end
|
||||
|
||||
odebug "Auditing signing"
|
||||
|
||||
is_in_skiplist = cask.tap&.audit_exception(:signing_audit_skiplist, cask.token)
|
||||
|
||||
extract_artifacts do |artifacts, tmpdir|
|
||||
is_container = artifacts.any? { |a| a.is_a?(Artifact::App) || a.is_a?(Artifact::Pkg) }
|
||||
|
||||
artifacts.each do |artifact|
|
||||
next if artifact.is_a?(Artifact::Binary) && is_container == true
|
||||
any_signing_failure = artifacts.any? do |artifact|
|
||||
next false if artifact.is_a?(Artifact::Binary) && is_container == true
|
||||
|
||||
artifact_path = artifact.is_a?(Artifact::Pkg) ? artifact.path : artifact.source
|
||||
|
||||
path = tmpdir/artifact_path.relative_path_from(cask.staged_path)
|
||||
|
||||
unless Quarantine.detect(path)
|
||||
odebug "#{path} does not have quarantine attributes, skipping signing audit"
|
||||
next false
|
||||
end
|
||||
|
||||
result = case artifact
|
||||
when Artifact::Pkg
|
||||
system_command("spctl", args: ["--assess", "--type", "install", path], print_stderr: false)
|
||||
@ -521,21 +535,17 @@ module Cask
|
||||
system_command("gktool", args: ["scan", path], print_stderr: false)
|
||||
when Artifact::Binary
|
||||
# Shell scripts cannot be signed, so we skip them
|
||||
next if path.text_executable?
|
||||
next false if path.text_executable?
|
||||
|
||||
system_command("codesign", args: ["--verify", "-R=notarized", "--check-notarization", path],
|
||||
print_stderr: false)
|
||||
system_command("codesign", args: ["--verify", "-R=notarized", "--check-notarization", path],
|
||||
print_stderr: false)
|
||||
else
|
||||
add_error "Unknown artifact type: #{artifact.class}", location: url.location
|
||||
end
|
||||
|
||||
if result.success? && cask.deprecated? && cask.deprecation_reason == :unsigned
|
||||
add_error "Cask is deprecated as unsigned but artifacts are signed!"
|
||||
end
|
||||
|
||||
next if cask.deprecated? && cask.deprecation_reason == :unsigned
|
||||
|
||||
next if result.success?
|
||||
next false if result.success?
|
||||
next true if cask.deprecated? && cask.deprecation_reason == :fails_gatekeeper_check
|
||||
next true if is_in_skiplist
|
||||
|
||||
add_error <<~EOS, location: url.location
|
||||
Signature verification failed:
|
||||
@ -543,7 +553,21 @@ module Cask
|
||||
macOS on ARM requires software to be signed.
|
||||
Please contact the upstream developer to let them know they should sign and notarize their software.
|
||||
EOS
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
return if any_signing_failure
|
||||
|
||||
add_error "Cask is in the signing audit skiplist, but does not need to be skipped!" if is_in_skiplist
|
||||
|
||||
return unless cask.deprecated?
|
||||
return if cask.deprecation_reason != :fails_gatekeeper_check
|
||||
|
||||
add_error <<~EOS
|
||||
Cask is deprecated because it failed Gatekeeper checks but all artifacts now pass!
|
||||
Remove the deprecate/disable stanza or update the deprecate/disable reason.
|
||||
EOS
|
||||
end
|
||||
end
|
||||
|
||||
@ -619,6 +643,11 @@ module Cask
|
||||
.extract_nestedly(to: @tmpdir, verbose: false)
|
||||
end
|
||||
|
||||
# Process rename operations after extraction
|
||||
# Create a temporary installer to process renames in the audit directory
|
||||
temp_installer = Installer.new(@cask)
|
||||
temp_installer.process_rename_operations(target_dir: @tmpdir)
|
||||
|
||||
# Set the flag to indicate that extraction has occurred.
|
||||
@artifacts_extracted = T.let(true, T.nilable(TrueClass))
|
||||
|
||||
@ -640,10 +669,20 @@ module Cask
|
||||
extract_artifacts do |artifacts, tmpdir|
|
||||
is_container = artifacts.any? { |a| a.is_a?(Artifact::App) || a.is_a?(Artifact::Pkg) }
|
||||
|
||||
artifacts.each do |artifact|
|
||||
next if !artifact.is_a?(Artifact::App) && !artifact.is_a?(Artifact::Binary)
|
||||
next if artifact.is_a?(Artifact::Binary) && is_container
|
||||
mentions_rosetta = cask.caveats.include?("requires Rosetta 2")
|
||||
requires_intel = cask.depends_on.arch&.any? { |arch| arch[:type] == :intel }
|
||||
|
||||
artifacts_to_test = artifacts.filter do |artifact|
|
||||
next false if !artifact.is_a?(Artifact::App) && !artifact.is_a?(Artifact::Binary)
|
||||
next false if artifact.is_a?(Artifact::Binary) && is_container
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
next if artifacts_to_test.blank?
|
||||
|
||||
any_requires_rosetta = artifacts_to_test.any? do |artifact|
|
||||
artifact = T.cast(artifact, T.any(Artifact::App, Artifact::Binary))
|
||||
path = tmpdir/artifact.source.relative_path_from(cask.staged_path)
|
||||
|
||||
result = case artifact
|
||||
@ -665,7 +704,7 @@ module Cask
|
||||
end
|
||||
|
||||
# binary stanza can contain shell scripts, so we just continue if lipo fails.
|
||||
next unless result.success?
|
||||
next false unless result.success?
|
||||
|
||||
odebug "Architectures: #{result.merged_output}"
|
||||
|
||||
@ -675,17 +714,17 @@ module Cask
|
||||
next
|
||||
end
|
||||
|
||||
supports_arm = result.merged_output.include?("arm64")
|
||||
mentions_rosetta = cask.caveats.include?("requires Rosetta 2")
|
||||
requires_intel = cask.depends_on.arch&.any? { |arch| arch[:type] == :intel }
|
||||
result.merged_output.exclude?("arm64") && result.merged_output.include?("x86_64")
|
||||
end
|
||||
|
||||
if supports_arm && mentions_rosetta
|
||||
add_error "Artifacts do not require Rosetta 2 but the caveats say otherwise!",
|
||||
location: url.location
|
||||
elsif !supports_arm && !mentions_rosetta && !requires_intel
|
||||
add_error "Artifacts require Rosetta 2 but this is not indicated by the caveats!",
|
||||
if any_requires_rosetta
|
||||
if !mentions_rosetta && !requires_intel
|
||||
add_error "At least one artifact requires Rosetta 2 but this is not indicated by the caveats!",
|
||||
location: url.location
|
||||
end
|
||||
elsif mentions_rosetta
|
||||
add_error "No artifacts require Rosetta 2 but the caveats say otherwise!",
|
||||
location: url.location
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -896,6 +935,20 @@ module Cask
|
||||
add_error error, location: url.location if error
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def audit_forgejo_prerelease_version
|
||||
return if (url = cask.url).nil?
|
||||
|
||||
odebug "Auditing Forgejo prerelease"
|
||||
user, repo = get_repo_data(%r{https?://codeberg\.org/([^/]+)/([^/]+)/?.*}) if online?
|
||||
return if user.nil? || repo.nil?
|
||||
|
||||
tag = SharedAudits.forgejo_tag_from_url(url.to_s)
|
||||
tag ||= cask.version
|
||||
error = SharedAudits.forgejo_release(user, repo, tag, cask:)
|
||||
add_error error, location: url.location if error
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def audit_github_repository_archived
|
||||
# Deprecated/disabled casks may have an archived repository.
|
||||
@ -928,6 +981,23 @@ module Cask
|
||||
add_error "GitLab repo is archived", location: url.location if metadata["archived"]
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def audit_forgejo_repository_archived
|
||||
return if cask.deprecated? || cask.disabled?
|
||||
return if (url = cask.url).nil?
|
||||
|
||||
user, repo = get_repo_data(%r{https?://codeberg\.org/([^/]+)/([^/]+)/?.*}) if online?
|
||||
return if user.nil? || repo.nil?
|
||||
|
||||
metadata = SharedAudits.forgejo_repo_data(user, repo)
|
||||
return if metadata.nil?
|
||||
|
||||
return unless metadata["archived"]
|
||||
|
||||
add_error "Forgejo repository is archived since #{metadata["archived_at"]}",
|
||||
location: url.location
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def audit_github_repository
|
||||
return unless new_cask?
|
||||
@ -970,6 +1040,20 @@ module Cask
|
||||
add_error error, location: url.location if error
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def audit_forgejo_repository
|
||||
return unless new_cask?
|
||||
return if (url = cask.url).nil?
|
||||
|
||||
user, repo = get_repo_data(%r{https?://codeberg\.org/([^/]+)/([^/]+)/?.*})
|
||||
return if user.nil? || repo.nil?
|
||||
|
||||
odebug "Auditing Forgejo repo"
|
||||
|
||||
error = SharedAudits.forgejo(user, repo)
|
||||
add_error error, location: url.location if error
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def audit_denylist
|
||||
return unless cask.tap
|
||||
|
||||
@ -60,13 +60,14 @@ module Cask
|
||||
source: T.nilable(String),
|
||||
tap: T.nilable(Tap),
|
||||
loaded_from_api: T::Boolean,
|
||||
api_source: T.nilable(T::Hash[String, T.untyped]),
|
||||
config: T.nilable(Config),
|
||||
allow_reassignment: T::Boolean,
|
||||
loader: T.nilable(CaskLoader::ILoader),
|
||||
block: T.nilable(T.proc.bind(DSL).void),
|
||||
).void
|
||||
}
|
||||
def initialize(token, sourcefile_path: nil, source: nil, tap: nil, loaded_from_api: false,
|
||||
def initialize(token, sourcefile_path: nil, source: nil, tap: nil, loaded_from_api: false, api_source: nil,
|
||||
config: nil, allow_reassignment: false, loader: nil, &block)
|
||||
@token = token
|
||||
@sourcefile_path = sourcefile_path
|
||||
@ -74,6 +75,7 @@ module Cask
|
||||
@tap = tap
|
||||
@allow_reassignment = allow_reassignment
|
||||
@loaded_from_api = loaded_from_api
|
||||
@api_source = api_source
|
||||
@loader = loader
|
||||
# Sorbet has trouble with bound procs assigned to instance variables:
|
||||
# https://github.com/sorbet/sorbet/issues/6843
|
||||
@ -91,6 +93,9 @@ module Cask
|
||||
sig { returns(T::Boolean) }
|
||||
def loaded_from_api? = @loaded_from_api
|
||||
|
||||
sig { returns(T.nilable(T::Hash[String, T.untyped])) }
|
||||
attr_reader :api_source
|
||||
|
||||
# An old name for the cask.
|
||||
sig { returns(T::Array[String]) }
|
||||
def old_tokens
|
||||
@ -407,8 +412,8 @@ module Cask
|
||||
private_constant :HASH_KEYS_TO_SKIP
|
||||
|
||||
def to_hash_with_variations
|
||||
if loaded_from_api? && !Homebrew::EnvConfig.no_install_from_api?
|
||||
return api_to_local_hash(Homebrew::API::Cask.all_casks[token].dup)
|
||||
if loaded_from_api? && (json_cask = api_source) && !Homebrew::EnvConfig.no_install_from_api?
|
||||
return api_to_local_hash(json_cask.dup)
|
||||
end
|
||||
|
||||
hash = to_h
|
||||
|
||||
@ -18,6 +18,7 @@ module Cask
|
||||
|
||||
module ILoader
|
||||
extend T::Helpers
|
||||
|
||||
interface!
|
||||
|
||||
sig { abstract.params(config: T.nilable(Config)).returns(Cask) }
|
||||
@ -28,6 +29,7 @@ module Cask
|
||||
class AbstractContentLoader
|
||||
include ILoader
|
||||
extend T::Helpers
|
||||
|
||||
abstract!
|
||||
|
||||
sig { returns(String) }
|
||||
@ -306,8 +308,8 @@ module Cask
|
||||
return if Homebrew::EnvConfig.no_install_from_api?
|
||||
return unless ref.is_a?(String)
|
||||
return unless (token = ref[HOMEBREW_DEFAULT_TAP_CASK_REGEX, :token])
|
||||
if !Homebrew::API::Cask.all_casks.key?(token) &&
|
||||
!Homebrew::API::Cask.all_renames.key?(token)
|
||||
if Homebrew::API.cask_tokens.exclude?(token) &&
|
||||
!Homebrew::API.cask_renames.key?(token)
|
||||
return
|
||||
end
|
||||
|
||||
@ -336,6 +338,7 @@ module Cask
|
||||
|
||||
cask_options = {
|
||||
loaded_from_api: true,
|
||||
api_source: json_cask,
|
||||
sourcefile_path: @sourcefile_path,
|
||||
source: JSON.pretty_generate(json_cask),
|
||||
config:,
|
||||
|
||||
@ -19,6 +19,7 @@ require "cask/dsl/container"
|
||||
require "cask/dsl/depends_on"
|
||||
require "cask/dsl/postflight"
|
||||
require "cask/dsl/preflight"
|
||||
require "cask/dsl/rename"
|
||||
require "cask/dsl/uninstall_postflight"
|
||||
require "cask/dsl/uninstall_preflight"
|
||||
require "cask/dsl/version"
|
||||
@ -81,6 +82,7 @@ module Cask
|
||||
:language,
|
||||
:name,
|
||||
:os,
|
||||
:rename,
|
||||
:sha256,
|
||||
:staged_path,
|
||||
:url,
|
||||
@ -162,6 +164,7 @@ module Cask
|
||||
@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)
|
||||
@rename = T.let([], T::Array[DSL::Rename])
|
||||
@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))
|
||||
@ -343,6 +346,28 @@ module Cask
|
||||
end
|
||||
end
|
||||
|
||||
# Renames files after extraction.
|
||||
#
|
||||
# This is useful when the downloaded file has unpredictable names
|
||||
# that need to be normalized for proper artifact installation.
|
||||
#
|
||||
# ### Example
|
||||
#
|
||||
# ```ruby
|
||||
# rename "RØDECaster App*.pkg", "RØDECaster App.pkg"
|
||||
# ```
|
||||
#
|
||||
# @api public
|
||||
sig {
|
||||
params(from: String,
|
||||
to: String).returns(T::Array[DSL::Rename])
|
||||
}
|
||||
def rename(from = T.unsafe(nil), to = T.unsafe(nil))
|
||||
return @rename if from.nil?
|
||||
|
||||
@rename << DSL::Rename.new(T.must(from), T.must(to))
|
||||
end
|
||||
|
||||
# Sets the cask's version.
|
||||
#
|
||||
# ### Example
|
||||
@ -600,6 +625,9 @@ module Cask
|
||||
raise ArgumentError, "more than one of replacement, replacement_formula and/or replacement_cask specified!"
|
||||
end
|
||||
|
||||
# odeprecate: remove this remapping when the :unsigned reason is removed
|
||||
because = :fails_gatekeeper_check if because == :unsigned
|
||||
|
||||
if replacement
|
||||
odeprecated(
|
||||
"deprecate!(:replacement)",
|
||||
@ -626,6 +654,9 @@ module Cask
|
||||
raise ArgumentError, "more than one of replacement, replacement_formula and/or replacement_cask specified!"
|
||||
end
|
||||
|
||||
# odeprecate: remove this remapping when the :unsigned reason is removed
|
||||
because = :fails_gatekeeper_check if because == :unsigned
|
||||
|
||||
if replacement
|
||||
odeprecated(
|
||||
"disable!(:replacement)",
|
||||
|
||||
52
Library/Homebrew/cask/dsl/rename.rb
Normal file
52
Library/Homebrew/cask/dsl/rename.rb
Normal file
@ -0,0 +1,52 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Cask
|
||||
class DSL
|
||||
# Class corresponding to the `rename` stanza.
|
||||
class Rename
|
||||
sig { returns(String) }
|
||||
attr_reader :from, :to
|
||||
|
||||
sig { params(from: String, to: String).void }
|
||||
def initialize(from, to)
|
||||
@from = from
|
||||
@to = to
|
||||
end
|
||||
|
||||
sig { params(staged_path: Pathname).void }
|
||||
def perform_rename(staged_path)
|
||||
return unless staged_path.exist?
|
||||
|
||||
# Find files matching the glob pattern
|
||||
matching_files = if @from.include?("*")
|
||||
staged_path.glob(@from)
|
||||
else
|
||||
[staged_path.join(@from)].select(&:exist?)
|
||||
end
|
||||
|
||||
return if matching_files.empty?
|
||||
|
||||
# Rename the first matching file to the target path
|
||||
source_file = matching_files.first
|
||||
return if source_file.nil?
|
||||
|
||||
target_file = staged_path.join(@to)
|
||||
|
||||
# Ensure target directory exists
|
||||
target_file.dirname.mkpath
|
||||
|
||||
# Perform the rename
|
||||
source_file.rename(target_file.to_s) if source_file.exist?
|
||||
end
|
||||
|
||||
sig { returns(T::Hash[Symbol, String]) }
|
||||
def pairs
|
||||
{ from:, to: }
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def to_s = pairs.inspect
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -36,6 +36,8 @@ module Cask
|
||||
def self.info(cask, args:)
|
||||
puts get_info(cask)
|
||||
|
||||
return unless cask.tap.core_cask_tap?
|
||||
|
||||
require "utils/analytics"
|
||||
::Utils::Analytics.cask_output(cask, args:)
|
||||
end
|
||||
|
||||
@ -125,6 +125,7 @@ module Cask
|
||||
Caskroom.ensure_caskroom_exists
|
||||
|
||||
extract_primary_container
|
||||
process_rename_operations
|
||||
save_caskfile
|
||||
rescue => e
|
||||
purge_versioned_files
|
||||
@ -292,6 +293,19 @@ on_request: true)
|
||||
Quarantine.propagate(from: primary_container.path, to:)
|
||||
end
|
||||
|
||||
sig { params(target_dir: T.nilable(Pathname)).void }
|
||||
def process_rename_operations(target_dir: nil)
|
||||
return if @cask.rename.empty?
|
||||
|
||||
working_dir = target_dir || @cask.staged_path
|
||||
odebug "Processing rename operations in #{working_dir}"
|
||||
|
||||
@cask.rename.each do |rename_operation|
|
||||
odebug "Renaming #{rename_operation.from} to #{rename_operation.to}"
|
||||
rename_operation.perform_rename(working_dir)
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(predecessor: T.nilable(Cask)).void }
|
||||
def install_artifacts(predecessor: nil)
|
||||
already_installed_artifacts = []
|
||||
|
||||
@ -40,11 +40,12 @@ module Cask
|
||||
end
|
||||
private_class_method :swift_target_args
|
||||
|
||||
sig { returns(Symbol) }
|
||||
sig { returns([Symbol, T.nilable(String)]) }
|
||||
def self.check_quarantine_support
|
||||
odebug "Checking quarantine support"
|
||||
|
||||
if xattr.nil? || !system_command(xattr, args: ["-h"], print_stderr: false).success?
|
||||
check_output = nil
|
||||
status = if xattr.nil? || !system_command(xattr, args: ["-h"], print_stderr: false).success?
|
||||
odebug "There's no working version of `xattr` on this system."
|
||||
:xattr_broken
|
||||
elsif swift.nil?
|
||||
@ -55,21 +56,41 @@ module Cask
|
||||
args: [*swift_target_args, QUARANTINE_SCRIPT],
|
||||
print_stderr: false)
|
||||
|
||||
case api_check.exit_status
|
||||
exit_status = api_check.exit_status
|
||||
check_output = api_check.merged_output.to_s.strip
|
||||
error_output = api_check.stderr.to_s.strip
|
||||
|
||||
case exit_status
|
||||
when 2
|
||||
odebug "Quarantine is available."
|
||||
:quarantine_available
|
||||
when 1
|
||||
# Swift script ran but failed (likely due to CLT issues)
|
||||
odebug "Swift quarantine script failed: #{error_output}"
|
||||
if error_output.include?("does not exist") || error_output.include?("No such file")
|
||||
:swift_broken_clt
|
||||
elsif error_output.include?("compiler") || error_output.include?("SDK")
|
||||
:swift_compilation_failed
|
||||
else
|
||||
:swift_runtime_error
|
||||
end
|
||||
when 127
|
||||
# Command not found or execution failed
|
||||
odebug "Swift execution failed with exit status 127"
|
||||
:swift_not_executable
|
||||
else
|
||||
odebug "Unknown support status"
|
||||
:unknown
|
||||
odebug "Swift returned unexpected exit status: #{exit_status}"
|
||||
:swift_unexpected_error
|
||||
end
|
||||
end
|
||||
[status, check_output]
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def self.available?
|
||||
@status ||= check_quarantine_support
|
||||
@quarantine_support ||= check_quarantine_support
|
||||
|
||||
@status == :quarantine_available
|
||||
@quarantine_support[0] == :quarantine_available
|
||||
end
|
||||
|
||||
def self.detect(file)
|
||||
|
||||
@ -25,7 +25,7 @@ module Cask
|
||||
full_paths = remove_nonexistent(paths)
|
||||
return if full_paths.empty?
|
||||
|
||||
ohai "Changing ownership of paths required by #{@cask} with sudo; the password may be necessary."
|
||||
ohai "Changing ownership of paths required by #{@cask} with `sudo` (which may request your password)..."
|
||||
@command.run!("/usr/sbin/chown", args: ["-R", "--", "#{user}:#{group}", *full_paths],
|
||||
sudo: true)
|
||||
end
|
||||
|
||||
@ -40,6 +40,7 @@ module Cask
|
||||
attr_reader :tag, :branch, :revision, :only_path, :verified
|
||||
|
||||
extend Forwardable
|
||||
|
||||
def_delegators :uri, :path, :scheme, :to_s
|
||||
|
||||
# Creates a `url` stanza.
|
||||
|
||||
@ -171,7 +171,7 @@ module Homebrew
|
||||
|
||||
stable = formula.stable
|
||||
if resource_name == "patch"
|
||||
patch_hashes = stable&.patches&.filter_map { _1.resource.version if _1.external? }
|
||||
patch_hashes = stable&.patches&.filter_map { T.cast(_1, ExternalPatch).resource.version if _1.external? }
|
||||
return true unless patch_hashes&.include?(Checksum.new(version.to_s))
|
||||
elsif resource_name && stable && (resource_version = stable.resources[resource_name]&.version)
|
||||
return true if resource_version != version
|
||||
|
||||
@ -207,13 +207,13 @@ module Homebrew
|
||||
if formula_path.exist? ||
|
||||
(!Homebrew::EnvConfig.no_install_from_api? &&
|
||||
!CoreTap.instance.installed? &&
|
||||
Homebrew::API::Formula.all_formulae.key?(path.basename.to_s))
|
||||
Homebrew::API.formula_names.include?(path.basename.to_s))
|
||||
paths << formula_path
|
||||
end
|
||||
if cask_path.exist? ||
|
||||
(!Homebrew::EnvConfig.no_install_from_api? &&
|
||||
!CoreCaskTap.instance.installed? &&
|
||||
Homebrew::API::Cask.all_casks.key?(path.basename.to_s))
|
||||
Homebrew::API.cask_tokens.include?(path.basename.to_s))
|
||||
paths << cask_path
|
||||
end
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ module Homebrew
|
||||
module Cmd
|
||||
class Deps < AbstractCommand
|
||||
include DependenciesHelpers
|
||||
|
||||
cmd_args do
|
||||
description <<~EOS
|
||||
Show dependencies for <formula>. When given multiple formula arguments,
|
||||
@ -87,8 +88,8 @@ module Homebrew
|
||||
|
||||
sig { override.void }
|
||||
def run
|
||||
raise UsageError, "`brew deps --os=all` is not supported" if args.os == "all"
|
||||
raise UsageError, "`brew deps --arch=all` is not supported" if args.arch == "all"
|
||||
raise UsageError, "`brew deps --os=all` is not supported." if args.os == "all"
|
||||
raise UsageError, "`brew deps --arch=all` is not supported." if args.arch == "all"
|
||||
|
||||
os, arch = T.must(args.os_arch_combinations.first)
|
||||
eval_all = args.eval_all?
|
||||
|
||||
@ -11,6 +11,7 @@ module Homebrew
|
||||
module Cmd
|
||||
class FetchCmd < AbstractCommand
|
||||
include Fetch
|
||||
|
||||
FETCH_MAX_TRIES = 5
|
||||
|
||||
cmd_args do
|
||||
|
||||
@ -12,6 +12,7 @@ module Homebrew
|
||||
module Cmd
|
||||
class GistLogs < AbstractCommand
|
||||
include Install
|
||||
|
||||
cmd_args do
|
||||
description <<~EOS
|
||||
Upload logs for a failed build of <formula> to a new Gist. Presents an
|
||||
|
||||
@ -159,9 +159,9 @@ module Homebrew
|
||||
|
||||
case obj
|
||||
when Formula
|
||||
Utils::Analytics.formula_output(obj, args:)
|
||||
Utils::Analytics.formula_output(obj, args:) if obj.core_formula?
|
||||
when Cask::Cask
|
||||
Utils::Analytics.cask_output(obj, args:)
|
||||
Utils::Analytics.cask_output(obj, args:) if obj.tap.core_cask_tap?
|
||||
when FormulaOrCaskUnavailableError
|
||||
Utils::Analytics.output(filter: obj.name, args:)
|
||||
else
|
||||
@ -380,6 +380,8 @@ module Homebrew
|
||||
ohai "Caveats", caveats_string
|
||||
end
|
||||
|
||||
return unless formula.core_formula?
|
||||
|
||||
Utils::Analytics.formula_output(formula, args:)
|
||||
end
|
||||
|
||||
|
||||
@ -181,7 +181,7 @@ module Homebrew
|
||||
# `build.rb`. Instead, `hide_from_man_page` and don't do anything with
|
||||
# this argument here.
|
||||
# This odisabled should stick around indefinitely.
|
||||
odisabled "brew install --env", "`env :std` in specific formula files"
|
||||
odisabled "`brew install --env`", "`env :std` in specific formula files"
|
||||
end
|
||||
|
||||
args.named.each do |name|
|
||||
|
||||
@ -25,27 +25,27 @@ module Homebrew
|
||||
If `sudo` is passed, operate on `/Library/LaunchDaemons` or `/usr/lib/systemd/system` (started at boot).
|
||||
Otherwise, operate on `~/Library/LaunchAgents` or `~/.config/systemd/user` (started at login).
|
||||
|
||||
[`sudo`] `brew services` [`list`] (`--json`) (`--debug`):
|
||||
[`sudo`] `brew services` [`list`] [`--json`] [`--debug`]:
|
||||
List information about all managed services for the current user (or root).
|
||||
Provides more output from Homebrew and `launchctl`(1) or `systemctl`(1) if run with `--debug`.
|
||||
|
||||
[`sudo`] `brew services info` (<formula>|`--all`|`--json`):
|
||||
[`sudo`] `brew services info` (<formula>|`--all`) [`--json`]:
|
||||
List all managed services for the current user (or root).
|
||||
|
||||
[`sudo`] `brew services run` (<formula>|`--all`|`--file=`):
|
||||
[`sudo`] `brew services run` (<formula>|`--all`) [`--file=`]:
|
||||
Run the service <formula> without registering to launch at login (or boot).
|
||||
|
||||
[`sudo`] `brew services start` (<formula>|`--all`|`--file=`):
|
||||
[`sudo`] `brew services start` (<formula>|`--all`) [`--file=`]:
|
||||
Start the service <formula> immediately and register it to launch at login (or boot).
|
||||
|
||||
[`sudo`] `brew services stop` (`--keep`) (`--no-wait`|`--max-wait=`) (<formula>|`--all`):
|
||||
[`sudo`] `brew services stop` [`--keep`] [`--no-wait`|`--max-wait=`] (<formula>|`--all`):
|
||||
Stop the service <formula> immediately and unregister it from launching at login (or boot),
|
||||
unless `--keep` is specified.
|
||||
|
||||
[`sudo`] `brew services kill` (<formula>|`--all`):
|
||||
Stop the service <formula> immediately but keep it registered to launch at login (or boot).
|
||||
|
||||
[`sudo`] `brew services restart` (<formula>|`--all`|`--file=`):
|
||||
[`sudo`] `brew services restart` (<formula>|`--all`) [`--file=`]:
|
||||
Stop (if necessary) and start the service <formula> immediately and register it to launch at login (or boot).
|
||||
|
||||
[`sudo`] `brew services cleanup`:
|
||||
@ -58,15 +58,16 @@ module Homebrew
|
||||
flag "--max-wait=",
|
||||
description: "Wait at most this many seconds for `stop` to finish stopping a service. " \
|
||||
"Defaults to 60. Set this to zero (0) seconds to wait indefinitely."
|
||||
switch "--all",
|
||||
description: "Run <subcommand> on all services."
|
||||
switch "--json",
|
||||
description: "Output as JSON."
|
||||
switch "--no-wait",
|
||||
description: "Don't wait for `stop` to finish stopping the service."
|
||||
switch "--keep",
|
||||
description: "When stopped, don't unregister the service from launching at login (or boot)."
|
||||
switch "--all",
|
||||
description: "Run <subcommand> on all services."
|
||||
switch "--json",
|
||||
description: "Output as JSON."
|
||||
|
||||
conflicts "--all", "--file"
|
||||
conflicts "--max-wait=", "--no-wait"
|
||||
|
||||
named_args %w[list info run start stop kill restart cleanup]
|
||||
@ -112,7 +113,7 @@ module Homebrew
|
||||
]
|
||||
if no_named_formula_commands.include?(subcommand)
|
||||
raise UsageError, "The `#{subcommand}` subcommand does not accept a formula argument!" if formulae.present?
|
||||
raise UsageError, "The `#{subcommand}` subcommand does not accept the --all argument!" if args.all?
|
||||
raise UsageError, "The `#{subcommand}` subcommand does not accept the `--all` argument!" if args.all?
|
||||
end
|
||||
|
||||
if args.file
|
||||
@ -122,22 +123,22 @@ module Homebrew
|
||||
*Homebrew::Services::Commands::Restart::TRIGGERS,
|
||||
]
|
||||
if file_commands.exclude?(subcommand)
|
||||
raise UsageError, "The `#{subcommand}` subcommand does not accept the --file= argument!"
|
||||
elsif args.all?
|
||||
raise UsageError,
|
||||
"The `#{subcommand}` subcommand does not accept the --all and --file= arguments at the same time!"
|
||||
raise UsageError, "The `#{subcommand}` subcommand does not accept the `--file=` argument!"
|
||||
end
|
||||
end
|
||||
|
||||
unless Homebrew::Services::Commands::Stop::TRIGGERS.include?(subcommand)
|
||||
raise UsageError, "The `#{subcommand}` subcommand does not accept the --keep argument!" if args.keep?
|
||||
raise UsageError, "The `#{subcommand}` subcommand does not accept the --no-wait argument!" if args.no_wait?
|
||||
raise UsageError, "The `#{subcommand}` subcommand does not accept the `--keep` argument!" if args.keep?
|
||||
|
||||
if args.no_wait?
|
||||
raise UsageError, "The `#{subcommand}` subcommand does not accept the `--no-wait` argument!"
|
||||
end
|
||||
if args.max_wait
|
||||
raise UsageError, "The `#{subcommand}` subcommand does not accept the --max-wait= argument!"
|
||||
raise UsageError, "The `#{subcommand}` subcommand does not accept the `--max-wait=` argument!"
|
||||
end
|
||||
end
|
||||
|
||||
opoo "The --all argument overrides provided formula argument!" if formulae.present? && args.all?
|
||||
opoo "The `--all` argument overrides provided formula argument!" if formulae.present? && args.all?
|
||||
|
||||
targets = if args.all?
|
||||
if subcommand == "start"
|
||||
|
||||
@ -134,10 +134,7 @@ module Homebrew
|
||||
end
|
||||
|
||||
# Check if we can parse the JSON and do any Ruby-side follow-up.
|
||||
unless Homebrew::EnvConfig.no_install_from_api?
|
||||
Homebrew::API::Formula.write_names_and_aliases
|
||||
Homebrew::API::Cask.write_names
|
||||
end
|
||||
Homebrew::API.write_names_and_aliases unless Homebrew::EnvConfig.no_install_from_api?
|
||||
|
||||
Homebrew.failed = true if ENV["HOMEBREW_UPDATE_FAILED"]
|
||||
return if Homebrew::EnvConfig.disable_load_formula?
|
||||
|
||||
@ -126,7 +126,7 @@ module Homebrew
|
||||
sig { override.void }
|
||||
def run
|
||||
if args.build_from_source? && args.named.empty?
|
||||
raise ArgumentError, "--build-from-source requires at least one formula"
|
||||
raise ArgumentError, "`--build-from-source` requires at least one formula"
|
||||
end
|
||||
|
||||
formulae, casks = args.named.to_resolved_formulae_to_casks
|
||||
|
||||
@ -40,7 +40,7 @@ class CompilerFailure
|
||||
# Non-Apple compilers are in the format fails_with compiler => version
|
||||
if spec.is_a?(Hash)
|
||||
compiler, major_version = spec.first
|
||||
raise ArgumentError, "The hash `fails_with` syntax only supports GCC" if compiler != :gcc
|
||||
raise ArgumentError, "The `fails_with` hash syntax only supports GCC" if compiler != :gcc
|
||||
|
||||
type = compiler
|
||||
# so fails_with :gcc => '7' simply marks all 7 releases incompatible
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
#
|
||||
# - For changes to a command under `COMMANDS` or `DEVELOPER COMMANDS` sections):
|
||||
# - Find the source file in `Library/Homebrew/[dev-]cmd/<command>.{rb,sh}`.
|
||||
# - For `.rb` files, edit the `<command>_args` method.
|
||||
# - For `.rb` files, edit the `cmd_args` block.
|
||||
# - For `.sh` files, edit the top comment, being sure to use the line prefix
|
||||
# `#:` for the comments to be recognized as documentation. If in doubt,
|
||||
# compare with already documented commands.
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
#
|
||||
# - For changes to a command under `COMMANDS` or `DEVELOPER COMMANDS` sections):
|
||||
# - Find the source file in `Library/Homebrew/[dev-]cmd/<command>.{rb,sh}`.
|
||||
# - For `.rb` files, edit the `<command>_args` method.
|
||||
# - For `.rb` files, edit the `cmd_args` block.
|
||||
# - For `.sh` files, edit the top comment, being sure to use the line prefix
|
||||
# `#:` for the comments to be recognized as documentation. If in doubt,
|
||||
# compare with already documented commands.
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
#
|
||||
# - For changes to a command under `COMMANDS` or `DEVELOPER COMMANDS` sections):
|
||||
# - Find the source file in `Library/Homebrew/[dev-]cmd/<command>.{rb,sh}`.
|
||||
# - For `.rb` files, edit the `<command>_args` method.
|
||||
# - For `.rb` files, edit the `cmd_args` block.
|
||||
# - For `.sh` files, edit the top comment, being sure to use the line prefix
|
||||
# `#:` for the comments to be recognized as documentation. If in doubt,
|
||||
# compare with already documented commands.
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
{
|
||||
"licenseListVersion": "5dbff5c",
|
||||
"licenseListVersion": "3.27.0",
|
||||
"exceptions": [
|
||||
{
|
||||
"reference": "https://spdx.org/licenses/389-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/389-exception.json",
|
||||
"referenceNumber": 33,
|
||||
"referenceNumber": 36,
|
||||
"name": "389 Directory Server Exception",
|
||||
"licenseExceptionId": "389-exception",
|
||||
"seeAlso": [
|
||||
@ -17,7 +17,7 @@
|
||||
"reference": "https://spdx.org/licenses/Asterisk-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Asterisk-exception.json",
|
||||
"referenceNumber": 52,
|
||||
"referenceNumber": 16,
|
||||
"name": "Asterisk exception",
|
||||
"licenseExceptionId": "Asterisk-exception",
|
||||
"seeAlso": [
|
||||
@ -29,7 +29,7 @@
|
||||
"reference": "https://spdx.org/licenses/Asterisk-linking-protocols-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Asterisk-linking-protocols-exception.json",
|
||||
"referenceNumber": 75,
|
||||
"referenceNumber": 22,
|
||||
"name": "Asterisk linking protocols exception",
|
||||
"licenseExceptionId": "Asterisk-linking-protocols-exception",
|
||||
"seeAlso": [
|
||||
@ -40,7 +40,7 @@
|
||||
"reference": "https://spdx.org/licenses/Autoconf-exception-2.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Autoconf-exception-2.0.json",
|
||||
"referenceNumber": 60,
|
||||
"referenceNumber": 2,
|
||||
"name": "Autoconf exception 2.0",
|
||||
"licenseExceptionId": "Autoconf-exception-2.0",
|
||||
"seeAlso": [
|
||||
@ -52,7 +52,7 @@
|
||||
"reference": "https://spdx.org/licenses/Autoconf-exception-3.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Autoconf-exception-3.0.json",
|
||||
"referenceNumber": 1,
|
||||
"referenceNumber": 51,
|
||||
"name": "Autoconf exception 3.0",
|
||||
"licenseExceptionId": "Autoconf-exception-3.0",
|
||||
"seeAlso": [
|
||||
@ -63,7 +63,7 @@
|
||||
"reference": "https://spdx.org/licenses/Autoconf-exception-generic.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Autoconf-exception-generic.json",
|
||||
"referenceNumber": 59,
|
||||
"referenceNumber": 73,
|
||||
"name": "Autoconf generic exception",
|
||||
"licenseExceptionId": "Autoconf-exception-generic",
|
||||
"seeAlso": [
|
||||
@ -77,7 +77,7 @@
|
||||
"reference": "https://spdx.org/licenses/Autoconf-exception-generic-3.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Autoconf-exception-generic-3.0.json",
|
||||
"referenceNumber": 48,
|
||||
"referenceNumber": 40,
|
||||
"name": "Autoconf generic exception for GPL-3.0",
|
||||
"licenseExceptionId": "Autoconf-exception-generic-3.0",
|
||||
"seeAlso": [
|
||||
@ -88,7 +88,7 @@
|
||||
"reference": "https://spdx.org/licenses/Autoconf-exception-macro.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Autoconf-exception-macro.json",
|
||||
"referenceNumber": 15,
|
||||
"referenceNumber": 63,
|
||||
"name": "Autoconf macro exception",
|
||||
"licenseExceptionId": "Autoconf-exception-macro",
|
||||
"seeAlso": [
|
||||
@ -101,7 +101,7 @@
|
||||
"reference": "https://spdx.org/licenses/Bison-exception-1.24.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Bison-exception-1.24.json",
|
||||
"referenceNumber": 69,
|
||||
"referenceNumber": 56,
|
||||
"name": "Bison exception 1.24",
|
||||
"licenseExceptionId": "Bison-exception-1.24",
|
||||
"seeAlso": [
|
||||
@ -112,7 +112,7 @@
|
||||
"reference": "https://spdx.org/licenses/Bison-exception-2.2.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Bison-exception-2.2.json",
|
||||
"referenceNumber": 19,
|
||||
"referenceNumber": 28,
|
||||
"name": "Bison exception 2.2",
|
||||
"licenseExceptionId": "Bison-exception-2.2",
|
||||
"seeAlso": [
|
||||
@ -123,7 +123,7 @@
|
||||
"reference": "https://spdx.org/licenses/Bootloader-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Bootloader-exception.json",
|
||||
"referenceNumber": 68,
|
||||
"referenceNumber": 65,
|
||||
"name": "Bootloader Distribution Exception",
|
||||
"licenseExceptionId": "Bootloader-exception",
|
||||
"seeAlso": [
|
||||
@ -134,7 +134,7 @@
|
||||
"reference": "https://spdx.org/licenses/CGAL-linking-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/CGAL-linking-exception.json",
|
||||
"referenceNumber": 34,
|
||||
"referenceNumber": 74,
|
||||
"name": "CGAL Linking Exception",
|
||||
"licenseExceptionId": "CGAL-linking-exception",
|
||||
"seeAlso": [
|
||||
@ -146,7 +146,7 @@
|
||||
"reference": "https://spdx.org/licenses/Classpath-exception-2.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Classpath-exception-2.0.json",
|
||||
"referenceNumber": 66,
|
||||
"referenceNumber": 67,
|
||||
"name": "Classpath exception 2.0",
|
||||
"licenseExceptionId": "Classpath-exception-2.0",
|
||||
"seeAlso": [
|
||||
@ -158,7 +158,7 @@
|
||||
"reference": "https://spdx.org/licenses/CLISP-exception-2.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/CLISP-exception-2.0.json",
|
||||
"referenceNumber": 4,
|
||||
"referenceNumber": 10,
|
||||
"name": "CLISP exception 2.0",
|
||||
"licenseExceptionId": "CLISP-exception-2.0",
|
||||
"seeAlso": [
|
||||
@ -169,7 +169,7 @@
|
||||
"reference": "https://spdx.org/licenses/cryptsetup-OpenSSL-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/cryptsetup-OpenSSL-exception.json",
|
||||
"referenceNumber": 55,
|
||||
"referenceNumber": 46,
|
||||
"name": "cryptsetup OpenSSL exception",
|
||||
"licenseExceptionId": "cryptsetup-OpenSSL-exception",
|
||||
"seeAlso": [
|
||||
@ -185,7 +185,7 @@
|
||||
"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": 2,
|
||||
"referenceNumber": 48,
|
||||
"name": "Digia Qt LGPL Exception version 1.1",
|
||||
"licenseExceptionId": "Digia-Qt-LGPL-exception-1.1",
|
||||
"seeAlso": [
|
||||
@ -196,7 +196,7 @@
|
||||
"reference": "https://spdx.org/licenses/DigiRule-FOSS-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/DigiRule-FOSS-exception.json",
|
||||
"referenceNumber": 25,
|
||||
"referenceNumber": 53,
|
||||
"name": "DigiRule FOSS License Exception",
|
||||
"licenseExceptionId": "DigiRule-FOSS-exception",
|
||||
"seeAlso": [
|
||||
@ -207,7 +207,7 @@
|
||||
"reference": "https://spdx.org/licenses/eCos-exception-2.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/eCos-exception-2.0.json",
|
||||
"referenceNumber": 31,
|
||||
"referenceNumber": 61,
|
||||
"name": "eCos exception 2.0",
|
||||
"licenseExceptionId": "eCos-exception-2.0",
|
||||
"seeAlso": [
|
||||
@ -218,7 +218,7 @@
|
||||
"reference": "https://spdx.org/licenses/erlang-otp-linking-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/erlang-otp-linking-exception.json",
|
||||
"referenceNumber": 78,
|
||||
"referenceNumber": 13,
|
||||
"name": "Erlang/OTP Linking Exception",
|
||||
"licenseExceptionId": "erlang-otp-linking-exception",
|
||||
"seeAlso": [
|
||||
@ -231,7 +231,7 @@
|
||||
"reference": "https://spdx.org/licenses/Fawkes-Runtime-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Fawkes-Runtime-exception.json",
|
||||
"referenceNumber": 47,
|
||||
"referenceNumber": 21,
|
||||
"name": "Fawkes Runtime Exception",
|
||||
"licenseExceptionId": "Fawkes-Runtime-exception",
|
||||
"seeAlso": [
|
||||
@ -242,7 +242,7 @@
|
||||
"reference": "https://spdx.org/licenses/FLTK-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/FLTK-exception.json",
|
||||
"referenceNumber": 3,
|
||||
"referenceNumber": 66,
|
||||
"name": "FLTK exception",
|
||||
"licenseExceptionId": "FLTK-exception",
|
||||
"seeAlso": [
|
||||
@ -253,7 +253,7 @@
|
||||
"reference": "https://spdx.org/licenses/fmt-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/fmt-exception.json",
|
||||
"referenceNumber": 16,
|
||||
"referenceNumber": 77,
|
||||
"name": "fmt exception",
|
||||
"licenseExceptionId": "fmt-exception",
|
||||
"seeAlso": [
|
||||
@ -265,7 +265,7 @@
|
||||
"reference": "https://spdx.org/licenses/Font-exception-2.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Font-exception-2.0.json",
|
||||
"referenceNumber": 32,
|
||||
"referenceNumber": 35,
|
||||
"name": "Font exception 2.0",
|
||||
"licenseExceptionId": "Font-exception-2.0",
|
||||
"seeAlso": [
|
||||
@ -276,7 +276,7 @@
|
||||
"reference": "https://spdx.org/licenses/freertos-exception-2.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/freertos-exception-2.0.json",
|
||||
"referenceNumber": 44,
|
||||
"referenceNumber": 23,
|
||||
"name": "FreeRTOS Exception 2.0",
|
||||
"licenseExceptionId": "freertos-exception-2.0",
|
||||
"seeAlso": [
|
||||
@ -287,7 +287,7 @@
|
||||
"reference": "https://spdx.org/licenses/GCC-exception-2.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/GCC-exception-2.0.json",
|
||||
"referenceNumber": 6,
|
||||
"referenceNumber": 14,
|
||||
"name": "GCC Runtime Library exception 2.0",
|
||||
"licenseExceptionId": "GCC-exception-2.0",
|
||||
"seeAlso": [
|
||||
@ -299,7 +299,7 @@
|
||||
"reference": "https://spdx.org/licenses/GCC-exception-2.0-note.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/GCC-exception-2.0-note.json",
|
||||
"referenceNumber": 11,
|
||||
"referenceNumber": 20,
|
||||
"name": "GCC Runtime Library exception 2.0 - note variant",
|
||||
"licenseExceptionId": "GCC-exception-2.0-note",
|
||||
"seeAlso": [
|
||||
@ -310,7 +310,7 @@
|
||||
"reference": "https://spdx.org/licenses/GCC-exception-3.1.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/GCC-exception-3.1.json",
|
||||
"referenceNumber": 77,
|
||||
"referenceNumber": 25,
|
||||
"name": "GCC Runtime Library exception 3.1",
|
||||
"licenseExceptionId": "GCC-exception-3.1",
|
||||
"seeAlso": [
|
||||
@ -321,7 +321,7 @@
|
||||
"reference": "https://spdx.org/licenses/Gmsh-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Gmsh-exception.json",
|
||||
"referenceNumber": 35,
|
||||
"referenceNumber": 26,
|
||||
"name": "Gmsh exception",
|
||||
"licenseExceptionId": "Gmsh-exception",
|
||||
"seeAlso": [
|
||||
@ -332,7 +332,7 @@
|
||||
"reference": "https://spdx.org/licenses/GNAT-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/GNAT-exception.json",
|
||||
"referenceNumber": 18,
|
||||
"referenceNumber": 69,
|
||||
"name": "GNAT exception",
|
||||
"licenseExceptionId": "GNAT-exception",
|
||||
"seeAlso": [
|
||||
@ -343,7 +343,7 @@
|
||||
"reference": "https://spdx.org/licenses/GNOME-examples-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/GNOME-examples-exception.json",
|
||||
"referenceNumber": 49,
|
||||
"referenceNumber": 76,
|
||||
"name": "GNOME examples exception",
|
||||
"licenseExceptionId": "GNOME-examples-exception",
|
||||
"seeAlso": [
|
||||
@ -355,19 +355,18 @@
|
||||
"reference": "https://spdx.org/licenses/GNU-compiler-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/GNU-compiler-exception.json",
|
||||
"referenceNumber": 41,
|
||||
"referenceNumber": 58,
|
||||
"name": "GNU Compiler Exception",
|
||||
"licenseExceptionId": "GNU-compiler-exception",
|
||||
"seeAlso": [
|
||||
"https://sourceware.org/git?p\u003dbinutils-gdb.git;a\u003dblob;f\u003dlibiberty/unlink-if-ordinary.c;h\u003de49f2f2f67bfdb10d6b2bd579b0e01cad0fd708e;hb\u003dHEAD#l19",
|
||||
"https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/powerpc/lib/crtsavres.S?h\u003dv6.16-rc6#n34"
|
||||
"https://sourceware.org/git?p\u003dbinutils-gdb.git;a\u003dblob;f\u003dlibiberty/unlink-if-ordinary.c;h\u003de49f2f2f67bfdb10d6b2bd579b0e01cad0fd708e;hb\u003dHEAD#l19"
|
||||
]
|
||||
},
|
||||
{
|
||||
"reference": "https://spdx.org/licenses/gnu-javamail-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/gnu-javamail-exception.json",
|
||||
"referenceNumber": 72,
|
||||
"referenceNumber": 64,
|
||||
"name": "GNU JavaMail exception",
|
||||
"licenseExceptionId": "gnu-javamail-exception",
|
||||
"seeAlso": [
|
||||
@ -378,7 +377,7 @@
|
||||
"reference": "https://spdx.org/licenses/GPL-3.0-389-ds-base-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/GPL-3.0-389-ds-base-exception.json",
|
||||
"referenceNumber": 67,
|
||||
"referenceNumber": 18,
|
||||
"name": "GPL-3.0 389 DS Base Exception",
|
||||
"licenseExceptionId": "GPL-3.0-389-ds-base-exception",
|
||||
"seeAlso": []
|
||||
@ -387,7 +386,7 @@
|
||||
"reference": "https://spdx.org/licenses/GPL-3.0-interface-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/GPL-3.0-interface-exception.json",
|
||||
"referenceNumber": 76,
|
||||
"referenceNumber": 78,
|
||||
"name": "GPL-3.0 Interface Exception",
|
||||
"licenseExceptionId": "GPL-3.0-interface-exception",
|
||||
"seeAlso": [
|
||||
@ -398,7 +397,7 @@
|
||||
"reference": "https://spdx.org/licenses/GPL-3.0-linking-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/GPL-3.0-linking-exception.json",
|
||||
"referenceNumber": 51,
|
||||
"referenceNumber": 68,
|
||||
"name": "GPL-3.0 Linking Exception",
|
||||
"licenseExceptionId": "GPL-3.0-linking-exception",
|
||||
"seeAlso": [
|
||||
@ -409,7 +408,7 @@
|
||||
"reference": "https://spdx.org/licenses/GPL-3.0-linking-source-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/GPL-3.0-linking-source-exception.json",
|
||||
"referenceNumber": 50,
|
||||
"referenceNumber": 62,
|
||||
"name": "GPL-3.0 Linking Exception (with Corresponding Source)",
|
||||
"licenseExceptionId": "GPL-3.0-linking-source-exception",
|
||||
"seeAlso": [
|
||||
@ -421,7 +420,7 @@
|
||||
"reference": "https://spdx.org/licenses/GPL-CC-1.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/GPL-CC-1.0.json",
|
||||
"referenceNumber": 54,
|
||||
"referenceNumber": 33,
|
||||
"name": "GPL Cooperation Commitment 1.0",
|
||||
"licenseExceptionId": "GPL-CC-1.0",
|
||||
"seeAlso": [
|
||||
@ -433,7 +432,7 @@
|
||||
"reference": "https://spdx.org/licenses/GStreamer-exception-2005.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/GStreamer-exception-2005.json",
|
||||
"referenceNumber": 7,
|
||||
"referenceNumber": 4,
|
||||
"name": "GStreamer Exception (2005)",
|
||||
"licenseExceptionId": "GStreamer-exception-2005",
|
||||
"seeAlso": [
|
||||
@ -444,7 +443,7 @@
|
||||
"reference": "https://spdx.org/licenses/GStreamer-exception-2008.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/GStreamer-exception-2008.json",
|
||||
"referenceNumber": 56,
|
||||
"referenceNumber": 41,
|
||||
"name": "GStreamer Exception (2008)",
|
||||
"licenseExceptionId": "GStreamer-exception-2008",
|
||||
"seeAlso": [
|
||||
@ -455,7 +454,7 @@
|
||||
"reference": "https://spdx.org/licenses/harbour-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/harbour-exception.json",
|
||||
"referenceNumber": 63,
|
||||
"referenceNumber": 59,
|
||||
"name": "harbour exception",
|
||||
"licenseExceptionId": "harbour-exception",
|
||||
"seeAlso": [
|
||||
@ -466,7 +465,7 @@
|
||||
"reference": "https://spdx.org/licenses/i2p-gpl-java-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/i2p-gpl-java-exception.json",
|
||||
"referenceNumber": 36,
|
||||
"referenceNumber": 9,
|
||||
"name": "i2p GPL+Java Exception",
|
||||
"licenseExceptionId": "i2p-gpl-java-exception",
|
||||
"seeAlso": [
|
||||
@ -477,7 +476,7 @@
|
||||
"reference": "https://spdx.org/licenses/Independent-modules-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Independent-modules-exception.json",
|
||||
"referenceNumber": 13,
|
||||
"referenceNumber": 45,
|
||||
"name": "Independent Module Linking exception",
|
||||
"licenseExceptionId": "Independent-modules-exception",
|
||||
"seeAlso": [
|
||||
@ -488,7 +487,7 @@
|
||||
"reference": "https://spdx.org/licenses/KiCad-libraries-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/KiCad-libraries-exception.json",
|
||||
"referenceNumber": 23,
|
||||
"referenceNumber": 44,
|
||||
"name": "KiCad Libraries Exception",
|
||||
"licenseExceptionId": "KiCad-libraries-exception",
|
||||
"seeAlso": [
|
||||
@ -499,7 +498,7 @@
|
||||
"reference": "https://spdx.org/licenses/LGPL-3.0-linking-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/LGPL-3.0-linking-exception.json",
|
||||
"referenceNumber": 42,
|
||||
"referenceNumber": 32,
|
||||
"name": "LGPL-3.0 Linking Exception",
|
||||
"licenseExceptionId": "LGPL-3.0-linking-exception",
|
||||
"seeAlso": [
|
||||
@ -512,7 +511,7 @@
|
||||
"reference": "https://spdx.org/licenses/libpri-OpenH323-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/libpri-OpenH323-exception.json",
|
||||
"referenceNumber": 70,
|
||||
"referenceNumber": 19,
|
||||
"name": "libpri OpenH323 exception",
|
||||
"licenseExceptionId": "libpri-OpenH323-exception",
|
||||
"seeAlso": [
|
||||
@ -523,7 +522,7 @@
|
||||
"reference": "https://spdx.org/licenses/Libtool-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Libtool-exception.json",
|
||||
"referenceNumber": 22,
|
||||
"referenceNumber": 71,
|
||||
"name": "Libtool Exception",
|
||||
"licenseExceptionId": "Libtool-exception",
|
||||
"seeAlso": [
|
||||
@ -535,7 +534,7 @@
|
||||
"reference": "https://spdx.org/licenses/Linux-syscall-note.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Linux-syscall-note.json",
|
||||
"referenceNumber": 9,
|
||||
"referenceNumber": 37,
|
||||
"name": "Linux Syscall Note",
|
||||
"licenseExceptionId": "Linux-syscall-note",
|
||||
"seeAlso": [
|
||||
@ -546,7 +545,7 @@
|
||||
"reference": "https://spdx.org/licenses/LLGPL.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/LLGPL.json",
|
||||
"referenceNumber": 14,
|
||||
"referenceNumber": 24,
|
||||
"name": "LLGPL Preamble",
|
||||
"licenseExceptionId": "LLGPL",
|
||||
"seeAlso": [
|
||||
@ -557,7 +556,7 @@
|
||||
"reference": "https://spdx.org/licenses/LLVM-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/LLVM-exception.json",
|
||||
"referenceNumber": 28,
|
||||
"referenceNumber": 72,
|
||||
"name": "LLVM Exception",
|
||||
"licenseExceptionId": "LLVM-exception",
|
||||
"seeAlso": [
|
||||
@ -568,7 +567,7 @@
|
||||
"reference": "https://spdx.org/licenses/LZMA-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/LZMA-exception.json",
|
||||
"referenceNumber": 45,
|
||||
"referenceNumber": 30,
|
||||
"name": "LZMA exception",
|
||||
"licenseExceptionId": "LZMA-exception",
|
||||
"seeAlso": [
|
||||
@ -579,7 +578,7 @@
|
||||
"reference": "https://spdx.org/licenses/mif-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/mif-exception.json",
|
||||
"referenceNumber": 65,
|
||||
"referenceNumber": 29,
|
||||
"name": "Macros and Inline Functions Exception",
|
||||
"licenseExceptionId": "mif-exception",
|
||||
"seeAlso": [
|
||||
@ -592,7 +591,7 @@
|
||||
"reference": "https://spdx.org/licenses/mxml-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/mxml-exception.json",
|
||||
"referenceNumber": 71,
|
||||
"referenceNumber": 38,
|
||||
"name": "mxml Exception",
|
||||
"licenseExceptionId": "mxml-exception",
|
||||
"seeAlso": [
|
||||
@ -604,7 +603,7 @@
|
||||
"reference": "https://spdx.org/licenses/Nokia-Qt-exception-1.1.html",
|
||||
"isDeprecatedLicenseId": true,
|
||||
"detailsUrl": "https://spdx.org/licenses/Nokia-Qt-exception-1.1.json",
|
||||
"referenceNumber": 64,
|
||||
"referenceNumber": 47,
|
||||
"name": "Nokia Qt LGPL exception 1.1",
|
||||
"licenseExceptionId": "Nokia-Qt-exception-1.1",
|
||||
"seeAlso": [
|
||||
@ -615,7 +614,7 @@
|
||||
"reference": "https://spdx.org/licenses/OCaml-LGPL-linking-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/OCaml-LGPL-linking-exception.json",
|
||||
"referenceNumber": 61,
|
||||
"referenceNumber": 42,
|
||||
"name": "OCaml LGPL Linking Exception",
|
||||
"licenseExceptionId": "OCaml-LGPL-linking-exception",
|
||||
"seeAlso": [
|
||||
@ -626,7 +625,7 @@
|
||||
"reference": "https://spdx.org/licenses/OCCT-exception-1.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/OCCT-exception-1.0.json",
|
||||
"referenceNumber": 21,
|
||||
"referenceNumber": 17,
|
||||
"name": "Open CASCADE Exception 1.0",
|
||||
"licenseExceptionId": "OCCT-exception-1.0",
|
||||
"seeAlso": [
|
||||
@ -637,7 +636,7 @@
|
||||
"reference": "https://spdx.org/licenses/OpenJDK-assembly-exception-1.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/OpenJDK-assembly-exception-1.0.json",
|
||||
"referenceNumber": 40,
|
||||
"referenceNumber": 11,
|
||||
"name": "OpenJDK Assembly exception 1.0",
|
||||
"licenseExceptionId": "OpenJDK-assembly-exception-1.0",
|
||||
"seeAlso": [
|
||||
@ -648,7 +647,7 @@
|
||||
"reference": "https://spdx.org/licenses/openvpn-openssl-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/openvpn-openssl-exception.json",
|
||||
"referenceNumber": 53,
|
||||
"referenceNumber": 3,
|
||||
"name": "OpenVPN OpenSSL Exception",
|
||||
"licenseExceptionId": "openvpn-openssl-exception",
|
||||
"seeAlso": [
|
||||
@ -660,7 +659,7 @@
|
||||
"reference": "https://spdx.org/licenses/PCRE2-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/PCRE2-exception.json",
|
||||
"referenceNumber": 62,
|
||||
"referenceNumber": 12,
|
||||
"name": "PCRE2 exception",
|
||||
"licenseExceptionId": "PCRE2-exception",
|
||||
"seeAlso": [
|
||||
@ -671,7 +670,7 @@
|
||||
"reference": "https://spdx.org/licenses/polyparse-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/polyparse-exception.json",
|
||||
"referenceNumber": 27,
|
||||
"referenceNumber": 54,
|
||||
"name": "Polyparse Exception",
|
||||
"licenseExceptionId": "polyparse-exception",
|
||||
"seeAlso": [
|
||||
@ -682,7 +681,7 @@
|
||||
"reference": "https://spdx.org/licenses/PS-or-PDF-font-exception-20170817.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/PS-or-PDF-font-exception-20170817.json",
|
||||
"referenceNumber": 74,
|
||||
"referenceNumber": 43,
|
||||
"name": "PS/PDF font exception (2017-08-17)",
|
||||
"licenseExceptionId": "PS-or-PDF-font-exception-20170817",
|
||||
"seeAlso": [
|
||||
@ -693,7 +692,7 @@
|
||||
"reference": "https://spdx.org/licenses/QPL-1.0-INRIA-2004-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/QPL-1.0-INRIA-2004-exception.json",
|
||||
"referenceNumber": 24,
|
||||
"referenceNumber": 50,
|
||||
"name": "INRIA QPL 1.0 2004 variant exception",
|
||||
"licenseExceptionId": "QPL-1.0-INRIA-2004-exception",
|
||||
"seeAlso": [
|
||||
@ -705,7 +704,7 @@
|
||||
"reference": "https://spdx.org/licenses/Qt-GPL-exception-1.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Qt-GPL-exception-1.0.json",
|
||||
"referenceNumber": 20,
|
||||
"referenceNumber": 34,
|
||||
"name": "Qt GPL exception 1.0",
|
||||
"licenseExceptionId": "Qt-GPL-exception-1.0",
|
||||
"seeAlso": [
|
||||
@ -716,7 +715,7 @@
|
||||
"reference": "https://spdx.org/licenses/Qt-LGPL-exception-1.1.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Qt-LGPL-exception-1.1.json",
|
||||
"referenceNumber": 29,
|
||||
"referenceNumber": 39,
|
||||
"name": "Qt LGPL exception 1.1",
|
||||
"licenseExceptionId": "Qt-LGPL-exception-1.1",
|
||||
"seeAlso": [
|
||||
@ -727,7 +726,7 @@
|
||||
"reference": "https://spdx.org/licenses/Qwt-exception-1.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Qwt-exception-1.0.json",
|
||||
"referenceNumber": 10,
|
||||
"referenceNumber": 79,
|
||||
"name": "Qwt exception 1.0",
|
||||
"licenseExceptionId": "Qwt-exception-1.0",
|
||||
"seeAlso": [
|
||||
@ -738,7 +737,7 @@
|
||||
"reference": "https://spdx.org/licenses/romic-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/romic-exception.json",
|
||||
"referenceNumber": 79,
|
||||
"referenceNumber": 6,
|
||||
"name": "Romic Exception",
|
||||
"licenseExceptionId": "romic-exception",
|
||||
"seeAlso": [
|
||||
@ -754,7 +753,7 @@
|
||||
"reference": "https://spdx.org/licenses/RRDtool-FLOSS-exception-2.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/RRDtool-FLOSS-exception-2.0.json",
|
||||
"referenceNumber": 57,
|
||||
"referenceNumber": 7,
|
||||
"name": "RRDtool FLOSS exception 2.0",
|
||||
"licenseExceptionId": "RRDtool-FLOSS-exception-2.0",
|
||||
"seeAlso": [
|
||||
@ -766,7 +765,7 @@
|
||||
"reference": "https://spdx.org/licenses/SANE-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/SANE-exception.json",
|
||||
"referenceNumber": 8,
|
||||
"referenceNumber": 27,
|
||||
"name": "SANE Exception",
|
||||
"licenseExceptionId": "SANE-exception",
|
||||
"seeAlso": [
|
||||
@ -779,7 +778,7 @@
|
||||
"reference": "https://spdx.org/licenses/SHL-2.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/SHL-2.0.json",
|
||||
"referenceNumber": 17,
|
||||
"referenceNumber": 5,
|
||||
"name": "Solderpad Hardware License v2.0",
|
||||
"licenseExceptionId": "SHL-2.0",
|
||||
"seeAlso": [
|
||||
@ -790,7 +789,7 @@
|
||||
"reference": "https://spdx.org/licenses/SHL-2.1.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/SHL-2.1.json",
|
||||
"referenceNumber": 26,
|
||||
"referenceNumber": 1,
|
||||
"name": "Solderpad Hardware License v2.1",
|
||||
"licenseExceptionId": "SHL-2.1",
|
||||
"seeAlso": [
|
||||
@ -801,7 +800,7 @@
|
||||
"reference": "https://spdx.org/licenses/stunnel-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/stunnel-exception.json",
|
||||
"referenceNumber": 43,
|
||||
"referenceNumber": 49,
|
||||
"name": "stunnel Exception",
|
||||
"licenseExceptionId": "stunnel-exception",
|
||||
"seeAlso": [
|
||||
@ -812,7 +811,7 @@
|
||||
"reference": "https://spdx.org/licenses/SWI-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/SWI-exception.json",
|
||||
"referenceNumber": 73,
|
||||
"referenceNumber": 15,
|
||||
"name": "SWI exception",
|
||||
"licenseExceptionId": "SWI-exception",
|
||||
"seeAlso": [
|
||||
@ -823,7 +822,7 @@
|
||||
"reference": "https://spdx.org/licenses/Swift-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Swift-exception.json",
|
||||
"referenceNumber": 46,
|
||||
"referenceNumber": 52,
|
||||
"name": "Swift Exception",
|
||||
"licenseExceptionId": "Swift-exception",
|
||||
"seeAlso": [
|
||||
@ -835,7 +834,7 @@
|
||||
"reference": "https://spdx.org/licenses/Texinfo-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Texinfo-exception.json",
|
||||
"referenceNumber": 30,
|
||||
"referenceNumber": 60,
|
||||
"name": "Texinfo exception",
|
||||
"licenseExceptionId": "Texinfo-exception",
|
||||
"seeAlso": [
|
||||
@ -846,7 +845,7 @@
|
||||
"reference": "https://spdx.org/licenses/u-boot-exception-2.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/u-boot-exception-2.0.json",
|
||||
"referenceNumber": 5,
|
||||
"referenceNumber": 8,
|
||||
"name": "U-Boot exception 2.0",
|
||||
"licenseExceptionId": "u-boot-exception-2.0",
|
||||
"seeAlso": [
|
||||
@ -857,7 +856,7 @@
|
||||
"reference": "https://spdx.org/licenses/UBDL-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/UBDL-exception.json",
|
||||
"referenceNumber": 38,
|
||||
"referenceNumber": 75,
|
||||
"name": "Unmodified Binary Distribution exception",
|
||||
"licenseExceptionId": "UBDL-exception",
|
||||
"seeAlso": [
|
||||
@ -868,7 +867,7 @@
|
||||
"reference": "https://spdx.org/licenses/Universal-FOSS-exception-1.0.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/Universal-FOSS-exception-1.0.json",
|
||||
"referenceNumber": 58,
|
||||
"referenceNumber": 70,
|
||||
"name": "Universal FOSS Exception, Version 1.0",
|
||||
"licenseExceptionId": "Universal-FOSS-exception-1.0",
|
||||
"seeAlso": [
|
||||
@ -879,7 +878,7 @@
|
||||
"reference": "https://spdx.org/licenses/vsftpd-openssl-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/vsftpd-openssl-exception.json",
|
||||
"referenceNumber": 39,
|
||||
"referenceNumber": 55,
|
||||
"name": "vsftpd OpenSSL exception",
|
||||
"licenseExceptionId": "vsftpd-openssl-exception",
|
||||
"seeAlso": [
|
||||
@ -892,7 +891,7 @@
|
||||
"reference": "https://spdx.org/licenses/WxWindows-exception-3.1.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/WxWindows-exception-3.1.json",
|
||||
"referenceNumber": 12,
|
||||
"referenceNumber": 31,
|
||||
"name": "WxWindows Library Exception 3.1",
|
||||
"licenseExceptionId": "WxWindows-exception-3.1",
|
||||
"seeAlso": [
|
||||
@ -903,7 +902,7 @@
|
||||
"reference": "https://spdx.org/licenses/x11vnc-openssl-exception.html",
|
||||
"isDeprecatedLicenseId": false,
|
||||
"detailsUrl": "https://spdx.org/licenses/x11vnc-openssl-exception.json",
|
||||
"referenceNumber": 37,
|
||||
"referenceNumber": 57,
|
||||
"name": "x11vnc OpenSSL Exception",
|
||||
"licenseExceptionId": "x11vnc-openssl-exception",
|
||||
"seeAlso": [
|
||||
@ -911,5 +910,5 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"releaseDate": "2025-07-29T00:00:00Z"
|
||||
"releaseDate": "2025-07-01T00:00:00Z"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -5,12 +5,19 @@ require "options"
|
||||
|
||||
# Shared functions for classes which can be depended upon.
|
||||
module Dependable
|
||||
extend T::Helpers
|
||||
|
||||
# `:run` and `:linked` are no longer used but keep them here to avoid their
|
||||
# misuse in future.
|
||||
RESERVED_TAGS = [:build, :optional, :recommended, :run, :test, :linked, :implicit].freeze
|
||||
|
||||
attr_reader :tags
|
||||
|
||||
abstract!
|
||||
|
||||
sig { abstract.returns(T::Array[String]) }
|
||||
def option_names; end
|
||||
|
||||
def build?
|
||||
tags.include? :build
|
||||
end
|
||||
|
||||
@ -80,10 +80,10 @@ class DependencyCollector
|
||||
parse_spec(spec, Array(tags))
|
||||
end
|
||||
|
||||
sig { params(related_formula_names: T::Array[String]).returns(T.nilable(Dependency)) }
|
||||
sig { params(related_formula_names: T::Set[String]).returns(T.nilable(Dependency)) }
|
||||
def gcc_dep_if_needed(related_formula_names); end
|
||||
|
||||
sig { params(related_formula_names: T::Array[String]).returns(T.nilable(Dependency)) }
|
||||
sig { params(related_formula_names: T::Set[String]).returns(T.nilable(Dependency)) }
|
||||
def glibc_dep_if_needed(related_formula_names); end
|
||||
|
||||
def git_dep_if_needed(tags)
|
||||
@ -169,7 +169,7 @@ class DependencyCollector
|
||||
when :maximum_macos then MacOSRequirement.new(tags, comparator: "<=")
|
||||
when :xcode then XcodeRequirement.new(tags)
|
||||
else
|
||||
raise ArgumentError, "Unsupported special dependency #{spec.inspect}"
|
||||
raise ArgumentError, "Unsupported special dependency: #{spec.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -27,6 +27,8 @@ module DeprecateDisable
|
||||
no_longer_available: "is no longer available upstream",
|
||||
no_longer_meets_criteria: "no longer meets the criteria for acceptable casks",
|
||||
unmaintained: "is not maintained upstream",
|
||||
fails_gatekeeper_check: "does not pass the macOS Gatekeeper check",
|
||||
# odeprecate: remove the unsigned reason in a future release
|
||||
unsigned: "is unsigned or does not meet signature requirements",
|
||||
}.freeze, T::Hash[Symbol, String])
|
||||
|
||||
@ -67,6 +69,9 @@ module DeprecateDisable
|
||||
formula_or_cask.disable_reason
|
||||
end
|
||||
|
||||
# odeprecate: remove this remapping in a future release
|
||||
reason = :fails_gatekeeper_check if reason == :unsigned
|
||||
|
||||
reason = if formula_or_cask.is_a?(Formula) && FORMULA_DEPRECATE_DISABLE_REASONS.key?(reason)
|
||||
FORMULA_DEPRECATE_DISABLE_REASONS[reason]
|
||||
elsif formula_or_cask.is_a?(Cask::Cask) && CASK_DEPRECATE_DISABLE_REASONS.key?(reason)
|
||||
|
||||
@ -104,7 +104,7 @@ module Homebrew
|
||||
|
||||
sig { override.void }
|
||||
def run
|
||||
odeprecated "brew audit --token-conflicts" if args.token_conflicts?
|
||||
odeprecated "`brew audit --token-conflicts`" if args.token_conflicts?
|
||||
|
||||
Formulary.enable_factory_cache!
|
||||
|
||||
@ -142,7 +142,7 @@ module Homebrew
|
||||
|
||||
unless eval_all
|
||||
# This odisabled should probably stick around indefinitely.
|
||||
odisabled "brew audit",
|
||||
odisabled "`brew audit`",
|
||||
"`brew audit --eval-all` or set `HOMEBREW_EVAL_ALL=1`"
|
||||
end
|
||||
no_named_args = true
|
||||
@ -154,8 +154,8 @@ module Homebrew
|
||||
if args.named.any? { |named_arg| named_arg.end_with?(".rb") }
|
||||
# This odisabled should probably stick around indefinitely,
|
||||
# until at least we have a way to exclude error on these in the CLI parser.
|
||||
odisabled "brew audit [path ...]",
|
||||
"brew audit [name ...]"
|
||||
odisabled "`brew audit [path ...]`",
|
||||
"`brew audit [name ...]`"
|
||||
end
|
||||
|
||||
args.named.to_formulae_and_casks_with_taps
|
||||
|
||||
@ -539,8 +539,9 @@ module Homebrew
|
||||
|
||||
ohai "Detecting if #{local_filename} is relocatable..." if bottle_path.size > 1 * 1024 * 1024
|
||||
|
||||
prefix_check = if prefix == HOMEBREW_DEFAULT_PREFIX
|
||||
File.join(prefix, "opt")
|
||||
is_usr_local_prefix = prefix == "/usr/local"
|
||||
prefix_check = if is_usr_local_prefix
|
||||
"#{prefix}/opt"
|
||||
else
|
||||
prefix
|
||||
end
|
||||
@ -568,11 +569,17 @@ module Homebrew
|
||||
relocatable = false if keg_contain?(prefix_check, keg, ignores, formula_and_runtime_deps_names)
|
||||
relocatable = false if keg_contain?(cellar, keg, ignores, formula_and_runtime_deps_names)
|
||||
relocatable = false if keg_contain?(HOMEBREW_LIBRARY.to_s, keg, ignores, formula_and_runtime_deps_names)
|
||||
if prefix != prefix_check
|
||||
if is_usr_local_prefix
|
||||
relocatable = false if keg_contain_absolute_symlink_starting_with?(prefix, keg)
|
||||
relocatable = false if keg_contain?("#{prefix}/etc", keg, ignores)
|
||||
relocatable = false if keg_contain?("#{prefix}/var", keg, ignores)
|
||||
relocatable = false if keg_contain?("#{prefix}/share/vim", keg, ignores)
|
||||
if tap.disabled_new_usr_local_relocation_formulae.exclude?(formula.name)
|
||||
keg.new_usr_local_replacement_pairs.each_value do |value|
|
||||
relocatable = false if keg_contain?(value.fetch(:old), keg, ignores)
|
||||
end
|
||||
else
|
||||
relocatable = false if keg_contain?("#{prefix}/etc", keg, ignores)
|
||||
relocatable = false if keg_contain?("#{prefix}/var", keg, ignores)
|
||||
relocatable = false if keg_contain?("#{prefix}/share/vim", keg, ignores)
|
||||
end
|
||||
end
|
||||
skip_relocation = relocatable && !keg.require_relocation?
|
||||
end
|
||||
|
||||
@ -273,6 +273,8 @@ module Homebrew
|
||||
end
|
||||
languages.each do |language|
|
||||
new_cask = Cask::CaskLoader.load(tmp_contents)
|
||||
next unless new_cask.url
|
||||
|
||||
new_cask.config = if language.blank?
|
||||
tmp_cask.config
|
||||
else
|
||||
|
||||
@ -110,7 +110,7 @@ module Homebrew
|
||||
|
||||
raise TapUnavailableError, "#{tap_match[:user]}/#{tap_match[:repo]}"
|
||||
elsif cask || core_cask_path?(path)
|
||||
if !CoreCaskTap.instance.installed? && Homebrew::API::Cask.all_casks.key?(name)
|
||||
if !CoreCaskTap.instance.installed? && Homebrew::API.cask_tokens.include?(name)
|
||||
command = "brew tap --force #{CoreCaskTap.instance.name}"
|
||||
action = "tap #{CoreCaskTap.instance.name}"
|
||||
else
|
||||
@ -119,7 +119,7 @@ module Homebrew
|
||||
end
|
||||
elsif core_formula_path?(path) &&
|
||||
!CoreTap.instance.installed? &&
|
||||
Homebrew::API::Formula.all_formulae.key?(name)
|
||||
Homebrew::API.formula_names.include?(name)
|
||||
command = "brew tap --force #{CoreTap.instance.name}"
|
||||
action = "tap #{CoreTap.instance.name}"
|
||||
else
|
||||
|
||||
@ -379,6 +379,7 @@ module Homebrew
|
||||
when /^13\.?/ then "macOS Ventura (13)"
|
||||
when /^14\.?/ then "macOS Sonoma (14)"
|
||||
when /^15\.?/ then "macOS Sequoia (15)"
|
||||
when /^26\.?/ then "macOS Tahoe (26)"
|
||||
when /Ubuntu(-Server)? (14|16|18|20|22)\.04/ then "Ubuntu #{Regexp.last_match(2)}.04 LTS"
|
||||
when /Ubuntu(-Server)? (\d+\.\d+).\d ?(LTS)?/
|
||||
"Ubuntu #{Regexp.last_match(2)} #{Regexp.last_match(3)}".strip
|
||||
|
||||
@ -71,11 +71,24 @@ module Homebrew
|
||||
File.write("_data/cask_canonical.json", "#{canonical_json}\n") unless args.dry_run?
|
||||
|
||||
OnSystem::VALID_OS_ARCH_TAGS.each do |bottle_tag|
|
||||
variation_casks = all_casks.map do |_, cask|
|
||||
Homebrew::API.merge_variations(cask, bottle_tag:)
|
||||
renames = {}
|
||||
variation_casks = all_casks.to_h do |token, cask|
|
||||
cask = Homebrew::API.merge_variations(cask, bottle_tag:)
|
||||
|
||||
cask["old_tokens"]&.each do |old_token|
|
||||
renames[old_token] = token
|
||||
end
|
||||
|
||||
[token, cask]
|
||||
end
|
||||
|
||||
File.write("api/internal/cask.#{bottle_tag}.json", JSON.generate(variation_casks)) unless args.dry_run?
|
||||
json_contents = {
|
||||
casks: variation_casks,
|
||||
renames: renames,
|
||||
tap_migrations: CoreCaskTap.instance.tap_migrations,
|
||||
}
|
||||
|
||||
File.write("api/internal/cask.#{bottle_tag}.json", JSON.generate(json_contents)) unless args.dry_run?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -57,15 +57,15 @@ module Homebrew
|
||||
syntax_only = args.syntax_only?
|
||||
|
||||
repository = ENV.fetch("GITHUB_REPOSITORY", nil)
|
||||
raise UsageError, "The GITHUB_REPOSITORY environment variable must be set." if repository.blank?
|
||||
raise UsageError, "The `$GITHUB_REPOSITORY` environment variable must be set." if repository.blank?
|
||||
|
||||
tap = T.let(Tap.fetch(repository), Tap)
|
||||
|
||||
unless syntax_only
|
||||
raise UsageError, "Either `--cask` or `--url` must be specified." if !args.casks? && !args.url?
|
||||
raise UsageError, "Please provide a cask or url argument" if casks.blank? && pr_url.blank?
|
||||
raise UsageError, "Please provide a `--cask` or `--url` argument." if casks.blank? && pr_url.blank?
|
||||
end
|
||||
raise UsageError, "Only one url can be specified" if pr_url&.count&.> 1
|
||||
raise UsageError, "Only one `--url` can be specified." if pr_url&.count&.> 1
|
||||
|
||||
labels = if pr_url && (first_pr_url = pr_url.first)
|
||||
pr = GitHub::API.open_rest(first_pr_url)
|
||||
|
||||
@ -69,9 +69,19 @@ module Homebrew
|
||||
File.write("_data/formula_canonical.json", "#{canonical_json}\n") unless args.dry_run?
|
||||
|
||||
OnSystem::VALID_OS_ARCH_TAGS.each do |bottle_tag|
|
||||
aliases = {}
|
||||
renames = {}
|
||||
variation_formulae = all_formulae.to_h do |name, formula|
|
||||
formula = Homebrew::API.merge_variations(formula, bottle_tag:)
|
||||
|
||||
formula["aliases"]&.each do |alias_name|
|
||||
aliases[alias_name] = name
|
||||
end
|
||||
|
||||
formula["oldnames"]&.each do |oldname|
|
||||
renames[oldname] = name
|
||||
end
|
||||
|
||||
version = Version.new(formula.dig("versions", "stable"))
|
||||
pkg_version = PkgVersion.new(version, formula["revision"])
|
||||
rebuild = formula.dig("bottle", "stable", "rebuild") || 0
|
||||
@ -87,9 +97,14 @@ module Homebrew
|
||||
[name, [pkg_version.to_s, rebuild, sha256]]
|
||||
end
|
||||
|
||||
unless args.dry_run?
|
||||
File.write("api/internal/formula.#{bottle_tag}.json", JSON.generate(variation_formulae))
|
||||
end
|
||||
json_contents = {
|
||||
formulae: variation_formulae,
|
||||
aliases: aliases,
|
||||
renames: renames,
|
||||
tap_migrations: CoreTap.instance.tap_migrations,
|
||||
}
|
||||
|
||||
File.write("api/internal/formula.#{bottle_tag}.json", JSON.generate(json_contents)) unless args.dry_run?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -1000,12 +1000,12 @@ module Homebrew
|
||||
|
||||
locale_variables = ENV.keys.grep(/^(?:LC_\S+|LANG|LANGUAGE)\Z/).sort
|
||||
|
||||
add_info "Cask Environment Variables:", ((locale_variables + environment_variables).sort.each do |var|
|
||||
add_info "Cask Environment Variables:", (locale_variables + environment_variables).sort.each do |var|
|
||||
next unless ENV.key?(var)
|
||||
|
||||
var = %Q(#{var}="#{ENV.fetch(var)}")
|
||||
user_tilde(var)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
def check_cask_xattr
|
||||
@ -1040,21 +1040,6 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
def check_cask_quarantine_support
|
||||
case Cask::Quarantine.check_quarantine_support
|
||||
when :quarantine_available
|
||||
nil
|
||||
when :xattr_broken
|
||||
"No Cask quarantine support available: there's no working version of `xattr` on this system."
|
||||
when :no_swift
|
||||
"No Cask quarantine support available: there's no available version of `swift` on this system."
|
||||
when :linux
|
||||
"No Cask quarantine support available: not available on Linux."
|
||||
else
|
||||
"No Cask quarantine support available: unknown reason."
|
||||
end
|
||||
end
|
||||
|
||||
def non_core_taps
|
||||
@non_core_taps ||= Tap.installed.reject(&:core_tap?).reject(&:core_cask_tap?)
|
||||
end
|
||||
@ -1124,6 +1109,13 @@ module Homebrew
|
||||
def current_user
|
||||
ENV.fetch("USER", "$(whoami)")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(T::Array[Pathname]) }
|
||||
def paths
|
||||
@paths ||= T.let(ORIGINAL_PATHS.uniq.map(&:to_s), T.nilable(T::Array[Pathname]))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -148,6 +148,11 @@ class AbstractDownloadStrategy
|
||||
cached_location.basename
|
||||
end
|
||||
|
||||
sig { override.params(title: T.any(String, Exception), sput: T.anything).void }
|
||||
def ohai(title, *sput)
|
||||
super unless quiet?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
sig { params(args: T.anything).void }
|
||||
@ -155,11 +160,6 @@ class AbstractDownloadStrategy
|
||||
super unless quiet?
|
||||
end
|
||||
|
||||
sig { params(args: T.anything).void }
|
||||
def ohai(*args)
|
||||
super unless quiet?
|
||||
end
|
||||
|
||||
sig { params(args: String, options: T.untyped).returns(SystemCommand::Result) }
|
||||
def silent_command(*args, **options)
|
||||
system_command(*args, print_stderr: false, env:, **options)
|
||||
@ -1106,20 +1106,25 @@ class GitDownloadStrategy < VCSDownloadStrategy
|
||||
# Convert any shallow clone to full clone
|
||||
if shallow_dir?
|
||||
command! "git",
|
||||
args: ["fetch", "origin", "--unshallow"],
|
||||
chdir: cached_location,
|
||||
timeout: Utils::Timer.remaining(timeout)
|
||||
args: ["fetch", "origin", "--unshallow"],
|
||||
chdir: cached_location,
|
||||
timeout: Utils::Timer.remaining(timeout),
|
||||
reset_uid: true
|
||||
else
|
||||
command! "git",
|
||||
args: ["fetch", "origin"],
|
||||
chdir: cached_location,
|
||||
timeout: Utils::Timer.remaining(timeout)
|
||||
args: ["fetch", "origin"],
|
||||
chdir: cached_location,
|
||||
timeout: Utils::Timer.remaining(timeout),
|
||||
reset_uid: true
|
||||
end
|
||||
end
|
||||
|
||||
sig { override.params(timeout: T.nilable(Time)).void }
|
||||
def clone_repo(timeout: nil)
|
||||
command! "git", args: clone_args, timeout: Utils::Timer.remaining(timeout)
|
||||
command! "git",
|
||||
args: clone_args,
|
||||
timeout: Utils::Timer.remaining(timeout),
|
||||
reset_uid: true
|
||||
|
||||
command! "git",
|
||||
args: ["config", "homebrew.cacheversion", cache_version],
|
||||
@ -1595,7 +1600,7 @@ class DownloadStrategyDetector
|
||||
detect_from_symbol(using)
|
||||
else
|
||||
raise TypeError,
|
||||
"Unknown download strategy specification #{using.inspect}"
|
||||
"Unknown download strategy specification: #{using.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ module Downloadable
|
||||
@download_name = T.let(nil, T.nilable(String))
|
||||
end
|
||||
|
||||
sig { params(other: Object).void }
|
||||
sig { overridable.params(other: Downloadable).void }
|
||||
def initialize_dup(other)
|
||||
super
|
||||
@checksum = @checksum.dup
|
||||
@ -132,6 +132,26 @@ module Downloadable
|
||||
EOS
|
||||
end
|
||||
|
||||
sig { returns(Integer) }
|
||||
def hash
|
||||
[self.class, cached_download].hash
|
||||
end
|
||||
|
||||
sig { params(other: Object).returns(T::Boolean) }
|
||||
def eql?(other)
|
||||
return false if self.class != other.class
|
||||
|
||||
other = T.cast(other, Downloadable)
|
||||
cached_download == other.cached_download
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def to_s
|
||||
short_cached_download = cached_download.to_s
|
||||
.delete_prefix("#{HOMEBREW_CACHE}/downloads/")
|
||||
"#<#{self.class}: #{short_cached_download}>"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
sig { overridable.returns(String) }
|
||||
|
||||
@ -241,9 +241,10 @@ module Homebrew
|
||||
boolean: true,
|
||||
},
|
||||
HOMEBREW_FORBID_PACKAGES_FROM_PATHS: {
|
||||
description: "If set, Homebrew will refuse to read formulae or casks provided from file paths, " \
|
||||
"e.g. `brew install ./package.rb`.",
|
||||
boolean: true,
|
||||
description: "If set, Homebrew will refuse to read formulae or casks provided from file paths, " \
|
||||
"e.g. `brew install ./package.rb`.",
|
||||
boolean: true,
|
||||
default_text: "true unless `$HOMEBREW_DEVELOPER` is set.",
|
||||
},
|
||||
HOMEBREW_FORCE_API_AUTO_UPDATE: {
|
||||
description: "If set, update the Homebrew API formula or cask data even if " \
|
||||
@ -560,6 +561,7 @@ module Homebrew
|
||||
:HOMEBREW_MAKE_JOBS,
|
||||
:HOMEBREW_NO_FORCE_BREW_WRAPPER,
|
||||
:HOMEBREW_CASK_OPTS,
|
||||
:HOMEBREW_FORBID_PACKAGES_FROM_PATHS,
|
||||
]).freeze, T::Set[Symbol])
|
||||
|
||||
FALSY_VALUES = T.let(%w[false no off nil 0].freeze, T::Array[String])
|
||||
@ -660,6 +662,18 @@ module Homebrew
|
||||
cask_opts.include?("--require-sha")
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def forbid_packages_from_paths?
|
||||
# Undocumented opt-out for internal use.
|
||||
return false if ENV["HOMEBREW_INTERNAL_ALLOW_PACKAGES_FROM_PATHS"].present?
|
||||
|
||||
return true if ENV["HOMEBREW_FORBID_PACKAGES_FROM_PATHS"].present?
|
||||
|
||||
# Provide an opt-out for tests and developers.
|
||||
# Our testing framework installs formulae from file paths all over the place.
|
||||
ENV["HOMEBREW_TESTS"].blank? && ENV["HOMEBREW_DEVELOPER"].blank?
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def automatically_set_no_install_from_api?
|
||||
ENV["HOMEBREW_AUTOMATICALLY_SET_NO_INSTALL_FROM_API"].present?
|
||||
@ -683,5 +697,10 @@ module Homebrew
|
||||
|
||||
[concurrency, 1].max
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def use_internal_api?
|
||||
ENV["HOMEBREW_USE_INTERNAL_API"].present?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -267,7 +267,7 @@ module SharedEnvExtension
|
||||
ohai "Using a Fortran compiler found at #{gfortran}"
|
||||
end
|
||||
if gfortran
|
||||
puts "This may be changed by setting the FC environment variable."
|
||||
puts "This may be changed by setting the `$FC` environment variable."
|
||||
self["FC"] = self["F77"] = gfortran
|
||||
flags = FC_FLAG_VARS
|
||||
end
|
||||
|
||||
@ -44,11 +44,13 @@ module Kernel
|
||||
Formatter.headline(title, color: :blue)
|
||||
end
|
||||
|
||||
sig { params(title: T.any(String, Exception), sput: T.anything).void }
|
||||
def ohai(title, *sput)
|
||||
puts ohai_title(title.to_s)
|
||||
puts sput
|
||||
end
|
||||
|
||||
sig { params(title: T.any(String, Exception), sput: T.anything, always_display: T::Boolean).void }
|
||||
def odebug(title, *sput, always_display: false)
|
||||
debug = if respond_to?(:debug)
|
||||
T.unsafe(self).debug?
|
||||
@ -355,19 +357,6 @@ module Kernel
|
||||
nil
|
||||
end
|
||||
|
||||
def which_all(cmd, path = ENV.fetch("PATH"))
|
||||
PATH.new(path).filter_map do |p|
|
||||
begin
|
||||
pcmd = File.expand_path(cmd, p)
|
||||
rescue ArgumentError
|
||||
# File.expand_path will raise an ArgumentError if the path is malformed.
|
||||
# See https://github.com/Homebrew/legacy-homebrew/issues/32789
|
||||
next
|
||||
end
|
||||
Pathname.new(pcmd) if File.file?(pcmd) && File.executable?(pcmd)
|
||||
end.uniq
|
||||
end
|
||||
|
||||
def which_editor(silent: false)
|
||||
editor = Homebrew::EnvConfig.editor
|
||||
return editor if editor
|
||||
@ -458,11 +447,6 @@ module Kernel
|
||||
Formula[formula_name].ensure_installed!(reason:, latest:).opt_bin/name
|
||||
end
|
||||
|
||||
sig { returns(T::Array[Pathname]) }
|
||||
def paths
|
||||
@paths ||= T.let(ORIGINAL_PATHS.uniq.map(&:to_s), T.nilable(T::Array[Pathname]))
|
||||
end
|
||||
|
||||
sig { params(size_in_bytes: T.any(Integer, Float)).returns(String) }
|
||||
def disk_usage_readable(size_in_bytes)
|
||||
if size_in_bytes.abs >= 1_073_741_824
|
||||
|
||||
@ -10,9 +10,6 @@ module OS
|
||||
|
||||
requires_ancestor { ::Cask::Quarantine }
|
||||
|
||||
sig { returns(Symbol) }
|
||||
def check_quarantine_support = :linux
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def available? = false
|
||||
end
|
||||
|
||||
@ -10,6 +10,7 @@ require "os/linux/kernel"
|
||||
module OS
|
||||
module Linux
|
||||
module Diagnostic
|
||||
# Linux-specific diagnostic checks for Homebrew.
|
||||
module Checks
|
||||
extend T::Helpers
|
||||
|
||||
@ -28,6 +29,7 @@ module OS
|
||||
check_glibc_minimum_version
|
||||
check_kernel_minimum_version
|
||||
check_supported_architecture
|
||||
check_for_symlinked_home
|
||||
].freeze
|
||||
end
|
||||
|
||||
@ -154,6 +156,27 @@ module OS
|
||||
EOS
|
||||
end
|
||||
|
||||
def check_for_symlinked_home
|
||||
return unless File.symlink?("/home")
|
||||
|
||||
<<~EOS
|
||||
Your /home directory is a symlink.
|
||||
This is known to cause issues with formula linking, particularly when installing
|
||||
multiple formulae that create symlinks in shared directories.
|
||||
|
||||
While this may be a standard directory structure in some distributions
|
||||
(e.g. Fedora Silverblue) there are known issues as-is.
|
||||
|
||||
If you encounter linking issues, you may need to manually create conflicting
|
||||
directories or use `brew link --overwrite` as a workaround.
|
||||
|
||||
We'd welcome a PR to fix this functionality.
|
||||
See https://github.com/Homebrew/brew/issues/18036 for more context.
|
||||
|
||||
#{support_tier_message(tier: 2)}
|
||||
EOS
|
||||
end
|
||||
|
||||
def check_gcc_dependent_linkage
|
||||
gcc_dependents = ::Formula.installed.select do |formula|
|
||||
next false unless formula.tap&.core_tap?
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:disable Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
module OS
|
||||
@ -30,6 +30,7 @@ module OS
|
||||
def add_global_deps_to_spec(spec)
|
||||
return unless ::DevelopmentTools.needs_build_formulae?
|
||||
|
||||
@global_deps ||= T.let(nil, T.nilable(T::Array[Dependency]))
|
||||
@global_deps ||= begin
|
||||
dependency_collector = spec.dependency_collector
|
||||
related_formula_names = Set.new([
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
require "compilers"
|
||||
|
||||
class Keg
|
||||
def relocate_dynamic_linkage(relocation)
|
||||
def relocate_dynamic_linkage(relocation, skip_protodesc_cold: false)
|
||||
# Patching the dynamic linker of glibc breaks it.
|
||||
return if name.match? Version.formula_optionally_versioned_regex(:glibc)
|
||||
|
||||
@ -12,14 +12,19 @@ class Keg
|
||||
|
||||
elf_files.each do |file|
|
||||
file.ensure_writable do
|
||||
change_rpath!(file, old_prefix, new_prefix)
|
||||
change_rpath!(file, old_prefix, new_prefix, skip_protodesc_cold:)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def change_rpath!(file, old_prefix, new_prefix)
|
||||
def change_rpath!(file, old_prefix, new_prefix, skip_protodesc_cold: false)
|
||||
return false if !file.elf? || !file.dynamic_elf?
|
||||
|
||||
# Skip relocation of files with `protodesc_cold` sections because patchelf.rb seems to break them,
|
||||
# but only when bottling (as we don't want to break existing bottles that require relocation).
|
||||
# https://github.com/Homebrew/homebrew-core/pull/232490#issuecomment-3161362452
|
||||
return false if skip_protodesc_cold && file.section_names.include?("protodesc_cold")
|
||||
|
||||
updated = {}
|
||||
old_rpath = file.rpath
|
||||
new_rpath = if old_rpath
|
||||
|
||||
@ -417,7 +417,7 @@ module OS
|
||||
macOS won't move relative symlinks across volumes unless the target file already
|
||||
exists. Formulae known to be affected by this are Git and Narwhal.
|
||||
|
||||
You should set the "HOMEBREW_TEMP" environment variable to a suitable
|
||||
You should set the `$HOMEBREW_TEMP` environment variable to a suitable
|
||||
directory on the same volume as your Cellar.
|
||||
|
||||
#{support_tier_message(tier: 2)}
|
||||
@ -506,6 +506,88 @@ module OS
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def check_pkgconf_macos_sdk_mismatch
|
||||
# We don't provide suitable bottles for these versions.
|
||||
return if OS::Mac.version.prerelease? || OS::Mac.version.outdated_release?
|
||||
|
||||
pkgconf = begin
|
||||
::Formula["pkgconf"]
|
||||
rescue FormulaUnavailableError
|
||||
nil
|
||||
end
|
||||
return unless pkgconf
|
||||
return unless pkgconf.any_version_installed?
|
||||
|
||||
tab = Tab.for_formula(pkgconf)
|
||||
return unless tab.built_on
|
||||
|
||||
built_on_version = tab.built_on["os_version"]
|
||||
&.delete_prefix("macOS ")
|
||||
&.sub(/\.\d+$/, "")
|
||||
return unless built_on_version
|
||||
|
||||
current_version = MacOS.version.to_s
|
||||
return if built_on_version == current_version
|
||||
|
||||
<<~EOS
|
||||
You have pkgconf installed that was built on macOS #{built_on_version}
|
||||
but you are running macOS #{current_version}.
|
||||
|
||||
This can cause issues with packages that depend on system libraries, such as libffi.
|
||||
To fix this issue, reinstall pkgconf:
|
||||
brew reinstall pkgconf
|
||||
|
||||
For more information, see: https://github.com/Homebrew/brew/issues/16137
|
||||
We'd welcome a PR to automatically mitigate this instead of just warning about it.
|
||||
EOS
|
||||
end
|
||||
|
||||
def check_cask_quarantine_support
|
||||
status, check_output = ::Cask::Quarantine.check_quarantine_support
|
||||
|
||||
case status
|
||||
when :quarantine_available
|
||||
nil
|
||||
when :xattr_broken
|
||||
"No Cask quarantine support available: there's no working version of `xattr` on this system."
|
||||
when :no_swift
|
||||
"No Cask quarantine support available: there's no available version of `swift` on this system."
|
||||
when :swift_broken_clt
|
||||
<<~EOS
|
||||
No Cask quarantine support available: Swift is not working due to missing Command Line Tools.
|
||||
#{MacOS::CLT.installation_then_reinstall_instructions}
|
||||
EOS
|
||||
when :swift_compilation_failed
|
||||
<<~EOS
|
||||
No Cask quarantine support available: Swift compilation failed.
|
||||
This is usually due to a broken or incompatible Command Line Tools installation.
|
||||
#{MacOS::CLT.installation_then_reinstall_instructions}
|
||||
EOS
|
||||
when :swift_runtime_error
|
||||
<<~EOS
|
||||
No Cask quarantine support available: Swift runtime error.
|
||||
Your Command Line Tools installation may be broken or incomplete.
|
||||
#{MacOS::CLT.installation_then_reinstall_instructions}
|
||||
EOS
|
||||
when :swift_not_executable
|
||||
<<~EOS
|
||||
No Cask quarantine support available: Swift is not executable.
|
||||
Your Command Line Tools installation may be incomplete.
|
||||
#{MacOS::CLT.installation_then_reinstall_instructions}
|
||||
EOS
|
||||
when :swift_unexpected_error
|
||||
<<~EOS
|
||||
No Cask quarantine support available: Swift returned an unexpected error:
|
||||
#{check_output}
|
||||
EOS
|
||||
else
|
||||
<<~EOS
|
||||
No Cask quarantine support available: unknown reason: #{status.inspect}:
|
||||
#{check_output}
|
||||
EOS
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -20,7 +20,7 @@ module OS
|
||||
end
|
||||
end
|
||||
|
||||
def relocate_dynamic_linkage(relocation)
|
||||
def relocate_dynamic_linkage(relocation, skip_protodesc_cold: false)
|
||||
mach_o_files.each do |file|
|
||||
file.ensure_writable do
|
||||
modified = T.let(false, T::Boolean)
|
||||
|
||||
@ -1 +1 @@
|
||||
3.12
|
||||
3.13
|
||||
|
||||
@ -1,73 +1,61 @@
|
||||
#
|
||||
# This file is autogenerated by pip-compile with Python 3.12
|
||||
# This file is autogenerated by pip-compile with Python 3.13
|
||||
# by the following command:
|
||||
#
|
||||
# pip-compile --allow-unsafe --generate-hashes --strip-extras requirements.in
|
||||
#
|
||||
certifi==2025.7.14 \
|
||||
--hash=sha256:6b31f564a415d79ee77df69d757bb49a5bb53bd9f756cbbe24394ffd6fc1f4b2 \
|
||||
--hash=sha256:8ea99dbdfaaf2ba2f9bac77b9249ef62ec5218e7c2b2e903378ed5fccf765995
|
||||
certifi==2025.8.3 \
|
||||
--hash=sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407 \
|
||||
--hash=sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5
|
||||
# via influxdb3-python
|
||||
influxdb3-python==0.14.0 \
|
||||
--hash=sha256:63318c1eb53e026d1d793ef00fef51510acd40dd80bd69b528bf05332757dc67 \
|
||||
--hash=sha256:f3c676112bf8a6230278a3e0940dd4cc2b57a868906a9de8e20cc9efd708a339
|
||||
influxdb3-python==0.15.0 \
|
||||
--hash=sha256:47b5ea57cf9a6d7b3fbc51ab6eb0122f1196207d6472d4ec93e3da0191b54b1c \
|
||||
--hash=sha256:ccbf22dfef32fe86464d258f94ed66631257b5f6f1624ae0969e23522ca27e3d
|
||||
# via -r requirements.in
|
||||
pyarrow==20.0.0 \
|
||||
--hash=sha256:00138f79ee1b5aca81e2bdedb91e3739b987245e11fa3c826f9e57c5d102fb75 \
|
||||
--hash=sha256:11529a2283cb1f6271d7c23e4a8f9f8b7fd173f7360776b668e509d712a02eec \
|
||||
--hash=sha256:15aa1b3b2587e74328a730457068dc6c89e6dcbf438d4369f572af9d320a25ee \
|
||||
--hash=sha256:1bcbe471ef3349be7714261dea28fe280db574f9d0f77eeccc195a2d161fd861 \
|
||||
--hash=sha256:204a846dca751428991346976b914d6d2a82ae5b8316a6ed99789ebf976551e6 \
|
||||
--hash=sha256:211d5e84cecc640c7a3ab900f930aaff5cd2702177e0d562d426fb7c4f737781 \
|
||||
--hash=sha256:24ca380585444cb2a31324c546a9a56abbe87e26069189e14bdba19c86c049f0 \
|
||||
--hash=sha256:2c3a01f313ffe27ac4126f4c2e5ea0f36a5fc6ab51f8726cf41fee4b256680bd \
|
||||
--hash=sha256:30b3051b7975801c1e1d387e17c588d8ab05ced9b1e14eec57915f79869b5031 \
|
||||
--hash=sha256:3346babb516f4b6fd790da99b98bed9708e3f02e734c84971faccb20736848dc \
|
||||
--hash=sha256:3e1f8a47f4b4ae4c69c4d702cfbdfe4d41e18e5c7ef6f1bb1c50918c1e81c57b \
|
||||
--hash=sha256:4250e28a22302ce8692d3a0e8ec9d9dde54ec00d237cff4dfa9c1fbf79e472a8 \
|
||||
--hash=sha256:4680f01ecd86e0dd63e39eb5cd59ef9ff24a9d166db328679e36c108dc993d4c \
|
||||
--hash=sha256:4a8b029a07956b8d7bd742ffca25374dd3f634b35e46cc7a7c3fa4c75b297191 \
|
||||
--hash=sha256:4ba3cf4182828be7a896cbd232aa8dd6a31bd1f9e32776cc3796c012855e1199 \
|
||||
--hash=sha256:5605919fbe67a7948c1f03b9f3727d82846c053cd2ce9303ace791855923fd20 \
|
||||
--hash=sha256:5f0fb1041267e9968c6d0d2ce3ff92e3928b243e2b6d11eeb84d9ac547308232 \
|
||||
--hash=sha256:6102b4864d77102dbbb72965618e204e550135a940c2534711d5ffa787df2a5a \
|
||||
--hash=sha256:6415a0d0174487456ddc9beaead703d0ded5966129fa4fd3114d76b5d1c5ceae \
|
||||
--hash=sha256:6bb830757103a6cb300a04610e08d9636f0cd223d32f388418ea893a3e655f1c \
|
||||
--hash=sha256:6fc1499ed3b4b57ee4e090e1cea6eb3584793fe3d1b4297bbf53f09b434991a5 \
|
||||
--hash=sha256:75a51a5b0eef32727a247707d4755322cb970be7e935172b6a3a9f9ae98404ba \
|
||||
--hash=sha256:7a3a5dcf54286e6141d5114522cf31dd67a9e7c9133d150799f30ee302a7a1ab \
|
||||
--hash=sha256:7f4c8534e2ff059765647aa69b75d6543f9fef59e2cd4c6d18015192565d2b70 \
|
||||
--hash=sha256:82f1ee5133bd8f49d31be1299dc07f585136679666b502540db854968576faf9 \
|
||||
--hash=sha256:851c6a8260ad387caf82d2bbf54759130534723e37083111d4ed481cb253cc0d \
|
||||
--hash=sha256:89e030dc58fc760e4010148e6ff164d2f44441490280ef1e97a542375e41058e \
|
||||
--hash=sha256:95b330059ddfdc591a3225f2d272123be26c8fa76e8c9ee1a77aad507361cfdb \
|
||||
--hash=sha256:96d6a0a37d9c98be08f5ed6a10831d88d52cac7b13f5287f1e0f625a0de8062b \
|
||||
--hash=sha256:96e37f0766ecb4514a899d9a3554fadda770fb57ddf42b63d80f14bc20aa7db3 \
|
||||
--hash=sha256:97c8dc984ed09cb07d618d57d8d4b67a5100a30c3818c2fb0b04599f0da2de7b \
|
||||
--hash=sha256:991f85b48a8a5e839b2128590ce07611fae48a904cae6cab1f089c5955b57eb5 \
|
||||
--hash=sha256:9965a050048ab02409fb7cbbefeedba04d3d67f2cc899eff505cc084345959ca \
|
||||
--hash=sha256:9b71daf534f4745818f96c214dbc1e6124d7daf059167330b610fc69b6f3d3e3 \
|
||||
--hash=sha256:a15532e77b94c61efadde86d10957950392999503b3616b2ffcef7621a002893 \
|
||||
--hash=sha256:a18a14baef7d7ae49247e75641fd8bcbb39f44ed49a9fc4ec2f65d5031aa3b96 \
|
||||
--hash=sha256:a1f60dc14658efaa927f8214734f6a01a806d7690be4b3232ba526836d216122 \
|
||||
--hash=sha256:a2791f69ad72addd33510fec7bb14ee06c2a448e06b649e264c094c5b5f7ce28 \
|
||||
--hash=sha256:a5704f29a74b81673d266e5ec1fe376f060627c2e42c5c7651288ed4b0db29e9 \
|
||||
--hash=sha256:a6ad3e7758ecf559900261a4df985662df54fb7fdb55e8e3b3aa99b23d526b62 \
|
||||
--hash=sha256:aa0d288143a8585806e3cc7c39566407aab646fb9ece164609dac1cfff45f6ae \
|
||||
--hash=sha256:b6953f0114f8d6f3d905d98e987d0924dabce59c3cda380bdfaa25a6201563b4 \
|
||||
--hash=sha256:b8ff87cc837601532cc8242d2f7e09b4e02404de1b797aee747dd4ba4bd6313f \
|
||||
--hash=sha256:c7dd06fd7d7b410ca5dc839cc9d485d2bc4ae5240851bcd45d85105cc90a47d7 \
|
||||
--hash=sha256:ca151afa4f9b7bc45bcc791eb9a89e90a9eb2772767d0b1e5389609c7d03db63 \
|
||||
--hash=sha256:cb497649e505dc36542d0e68eca1a3c94ecbe9799cb67b578b55f2441a247fbc \
|
||||
--hash=sha256:d5382de8dc34c943249b01c19110783d0d64b207167c728461add1ecc2db88e4 \
|
||||
--hash=sha256:db53390eaf8a4dab4dbd6d93c85c5cf002db24902dbff0ca7d988beb5c9dd15b \
|
||||
--hash=sha256:dd43f58037443af715f34f1322c782ec463a3c8a94a85fdb2d987ceb5658e061 \
|
||||
--hash=sha256:e22f80b97a271f0a7d9cd07394a7d348f80d3ac63ed7cc38b6d1b696ab3b2619 \
|
||||
--hash=sha256:e724a3fd23ae5b9c010e7be857f4405ed5e679db5c93e66204db1a69f733936a \
|
||||
--hash=sha256:e8b88758f9303fa5a83d6c90e176714b2fd3852e776fc2d7e42a22dd6c2fb368 \
|
||||
--hash=sha256:f2d67ac28f57a362f1a2c1e6fa98bfe2f03230f7e15927aecd067433b1e70ce8 \
|
||||
--hash=sha256:f3b117b922af5e4c6b9a9115825726cac7d8b1421c37c2b5e24fbacc8930612c \
|
||||
--hash=sha256:febc4a913592573c8d5805091a6c2b5064c8bd6e002131f01061797d91c783c1
|
||||
pyarrow==21.0.0 \
|
||||
--hash=sha256:067c66ca29aaedae08218569a114e413b26e742171f526e828e1064fcdec13f4 \
|
||||
--hash=sha256:072116f65604b822a7f22945a7a6e581cfa28e3454fdcc6939d4ff6090126623 \
|
||||
--hash=sha256:0c4e75d13eb76295a49e0ea056eb18dbd87d81450bfeb8afa19a7e5a75ae2ad7 \
|
||||
--hash=sha256:186aa00bca62139f75b7de8420f745f2af12941595bbbfa7ed3870ff63e25636 \
|
||||
--hash=sha256:1e005378c4a2c6db3ada3ad4c217b381f6c886f0a80d6a316fe586b90f77efd7 \
|
||||
--hash=sha256:203003786c9fd253ebcafa44b03c06983c9c8d06c3145e37f1b76a1f317aeae1 \
|
||||
--hash=sha256:222c39e2c70113543982c6b34f3077962b44fca38c0bd9e68bb6781534425c10 \
|
||||
--hash=sha256:26bfd95f6bff443ceae63c65dc7e048670b7e98bc892210acba7e4995d3d4b51 \
|
||||
--hash=sha256:3a302f0e0963db37e0a24a70c56cf91a4faa0bca51c23812279ca2e23481fccd \
|
||||
--hash=sha256:3a81486adc665c7eb1a2bde0224cfca6ceaba344a82a971ef059678417880eb8 \
|
||||
--hash=sha256:3b4d97e297741796fead24867a8dabf86c87e4584ccc03167e4a811f50fdf74d \
|
||||
--hash=sha256:40ebfcb54a4f11bcde86bc586cbd0272bac0d516cfa539c799c2453768477569 \
|
||||
--hash=sha256:479ee41399fcddc46159a551705b89c05f11e8b8cb8e968f7fec64f62d91985e \
|
||||
--hash=sha256:5051f2dccf0e283ff56335760cbc8622cf52264d67e359d5569541ac11b6d5bc \
|
||||
--hash=sha256:555ca6935b2cbca2c0e932bedd853e9bc523098c39636de9ad4693b5b1df86d6 \
|
||||
--hash=sha256:585e7224f21124dd57836b1530ac8f2df2afc43c861d7bf3d58a4870c42ae36c \
|
||||
--hash=sha256:58c30a1729f82d201627c173d91bd431db88ea74dcaa3885855bc6203e433b82 \
|
||||
--hash=sha256:6299449adf89df38537837487a4f8d3bd91ec94354fdd2a7d30bc11c48ef6e79 \
|
||||
--hash=sha256:65f8e85f79031449ec8706b74504a316805217b35b6099155dd7e227eef0d4b6 \
|
||||
--hash=sha256:689f448066781856237eca8d1975b98cace19b8dd2ab6145bf49475478bcaa10 \
|
||||
--hash=sha256:69cbbdf0631396e9925e048cfa5bce4e8c3d3b41562bbd70c685a8eb53a91e61 \
|
||||
--hash=sha256:731c7022587006b755d0bdb27626a1a3bb004bb56b11fb30d98b6c1b4718579d \
|
||||
--hash=sha256:7be45519b830f7c24b21d630a31d48bcebfd5d4d7f9d3bdb49da9cdf6d764edb \
|
||||
--hash=sha256:898afce396b80fdda05e3086b4256f8677c671f7b1d27a6976fa011d3fd0a86e \
|
||||
--hash=sha256:8d58d8497814274d3d20214fbb24abcad2f7e351474357d552a8d53bce70c70e \
|
||||
--hash=sha256:9b0b14b49ac10654332a805aedfc0147fb3469cbf8ea951b3d040dab12372594 \
|
||||
--hash=sha256:9d9f8bcb4c3be7738add259738abdeddc363de1b80e3310e04067aa1ca596634 \
|
||||
--hash=sha256:a7a102574faa3f421141a64c10216e078df467ab9576684d5cd696952546e2da \
|
||||
--hash=sha256:a7f6524e3747e35f80744537c78e7302cd41deee8baa668d56d55f77d9c464b3 \
|
||||
--hash=sha256:b6b27cf01e243871390474a211a7922bfbe3bda21e39bc9160daf0da3fe48876 \
|
||||
--hash=sha256:b7ae0bbdc8c6674259b25bef5d2a1d6af5d39d7200c819cf99e07f7dfef1c51e \
|
||||
--hash=sha256:bd04ec08f7f8bd113c55868bd3fc442a9db67c27af098c5f814a3091e71cc61a \
|
||||
--hash=sha256:c077f48aab61738c237802836fc3844f85409a46015635198761b0d6a688f87b \
|
||||
--hash=sha256:cdc4c17afda4dab2a9c0b79148a43a7f4e1094916b3e18d8975bfd6d6d52241f \
|
||||
--hash=sha256:cf56ec8b0a5c8c9d7021d6fd754e688104f9ebebf1bf4449613c9531f5346a18 \
|
||||
--hash=sha256:d2fe8e7f3ce329a71b7ddd7498b3cfac0eeb200c2789bd840234f0dc271a8efe \
|
||||
--hash=sha256:dc56bc708f2d8ac71bd1dcb927e458c93cec10b98eb4120206a4091db7b67b99 \
|
||||
--hash=sha256:e563271e2c5ff4d4a4cbeb2c83d5cf0d4938b891518e676025f7268c6fe5fe26 \
|
||||
--hash=sha256:e72a8ec6b868e258a2cd2672d91f2860ad532d590ce94cdf7d5e7ec674ccf03d \
|
||||
--hash=sha256:e99310a4ebd4479bcd1964dff9e14af33746300cb014aa4a3781738ac63baf4a \
|
||||
--hash=sha256:f522e5709379d72fb3da7785aa489ff0bb87448a9dc5a75f45763a795a089ebd \
|
||||
--hash=sha256:fc0d2f88b81dcf3ccf9a6ae17f89183762c8a94a5bdcfa09e05cfe413acf0503 \
|
||||
--hash=sha256:fee33b0ca46f4c85443d6c450357101e47d53e6c3f008d658c27a2d020d44c79
|
||||
# via influxdb3-python
|
||||
python-dateutil==2.9.0.post0 \
|
||||
--hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \
|
||||
|
||||
@ -557,6 +557,12 @@ class Formula
|
||||
# @see .loaded_from_api?
|
||||
delegate loaded_from_api?: :"self.class"
|
||||
|
||||
# The API source data used to load this formula.
|
||||
# Returns `nil` if the formula was not loaded from the API.
|
||||
# @!method api_source
|
||||
# @see .api_source
|
||||
delegate api_source: :"self.class"
|
||||
|
||||
sig { void }
|
||||
def update_head_version
|
||||
return unless head?
|
||||
@ -1675,7 +1681,10 @@ class Formula
|
||||
# don't consider this keg current if there's a newer formula available
|
||||
next if follow_installed_alias? && new_formula_available?
|
||||
|
||||
# this keg is the current version of the formula, so it's not outdated
|
||||
# this keg is the current version of the formula, but only consider it current
|
||||
# if it's actually linked - an unlinked current version means we're outdated
|
||||
next if !keg.optlinked? && !keg.linked? && !pinned?
|
||||
|
||||
current_version = true
|
||||
break
|
||||
end
|
||||
@ -2625,9 +2634,8 @@ class Formula
|
||||
hash = to_hash
|
||||
|
||||
# Take from API, merging in local install status.
|
||||
if loaded_from_api? && !Homebrew::EnvConfig.no_install_from_api?
|
||||
json_formula = Homebrew::API::Formula.all_formulae.fetch(name).dup
|
||||
return json_formula.merge(
|
||||
if loaded_from_api? && (json_formula = api_source) && !Homebrew::EnvConfig.no_install_from_api?
|
||||
return json_formula.dup.merge(
|
||||
hash.slice("name", "installed", "linked_keg", "pinned", "outdated"),
|
||||
)
|
||||
end
|
||||
@ -3062,12 +3070,12 @@ class Formula
|
||||
|
||||
@exec_count ||= T.let(0, T.nilable(Integer))
|
||||
@exec_count += 1
|
||||
logfn = format("#{logs}/#{active_log_prefix}%02<exec_count>d.%<cmd_base>s",
|
||||
exec_count: @exec_count,
|
||||
cmd_base: File.basename(cmd).split.first)
|
||||
log_filename = format("#{logs}/#{active_log_prefix}%02<exec_count>d.%<cmd_base>s.log",
|
||||
exec_count: @exec_count,
|
||||
cmd_base: File.basename(cmd).split.first)
|
||||
logs.mkpath
|
||||
|
||||
File.open(logfn, "w") do |log|
|
||||
File.open(log_filename, "w") do |log|
|
||||
log.puts Time.now, "", cmd, args, ""
|
||||
log.flush
|
||||
|
||||
@ -3077,7 +3085,7 @@ class Formula
|
||||
pid = fork do
|
||||
rd.close
|
||||
log.close
|
||||
exec_cmd(cmd, args, wr, logfn)
|
||||
exec_cmd(cmd, args, wr, log_filename)
|
||||
end
|
||||
wr.close
|
||||
|
||||
@ -3104,7 +3112,7 @@ class Formula
|
||||
end
|
||||
else
|
||||
pid = fork do
|
||||
exec_cmd(cmd, args, log, logfn)
|
||||
exec_cmd(cmd, args, log, log_filename)
|
||||
end
|
||||
end
|
||||
|
||||
@ -3117,8 +3125,8 @@ class Formula
|
||||
|
||||
log.flush
|
||||
if !verbose? || verbose_using_dots
|
||||
puts "Last #{log_lines} lines from #{logfn}:"
|
||||
Kernel.system "/usr/bin/tail", "-n", log_lines.to_s, logfn
|
||||
puts "Last #{log_lines} lines from #{log_filename}:"
|
||||
Kernel.system "/usr/bin/tail", "-n", log_lines.to_s, log_filename
|
||||
end
|
||||
log.puts
|
||||
|
||||
@ -3259,14 +3267,14 @@ class Formula
|
||||
|
||||
sig {
|
||||
params(
|
||||
cmd: T.any(String, Pathname),
|
||||
args: T::Array[T.any(String, Integer, Pathname, Symbol)],
|
||||
out: IO,
|
||||
logfn: T.nilable(String),
|
||||
cmd: T.any(String, Pathname),
|
||||
args: T::Array[T.any(String, Integer, Pathname, Symbol)],
|
||||
out: IO,
|
||||
log_filename: T.nilable(String),
|
||||
).void
|
||||
}
|
||||
def exec_cmd(cmd, args, out, logfn)
|
||||
ENV["HOMEBREW_CC_LOG_PATH"] = logfn
|
||||
def exec_cmd(cmd, args, out, log_filename)
|
||||
ENV["HOMEBREW_CC_LOG_PATH"] = log_filename
|
||||
|
||||
ENV.remove_cc_etc if cmd.to_s.start_with? "xcodebuild"
|
||||
|
||||
@ -3358,6 +3366,7 @@ class Formula
|
||||
@skip_clean_paths = T.let(Set.new, T.nilable(T::Set[T.any(String, Symbol)]))
|
||||
@link_overwrite_paths = T.let(Set.new, T.nilable(T::Set[String]))
|
||||
@loaded_from_api = T.let(false, T.nilable(T::Boolean))
|
||||
@api_source = T.let(nil, T.nilable(T::Hash[String, T.untyped]))
|
||||
@on_system_blocks_exist = T.let(false, T.nilable(T::Boolean))
|
||||
@network_access_allowed = T.let(SUPPORTED_NETWORK_ACCESS_PHASES.to_h do |phase|
|
||||
[phase, DEFAULT_NETWORK_ACCESS_ALLOWED]
|
||||
@ -3382,6 +3391,10 @@ class Formula
|
||||
sig { returns(T::Boolean) }
|
||||
def loaded_from_api? = !!@loaded_from_api
|
||||
|
||||
# Whether this formula was loaded using the formulae.brew.sh API.
|
||||
sig { returns(T.nilable(T::Hash[String, T.untyped])) }
|
||||
attr_reader :api_source
|
||||
|
||||
# Whether this formula contains OS/arch-specific blocks
|
||||
# (e.g. `on_macos`, `on_arm`, `on_monterey :or_older`, `on_system :linux, macos: :big_sur_or_newer`).
|
||||
sig { returns(T::Boolean) }
|
||||
@ -3797,12 +3810,12 @@ class Formula
|
||||
# If called as a method this provides just the {url} for the {SoftwareSpec}.
|
||||
# If a block is provided you can also add {.depends_on} and {Patch}es just to the {.head} {SoftwareSpec}.
|
||||
# The download strategies (e.g. `:using =>`) are the same as for {url}.
|
||||
# `master` is the default branch for Git and doesn't need stating with a `branch:` parameter.
|
||||
# Git repositories must always specify `branch:`.
|
||||
#
|
||||
# ### Example
|
||||
#
|
||||
# ```ruby
|
||||
# head "https://we.prefer.https.over.git.example.com/.git"
|
||||
# head "https://we.prefer.https.over.git.example.com/.git", branch: "main"
|
||||
# ```
|
||||
#
|
||||
# ```ruby
|
||||
|
||||
@ -677,6 +677,19 @@ module Homebrew
|
||||
problem "GitLab repository is archived" if metadata["archived"]
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def audit_forgejo_repository_archived
|
||||
return if formula.deprecated? || formula.disabled?
|
||||
|
||||
user, repo = get_repo_data(%r{https?://codeberg\.org/([^/]+)/([^/]+)/?.*}) if @online
|
||||
return if user.blank?
|
||||
|
||||
metadata = SharedAudits.forgejo_repo_data(user, repo)
|
||||
return if metadata.nil?
|
||||
|
||||
problem "Forgejo repository is archived since #{metadata["archived_at"]}" if metadata["archived"]
|
||||
end
|
||||
|
||||
def audit_github_repository
|
||||
user, repo = get_repo_data(%r{https?://github\.com/([^/]+)/([^/]+)/?.*}) if @new_formula
|
||||
|
||||
@ -708,6 +721,17 @@ module Homebrew
|
||||
new_formula_problem warning
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def audit_forgejo_repository
|
||||
user, repo = get_repo_data(%r{https?://codeberg\.org/([^/]+)/([^/]+)/?.*}) if @new_formula
|
||||
return if user.blank?
|
||||
|
||||
warning = SharedAudits.forgejo(user, repo)
|
||||
return if warning.nil?
|
||||
|
||||
new_formula_problem warning
|
||||
end
|
||||
|
||||
def get_repo_data(regex)
|
||||
return unless @core_tap
|
||||
return unless @online
|
||||
@ -791,7 +815,7 @@ module Homebrew
|
||||
formula_suffix = stable.version.patch.to_i
|
||||
throttled_rate = formula.livecheck.throttle
|
||||
if throttled_rate && formula_suffix.modulo(throttled_rate).nonzero?
|
||||
problem "should only be updated every #{throttled_rate} releases on multiples of #{throttled_rate}"
|
||||
problem "Should only be updated every #{throttled_rate} releases on multiples of #{throttled_rate}"
|
||||
end
|
||||
|
||||
case (url = stable.url)
|
||||
@ -839,6 +863,16 @@ module Homebrew
|
||||
error = SharedAudits.github_release(owner, repo, tag, formula:)
|
||||
problem error if error
|
||||
end
|
||||
when %r{^https://codeberg\.org/([\w-]+)/([\w-]+)}
|
||||
owner = T.must(Regexp.last_match(1))
|
||||
repo = T.must(Regexp.last_match(2))
|
||||
tag = SharedAudits.forgejo_tag_from_url(url)
|
||||
tag ||= formula.stable.specs[:tag]
|
||||
|
||||
if @online && !tag.nil?
|
||||
error = SharedAudits.forgejo_release(owner, repo, tag, formula:)
|
||||
problem error if error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -382,7 +382,7 @@ class FormulaInstaller
|
||||
check_installation_already_attempted
|
||||
|
||||
if force_bottle? && !pour_bottle?
|
||||
raise CannotInstallFormulaError, "--force-bottle passed but #{formula.full_name} has no bottle!"
|
||||
raise CannotInstallFormulaError, "`--force-bottle` passed but #{formula.full_name} has no bottle!"
|
||||
end
|
||||
|
||||
if Homebrew.default_prefix? &&
|
||||
@ -477,7 +477,7 @@ class FormulaInstaller
|
||||
|
||||
raise CannotInstallFormulaError,
|
||||
"You must `brew unpin #{pinned_unsatisfied_deps * " "}` as installing " \
|
||||
"#{formula.full_name} requires the latest version of pinned dependencies"
|
||||
"#{formula.full_name} requires the latest version of pinned dependencies."
|
||||
end
|
||||
|
||||
sig { params(_formula: Formula).returns(T.nilable(T::Boolean)) }
|
||||
|
||||
34
Library/Homebrew/formula_stub.rb
Normal file
34
Library/Homebrew/formula_stub.rb
Normal file
@ -0,0 +1,34 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "pkg_version"
|
||||
|
||||
module Homebrew
|
||||
# A stub for a formula, with only the information needed to fetch the bottle manifest.
|
||||
class FormulaStub < T::Struct
|
||||
const :name, String
|
||||
const :pkg_version, PkgVersion
|
||||
const :rebuild, Integer, default: 0
|
||||
const :sha256, T.nilable(String)
|
||||
|
||||
sig { returns(Version) }
|
||||
def version
|
||||
pkg_version.version
|
||||
end
|
||||
|
||||
sig { returns(Integer) }
|
||||
def revision
|
||||
pkg_version.revision
|
||||
end
|
||||
|
||||
sig { params(other: T.anything).returns(T::Boolean) }
|
||||
def ==(other)
|
||||
case other
|
||||
when FormulaStub
|
||||
name == other.name && pkg_version == other.pkg_version && rebuild == other.rebuild && sha256 == other.sha256
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -60,6 +60,7 @@ class FormulaVersions
|
||||
# We rescue these so that we can skip bad versions and
|
||||
# continue walking the history
|
||||
odebug "#{e} in #{name} at revision #{revision}", Utils::Backtrace.clean(e)
|
||||
nil
|
||||
rescue FormulaUnavailableError
|
||||
nil
|
||||
ensure
|
||||
|
||||
@ -173,9 +173,9 @@ module Formulary
|
||||
platform_cache[:path][path] = klass
|
||||
end
|
||||
|
||||
sig { params(name: String, flags: T::Array[String]).returns(T.class_of(Formula)) }
|
||||
def self.load_formula_from_api!(name, flags:)
|
||||
namespace = :"FormulaNamespaceAPI#{namespace_key(name)}"
|
||||
sig { params(name: String, json_formula_with_variations: T::Hash[String, T.untyped], flags: T::Array[String]).returns(T.class_of(Formula)) }
|
||||
def self.load_formula_from_json!(name, json_formula_with_variations, flags:)
|
||||
namespace = :"FormulaNamespaceAPI#{namespace_key(json_formula_with_variations.to_json)}"
|
||||
|
||||
mod = Module.new
|
||||
remove_const(namespace) if const_defined?(namespace)
|
||||
@ -184,10 +184,7 @@ module Formulary
|
||||
mod.const_set(:BUILD_FLAGS, flags)
|
||||
|
||||
class_name = class_s(name)
|
||||
json_formula = Homebrew::API::Formula.all_formulae[name]
|
||||
raise FormulaUnavailableError, name if json_formula.nil?
|
||||
|
||||
json_formula = Homebrew::API.merge_variations(json_formula)
|
||||
json_formula = Homebrew::API.merge_variations(json_formula_with_variations)
|
||||
|
||||
uses_from_macos_names = json_formula.fetch("uses_from_macos", []).map do |dep|
|
||||
next dep unless dep.is_a? Hash
|
||||
@ -273,6 +270,7 @@ module Formulary
|
||||
# rubocop:todo Sorbet/BlockMethodDefinition
|
||||
klass = Class.new(::Formula) do
|
||||
@loaded_from_api = true
|
||||
@api_source = json_formula_with_variations
|
||||
|
||||
desc json_formula["desc"]
|
||||
homepage json_formula["homepage"]
|
||||
@ -618,8 +616,28 @@ module Formulary
|
||||
|
||||
return unless path.expand_path.exist?
|
||||
|
||||
return if Homebrew::EnvConfig.forbid_packages_from_paths? &&
|
||||
!path.realpath.to_s.start_with?("#{HOMEBREW_CELLAR}/", "#{HOMEBREW_LIBRARY}/Taps/")
|
||||
if Homebrew::EnvConfig.forbid_packages_from_paths?
|
||||
path_realpath = path.realpath.to_s
|
||||
path_string = path.to_s
|
||||
if (path_realpath.end_with?(".rb") || path_string.end_with?(".rb")) &&
|
||||
!path_realpath.start_with?("#{HOMEBREW_CELLAR}/", "#{HOMEBREW_LIBRARY}/Taps/", "#{HOMEBREW_CACHE}/") &&
|
||||
!path_string.start_with?("#{HOMEBREW_CELLAR}/", "#{HOMEBREW_LIBRARY}/Taps/", "#{HOMEBREW_CACHE}/")
|
||||
if path_string.include?("./") || path_string.end_with?(".rb") || path_string.count("/") != 2
|
||||
raise <<~WARNING
|
||||
Homebrew requires formulae to be in a tap, rejecting:
|
||||
#{path_string} (#{path_realpath})
|
||||
|
||||
To create a tap, run e.g.
|
||||
brew tap-new <user|org>/<repository>
|
||||
To create a formula in a tap run e.g.
|
||||
brew create <url> --tap=<user|org>/<repository>
|
||||
WARNING
|
||||
elsif path_string.count("/") == 2
|
||||
# Looks like a tap, let's quietly return but not error.
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (tap = Tap.from_path(path))
|
||||
# Only treat symlinks in taps as aliases.
|
||||
@ -693,7 +711,7 @@ module Formulary
|
||||
if ALLOWED_URL_SCHEMES.exclude?(url_scheme)
|
||||
raise UnsupportedInstallationMethod,
|
||||
"Non-checksummed download of #{name} formula file from an arbitrary URL is unsupported! " \
|
||||
"`brew extract` or `brew create` and `brew tap-new` to create a formula file in a tap " \
|
||||
"Use `brew extract` or `brew create` and `brew tap-new` to create a formula file in a tap " \
|
||||
"on GitHub instead."
|
||||
end
|
||||
HOMEBREW_CACHE_FORMULA.mkpath
|
||||
@ -877,9 +895,9 @@ module Formulary
|
||||
return if Homebrew::EnvConfig.no_install_from_api?
|
||||
return unless ref.is_a?(String)
|
||||
return unless (name = ref[HOMEBREW_DEFAULT_TAP_FORMULA_REGEX, :name])
|
||||
if !Homebrew::API::Formula.all_formulae.key?(name) &&
|
||||
!Homebrew::API::Formula.all_aliases.key?(name) &&
|
||||
!Homebrew::API::Formula.all_renames.key?(name)
|
||||
if Homebrew::API.formula_names.exclude?(name) &&
|
||||
!Homebrew::API.formula_aliases.key?(name) &&
|
||||
!Homebrew::API.formula_renames.key?(name)
|
||||
return
|
||||
end
|
||||
|
||||
@ -911,7 +929,10 @@ module Formulary
|
||||
private
|
||||
|
||||
def load_from_api(flags:)
|
||||
Formulary.load_formula_from_api!(name, flags:)
|
||||
json_formula = Homebrew::API::Formula.all_formulae[name]
|
||||
raise FormulaUnavailableError, name if json_formula.nil?
|
||||
|
||||
Formulary.load_formula_from_json!(name, json_formula, flags:)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
module Ignorable
|
||||
include Kernel
|
||||
|
||||
# This is a workaround to enable `raise` to be aliased
|
||||
# @see https://github.com/sorbet/sorbet/issues/2378#issuecomment-569474238
|
||||
def self.raise(*); end
|
||||
|
||||
@ -83,10 +83,10 @@ module Homebrew
|
||||
skip_link: false,
|
||||
overwrite: false
|
||||
)
|
||||
# head-only without --HEAD is an error
|
||||
# HEAD-only without --HEAD is an error
|
||||
if !head && formula.stable.nil?
|
||||
odie <<~EOS
|
||||
#{formula.full_name} is a head-only formula.
|
||||
#{formula.full_name} is a HEAD-only formula.
|
||||
To install it, run:
|
||||
brew install --HEAD #{formula.full_name}
|
||||
EOS
|
||||
|
||||
@ -78,15 +78,43 @@ class Keg
|
||||
end
|
||||
end
|
||||
|
||||
def relocate_dynamic_linkage(_relocation)
|
||||
def relocate_dynamic_linkage(_relocation, skip_protodesc_cold: false)
|
||||
[]
|
||||
end
|
||||
|
||||
JAVA_REGEX = %r{#{HOMEBREW_PREFIX}/opt/openjdk(@\d+(\.\d+)*)?/libexec(/openjdk\.jdk/Contents/Home)?}
|
||||
|
||||
sig { returns(T::Hash[Symbol, T::Hash[Symbol, String]]) }
|
||||
def new_usr_local_replacement_pairs
|
||||
{
|
||||
prefix: {
|
||||
old: "/usr/local/opt",
|
||||
new: "#{PREFIX_PLACEHOLDER}/opt",
|
||||
},
|
||||
caskroom: {
|
||||
old: "/usr/local/Caskroom",
|
||||
new: "#{PREFIX_PLACEHOLDER}/Caskroom",
|
||||
},
|
||||
var_homebrew: {
|
||||
old: "/usr/local/var/homebrew",
|
||||
new: "#{PREFIX_PLACEHOLDER}/var/homebrew",
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
def prepare_relocation_to_placeholders
|
||||
relocation = Relocation.new
|
||||
relocation.add_replacement_pair(:prefix, HOMEBREW_PREFIX.to_s, PREFIX_PLACEHOLDER, path: true)
|
||||
|
||||
# Use selective HOMEBREW_PREFIX replacement when HOMEBREW_PREFIX=/usr/local
|
||||
# This avoids overzealous replacement of system paths when a script refers to e.g. /usr/local/bin
|
||||
if new_usr_local_relocation?
|
||||
new_usr_local_replacement_pairs.each do |key, value|
|
||||
relocation.add_replacement_pair(key, value.fetch(:old), value.fetch(:new), path: true)
|
||||
end
|
||||
else
|
||||
relocation.add_replacement_pair(:prefix, HOMEBREW_PREFIX.to_s, PREFIX_PLACEHOLDER, path: true)
|
||||
end
|
||||
|
||||
relocation.add_replacement_pair(:cellar, HOMEBREW_CELLAR.to_s, CELLAR_PLACEHOLDER, path: true)
|
||||
# when HOMEBREW_PREFIX == HOMEBREW_REPOSITORY we should use HOMEBREW_PREFIX for all relocations to avoid
|
||||
# being unable to differentiate between them.
|
||||
@ -104,7 +132,7 @@ class Keg
|
||||
|
||||
def replace_locations_with_placeholders
|
||||
relocation = prepare_relocation_to_placeholders.freeze
|
||||
relocate_dynamic_linkage(relocation)
|
||||
relocate_dynamic_linkage(relocation, skip_protodesc_cold: true)
|
||||
replace_text_in_files(relocation)
|
||||
end
|
||||
|
||||
@ -361,6 +389,25 @@ class Keg
|
||||
def self.file_linked_libraries(_file, _string)
|
||||
[]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def new_usr_local_relocation?
|
||||
return false if HOMEBREW_PREFIX.to_s != "/usr/local"
|
||||
|
||||
formula = begin
|
||||
Formula[name]
|
||||
rescue FormulaUnavailableError
|
||||
nil
|
||||
end
|
||||
return true unless formula
|
||||
|
||||
tap = formula.tap
|
||||
return true unless tap
|
||||
|
||||
tap.disabled_new_usr_local_relocation_formulae.exclude?(name)
|
||||
end
|
||||
end
|
||||
|
||||
require "extend/os/keg_relocate"
|
||||
|
||||
@ -286,7 +286,7 @@ module Language
|
||||
def slice_resources!(resources_hash, resource_names)
|
||||
resource_names.map do |resource_name|
|
||||
resources_hash.delete(resource_name) do
|
||||
raise ArgumentError, "Resource \"#{resource_name}\" is not defined in formula or is already used"
|
||||
raise ArgumentError, "Resource \"#{resource_name}\" is not defined in formula or is already used."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -245,7 +245,7 @@ module Homebrew
|
||||
end
|
||||
|
||||
# Use the `stable` version for comparison except for installed
|
||||
# head-only formulae. A formula with `stable` and `head` that's
|
||||
# HEAD-only formulae. A formula with `stable` and `head` that's
|
||||
# installed using `--head` will still use the `stable` version for
|
||||
# comparison.
|
||||
current = if formula
|
||||
|
||||
@ -120,7 +120,7 @@ module Homebrew
|
||||
}
|
||||
private_class_method def self.cask_deprecated(cask, livecheck_defined, full_name: false, verbose: false)
|
||||
return {} if !cask.deprecated? || livecheck_defined
|
||||
return {} if cask.disable_date && cask.deprecation_reason == :unsigned
|
||||
return {} if cask.disable_date && cask.deprecation_reason == :fails_gatekeeper_check
|
||||
|
||||
Livecheck.status_hash(cask, "deprecated", full_name:, verbose:)
|
||||
end
|
||||
|
||||
@ -8,6 +8,7 @@ module Homebrew
|
||||
# method implementations here.
|
||||
module Strategic
|
||||
extend T::Helpers
|
||||
|
||||
interface!
|
||||
|
||||
# Whether the strategy can be applied to the provided URL.
|
||||
|
||||
@ -66,7 +66,7 @@ module Homebrew
|
||||
return values if match.blank?
|
||||
|
||||
# The directory listing page for the project's files
|
||||
values[:url] = "https://ftp.gnu.org/gnu/#{match[:project_name]}/"
|
||||
values[:url] = "https://ftpmirror.gnu.org/gnu/#{match[:project_name]}/"
|
||||
|
||||
regex_name = Regexp.escape(T.must(match[:project_name])).gsub("\\-", "-")
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
# A {Messages} object collects messages that may need to be displayed together
|
||||
# at the end of a multi-step `brew` command run.
|
||||
class Messages
|
||||
sig { returns(T::Array[T::Hash[Symbol, Symbol]]) }
|
||||
sig { returns(T::Array[{ package: String, caveats: T.any(String, Caveats) }]) }
|
||||
attr_reader :caveats
|
||||
|
||||
sig { returns(Integer) }
|
||||
@ -15,7 +15,7 @@ class Messages
|
||||
|
||||
sig { void }
|
||||
def initialize
|
||||
@caveats = T.let([], T::Array[T::Hash[Symbol, Symbol]])
|
||||
@caveats = T.let([], T::Array[{ package: String, caveats: T.any(String, Caveats) }])
|
||||
@completions_and_elisp = T.let(Set.new, T::Set[String])
|
||||
@package_count = T.let(0, Integer)
|
||||
@install_times = T.let([], T::Array[T::Hash[String, Float]])
|
||||
@ -53,7 +53,7 @@ class Messages
|
||||
return if @package_count == 1 && !force
|
||||
|
||||
oh1 "Caveats" if @completions_and_elisp.empty?
|
||||
@caveats.each { |c| ohai c[:package], c[:caveats] }
|
||||
@caveats.each { |c| ohai c.fetch(:package), c.fetch(:caveats) }
|
||||
end
|
||||
|
||||
sig { void }
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "os/linux/ld"
|
||||
@ -44,7 +44,8 @@ module ELFShim
|
||||
|
||||
requires_ancestor { Pathname }
|
||||
|
||||
def initialize(*args)
|
||||
sig { params(path: T.anything).void }
|
||||
def initialize(path)
|
||||
@elf = T.let(nil, T.nilable(T::Boolean))
|
||||
@arch = T.let(nil, T.nilable(Symbol))
|
||||
@elf_type = T.let(nil, T.nilable(Symbol))
|
||||
@ -52,15 +53,16 @@ module ELFShim
|
||||
@interpreter = T.let(nil, T.nilable(String))
|
||||
@dynamic_elf = T.let(nil, T.nilable(T::Boolean))
|
||||
@metadata = T.let(nil, T.nilable(Metadata))
|
||||
@patchelf_patcher = nil
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
sig { params(offset: Integer).returns(Integer) }
|
||||
def read_uint8(offset)
|
||||
read(1, offset).unpack1("C")
|
||||
end
|
||||
|
||||
sig { params(offset: Integer).returns(Integer) }
|
||||
def read_uint16(offset)
|
||||
read(2, offset).unpack1("v")
|
||||
end
|
||||
@ -91,6 +93,7 @@ module ELFShim
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(wanted_arch: Symbol).returns(T::Boolean) }
|
||||
def arch_compatible?(wanted_arch)
|
||||
return true unless elf?
|
||||
|
||||
@ -111,10 +114,12 @@ module ELFShim
|
||||
end
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def dylib?
|
||||
elf_type == :dylib
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def binary_executable?
|
||||
elf_type == :executable
|
||||
end
|
||||
@ -123,20 +128,22 @@ module ELFShim
|
||||
# "/lib:/usr/lib:/usr/local/lib"
|
||||
sig { returns(T.nilable(String)) }
|
||||
def rpath
|
||||
@rpath ||= rpath_using_patchelf_rb
|
||||
metadata.rpath
|
||||
end
|
||||
|
||||
# An array of runtime search path entries, such as:
|
||||
# ["/lib", "/usr/lib", "/usr/local/lib"]
|
||||
sig { returns(T::Array[String]) }
|
||||
def rpaths
|
||||
Array(rpath&.split(":"))
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(String)) }
|
||||
def interpreter
|
||||
@interpreter ||= patchelf_patcher.interpreter
|
||||
metadata.interpreter
|
||||
end
|
||||
|
||||
sig { params(interpreter: T.nilable(String), rpath: T.nilable(String)).void }
|
||||
def patch!(interpreter: nil, rpath: nil)
|
||||
return if interpreter.blank? && rpath.blank?
|
||||
|
||||
@ -145,7 +152,12 @@ module ELFShim
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def dynamic_elf?
|
||||
@dynamic_elf ||= patchelf_patcher.elf.segment_by_type(:DYNAMIC).present?
|
||||
metadata.dynamic_elf?
|
||||
end
|
||||
|
||||
sig { returns(T::Array[String]) }
|
||||
def section_names
|
||||
metadata.section_names
|
||||
end
|
||||
|
||||
# Helper class for reading metadata from an ELF file.
|
||||
@ -156,35 +168,56 @@ module ELFShim
|
||||
sig { returns(T.nilable(String)) }
|
||||
attr_reader :dylib_id
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def dynamic_elf?
|
||||
@dynamic_elf
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(String)) }
|
||||
attr_reader :interpreter
|
||||
|
||||
sig { returns(T.nilable(String)) }
|
||||
attr_reader :rpath
|
||||
|
||||
sig { returns(T::Array[String]) }
|
||||
attr_reader :dylibs
|
||||
attr_reader :section_names
|
||||
|
||||
sig { params(path: ELFShim).void }
|
||||
def initialize(path)
|
||||
@path = T.let(path, ELFShim)
|
||||
@dylibs = T.let([], T::Array[String])
|
||||
@dylib_id = T.let(nil, T.nilable(String))
|
||||
@dylib_id, needed = needed_libraries path
|
||||
@dylibs = needed.map { |lib| find_full_lib_path(lib).to_s } if needed.present?
|
||||
require "patchelf"
|
||||
patcher = path.patchelf_patcher
|
||||
|
||||
@metadata = T.let(nil, T.nilable(T::Hash[String, T.untyped]))
|
||||
@path = T.let(path, ELFShim)
|
||||
@dylibs = T.let(nil, T.nilable(T::Array[String]))
|
||||
@dylib_id = T.let(nil, T.nilable(String))
|
||||
@needed = T.let([], T::Array[String])
|
||||
|
||||
dynamic_segment = patcher.elf.segment_by_type(:dynamic)
|
||||
@dynamic_elf = T.let(dynamic_segment.present?, T::Boolean)
|
||||
@dylib_id, @needed = if @dynamic_elf
|
||||
[patcher.soname, patcher.needed]
|
||||
else
|
||||
[nil, []]
|
||||
end
|
||||
|
||||
@interpreter = T.let(patcher.interpreter, T.nilable(String))
|
||||
@rpath = T.let(patcher.runpath || patcher.rpath, T.nilable(String))
|
||||
@section_names = T.let(patcher.elf.sections.map(&:name).compact_blank, T::Array[String])
|
||||
|
||||
@dt_flags_1 = T.let(dynamic_segment&.tag_by_type(:flags_1)&.value, T.nilable(Integer))
|
||||
end
|
||||
|
||||
sig { returns(T::Array[String]) }
|
||||
def dylibs
|
||||
@dylibs ||= @needed.map { |lib| find_full_lib_path(lib).to_s }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def needed_libraries(path)
|
||||
return [nil, []] unless path.dynamic_elf?
|
||||
|
||||
needed_libraries_using_patchelf_rb path
|
||||
end
|
||||
|
||||
def needed_libraries_using_patchelf_rb(path)
|
||||
patcher = path.patchelf_patcher
|
||||
[patcher.soname, patcher.needed]
|
||||
end
|
||||
|
||||
sig { params(basename: String).returns(Pathname) }
|
||||
def find_full_lib_path(basename)
|
||||
local_paths = (path.patchelf_patcher.runpath || path.patchelf_patcher.rpath)&.split(":")
|
||||
basename = Pathname(basename)
|
||||
local_paths = rpath&.split(":")
|
||||
|
||||
# Search for dependencies in the runpath/rpath first
|
||||
local_paths&.each do |local_path|
|
||||
@ -194,11 +227,10 @@ module ELFShim
|
||||
end
|
||||
|
||||
# Check if DF_1_NODEFLIB is set
|
||||
dt_flags_1 = path.patchelf_patcher.elf.segment_by_type(:dynamic)&.tag_by_type(:flags_1)
|
||||
nodeflib_flag = if dt_flags_1.nil?
|
||||
nodeflib_flag = if @dt_flags_1.nil?
|
||||
false
|
||||
else
|
||||
dt_flags_1.value & ELFTools::Constants::DF::DF_1_NODEFLIB != 0
|
||||
@dt_flags_1 & ELFTools::Constants::DF::DF_1_NODEFLIB != 0
|
||||
end
|
||||
|
||||
linker_library_paths = OS::Linux::Ld.library_paths
|
||||
@ -232,6 +264,7 @@ module ELFShim
|
||||
end
|
||||
private_constant :Metadata
|
||||
|
||||
sig { params(new_interpreter: T.nilable(String), new_rpath: T.nilable(String)).void }
|
||||
def save_using_patchelf_rb(new_interpreter, new_rpath)
|
||||
patcher = patchelf_patcher
|
||||
patcher.interpreter = new_interpreter if new_interpreter.present?
|
||||
@ -239,13 +272,13 @@ module ELFShim
|
||||
patcher.save(patchelf_compatible: true)
|
||||
end
|
||||
|
||||
def rpath_using_patchelf_rb
|
||||
patchelf_patcher.runpath || patchelf_patcher.rpath
|
||||
end
|
||||
|
||||
# Don't cache the patcher; it keeps the ELF file open so long as it is alive.
|
||||
# Instead, for read-only access to the ELF file's metadata, fetch it and cache
|
||||
# it with {Metadata}.
|
||||
sig { returns(::PatchELF::Patcher) }
|
||||
def patchelf_patcher
|
||||
require "patchelf"
|
||||
@patchelf_patcher ||= ::PatchELF::Patcher.new to_s, on_error: :silent
|
||||
::PatchELF::Patcher.new to_s, on_error: :silent
|
||||
end
|
||||
|
||||
sig { returns(Metadata) }
|
||||
@ -254,11 +287,13 @@ module ELFShim
|
||||
end
|
||||
private :metadata
|
||||
|
||||
sig { returns(T.nilable(String)) }
|
||||
def dylib_id
|
||||
metadata.dylib_id
|
||||
end
|
||||
|
||||
def dynamically_linked_libraries(*)
|
||||
sig { params(except: Symbol, resolve_variable_references: T::Boolean).returns(T::Array[String]) }
|
||||
def dynamically_linked_libraries(except: :none, resolve_variable_references: true)
|
||||
metadata.dylibs
|
||||
end
|
||||
end
|
||||
|
||||
@ -49,6 +49,8 @@ module OS
|
||||
def self.library_paths(conf_path = Pathname(sysconfdir)/"ld.so.conf")
|
||||
conf_file = Pathname(conf_path)
|
||||
return [] unless conf_file.exist?
|
||||
return [] unless conf_file.file?
|
||||
return [] unless conf_file.readable?
|
||||
|
||||
@library_paths_cache ||= T.let({}, T.nilable(T::Hash[String, T::Array[String]]))
|
||||
cache_key = conf_file.to_s
|
||||
|
||||
@ -327,6 +327,19 @@ module OS
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(reason: String).returns(String) }
|
||||
def self.reinstall_instructions(reason: "resolve your issues")
|
||||
<<~EOS
|
||||
If that doesn't #{reason}, run:
|
||||
sudo rm -rf /Library/Developer/CommandLineTools
|
||||
sudo xcode-select --install
|
||||
|
||||
Alternatively, manually download them from:
|
||||
#{Formatter.url(MacOS::Xcode::APPLE_DEVELOPER_DOWNLOAD_URL)}.
|
||||
You should download the Command Line Tools for Xcode #{MacOS::Xcode.latest_version}.
|
||||
EOS
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def self.update_instructions
|
||||
return installation_instructions if OS::Mac.version.prerelease?
|
||||
@ -342,13 +355,15 @@ module OS
|
||||
<<~EOS
|
||||
Update them from Software Update in #{software_update_location}.
|
||||
|
||||
If that doesn't show you any updates, run:
|
||||
sudo rm -rf /Library/Developer/CommandLineTools
|
||||
sudo xcode-select --install
|
||||
#{reinstall_instructions(reason: "show you any updates")}
|
||||
EOS
|
||||
end
|
||||
|
||||
Alternatively, manually download them from:
|
||||
#{Formatter.url(MacOS::Xcode::APPLE_DEVELOPER_DOWNLOAD_URL)}.
|
||||
You should download the Command Line Tools for Xcode #{MacOS::Xcode.latest_version}.
|
||||
sig { returns(String) }
|
||||
def self.installation_then_reinstall_instructions
|
||||
<<~EOS
|
||||
#{installation_instructions}
|
||||
#{reinstall_instructions}
|
||||
EOS
|
||||
end
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ module Patch
|
||||
when nil
|
||||
raise ArgumentError, "nil value for strip"
|
||||
else
|
||||
raise ArgumentError, "Unexpected value #{strip.inspect} for strip"
|
||||
raise ArgumentError, "Unexpected value for strip: #{strip.inspect}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -14,7 +14,10 @@ require "cmd/postinstall"
|
||||
require "json/add/exception"
|
||||
|
||||
begin
|
||||
ENV.delete("HOMEBREW_FORBID_PACKAGES_FROM_PATHS")
|
||||
# Undocumented opt-out for internal use.
|
||||
# We need to allow formulae from paths here due to how we pass them through.
|
||||
ENV["HOMEBREW_INTERNAL_ALLOW_PACKAGES_FROM_PATHS"] = "1"
|
||||
|
||||
args = Homebrew::Cmd::Postinstall.new.args
|
||||
error_pipe = Utils::UNIXSocketExt.open(ENV.fetch("HOMEBREW_ERROR_PIPE"), &:recv_io)
|
||||
error_pipe.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
||||
@ -29,7 +32,7 @@ begin
|
||||
formula.run_post_install
|
||||
# Handle all possible exceptions.
|
||||
rescue Exception => e # rubocop:disable Lint/RescueException
|
||||
error_pipe.puts e.to_json
|
||||
error_pipe.close
|
||||
error_pipe&.puts e.to_json
|
||||
error_pipe&.close
|
||||
exit! 1
|
||||
end
|
||||
|
||||
@ -172,10 +172,6 @@ class Requirement
|
||||
super(cmd, PATH.new(ORIGINAL_PATHS))
|
||||
end
|
||||
|
||||
def which_all(cmd)
|
||||
super(cmd, PATH.new(ORIGINAL_PATHS))
|
||||
end
|
||||
|
||||
class << self
|
||||
include BuildEnvironment::DSL
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ class Resource
|
||||
instance_eval(&block) if block
|
||||
end
|
||||
|
||||
sig { params(other: Object).void }
|
||||
sig { override.params(other: T.any(Resource, Downloadable)).void }
|
||||
def initialize_dup(other)
|
||||
super
|
||||
@name = @name.dup
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user