mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
Merge branch 'master' into master
This commit is contained in:
commit
27a040cc32
7
.github/codeql/extensions/homebrew-actions.yml
vendored
Normal file
7
.github/codeql/extensions/homebrew-actions.yml
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
# This file is synced from the `.github` repository, do not modify it directly.
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/actions-all
|
||||
extensible: trustedActionsOwnerDataModel
|
||||
data:
|
||||
- ["Homebrew"]
|
63
.github/workflows/actionlint.yml
vendored
63
.github/workflows/actionlint.yml
vendored
@ -1,18 +1,19 @@
|
||||
name: actionlint
|
||||
# This file is synced from the `.github` repository, do not modify it directly.
|
||||
name: Actionlint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
paths:
|
||||
- '.github/workflows/*.ya?ml'
|
||||
- 'Formula/a/actionlint.rb'
|
||||
- 'Formula/s/shellcheck.rb'
|
||||
- 'Formula/z/zizmor.rb'
|
||||
pull_request:
|
||||
paths:
|
||||
- '.github/workflows/*.ya?ml'
|
||||
- '.github/actionlint.yaml'
|
||||
|
||||
env:
|
||||
HOMEBREW_DEVELOPER: 1
|
||||
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||
HOMEBREW_NO_ENV_HINTS: 1
|
||||
|
||||
defaults:
|
||||
run:
|
||||
@ -22,16 +23,23 @@ concurrency:
|
||||
group: "actionlint-${{ github.ref }}"
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
env:
|
||||
HOMEBREW_DEVELOPER: 1
|
||||
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||
HOMEBREW_NO_ENV_HINTS: 1
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
workflow_syntax:
|
||||
if: github.repository_owner == 'Homebrew'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: setup-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
@ -40,31 +48,42 @@ jobs:
|
||||
- name: Install tools
|
||||
run: brew install actionlint shellcheck zizmor
|
||||
|
||||
- name: Set up GITHUB_WORKSPACE
|
||||
env:
|
||||
HOMEBREW_REPOSITORY: ${{ steps.setup-homebrew.outputs.repository-path }}
|
||||
run: |
|
||||
# Annotations work only relative to GITHUB_WORKSPACE
|
||||
(shopt -s dotglob; rm -rf "${GITHUB_WORKSPACE:?}"/*; mv "${HOMEBREW_REPOSITORY:?}"/* "$GITHUB_WORKSPACE")
|
||||
rmdir "$HOMEBREW_REPOSITORY"
|
||||
ln -vs "$GITHUB_WORKSPACE" "$HOMEBREW_REPOSITORY"
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
echo "::add-matcher::.github/actionlint-matcher.json"
|
||||
|
||||
- run: |
|
||||
# NOTE: exit code intentionally suppressed here
|
||||
zizmor --format sarif . > results.sarif || true
|
||||
- run: zizmor --format sarif . > results.sarif
|
||||
|
||||
- name: Upload SARIF file
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
# We can't use the SARIF file when triggered by `merge_group` so we don't upload it.
|
||||
if: always() && github.event_name != 'merge_group'
|
||||
with:
|
||||
name: results.sarif
|
||||
path: results.sarif
|
||||
|
||||
- name: Set up actionlint
|
||||
run: |
|
||||
# In homebrew-core, setting `shell: /bin/bash` prevents shellcheck from running on
|
||||
# those steps, so let's change them to `shell: bash` temporarily for better linting.
|
||||
sed -i 's|shell: /bin/bash -x|shell: bash -x|' .github/workflows/*.y*ml
|
||||
|
||||
# In homebrew-core, the JSON matcher needs to be accessible to the container host.
|
||||
cp "$(brew --repository)/.github/actionlint-matcher.json" "$HOME"
|
||||
|
||||
echo "::add-matcher::$HOME/actionlint-matcher.json"
|
||||
|
||||
- run: actionlint
|
||||
|
||||
upload_sarif:
|
||||
needs: workflow_syntax
|
||||
# We want to always upload this even if `actionlint` failed.
|
||||
# This is only available on public repositories.
|
||||
if: >
|
||||
always() &&
|
||||
!contains(fromJSON('["cancelled", "skipped"]'), needs.workflow_syntax.result) &&
|
||||
!github.event.repository.private &&
|
||||
github.event_name != 'merge_group'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
@ -77,7 +96,7 @@ jobs:
|
||||
path: results.sarif
|
||||
|
||||
- name: Upload SARIF file
|
||||
uses: github/codeql-action/upload-sarif@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
|
||||
uses: github/codeql-action/upload-sarif@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
category: zizmor
|
||||
|
2
.github/workflows/autogenerated-files.yml
vendored
2
.github/workflows/autogenerated-files.yml
vendored
@ -27,7 +27,7 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
|
7
.github/workflows/codeql-analysis.yml
vendored
7
.github/workflows/codeql-analysis.yml
vendored
@ -3,10 +3,9 @@ name: "CodeQL"
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
defaults:
|
||||
run:
|
||||
@ -28,7 +27,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
|
||||
uses: github/codeql-action/init@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0
|
||||
with:
|
||||
languages: ruby
|
||||
config: |
|
||||
@ -36,4 +35,4 @@ jobs:
|
||||
- Library/Homebrew/vendor
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
|
||||
uses: github/codeql-action/analyze@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0
|
||||
|
15
.github/workflows/docker.yml
vendored
15
.github/workflows/docker.yml
vendored
@ -4,6 +4,7 @@ on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
merge_group:
|
||||
release:
|
||||
@ -38,8 +39,8 @@ jobs:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Fetch origin/master from Git
|
||||
run: git fetch origin master
|
||||
- name: Fetch origin/HEAD from Git
|
||||
run: git fetch origin HEAD
|
||||
|
||||
- name: Determine build attributes
|
||||
id: attributes
|
||||
@ -83,12 +84,16 @@ jobs:
|
||||
)
|
||||
fi
|
||||
elif [[ "${GITHUB_EVENT_NAME}" == "push" &&
|
||||
"${GITHUB_REF}" == "refs/heads/master" &&
|
||||
("${GITHUB_REF}" == "refs/heads/master" || "${GITHUB_REF}" == "refs/heads/main") &&
|
||||
"${version}" == "22.04" ]]; then
|
||||
tags+=(
|
||||
"ghcr.io/homebrew/brew:main"
|
||||
"ghcr.io/homebrew/brew:master"
|
||||
"ghcr.io/homebrew/ubuntu${version}:main"
|
||||
"ghcr.io/homebrew/ubuntu${version}:master"
|
||||
"homebrew/brew:main"
|
||||
"homebrew/brew:master"
|
||||
"homebrew/ubuntu${version}:main"
|
||||
"homebrew/ubuntu${version}:master"
|
||||
)
|
||||
fi
|
||||
@ -160,8 +165,8 @@ jobs:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Fetch origin/master from Git
|
||||
run: git fetch origin master
|
||||
- name: Fetch origin/HEAD from Git
|
||||
run: git fetch origin HEAD
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
|
||||
|
6
.github/workflows/docs.yml
vendored
6
.github/workflows/docs.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
@ -52,7 +52,7 @@ jobs:
|
||||
run: vale docs/
|
||||
|
||||
- name: Install Ruby
|
||||
uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
|
||||
uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # v1.245.0
|
||||
with:
|
||||
bundler-cache: true
|
||||
working-directory: docs
|
||||
@ -67,7 +67,7 @@ jobs:
|
||||
- name: Generate formulae.brew.sh API samples
|
||||
if: github.repository == 'Homebrew/formulae.brew.sh'
|
||||
working-directory: docs
|
||||
run: ../script/generate-api-samples.rb
|
||||
run: ../script/generate-api-samples.rb --template
|
||||
|
||||
- name: Build the site and check for broken links
|
||||
working-directory: docs
|
||||
|
4
.github/workflows/doctor.yml
vendored
4
.github/workflows/doctor.yml
vendored
@ -28,7 +28,7 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
@ -55,7 +55,7 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
|
8
.github/workflows/pkg-installer.yml
vendored
8
.github/workflows/pkg-installer.yml
vendored
@ -43,7 +43,7 @@ jobs:
|
||||
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
@ -135,7 +135,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Generate build provenance
|
||||
uses: actions/attest-build-provenance@db473fddc028af60658334401dc6fa3ffd8669fd # v2.3.0
|
||||
uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.4.0
|
||||
with:
|
||||
subject-path: Homebrew-${{ steps.homebrew-version.outputs.version }}.pkg
|
||||
|
||||
@ -251,7 +251,7 @@ jobs:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Open, update, or close pkg installer issue
|
||||
uses: Homebrew/actions/create-or-update-issue@master
|
||||
uses: Homebrew/actions/create-or-update-issue@main
|
||||
with:
|
||||
title: Failed to publish pkg installer
|
||||
body: >
|
||||
@ -259,7 +259,7 @@ jobs:
|
||||
${{ github.ref_name }}. No pkg installer was uploaded to the GitHub
|
||||
release.
|
||||
labels: bug,release blocker
|
||||
update-existing: ${{ contains(needs.*.result, 'failure') }}
|
||||
update-existing: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }}
|
||||
close-existing: ${{ needs.upload.result == 'success' }}
|
||||
close-from-author: github-actions[bot]
|
||||
close-comment: >
|
||||
|
5
.github/workflows/rubydoc.yml
vendored
5
.github/workflows/rubydoc.yml
vendored
@ -3,6 +3,7 @@ name: Ruby Documentation CI
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
pull_request:
|
||||
|
||||
@ -28,7 +29,7 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
@ -42,7 +43,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Install Ruby
|
||||
uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0
|
||||
uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # v1.245.0
|
||||
with:
|
||||
bundler-cache: true
|
||||
working-directory: rubydoc
|
||||
|
@ -1,9 +1,10 @@
|
||||
name: Update schema data
|
||||
name: Update SBOM schema
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- .github/workflows/schemas.yml
|
||||
- .github/workflows/sbom.yml
|
||||
branches-ignore:
|
||||
- main
|
||||
- master
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
@ -17,25 +18,25 @@ defaults:
|
||||
shell: bash -xeuo pipefail {0}
|
||||
|
||||
jobs:
|
||||
spdx:
|
||||
sbom:
|
||||
if: github.repository == 'Homebrew/brew'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
test-bot: false
|
||||
|
||||
- name: Configure Git user
|
||||
uses: Homebrew/actions/git-user-config@master
|
||||
uses: Homebrew/actions/git-user-config@main
|
||||
with:
|
||||
username: BrewTestBot
|
||||
|
||||
- name: Set up commit signing
|
||||
uses: Homebrew/actions/setup-commit-signing@master
|
||||
uses: Homebrew/actions/setup-commit-signing@main
|
||||
with:
|
||||
signing_key: ${{ secrets.BREWTESTBOT_SSH_SIGNING_KEY }}
|
||||
|
||||
@ -55,7 +56,7 @@ jobs:
|
||||
git checkout "${BRANCH}"
|
||||
git checkout "Library/Homebrew/data/schemas"
|
||||
else
|
||||
git checkout --no-track -B "${BRANCH}" origin/master
|
||||
git checkout --no-track -B "${BRANCH}" origin/HEAD
|
||||
fi
|
||||
|
||||
# Intentionally tracking 2.3.x to match what we output in sbom.rb. 3.0 also doesn't have a JSON Schema.
|
||||
@ -67,9 +68,10 @@ jobs:
|
||||
if ! git diff --exit-code Library/Homebrew/data/schemas
|
||||
then
|
||||
git add "Library/Homebrew/data/schemas"
|
||||
git commit -m "data/schemas: update schema data." -m "Autogenerated by [a scheduled GitHub Action](https://github.com/Homebrew/brew/blob/master/.github/workflows/schemas.yml)."
|
||||
git commit -m "data/schemas: update schema data." -m "Autogenerated by [a scheduled GitHub Action](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/schemas.yml)."
|
||||
|
||||
echo "committed=true" >> "$GITHUB_OUTPUT"
|
||||
PULL_REQUEST_STATE="$(gh pr view --json=state | jq -r ".state")"
|
||||
PULL_REQUEST_STATE="$(gh pr view --json=state | jq -r ".state" || true)"
|
||||
if [[ "${PULL_REQUEST_STATE}" != "OPEN" ]]
|
||||
then
|
||||
echo "pull_request=true" >> "$GITHUB_OUTPUT"
|
||||
@ -78,13 +80,13 @@ jobs:
|
||||
|
||||
- name: Push commits
|
||||
if: steps.update.outputs.committed == 'true'
|
||||
uses: Homebrew/actions/git-try-push@master
|
||||
uses: Homebrew/actions/git-try-push@main
|
||||
with:
|
||||
token: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }}
|
||||
directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
|
||||
branch: ${{ steps.update.outputs.branch }}
|
||||
force: true
|
||||
origin_branch: "master"
|
||||
origin_branch: "HEAD"
|
||||
|
||||
- name: Open a pull request
|
||||
if: steps.update.outputs.pull_request == 'true'
|
||||
@ -92,3 +94,26 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }}
|
||||
working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
|
||||
|
||||
issue:
|
||||
needs: sbom
|
||||
if: always() && github.event_name == 'schedule'
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
permissions:
|
||||
# To create or update issues
|
||||
issues: write
|
||||
steps:
|
||||
- name: Open, update, or close schema issue
|
||||
uses: Homebrew/actions/create-or-update-issue@main
|
||||
with:
|
||||
title: Failed to update SBOM schema
|
||||
body: >
|
||||
The SBOM schema workflow [failed](${{ env.RUN_URL }}). No SBOM schema was updated.
|
||||
labels: bug
|
||||
update-existing: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }}
|
||||
close-existing: ${{ needs.sbom.result == 'success' }}
|
||||
close-from-author: github-actions[bot]
|
||||
close-comment: >
|
||||
The SBOM schema workflow [succeeded](${{ env.RUN_URL }}). Closing this issue.
|
42
.github/workflows/sorbet.yml
vendored
42
.github/workflows/sorbet.yml
vendored
@ -10,6 +10,7 @@ on:
|
||||
paths:
|
||||
- .github/workflows/sorbet.yml
|
||||
branches-ignore:
|
||||
- main
|
||||
- master
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
@ -29,7 +30,7 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
@ -37,13 +38,13 @@ jobs:
|
||||
|
||||
- name: Configure Git user
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: Homebrew/actions/git-user-config@master
|
||||
uses: Homebrew/actions/git-user-config@main
|
||||
with:
|
||||
username: BrewTestBot
|
||||
|
||||
- name: Set up commit signing
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: Homebrew/actions/setup-commit-signing@master
|
||||
uses: Homebrew/actions/setup-commit-signing@main
|
||||
with:
|
||||
signing_key: ${{ secrets.BREWTESTBOT_SSH_SIGNING_KEY }}
|
||||
|
||||
@ -63,7 +64,7 @@ jobs:
|
||||
git checkout "${BRANCH}"
|
||||
git checkout "Library/Homebrew/sorbet"
|
||||
else
|
||||
git checkout --no-track -B "${BRANCH}" origin/master
|
||||
git checkout --no-track -B "${BRANCH}" origin/HEAD
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -80,17 +81,17 @@ jobs:
|
||||
then
|
||||
git add "Library/Homebrew/sorbet"
|
||||
git commit -m "sorbet: Update RBI files." \
|
||||
-m "Autogenerated by the [sorbet](https://github.com/Homebrew/brew/blob/master/.github/workflows/sorbet.yml) workflow."
|
||||
-m "Autogenerated by the [sorbet](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/sorbet.yml) workflow."
|
||||
|
||||
if ! git diff --stat --exit-code "Library/Homebrew"
|
||||
then
|
||||
git add "Library/Homebrew/"
|
||||
git commit -m "sorbet: Autobump sigils via Spoom" \
|
||||
-m "Autogenerated by the [sorbet](https://github.com/Homebrew/brew/blob/master/.github/workflows/sorbet.yml) workflow."
|
||||
-m "Autogenerated by the [sorbet](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/sorbet.yml) workflow."
|
||||
fi
|
||||
|
||||
echo "committed=true" >> "$GITHUB_OUTPUT"
|
||||
PULL_REQUEST_STATE="$(gh pr view --json=state | jq -r ".state")"
|
||||
PULL_REQUEST_STATE="$(gh pr view --json=state | jq -r ".state" || true)"
|
||||
if [[ "${PULL_REQUEST_STATE}" != "OPEN" ]]
|
||||
then
|
||||
echo "pull_request=true" >> "$GITHUB_OUTPUT"
|
||||
@ -99,13 +100,13 @@ jobs:
|
||||
|
||||
- name: Push commits
|
||||
if: steps.commit.outputs.committed == 'true'
|
||||
uses: Homebrew/actions/git-try-push@master
|
||||
uses: Homebrew/actions/git-try-push@main
|
||||
with:
|
||||
token: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }}
|
||||
directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
|
||||
branch: ${{ steps.update.outputs.branch }}
|
||||
force: true
|
||||
origin_branch: "master"
|
||||
origin_branch: "HEAD"
|
||||
|
||||
- name: Open a pull request
|
||||
if: steps.commit.outputs.pull_request == 'true'
|
||||
@ -113,3 +114,26 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }}
|
||||
working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
|
||||
|
||||
issue:
|
||||
needs: tapioca
|
||||
if: always() && github.event_name == 'schedule'
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
permissions:
|
||||
# To create or update issues
|
||||
issues: write
|
||||
steps:
|
||||
- name: Open, update, or close Sorbet issue
|
||||
uses: Homebrew/actions/create-or-update-issue@main
|
||||
with:
|
||||
title: Failed to update RBI files
|
||||
body: >
|
||||
The Sorbet workflow [failed](${{ env.RUN_URL }}). No RBI files were updated.
|
||||
labels: bug
|
||||
update-existing: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }}
|
||||
close-existing: ${{ needs.tapioca.result == 'success' }}
|
||||
close-from-author: github-actions[bot]
|
||||
close-comment: >
|
||||
The Sorbet workflow [succeeded](${{ env.RUN_URL }}). Closing this issue.
|
||||
|
41
.github/workflows/spdx.yml
vendored
41
.github/workflows/spdx.yml
vendored
@ -4,6 +4,7 @@ on:
|
||||
paths:
|
||||
- .github/workflows/spdx.yml
|
||||
branches-ignore:
|
||||
- main
|
||||
- master
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
@ -23,19 +24,19 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
test-bot: false
|
||||
|
||||
- name: Configure Git user
|
||||
uses: Homebrew/actions/git-user-config@master
|
||||
uses: Homebrew/actions/git-user-config@main
|
||||
with:
|
||||
username: BrewTestBot
|
||||
|
||||
- name: Set up commit signing
|
||||
uses: Homebrew/actions/setup-commit-signing@master
|
||||
uses: Homebrew/actions/setup-commit-signing@main
|
||||
with:
|
||||
signing_key: ${{ secrets.BREWTESTBOT_SSH_SIGNING_KEY }}
|
||||
|
||||
@ -55,15 +56,16 @@ jobs:
|
||||
git checkout "${BRANCH}"
|
||||
git checkout "Library/Homebrew/data/spdx"
|
||||
else
|
||||
git checkout --no-track -B "${BRANCH}" origin/master
|
||||
git checkout --no-track -B "${BRANCH}" origin/HEAD
|
||||
fi
|
||||
|
||||
if brew update-license-data
|
||||
then
|
||||
git add "Library/Homebrew/data/spdx"
|
||||
git commit -m "spdx: update license data." -m "Autogenerated by [a scheduled GitHub Action](https://github.com/Homebrew/brew/blob/master/.github/workflows/spdx.yml)."
|
||||
git commit -m "spdx: update license data." -m "Autogenerated by [a scheduled GitHub Action](https://github.com/Homebrew/brew/blob/HEAD/.github/workflows/spdx.yml)."
|
||||
|
||||
echo "committed=true" >> "$GITHUB_OUTPUT"
|
||||
PULL_REQUEST_STATE="$(gh pr view --json=state | jq -r ".state")"
|
||||
PULL_REQUEST_STATE="$(gh pr view --json=state | jq -r ".state" || true)"
|
||||
if [[ "${PULL_REQUEST_STATE}" != "OPEN" ]]
|
||||
then
|
||||
echo "pull_request=true" >> "$GITHUB_OUTPUT"
|
||||
@ -72,13 +74,13 @@ jobs:
|
||||
|
||||
- name: Push commits
|
||||
if: steps.update.outputs.committed == 'true'
|
||||
uses: Homebrew/actions/git-try-push@master
|
||||
uses: Homebrew/actions/git-try-push@main
|
||||
with:
|
||||
token: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }}
|
||||
directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
|
||||
branch: ${{ steps.update.outputs.branch }}
|
||||
force: true
|
||||
origin_branch: "master"
|
||||
origin_branch: "HEAD"
|
||||
|
||||
- name: Open a pull request
|
||||
if: steps.update.outputs.pull_request == 'true'
|
||||
@ -86,3 +88,26 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }}
|
||||
working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
|
||||
|
||||
issue:
|
||||
needs: spdx
|
||||
if: always() && github.event_name == 'schedule'
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
permissions:
|
||||
# To create or update issues
|
||||
issues: write
|
||||
steps:
|
||||
- name: Open, update, or close SPDX issue
|
||||
uses: Homebrew/actions/create-or-update-issue@main
|
||||
with:
|
||||
title: Failed to update SPDX license data
|
||||
body: >
|
||||
The SPDX license data workflow [failed](${{ env.RUN_URL }}). No SPDX license data was updated.
|
||||
labels: bug
|
||||
update-existing: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }}
|
||||
close-existing: ${{ needs.spdx.result == 'success' }}
|
||||
close-from-author: github-actions[bot]
|
||||
close-comment: >
|
||||
The SPDX license data workflow [succeeded](${{ env.RUN_URL }}). Closing this issue.
|
||||
|
@ -3,6 +3,7 @@ name: Update sponsors, maintainers, manpage and completions
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
paths:
|
||||
- .github/workflows/sponsors-maintainers-man-completions.yml
|
||||
@ -32,19 +33,19 @@ jobs:
|
||||
steps:
|
||||
- name: Setup Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
test-bot: false
|
||||
|
||||
- name: Configure Git user
|
||||
uses: Homebrew/actions/git-user-config@master
|
||||
uses: Homebrew/actions/git-user-config@main
|
||||
with:
|
||||
username: BrewTestBot
|
||||
|
||||
- name: Set up commit signing
|
||||
uses: Homebrew/actions/setup-commit-signing@master
|
||||
uses: Homebrew/actions/setup-commit-signing@main
|
||||
with:
|
||||
signing_key: ${{ secrets.BREWTESTBOT_SSH_SIGNING_KEY }}
|
||||
|
||||
@ -60,7 +61,7 @@ jobs:
|
||||
run: |
|
||||
git fetch origin
|
||||
|
||||
if [[ -n "$GITHUB_REF_NAME" && "$GITHUB_REF_NAME" != "master" ]]
|
||||
if [[ -n "$GITHUB_REF_NAME" && "$GITHUB_REF_NAME" != "master" && "$GITHUB_REF_NAME" != "main" ]]
|
||||
then
|
||||
BRANCH="$GITHUB_REF_NAME"
|
||||
else
|
||||
@ -76,7 +77,7 @@ jobs:
|
||||
"manpages/brew.1" \
|
||||
"completions"
|
||||
else
|
||||
git checkout --force --no-track -B "${BRANCH}" origin/master
|
||||
git checkout --force --no-track -B "${BRANCH}" origin/HEAD
|
||||
fi
|
||||
|
||||
if brew update-sponsors
|
||||
@ -111,7 +112,7 @@ jobs:
|
||||
if [[ -n "${COMMITTED-}" ]]
|
||||
then
|
||||
echo "committed=true" >> "$GITHUB_OUTPUT"
|
||||
PULL_REQUEST_STATE="$(gh pr view --json=state | jq -r ".state")"
|
||||
PULL_REQUEST_STATE="$(gh pr view --json=state | jq -r ".state" || true)"
|
||||
if [[ "${PULL_REQUEST_STATE}" != "OPEN" ]]
|
||||
then
|
||||
echo "pull_request=true" >> "$GITHUB_OUTPUT"
|
||||
@ -124,7 +125,7 @@ jobs:
|
||||
|
||||
- name: Push commits
|
||||
if: steps.update.outputs.committed == 'true'
|
||||
uses: Homebrew/actions/git-try-push@master
|
||||
uses: Homebrew/actions/git-try-push@main
|
||||
with:
|
||||
token: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }}
|
||||
directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
|
||||
@ -137,3 +138,26 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.HOMEBREW_GITHUB_PUBLIC_REPO_TOKEN }}
|
||||
working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
|
||||
|
||||
issue:
|
||||
needs: updates
|
||||
if: always() && github.event_name == 'schedule'
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
permissions:
|
||||
# To create or update issues
|
||||
issues: write
|
||||
steps:
|
||||
- name: Open, update, or close sponsors, maintainers, manpage and completions issue
|
||||
uses: Homebrew/actions/create-or-update-issue@main
|
||||
with:
|
||||
title: Failed to update sponsors, maintainers, manpage and completions
|
||||
body: >
|
||||
The sponsors, maintainers, manpage and completions workflow [failed](${{ env.RUN_URL }}). No sponsors, maintainers, manpage and completions were updated.
|
||||
labels: bug
|
||||
update-existing: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped') }}
|
||||
close-existing: ${{ needs.updates.result == 'success' }}
|
||||
close-from-author: github-actions[bot]
|
||||
close-comment: >
|
||||
The sponsors, maintainers, manpage and completions workflow [succeeded](${{ env.RUN_URL }}). Closing this issue.
|
||||
|
63
.github/workflows/sync-default-branches.yml
vendored
Normal file
63
.github/workflows/sync-default-branches.yml
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
name: Sync default branches
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/sync-default-branches.yml
|
||||
|
||||
permissions: {}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash -xeuo pipefail {0}
|
||||
|
||||
concurrency:
|
||||
group: "sync-default-branches-${{ github.ref }}"
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Configure Git user
|
||||
uses: Homebrew/actions/git-user-config@main
|
||||
with:
|
||||
username: github-actions[bot]
|
||||
|
||||
- name: Determine source and target branches
|
||||
id: branches
|
||||
run: |
|
||||
if [[ "${GITHUB_REF_NAME}" == "main" ]]; then
|
||||
target="master"
|
||||
source="main"
|
||||
else
|
||||
target="main"
|
||||
source="master"
|
||||
fi
|
||||
echo "target=${target}" >> "$GITHUB_OUTPUT"
|
||||
echo "source=${source}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: true
|
||||
|
||||
- name: Setup target branch
|
||||
run: |
|
||||
git checkout "${TARGET_BRANCH}" || git checkout -b "${TARGET_BRANCH}"
|
||||
git reset --hard "origin/${SOURCE_BRANCH}"
|
||||
env:
|
||||
SOURCE_BRANCH: ${{ steps.branches.outputs.source }}
|
||||
TARGET_BRANCH: ${{ steps.branches.outputs.target }}
|
||||
|
||||
- name: Push target branch
|
||||
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
|
||||
run: git push origin "${TARGET_BRANCH}" --force-with-lease
|
||||
env:
|
||||
TARGET_BRANCH: ${{ steps.branches.outputs.target }}
|
25
.github/workflows/tests.yml
vendored
25
.github/workflows/tests.yml
vendored
@ -3,6 +3,7 @@ name: CI
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
pull_request:
|
||||
merge_group:
|
||||
@ -32,7 +33,7 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
@ -84,7 +85,7 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: true
|
||||
cask: true
|
||||
@ -135,11 +136,12 @@ jobs:
|
||||
if: github.repository_owner == 'Homebrew' && github.event_name != 'push'
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
# TODO: switch to main when we're pushing those images
|
||||
image: ghcr.io/homebrew/brew:master
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
@ -162,7 +164,7 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: true
|
||||
@ -185,14 +187,14 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
test-bot: false
|
||||
|
||||
- name: Configure Git user
|
||||
uses: Homebrew/actions/git-user-config@master
|
||||
uses: Homebrew/actions/git-user-config@main
|
||||
with:
|
||||
username: BrewTestBot
|
||||
|
||||
@ -220,7 +222,7 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
@ -255,7 +257,7 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
# We only test needs_homebrew_core tests on macOS because
|
||||
# homebrew/core is not available by default on GitHub-hosted Ubuntu
|
||||
@ -355,6 +357,7 @@ jobs:
|
||||
container: ghcr.io/homebrew/ubuntu24.04:latest
|
||||
- name: test-bot (Linux x86_64)
|
||||
runs-on: ubuntu-latest
|
||||
# TODO: switch to main when we've migrated to it
|
||||
container: ghcr.io/homebrew/ubuntu22.04:master
|
||||
# Use Debian Old Stable for testing Homebrew's glibc support.
|
||||
- name: test-bot (Linux Homebrew glibc)
|
||||
@ -402,7 +405,7 @@ jobs:
|
||||
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
@ -442,7 +445,7 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
@ -496,7 +499,7 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
||||
|
9
.github/workflows/vendor-gems.yml
vendored
9
.github/workflows/vendor-gems.yml
vendored
@ -9,6 +9,7 @@ on:
|
||||
paths:
|
||||
- .github/workflows/vendor-gems.yml
|
||||
branches-ignore:
|
||||
- main
|
||||
- master
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
@ -31,7 +32,7 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
@ -39,13 +40,13 @@ jobs:
|
||||
|
||||
- name: Configure Git user
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
uses: Homebrew/actions/git-user-config@master
|
||||
uses: Homebrew/actions/git-user-config@main
|
||||
with:
|
||||
username: BrewTestBot
|
||||
|
||||
- name: Set up commit signing
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
uses: Homebrew/actions/setup-commit-signing@master
|
||||
uses: Homebrew/actions/setup-commit-signing@main
|
||||
with:
|
||||
signing_key: ${{ secrets.BREWTESTBOT_SSH_SIGNING_KEY }}
|
||||
|
||||
@ -100,7 +101,7 @@ jobs:
|
||||
|
||||
- name: Push to pull request
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
uses: Homebrew/actions/git-try-push@master
|
||||
uses: Homebrew/actions/git-try-push@main
|
||||
with:
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
|
||||
|
2
.github/workflows/vendor-version.yml
vendored
2
.github/workflows/vendor-version.yml
vendored
@ -19,7 +19,7 @@ jobs:
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
core: false
|
||||
cask: false
|
||||
|
1
.github/zizmor.yml
vendored
1
.github/zizmor.yml
vendored
@ -1,3 +1,4 @@
|
||||
# This file is synced from the `.github` repository, do not modify it directly.
|
||||
rules:
|
||||
unpinned-uses:
|
||||
config:
|
||||
|
11
.vscode/mcp.json
vendored
Normal file
11
.vscode/mcp.json
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"servers": {
|
||||
"Homebrew": {
|
||||
"type": "stdio",
|
||||
"command": "brew",
|
||||
"args": [
|
||||
"mcp-server"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
9
.vscode/ruby-lsp-activate.sh
vendored
9
.vscode/ruby-lsp-activate.sh
vendored
@ -1,5 +1,12 @@
|
||||
#!/bin/bash
|
||||
HOMEBREW_PREFIX="$(cd "$(dirname "$0")"/../ && pwd)"
|
||||
if [[ -n "${BASH_SOURCE[0]}" ]]; then
|
||||
SCRIPT_PATH="${BASH_SOURCE[0]}"
|
||||
elif [[ -n "${ZSH_VERSION}" ]]; then
|
||||
SCRIPT_PATH="${(%):-%x}"
|
||||
else
|
||||
SCRIPT_PATH="$0"
|
||||
fi
|
||||
HOMEBREW_PREFIX="$(cd "$(dirname "${SCRIPT_PATH}")"/../ && pwd)"
|
||||
|
||||
"${HOMEBREW_PREFIX}/bin/brew" install-bundler-gems --add-groups=style,typecheck,vscode >/dev/null 2>&1
|
||||
|
||||
|
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -40,7 +40,6 @@
|
||||
"id": "default",
|
||||
"name": "Brew Typecheck",
|
||||
"description": "Default configuration",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"command": [
|
||||
"./bin/brew",
|
||||
"typecheck",
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "api/analytics"
|
||||
@ -11,10 +11,10 @@ module Homebrew
|
||||
module API
|
||||
extend Cachable
|
||||
|
||||
HOMEBREW_CACHE_API = (HOMEBREW_CACHE/"api").freeze
|
||||
HOMEBREW_CACHE_API_SOURCE = (HOMEBREW_CACHE/"api-source").freeze
|
||||
HOMEBREW_CACHE_API = T.let((HOMEBREW_CACHE/"api").freeze, Pathname)
|
||||
HOMEBREW_CACHE_API_SOURCE = T.let((HOMEBREW_CACHE/"api-source").freeze, Pathname)
|
||||
|
||||
sig { params(endpoint: String).returns(Hash) }
|
||||
sig { params(endpoint: String).returns(T::Hash[String, T.untyped]) }
|
||||
def self.fetch(endpoint)
|
||||
return cache[endpoint] if cache.present? && cache.key?(endpoint)
|
||||
|
||||
@ -33,7 +33,8 @@ module Homebrew
|
||||
end
|
||||
|
||||
sig {
|
||||
params(endpoint: String, target: Pathname, stale_seconds: Integer).returns([T.any(Array, Hash), T::Boolean])
|
||||
params(endpoint: String, target: Pathname,
|
||||
stale_seconds: Integer).returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
|
||||
}
|
||||
def self.fetch_json_api_file(endpoint, target: HOMEBREW_CACHE_API/endpoint,
|
||||
stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i)
|
||||
@ -96,7 +97,8 @@ module Homebrew
|
||||
|
||||
mtime = insecure_download ? Time.new(1970, 1, 1) : Time.now
|
||||
FileUtils.touch(target, mtime:) unless skip_download
|
||||
JSON.parse(target.read(encoding: Encoding::UTF_8), freeze: true)
|
||||
# Can use `target.read` again when/if https://github.com/sorbet/sorbet/pull/8999 is merged/released.
|
||||
JSON.parse(File.read(target, encoding: Encoding::UTF_8), freeze: true)
|
||||
rescue JSON::ParserError
|
||||
target.unlink
|
||||
retry_count += 1
|
||||
@ -122,8 +124,11 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(json: Hash, bottle_tag: T.nilable(::Utils::Bottles::Tag)).returns(Hash) }
|
||||
def self.merge_variations(json, bottle_tag: nil)
|
||||
sig {
|
||||
params(json: T::Hash[String, T.untyped],
|
||||
bottle_tag: ::Utils::Bottles::Tag).returns(T::Hash[String, T.untyped])
|
||||
}
|
||||
def self.merge_variations(json, bottle_tag: T.unsafe(nil))
|
||||
return json unless json.key?("variations")
|
||||
|
||||
bottle_tag ||= Homebrew::SimulateSystem.current_tag
|
||||
@ -147,7 +152,10 @@ module Homebrew
|
||||
false
|
||||
end
|
||||
|
||||
sig { params(json_data: Hash).returns([T::Boolean, T.any(String, Array, Hash)]) }
|
||||
sig {
|
||||
params(json_data: T::Hash[String, T.untyped])
|
||||
.returns([T::Boolean, T.any(String, T::Array[T.untyped], T::Hash[String, T.untyped])])
|
||||
}
|
||||
private_class_method def self.verify_and_parse_jws(json_data)
|
||||
signatures = json_data["signatures"]
|
||||
homebrew_signature = signatures&.find { |sig| sig.dig("header", "kid") == "homebrew-1" }
|
||||
|
@ -10,7 +10,6 @@ module Homebrew
|
||||
def analytics_api_path
|
||||
"analytics"
|
||||
end
|
||||
alias generic_analytics_api_path analytics_api_path
|
||||
|
||||
sig { params(category: String, days: T.any(Integer, String)).returns(T::Hash[String, T.untyped]) }
|
||||
def fetch(category, days)
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "cachable"
|
||||
@ -21,7 +21,7 @@ module Homebrew
|
||||
|
||||
private_class_method :cache
|
||||
|
||||
sig { params(token: String).returns(Hash) }
|
||||
sig { params(token: String).returns(T::Hash[String, T.untyped]) }
|
||||
def self.fetch(token)
|
||||
Homebrew::API.fetch "cask/#{token}.json"
|
||||
end
|
||||
@ -47,6 +47,7 @@ module Homebrew
|
||||
.load(config: cask.config)
|
||||
end
|
||||
|
||||
sig { returns(Pathname) }
|
||||
def self.cached_json_file_path
|
||||
HOMEBREW_CACHE_API/api_filename
|
||||
end
|
||||
@ -70,7 +71,7 @@ module Homebrew
|
||||
end
|
||||
private_class_method :download_and_cache_data!
|
||||
|
||||
sig { returns(T::Hash[String, Hash]) }
|
||||
sig { returns(T::Hash[String, T::Hash[String, T.untyped]]) }
|
||||
def self.all_casks
|
||||
unless cache.key?("casks")
|
||||
json_updated = download_and_cache_data!
|
||||
|
@ -1,22 +1,26 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Used to substitute common paths with generic placeholders when generating JSON for the API.
|
||||
module APIHashable
|
||||
sig { void }
|
||||
def generating_hash!
|
||||
return if generating_hash?
|
||||
|
||||
# Apply monkeypatches for API generation
|
||||
@old_homebrew_prefix = HOMEBREW_PREFIX
|
||||
@old_homebrew_cellar = HOMEBREW_CELLAR
|
||||
@old_home = Dir.home
|
||||
@old_homebrew_prefix = T.let(HOMEBREW_PREFIX, T.nilable(Pathname))
|
||||
@old_homebrew_cellar = T.let(HOMEBREW_CELLAR, T.nilable(Pathname))
|
||||
@old_home = T.let(Dir.home, T.nilable(String))
|
||||
@old_git_config_global = T.let(ENV.fetch("GIT_CONFIG_GLOBAL", nil), T.nilable(String))
|
||||
Object.send(:remove_const, :HOMEBREW_PREFIX)
|
||||
Object.const_set(:HOMEBREW_PREFIX, Pathname.new(HOMEBREW_PREFIX_PLACEHOLDER))
|
||||
ENV["HOME"] = HOMEBREW_HOME_PLACEHOLDER
|
||||
ENV["GIT_CONFIG_GLOBAL"] = File.join(@old_home, ".gitconfig")
|
||||
|
||||
@generating_hash = true
|
||||
@generating_hash = T.let(true, T.nilable(T::Boolean))
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def generated_hash!
|
||||
return unless generating_hash?
|
||||
|
||||
@ -24,10 +28,12 @@ module APIHashable
|
||||
Object.send(:remove_const, :HOMEBREW_PREFIX)
|
||||
Object.const_set(:HOMEBREW_PREFIX, @old_homebrew_prefix)
|
||||
ENV["HOME"] = @old_home
|
||||
ENV["GIT_CONFIG_GLOBAL"] = @old_git_config_global
|
||||
|
||||
@generating_hash = false
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def generating_hash?
|
||||
@generating_hash ||= false
|
||||
@generating_hash == true
|
||||
|
@ -52,4 +52,4 @@ FORMULA_COMPONENT_PRECEDENCE_LIST = T.let([
|
||||
[{ name: :caveats, type: :method_definition }],
|
||||
[{ name: :plist_options, type: :method_call }, { name: :plist, type: :method_definition }],
|
||||
[{ name: :test, type: :block_call }],
|
||||
].freeze, T::Array[[{ name: Symbol, type: Symbol }]])
|
||||
].freeze, T::Array[T::Array[{ name: Symbol, type: Symbol }]])
|
||||
|
@ -614,6 +614,8 @@ esac
|
||||
# and, if needed:
|
||||
# - MacOSVersion::SYMBOLS
|
||||
HOMEBREW_MACOS_NEWEST_UNSUPPORTED="16"
|
||||
# TODO: bump version when new macOS is released
|
||||
HOMEBREW_MACOS_NEWEST_SUPPORTED="15"
|
||||
# TODO: bump version when new macOS is released and update references in:
|
||||
# - docs/Installation.md
|
||||
# - HOMEBREW_MACOS_OLDEST_SUPPORTED in .github/workflows/pkg-installer.yml
|
||||
@ -841,6 +843,7 @@ export HOMEBREW_OS_VERSION
|
||||
export HOMEBREW_MACOS_VERSION
|
||||
export HOMEBREW_MACOS_VERSION_NUMERIC
|
||||
export HOMEBREW_MACOS_NEWEST_UNSUPPORTED
|
||||
export HOMEBREW_MACOS_NEWEST_SUPPORTED
|
||||
export HOMEBREW_MACOS_OLDEST_SUPPORTED
|
||||
export HOMEBREW_MACOS_OLDEST_ALLOWED
|
||||
export HOMEBREW_USER_AGENT
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "bundle/adder"
|
||||
@ -7,6 +7,7 @@ module Homebrew
|
||||
module Bundle
|
||||
module Commands
|
||||
module Add
|
||||
sig { params(args: String, type: Symbol, global: T::Boolean, file: T.nilable(String)).void }
|
||||
def self.run(*args, type:, global:, file:)
|
||||
Homebrew::Bundle::Adder.add(*args, type:, global:, file:)
|
||||
end
|
||||
|
@ -19,7 +19,6 @@ module Homebrew
|
||||
puts "Installing #{name} tap. It is not currently installed." if verbose
|
||||
args = []
|
||||
args << "--force" if force
|
||||
args.append("--force-auto-update") if options[:force_auto_update]
|
||||
|
||||
success = if options[:clone_target]
|
||||
Bundle.brew("tap", name, options[:clone_target], *args, verbose:)
|
||||
|
@ -139,7 +139,11 @@ module Cask
|
||||
|
||||
def initialize(cask, *dsl_args)
|
||||
@cask = cask
|
||||
@dirmethod = nil
|
||||
@dsl_args = dsl_args.deep_dup
|
||||
@dsl_key = nil
|
||||
@english_article = nil
|
||||
@english_name = nil
|
||||
end
|
||||
|
||||
def config
|
||||
|
@ -41,7 +41,9 @@ module Cask
|
||||
super
|
||||
|
||||
target = target_hash[:target]
|
||||
@source = nil
|
||||
@source_string = source.to_s
|
||||
@target = nil
|
||||
@target_string = target.to_s
|
||||
end
|
||||
|
||||
|
@ -1,9 +1,14 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Cask
|
||||
# Sorted set containing all cask artifacts.
|
||||
class ArtifactSet < ::Set
|
||||
extend T::Generic
|
||||
|
||||
Elem = type_member(:out) { { fixed: Artifact::AbstractArtifact } }
|
||||
|
||||
sig { params(block: T.nilable(T.proc.params(arg0: Elem).returns(T.untyped))).void }
|
||||
def each(&block)
|
||||
return enum_for(T.must(__method__)) { size } unless block
|
||||
|
||||
@ -11,6 +16,7 @@ module Cask
|
||||
self
|
||||
end
|
||||
|
||||
sig { returns(T::Array[Artifact::AbstractArtifact]) }
|
||||
def to_a
|
||||
super.sort
|
||||
end
|
||||
|
@ -653,11 +653,12 @@ module Cask
|
||||
|
||||
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 }
|
||||
|
||||
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
|
||||
elsif !supports_arm && !mentions_rosetta && !requires_intel
|
||||
add_error "Artifacts require Rosetta 2 but this is not indicated by the caveats!",
|
||||
location: url.location
|
||||
end
|
||||
@ -701,45 +702,53 @@ module Cask
|
||||
return unless online?
|
||||
return unless strict?
|
||||
|
||||
odebug "Auditing minimum OS version"
|
||||
odebug "Auditing minimum macOS version"
|
||||
|
||||
plist_min_os = cask_plist_min_os
|
||||
sparkle_min_os = livecheck_min_os
|
||||
bundle_min_os = cask_bundle_min_os
|
||||
sparkle_min_os = cask_sparkle_min_os
|
||||
|
||||
app_min_os = [bundle_min_os, sparkle_min_os].compact.max
|
||||
debug_messages = []
|
||||
debug_messages << "Plist #{plist_min_os}" if plist_min_os
|
||||
debug_messages << "Sparkle #{sparkle_min_os}" if sparkle_min_os
|
||||
odebug "Detected minimum OS version: #{debug_messages.join(" | ")}" unless debug_messages.empty?
|
||||
min_os = [plist_min_os, sparkle_min_os].compact.max
|
||||
|
||||
return if min_os.nil? || min_os <= HOMEBREW_MACOS_OLDEST_ALLOWED
|
||||
debug_messages << "from artifact: #{bundle_min_os.to_sym}" if bundle_min_os
|
||||
debug_messages << "from upstream: #{sparkle_min_os.to_sym}" if sparkle_min_os
|
||||
odebug "Detected minimum macOS: #{app_min_os.to_sym} (#{debug_messages.join(" | ")})" if app_min_os
|
||||
return if app_min_os.nil? || app_min_os <= HOMEBREW_MACOS_OLDEST_ALLOWED
|
||||
|
||||
on_system_block_min_os = cask.on_system_block_min_os
|
||||
cask_min_os = [on_system_block_min_os, cask.depends_on.macos&.minimum_version].compact.max
|
||||
odebug "Declared minimum OS version: #{cask_min_os&.to_sym}"
|
||||
return if cask_min_os&.to_sym == min_os.to_sym
|
||||
return if cask.on_system_blocks_exist? &&
|
||||
OnSystem.arch_condition_met?(:arm) &&
|
||||
depends_on_min_os = cask.depends_on.macos&.minimum_version
|
||||
|
||||
cask_min_os = [on_system_block_min_os, depends_on_min_os].compact.max
|
||||
debug_messages = []
|
||||
debug_messages << "from on_system block: #{on_system_block_min_os.to_sym}" if on_system_block_min_os
|
||||
if depends_on_min_os > HOMEBREW_MACOS_OLDEST_ALLOWED
|
||||
debug_messages << "from depends_on stanza: #{depends_on_min_os.to_sym}"
|
||||
end
|
||||
odebug "Declared minimum macOS: #{cask_min_os.to_sym} (#{debug_messages.join(" | ").presence || "default"})"
|
||||
return if cask_min_os.to_sym == app_min_os.to_sym
|
||||
# ignore declared minimum OS < 11.x when auditing as ARM a cask with arch-specific artifacts
|
||||
return if OnSystem.arch_condition_met?(:arm) &&
|
||||
cask.on_system_blocks_exist? &&
|
||||
cask_min_os.present? &&
|
||||
cask_min_os < MacOSVersion.new("11")
|
||||
|
||||
min_os_definition = if cask_min_os.present?
|
||||
if on_system_block_min_os.present? &&
|
||||
on_system_block_min_os > cask.depends_on.macos&.minimum_version
|
||||
"a block with a minimum OS version of #{cask_min_os.to_sym.inspect}"
|
||||
min_os_definition = if cask_min_os > HOMEBREW_MACOS_OLDEST_ALLOWED
|
||||
definition = if T.must(on_system_block_min_os.to_s <=> depends_on_min_os.to_s).positive?
|
||||
"an on_system block"
|
||||
else
|
||||
cask_min_os.to_sym.inspect
|
||||
"a depends_on stanza"
|
||||
end
|
||||
"#{definition} with a minimum macOS version of #{cask_min_os.to_sym.inspect}"
|
||||
else
|
||||
"no minimum OS version"
|
||||
"no minimum macOS version"
|
||||
end
|
||||
add_error "Upstream defined #{min_os.to_sym.inspect} as the minimum OS version " \
|
||||
source = T.must(bundle_min_os.to_s <=> sparkle_min_os.to_s).positive? ? "Artifact" : "Upstream"
|
||||
add_error "#{source} defined #{app_min_os.to_sym.inspect} as the minimum macOS version " \
|
||||
"but the cask declared #{min_os_definition}",
|
||||
strict_only: true
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(MacOSVersion)) }
|
||||
def livecheck_min_os
|
||||
def cask_sparkle_min_os
|
||||
return unless online?
|
||||
return unless cask.livecheck_defined?
|
||||
return if cask.livecheck.strategy != :sparkle
|
||||
@ -772,10 +781,10 @@ module Cask
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(MacOSVersion)) }
|
||||
def cask_plist_min_os
|
||||
def cask_bundle_min_os
|
||||
return unless online?
|
||||
|
||||
plist_min_os = T.let(nil, T.untyped)
|
||||
min_os = T.let(nil, T.untyped)
|
||||
@staged_path ||= cask.staged_path
|
||||
|
||||
extract_artifacts do |artifacts, tmpdir|
|
||||
@ -786,13 +795,33 @@ module Cask
|
||||
next unless File.exist?(plist_path)
|
||||
|
||||
plist = system_command!("plutil", args: ["-convert", "xml1", "-o", "-", plist_path]).plist
|
||||
plist_min_os = plist["LSMinimumSystemVersion"].presence
|
||||
break if plist_min_os
|
||||
min_os = plist["LSMinimumSystemVersion"].presence
|
||||
break if min_os
|
||||
|
||||
next unless (main_binary = get_plist_main_binary(path))
|
||||
next if !File.exist?(main_binary) || File.open(main_binary, "rb") { |f| f.read(2) == "#!" }
|
||||
|
||||
macho = MachO.open(main_binary)
|
||||
min_os = case macho
|
||||
when MachO::MachOFile
|
||||
[
|
||||
macho[:LC_VERSION_MIN_MACOSX].first&.version_string,
|
||||
macho[:LC_BUILD_VERSION].first&.minos_string,
|
||||
]
|
||||
when MachO::FatFile
|
||||
macho.machos.map do |slice|
|
||||
[
|
||||
slice[:LC_VERSION_MIN_MACOSX].first&.version_string,
|
||||
slice[:LC_BUILD_VERSION].first&.minos_string,
|
||||
]
|
||||
end.flatten
|
||||
end.compact.min
|
||||
break if min_os
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
MacOSVersion.new(plist_min_os).strip_patch
|
||||
MacOSVersion.new(min_os).strip_patch
|
||||
rescue MacOSVersion::Error
|
||||
nil
|
||||
end
|
||||
|
@ -295,7 +295,7 @@ module Cask
|
||||
sig { returns(Pathname) }
|
||||
attr_reader :path
|
||||
|
||||
sig { returns(T.nilable(T::Hash[T.any(String, Symbol), T.anything])) }
|
||||
sig { returns(T.nilable(T::Hash[String, T.untyped])) }
|
||||
attr_reader :from_json
|
||||
|
||||
sig {
|
||||
@ -320,7 +320,7 @@ module Cask
|
||||
sig {
|
||||
params(
|
||||
token: String,
|
||||
from_json: T.nilable(T::Hash[T.any(String, Symbol), T.anything]),
|
||||
from_json: T.nilable(T::Hash[String, T.untyped]),
|
||||
path: T.nilable(Pathname),
|
||||
).void
|
||||
}
|
||||
|
@ -69,7 +69,6 @@ module Cask
|
||||
].freeze
|
||||
|
||||
DSL_METHODS = Set.new([
|
||||
:appcast,
|
||||
:arch,
|
||||
:artifacts,
|
||||
:auto_updates,
|
||||
@ -123,15 +122,21 @@ module Cask
|
||||
|
||||
sig { params(cask: Cask).void }
|
||||
def initialize(cask)
|
||||
# NOTE: Variables set by `set_unique_stanza` must be initialized to `nil`.
|
||||
@auto_updates = T.let(nil, T.nilable(T::Boolean))
|
||||
# NOTE: `:"@#{stanza}"` variables set by `set_unique_stanza` must be
|
||||
# initialized to `nil`.
|
||||
@arch = T.let(nil, T.nilable(String))
|
||||
@arch_set_in_block = T.let(false, T::Boolean)
|
||||
@artifacts = T.let(ArtifactSet.new, ArtifactSet)
|
||||
@auto_updates = T.let(nil, T.nilable(T::Boolean))
|
||||
@auto_updates_set_in_block = T.let(false, T::Boolean)
|
||||
@autobump = T.let(true, T::Boolean)
|
||||
@called_in_on_system_block = T.let(false, T::Boolean)
|
||||
@cask = T.let(cask, Cask)
|
||||
@caveats = T.let(DSL::Caveats.new(cask), DSL::Caveats)
|
||||
@conflicts_with = T.let(nil, T.nilable(DSL::ConflictsWith))
|
||||
@conflicts_with_set_in_block = T.let(false, T::Boolean)
|
||||
@container = T.let(nil, T.nilable(DSL::Container))
|
||||
@container_set_in_block = T.let(false, T::Boolean)
|
||||
@depends_on = T.let(DSL::DependsOn.new, DSL::DependsOn)
|
||||
@depends_on_set_in_block = T.let(false, T::Boolean)
|
||||
@deprecated = T.let(false, T::Boolean)
|
||||
@ -140,27 +145,32 @@ module Cask
|
||||
@deprecation_replacement_cask = T.let(nil, T.nilable(String))
|
||||
@deprecation_replacement_formula = T.let(nil, T.nilable(String))
|
||||
@desc = T.let(nil, T.nilable(String))
|
||||
@desc_set_in_block = T.let(false, T::Boolean)
|
||||
@disable_date = T.let(nil, T.nilable(Date))
|
||||
@disable_reason = T.let(nil, T.nilable(T.any(String, Symbol)))
|
||||
@disable_replacement_cask = T.let(nil, T.nilable(String))
|
||||
@disable_replacement_formula = T.let(nil, T.nilable(String))
|
||||
@disabled = T.let(false, T::Boolean)
|
||||
@homepage = T.let(nil, T.nilable(String))
|
||||
@homepage_set_in_block = T.let(false, T::Boolean)
|
||||
@language_blocks = T.let({}, T::Hash[T::Array[String], Proc])
|
||||
@language_eval = T.let(nil, T.nilable(String))
|
||||
@livecheck = T.let(Livecheck.new(cask), Livecheck)
|
||||
@livecheck_defined = T.let(false, T::Boolean)
|
||||
@name = T.let([], T::Array[String])
|
||||
@autobump = T.let(true, T::Boolean)
|
||||
@no_autobump_defined = T.let(false, T::Boolean)
|
||||
@on_system_blocks_exist = T.let(false, T::Boolean)
|
||||
@os = T.let(nil, T.nilable(String))
|
||||
@on_system_block_min_os = T.let(nil, T.nilable(MacOSVersion))
|
||||
@os = T.let(nil, T.nilable(String))
|
||||
@os_set_in_block = T.let(false, T::Boolean)
|
||||
@sha256 = T.let(nil, T.nilable(T.any(Checksum, Symbol)))
|
||||
@sha256_set_in_block = T.let(false, T::Boolean)
|
||||
@staged_path = T.let(nil, T.nilable(Pathname))
|
||||
@token = T.let(cask.token, String)
|
||||
@url = T.let(nil, T.nilable(URL))
|
||||
@url_set_in_block = T.let(false, T::Boolean)
|
||||
@version = T.let(nil, T.nilable(DSL::Version))
|
||||
@version_set_in_block = T.let(false, T::Boolean)
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
@ -216,7 +226,7 @@ module Cask
|
||||
raise CaskInvalidError.new(cask, "'#{stanza}' stanza may only appear once.")
|
||||
end
|
||||
|
||||
if instance_variable_defined?(:"@#{stanza}_set_in_block") && @called_in_on_system_block
|
||||
if instance_variable_get(:"@#{stanza}_set_in_block") && @called_in_on_system_block
|
||||
raise CaskInvalidError.new(cask, "'#{stanza}' stanza may only be overridden once.")
|
||||
end
|
||||
end
|
||||
@ -476,7 +486,7 @@ module Cask
|
||||
def add_implicit_macos_dependency
|
||||
return if (cask_depends_on = @depends_on).present? && cask_depends_on.macos.present?
|
||||
|
||||
depends_on macos: ">= :#{MacOSVersion::SYMBOLS.key MacOSVersion::SYMBOLS.values.min}"
|
||||
depends_on macos: ">= #{MacOSVersion.new(HOMEBREW_MACOS_OLDEST_ALLOWED).to_sym.inspect}"
|
||||
end
|
||||
|
||||
# Declare conflicts that keep a cask from installing or working correctly.
|
||||
|
@ -52,16 +52,17 @@ module Cask
|
||||
raise "Only a single 'depends_on macos' is allowed." if defined?(@macos)
|
||||
|
||||
# workaround for https://github.com/sorbet/sorbet/issues/6860
|
||||
first_arg = args.first&.to_s
|
||||
first_arg = args.first
|
||||
first_arg_s = first_arg&.to_s
|
||||
|
||||
begin
|
||||
@macos = if args.count > 1
|
||||
MacOSRequirement.new([args], comparator: "==")
|
||||
elsif MacOSVersion::SYMBOLS.key?(args.first)
|
||||
elsif first_arg.is_a?(Symbol) && MacOSVersion::SYMBOLS.key?(first_arg)
|
||||
MacOSRequirement.new([args.first], comparator: "==")
|
||||
elsif (md = /^\s*(?<comparator><|>|[=<>]=)\s*:(?<version>\S+)\s*$/.match(first_arg))
|
||||
elsif (md = /^\s*(?<comparator><|>|[=<>]=)\s*:(?<version>\S+)\s*$/.match(first_arg_s))
|
||||
MacOSRequirement.new([T.must(md[:version]).to_sym], comparator: md[:comparator])
|
||||
elsif (md = /^\s*(?<comparator><|>|[=<>]=)\s*(?<version>\S+)\s*$/.match(first_arg))
|
||||
elsif (md = /^\s*(?<comparator><|>|[=<>]=)\s*(?<version>\S+)\s*$/.match(first_arg_s))
|
||||
MacOSRequirement.new([md[:version]], comparator: md[:comparator])
|
||||
# This is not duplicate of the first case: see `args.first` and a different comparator.
|
||||
else # rubocop:disable Lint/DuplicateBranch
|
||||
|
@ -4,6 +4,7 @@
|
||||
require "formula_installer"
|
||||
require "unpack_strategy"
|
||||
require "utils/topological_hash"
|
||||
require "utils/analytics"
|
||||
|
||||
require "cask/config"
|
||||
require "cask/download"
|
||||
@ -303,6 +304,20 @@ on_request: true)
|
||||
|
||||
next if artifact.is_a?(Artifact::Binary) && !binaries?
|
||||
|
||||
artifact = T.cast(
|
||||
artifact,
|
||||
T.any(
|
||||
Artifact::AbstractFlightBlock,
|
||||
Artifact::Installer,
|
||||
Artifact::KeyboardLayout,
|
||||
Artifact::Mdimporter,
|
||||
Artifact::Moved,
|
||||
Artifact::Pkg,
|
||||
Artifact::Qlplugin,
|
||||
Artifact::Symlinked,
|
||||
),
|
||||
)
|
||||
|
||||
artifact.install_phase(
|
||||
command: @command, verbose: verbose?, adopt: adopt?, auto_updates: @cask.auto_updates,
|
||||
force: force?, predecessor:
|
||||
@ -548,6 +563,18 @@ on_request: true)
|
||||
|
||||
artifacts.each do |artifact|
|
||||
if artifact.respond_to?(:uninstall_phase)
|
||||
artifact = T.cast(
|
||||
artifact,
|
||||
T.any(
|
||||
Artifact::AbstractFlightBlock,
|
||||
Artifact::KeyboardLayout,
|
||||
Artifact::Moved,
|
||||
Artifact::Qlplugin,
|
||||
Artifact::Symlinked,
|
||||
Artifact::Uninstall,
|
||||
),
|
||||
)
|
||||
|
||||
odebug "Uninstalling artifact of class #{artifact.class}"
|
||||
artifact.uninstall_phase(
|
||||
command: @command,
|
||||
@ -562,6 +589,8 @@ on_request: true)
|
||||
|
||||
next unless artifact.respond_to?(:post_uninstall_phase)
|
||||
|
||||
artifact = T.cast(artifact, Artifact::Uninstall)
|
||||
|
||||
odebug "Post-uninstalling artifact of class #{artifact.class}"
|
||||
artifact.post_uninstall_phase(
|
||||
command: @command,
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "abstract_command"
|
||||
@ -6,6 +6,7 @@ require "formula"
|
||||
require "fetch"
|
||||
require "cask/download"
|
||||
require "retryable_download"
|
||||
require "download_queue"
|
||||
|
||||
module Homebrew
|
||||
module Cmd
|
||||
@ -69,15 +70,16 @@ module Homebrew
|
||||
named_args [:formula, :cask], min: 1
|
||||
end
|
||||
|
||||
sig { returns(Integer) }
|
||||
def concurrency
|
||||
@concurrency ||= args.concurrency&.to_i || 1
|
||||
@concurrency ||= T.let(args.concurrency&.to_i || 1, T.nilable(Integer))
|
||||
end
|
||||
|
||||
sig { returns(DownloadQueue) }
|
||||
def download_queue
|
||||
@download_queue ||= begin
|
||||
require "download_queue"
|
||||
@download_queue ||= T.let(begin
|
||||
DownloadQueue.new(concurrency)
|
||||
end
|
||||
end, T.nilable(DownloadQueue))
|
||||
end
|
||||
|
||||
class Spinner
|
||||
@ -96,8 +98,8 @@ module Homebrew
|
||||
|
||||
sig { void }
|
||||
def initialize
|
||||
@start = Time.now
|
||||
@i = 0
|
||||
@start = T.let(Time.now, Time)
|
||||
@i = T.let(0, Integer)
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
@ -136,7 +138,7 @@ module Homebrew
|
||||
bucket.each do |formula_or_cask|
|
||||
case formula_or_cask
|
||||
when Formula
|
||||
formula = T.cast(formula_or_cask, Formula)
|
||||
formula = formula_or_cask
|
||||
ref = formula.loaded_from_api? ? formula.full_name : formula.path
|
||||
|
||||
os_arch_combinations.each do |os, arch|
|
||||
@ -189,7 +191,9 @@ module Homebrew
|
||||
|
||||
next if fetched_bottle
|
||||
|
||||
fetch_downloadable(formula.resource)
|
||||
if (resource = formula.resource)
|
||||
fetch_downloadable(resource)
|
||||
end
|
||||
|
||||
formula.resources.each do |r|
|
||||
fetch_downloadable(r)
|
||||
@ -231,7 +235,7 @@ module Homebrew
|
||||
end
|
||||
else
|
||||
spinner = Spinner.new
|
||||
remaining_downloads = downloads.dup
|
||||
remaining_downloads = downloads.dup.to_a
|
||||
previous_pending_line_count = 0
|
||||
|
||||
begin
|
||||
@ -332,10 +336,13 @@ module Homebrew
|
||||
|
||||
private
|
||||
|
||||
sig { returns(T::Hash[T.any(Resource, Bottle, Cask::Download), Concurrent::Promises::Future]) }
|
||||
def downloads
|
||||
@downloads ||= {}
|
||||
@downloads ||= T.let({}, T.nilable(T::Hash[T.any(Resource, Bottle, Cask::Download),
|
||||
Concurrent::Promises::Future]))
|
||||
end
|
||||
|
||||
sig { params(downloadable: T.any(Resource, Bottle, Cask::Download)).void }
|
||||
def fetch_downloadable(downloadable)
|
||||
downloads[downloadable] ||= begin
|
||||
tries = args.retry? ? {} : { tries: 1 }
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "abstract_command"
|
||||
@ -18,7 +18,7 @@ module Homebrew
|
||||
class Info < AbstractCommand
|
||||
VALID_DAYS = %w[30 90 365].freeze
|
||||
VALID_FORMULA_CATEGORIES = %w[install install-on-request build-error].freeze
|
||||
VALID_CATEGORIES = (VALID_FORMULA_CATEGORIES + %w[cask-install os-version]).freeze
|
||||
VALID_CATEGORIES = T.let((VALID_FORMULA_CATEGORIES + %w[cask-install os-version]).freeze, T::Array[String])
|
||||
|
||||
cmd_args do
|
||||
description <<~EOS
|
||||
@ -96,14 +96,17 @@ module Homebrew
|
||||
end
|
||||
|
||||
print_analytics
|
||||
elsif args.json
|
||||
elsif (json = args.json)
|
||||
all = args.eval_all?
|
||||
|
||||
print_json(all)
|
||||
print_json(json, all)
|
||||
elsif args.github?
|
||||
raise FormulaOrCaskUnspecifiedError if args.no_named?
|
||||
|
||||
exec_browser(*args.named.to_formulae_and_casks.map { |f| github_info(f) })
|
||||
exec_browser(*args.named.to_formulae_and_casks.map do |formula_keg_or_cask|
|
||||
formula_or_cask = T.cast(formula_keg_or_cask, T.any(Formula, Cask::Cask))
|
||||
github_info(formula_or_cask)
|
||||
end)
|
||||
elsif args.no_named?
|
||||
print_statistics
|
||||
else
|
||||
@ -111,6 +114,7 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(remote: String, path: String).returns(String) }
|
||||
def github_remote_path(remote, path)
|
||||
if remote =~ %r{^(?:https?://|git(?:@|://))github\.com[:/](.+)/(.+?)(?:\.git)?$}
|
||||
"https://github.com/#{Regexp.last_match(1)}/#{Regexp.last_match(2)}/blob/HEAD/#{path}"
|
||||
@ -175,6 +179,7 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(version: T.any(T::Boolean, String)).returns(Symbol) }
|
||||
def json_version(version)
|
||||
version_hash = {
|
||||
true => :default,
|
||||
@ -187,11 +192,11 @@ module Homebrew
|
||||
version_hash[version]
|
||||
end
|
||||
|
||||
sig { params(all: T::Boolean).void }
|
||||
def print_json(all)
|
||||
sig { params(json: T.any(T::Boolean, String), all: T::Boolean).void }
|
||||
def print_json(json, all)
|
||||
raise FormulaOrCaskUnspecifiedError if !(all || args.installed?) && args.no_named?
|
||||
|
||||
json = case json_version(args.json)
|
||||
json = case json_version(json)
|
||||
when :v1, :default
|
||||
raise UsageError, "Cannot specify `--cask` when using `--json=v1`!" if args.cask?
|
||||
|
||||
@ -240,25 +245,31 @@ module Homebrew
|
||||
puts JSON.pretty_generate(json)
|
||||
end
|
||||
|
||||
sig { params(formula_or_cask: T.any(Formula, Cask::Cask)).returns(String) }
|
||||
def github_info(formula_or_cask)
|
||||
return formula_or_cask.path if formula_or_cask.tap.blank? || formula_or_cask.tap.remote.blank?
|
||||
|
||||
path = case formula_or_cask
|
||||
when Formula
|
||||
formula = formula_or_cask
|
||||
formula.path.relative_path_from(T.must(formula.tap).path)
|
||||
tap = formula.tap
|
||||
return formula.path.to_s if tap.blank? || tap.remote.blank?
|
||||
|
||||
formula.path.relative_path_from(tap.path)
|
||||
when Cask::Cask
|
||||
cask = formula_or_cask
|
||||
tap = cask.tap
|
||||
return cask.sourcefile_path.to_s if tap.blank? || tap.remote.blank?
|
||||
|
||||
if cask.sourcefile_path.blank? || cask.sourcefile_path.extname != ".rb"
|
||||
return "#{cask.tap.default_remote}/blob/HEAD/#{cask.tap.relative_cask_path(cask.token)}"
|
||||
return "#{tap.default_remote}/blob/HEAD/#{tap.relative_cask_path(cask.token)}"
|
||||
end
|
||||
|
||||
cask.sourcefile_path.relative_path_from(cask.tap.path)
|
||||
cask.sourcefile_path.relative_path_from(tap.path)
|
||||
end
|
||||
|
||||
github_remote_path(formula_or_cask.tap.remote, path)
|
||||
github_remote_path(tap.remote, path.to_s)
|
||||
end
|
||||
|
||||
sig { params(formula: Formula).void }
|
||||
def info_formula(formula)
|
||||
specs = []
|
||||
|
||||
@ -356,6 +367,7 @@ module Homebrew
|
||||
Utils::Analytics.formula_output(formula, args:)
|
||||
end
|
||||
|
||||
sig { params(dependencies: T::Array[Dependency]).returns(String) }
|
||||
def decorate_dependencies(dependencies)
|
||||
deps_status = dependencies.map do |dep|
|
||||
if dep.satisfied?([])
|
||||
@ -367,6 +379,7 @@ module Homebrew
|
||||
deps_status.join(", ")
|
||||
end
|
||||
|
||||
sig { params(requirements: T::Array[Requirement]).returns(String) }
|
||||
def decorate_requirements(requirements)
|
||||
req_status = requirements.map do |req|
|
||||
req_s = req.display_s
|
||||
@ -375,12 +388,14 @@ module Homebrew
|
||||
req_status.join(", ")
|
||||
end
|
||||
|
||||
sig { params(dep: Dependency).returns(String) }
|
||||
def dep_display_s(dep)
|
||||
return dep.name if dep.option_tags.empty?
|
||||
|
||||
"#{dep.name} #{dep.option_tags.map { |o| "--#{o}" }.join(" ")}"
|
||||
end
|
||||
|
||||
sig { params(cask: Cask::Cask).void }
|
||||
def info_cask(cask)
|
||||
require "cask/info"
|
||||
|
||||
|
@ -63,6 +63,8 @@ module Homebrew
|
||||
puts info
|
||||
else
|
||||
info = ""
|
||||
default_branches = %w[main master].freeze
|
||||
|
||||
taps.each_with_index do |tap, i|
|
||||
puts unless i.zero?
|
||||
info = "#{tap}: "
|
||||
@ -79,7 +81,7 @@ module Homebrew
|
||||
info += "\norigin: #{tap.remote}" if tap.remote != tap.default_remote
|
||||
info += "\nHEAD: #{tap.git_head || "(none)"}"
|
||||
info += "\nlast commit: #{tap.git_last_commit || "never"}"
|
||||
info += "\nbranch: #{tap.git_branch || "(none)"}" if tap.git_branch != "master"
|
||||
info += "\nbranch: #{tap.git_branch || "(none)"}" if default_branches.exclude?(tap.git_branch)
|
||||
else
|
||||
info += "Not installed"
|
||||
end
|
||||
|
@ -33,8 +33,6 @@ module Homebrew
|
||||
"integration.",
|
||||
replacement: false,
|
||||
disable: true
|
||||
switch "--[no-]force-auto-update",
|
||||
hidden: true
|
||||
switch "--custom-remote",
|
||||
description: "Install or change a tap with a custom remote. Useful for mirrors."
|
||||
switch "--repair",
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "abstract_command"
|
||||
@ -39,13 +39,15 @@ module Homebrew
|
||||
|
||||
private
|
||||
|
||||
sig { void }
|
||||
def auto_update_header
|
||||
@auto_update_header ||= begin
|
||||
@auto_update_header ||= T.let(begin
|
||||
ohai "Auto-updated Homebrew!" if args.auto_update?
|
||||
true
|
||||
end
|
||||
end, T.nilable(T::Boolean))
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def output_update_report
|
||||
# Run `brew update` (again) if we've got a linuxbrew-core CoreTap
|
||||
if CoreTap.instance.installed? && CoreTap.instance.linuxbrew_core? &&
|
||||
@ -293,14 +295,17 @@ module Homebrew
|
||||
EOS
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def no_changes_message
|
||||
"No changes to formulae or casks."
|
||||
end
|
||||
|
||||
sig { params(revision: String).returns(String) }
|
||||
def shorten_revision(revision)
|
||||
Utils.popen_read("git", "-C", HOMEBREW_REPOSITORY, "rev-parse", "--short", revision).chomp
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def tap_or_untap_core_taps_if_necessary
|
||||
return if ENV["HOMEBREW_UPDATE_TEST"]
|
||||
|
||||
@ -320,10 +325,11 @@ module Homebrew
|
||||
return if (HOMEBREW_PREFIX/".homebrewdocker").exist?
|
||||
|
||||
tap_output_header_printed = T.let(false, T::Boolean)
|
||||
default_branches = %w[main master].freeze
|
||||
[CoreTap.instance, CoreCaskTap.instance].each do |tap|
|
||||
next unless tap.installed?
|
||||
|
||||
if tap.git_branch == "master" &&
|
||||
if default_branches.include?(tap.git_branch) &&
|
||||
(Date.parse(T.must(tap.git_repository.last_commit_date)) <= Date.today.prev_month)
|
||||
ohai "#{tap.name} is old and unneeded, untapping to save space..."
|
||||
tap.uninstall
|
||||
@ -339,6 +345,7 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(repository: Pathname).void }
|
||||
def link_completions_manpages_and_docs(repository = HOMEBREW_REPOSITORY)
|
||||
command = "brew update"
|
||||
Utils::Link.link_completions(repository, command)
|
||||
@ -351,10 +358,12 @@ module Homebrew
|
||||
EOS
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def migrate_gcc_dependents_if_needed
|
||||
# do nothing
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def analytics_message
|
||||
return if Utils::Analytics.messages_displayed?
|
||||
return if Utils::Analytics.no_message_output?
|
||||
@ -384,6 +393,7 @@ module Homebrew
|
||||
Utils::Analytics.messages_displayed! if $stdout.tty?
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def donation_message
|
||||
return if Settings.read("donationmessage") == "true"
|
||||
|
||||
@ -394,6 +404,7 @@ module Homebrew
|
||||
Settings.write "donationmessage", true if $stdout.tty?
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def install_from_api_message
|
||||
return if Settings.read("installfromapimessage") == "true"
|
||||
|
||||
@ -418,30 +429,38 @@ require "extend/os/cmd/update-report"
|
||||
|
||||
class Reporter
|
||||
class ReporterRevisionUnsetError < RuntimeError
|
||||
sig { params(var_name: String).void }
|
||||
def initialize(var_name)
|
||||
super "#{var_name} is unset!"
|
||||
end
|
||||
end
|
||||
|
||||
sig {
|
||||
params(tap: Tap, api_names_txt: T.nilable(Pathname), api_names_before_txt: T.nilable(Pathname),
|
||||
api_dir_prefix: T.nilable(Pathname)).void
|
||||
}
|
||||
def initialize(tap, api_names_txt: nil, api_names_before_txt: nil, api_dir_prefix: nil)
|
||||
@tap = tap
|
||||
|
||||
# This is slightly involved/weird but all the #report logic is shared so it's worth it.
|
||||
if installed_from_api?(api_names_txt, api_names_before_txt, api_dir_prefix)
|
||||
@api_names_txt = api_names_txt
|
||||
@api_names_before_txt = api_names_before_txt
|
||||
@api_dir_prefix = api_dir_prefix
|
||||
@api_names_txt = T.let(api_names_txt, T.nilable(Pathname))
|
||||
@api_names_before_txt = T.let(api_names_before_txt, T.nilable(Pathname))
|
||||
@api_dir_prefix = T.let(api_dir_prefix, T.nilable(Pathname))
|
||||
else
|
||||
initial_revision_var = "HOMEBREW_UPDATE_BEFORE#{tap.repository_var_suffix}"
|
||||
@initial_revision = ENV[initial_revision_var].to_s
|
||||
@initial_revision = T.let(ENV[initial_revision_var].to_s, String)
|
||||
raise ReporterRevisionUnsetError, initial_revision_var if @initial_revision.empty?
|
||||
|
||||
current_revision_var = "HOMEBREW_UPDATE_AFTER#{tap.repository_var_suffix}"
|
||||
@current_revision = ENV[current_revision_var].to_s
|
||||
@current_revision = T.let(ENV[current_revision_var].to_s, String)
|
||||
raise ReporterRevisionUnsetError, current_revision_var if @current_revision.empty?
|
||||
end
|
||||
|
||||
@report = T.let(nil, T.nilable(T::Hash[Symbol, T::Array[String]]))
|
||||
end
|
||||
|
||||
sig { params(auto_update: T::Boolean).returns(T::Hash[Symbol, T::Array[String]]) }
|
||||
def report(auto_update: false)
|
||||
return @report if @report
|
||||
|
||||
@ -482,9 +501,9 @@ class Reporter
|
||||
case status
|
||||
when "A", "D"
|
||||
full_name = tap.formula_file_to_name(src)
|
||||
name = full_name.split("/").last
|
||||
name = T.must(full_name.split("/").last)
|
||||
new_tap = tap.tap_migrations[name]
|
||||
@report[status.to_sym] << full_name unless new_tap
|
||||
@report[T.must(status).to_sym] << full_name unless new_tap
|
||||
when "M"
|
||||
name = tap.formula_file_to_name(src)
|
||||
|
||||
@ -584,6 +603,7 @@ class Reporter
|
||||
@report
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def updated?
|
||||
if installed_from_api?
|
||||
diff.present?
|
||||
@ -592,9 +612,10 @@ class Reporter
|
||||
end
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def migrate_tap_migration
|
||||
(report[:D] + report[:DC]).each do |full_name|
|
||||
name = full_name.split("/").last
|
||||
(Array(report[:D]) + Array(report[:DC])).each do |full_name|
|
||||
name = T.must(full_name.split("/").last)
|
||||
new_tap_name = tap.tap_migrations[name]
|
||||
next if new_tap_name.nil? # skip if not in tap_migrations list.
|
||||
|
||||
@ -609,7 +630,7 @@ class Reporter
|
||||
end
|
||||
|
||||
# This means it is a cask
|
||||
if report[:DC].include? full_name
|
||||
if Array(report[:DC]).include? full_name
|
||||
next unless (HOMEBREW_PREFIX/"Caskroom"/new_name).exist?
|
||||
|
||||
new_tap = Tap.fetch(new_tap_name)
|
||||
@ -675,12 +696,14 @@ class Reporter
|
||||
end
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def migrate_cask_rename
|
||||
Cask::Caskroom.casks.each do |cask|
|
||||
Cask::Migrator.migrate_if_needed(cask)
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(force: T::Boolean, verbose: T::Boolean).void }
|
||||
def migrate_formula_rename(force:, verbose:)
|
||||
Formula.installed.each do |formula|
|
||||
next unless Migrator.needs_migration?(formula)
|
||||
@ -704,14 +727,36 @@ class Reporter
|
||||
|
||||
private
|
||||
|
||||
attr_reader :tap, :initial_revision, :current_revision, :api_names_txt, :api_names_before_txt, :api_dir_prefix
|
||||
sig { returns(Tap) }
|
||||
attr_reader :tap
|
||||
|
||||
sig { returns(String) }
|
||||
attr_reader :initial_revision
|
||||
|
||||
sig { returns(String) }
|
||||
attr_reader :current_revision
|
||||
|
||||
sig { returns(T.nilable(Pathname)) }
|
||||
attr_reader :api_names_txt
|
||||
|
||||
sig { returns(T.nilable(Pathname)) }
|
||||
attr_reader :api_names_before_txt
|
||||
|
||||
sig { returns(T.nilable(Pathname)) }
|
||||
attr_reader :api_dir_prefix
|
||||
|
||||
sig {
|
||||
params(api_names_txt: T.nilable(Pathname), api_names_before_txt: T.nilable(Pathname),
|
||||
api_dir_prefix: T.nilable(Pathname)).returns(T::Boolean)
|
||||
}
|
||||
def installed_from_api?(api_names_txt = @api_names_txt, api_names_before_txt = @api_names_before_txt,
|
||||
api_dir_prefix = @api_dir_prefix)
|
||||
!api_names_txt.nil? && !api_names_before_txt.nil? && !api_dir_prefix.nil?
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def diff
|
||||
@diff ||= T.let(nil, T.nilable(String))
|
||||
@diff ||= if installed_from_api?
|
||||
# Hack `git diff` output with regexes to look like `git diff-tree` output.
|
||||
# Yes, I know this is a bit filthy but it saves duplicating the #report logic.
|
||||
@ -719,12 +764,14 @@ class Reporter
|
||||
header_regex = /^(---|\+\+\+) /
|
||||
add_delete_characters = ["+", "-"].freeze
|
||||
|
||||
api_dir_prefix_basename = T.must(api_dir_prefix).basename
|
||||
|
||||
diff_output.lines.filter_map do |line|
|
||||
next if line.match?(header_regex)
|
||||
next unless add_delete_characters.include?(line[0])
|
||||
|
||||
line.sub(/^\+/, "A #{api_dir_prefix.basename}/")
|
||||
.sub(/^-/, "D #{api_dir_prefix.basename}/")
|
||||
line.sub(/^\+/, "A #{api_dir_prefix_basename}/")
|
||||
.sub(/^-/, "D #{api_dir_prefix_basename}/")
|
||||
.sub(/$/, ".rb")
|
||||
.chomp
|
||||
end.join("\n")
|
||||
@ -738,28 +785,33 @@ class Reporter
|
||||
end
|
||||
|
||||
class ReporterHub
|
||||
sig { returns(T::Array[Reporter]) }
|
||||
attr_reader :reporters
|
||||
|
||||
sig { void }
|
||||
def initialize
|
||||
@hash = {}
|
||||
@reporters = []
|
||||
@hash = T.let({}, T::Hash[Symbol, T::Array[String]])
|
||||
@reporters = T.let([], T::Array[Reporter])
|
||||
end
|
||||
|
||||
sig { params(key: Symbol).returns(T::Array[String]) }
|
||||
def select_formula_or_cask(key)
|
||||
@hash.fetch(key, [])
|
||||
end
|
||||
|
||||
sig { params(reporter: Reporter, auto_update: T::Boolean).void }
|
||||
def add(reporter, auto_update: false)
|
||||
@reporters << reporter
|
||||
report = reporter.report(auto_update:).delete_if { |_k, v| v.empty? }
|
||||
@hash.update(report) { |_key, oldval, newval| oldval.concat(newval) }
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def empty?
|
||||
@hash.empty?
|
||||
end
|
||||
|
||||
sig { params(auto_update: T::Boolean).void }
|
||||
def dump(auto_update: false)
|
||||
unless Homebrew::EnvConfig.no_update_report_new?
|
||||
dump_new_formula_report
|
||||
@ -814,12 +866,14 @@ class ReporterHub
|
||||
|
||||
private
|
||||
|
||||
sig { void }
|
||||
def dump_new_formula_report
|
||||
formulae = select_formula_or_cask(:A).sort.reject { |name| installed?(name) }
|
||||
|
||||
output_dump_formula_or_cask_report "New Formulae", formulae
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def dump_new_cask_report
|
||||
return if Homebrew::SimulateSystem.simulating_or_running_on_linux?
|
||||
|
||||
@ -830,6 +884,7 @@ class ReporterHub
|
||||
output_dump_formula_or_cask_report "New Casks", casks
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def dump_deleted_formula_report
|
||||
formulae = select_formula_or_cask(:D).sort.filter_map do |name|
|
||||
pretty_uninstalled(name) if installed?(name)
|
||||
@ -838,37 +893,43 @@ class ReporterHub
|
||||
output_dump_formula_or_cask_report "Deleted Installed Formulae", formulae
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def dump_deleted_cask_report
|
||||
return if Homebrew::SimulateSystem.simulating_or_running_on_linux?
|
||||
|
||||
casks = select_formula_or_cask(:DC).sort.filter_map do |name|
|
||||
name = name.split("/").last
|
||||
name = T.must(name.split("/").last)
|
||||
pretty_uninstalled(name) if cask_installed?(name)
|
||||
end
|
||||
|
||||
output_dump_formula_or_cask_report "Deleted Installed Casks", casks
|
||||
end
|
||||
|
||||
sig { params(title: String, formulae_or_casks: T::Array[String]).void }
|
||||
def output_dump_formula_or_cask_report(title, formulae_or_casks)
|
||||
return if formulae_or_casks.blank?
|
||||
|
||||
ohai title, Formatter.columns(formulae_or_casks.sort)
|
||||
end
|
||||
|
||||
sig { params(formula: String).returns(T::Boolean) }
|
||||
def installed?(formula)
|
||||
(HOMEBREW_CELLAR/formula.split("/").last).directory?
|
||||
end
|
||||
|
||||
sig { params(formula: String).returns(T::Boolean) }
|
||||
def outdated?(formula)
|
||||
Formula[formula].outdated?
|
||||
rescue FormulaUnavailableError
|
||||
false
|
||||
end
|
||||
|
||||
sig { params(cask: String).returns(T::Boolean) }
|
||||
def cask_installed?(cask)
|
||||
(Cask::Caskroom.path/cask).directory?
|
||||
end
|
||||
|
||||
sig { params(cask: String).returns(T::Boolean) }
|
||||
def cask_outdated?(cask)
|
||||
Cask::CaskLoader.load(cask).outdated?
|
||||
rescue Cask::CaskError
|
||||
|
@ -54,9 +54,10 @@ git_init_if_necessary() {
|
||||
fi
|
||||
git config remote.origin.url "${HOMEBREW_BREW_GIT_REMOTE}"
|
||||
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
|
||||
git config fetch.prune true
|
||||
git fetch --force --tags origin
|
||||
git remote set-head origin --auto >/dev/null
|
||||
git reset --hard origin/master
|
||||
git reset --hard origin/HEAD
|
||||
SKIP_FETCH_BREW_REPOSITORY=1
|
||||
set +e
|
||||
trap - EXIT
|
||||
@ -77,9 +78,10 @@ git_init_if_necessary() {
|
||||
fi
|
||||
git config remote.origin.url "${HOMEBREW_CORE_GIT_REMOTE}"
|
||||
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
|
||||
git fetch --force origin refs/heads/master:refs/remotes/origin/master
|
||||
git config fetch.prune true
|
||||
git fetch --force origin
|
||||
git remote set-head origin --auto >/dev/null
|
||||
git reset --hard origin/master
|
||||
git reset --hard origin/HEAD
|
||||
SKIP_FETCH_CORE_REPOSITORY=1
|
||||
set +e
|
||||
trap - EXIT
|
||||
@ -110,7 +112,7 @@ upstream_branch() {
|
||||
upstream_branch="$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null)"
|
||||
fi
|
||||
upstream_branch="${upstream_branch#refs/remotes/origin/}"
|
||||
[[ -z "${upstream_branch}" ]] && upstream_branch="master"
|
||||
[[ -z "${upstream_branch}" ]] && upstream_branch="main"
|
||||
echo "${upstream_branch}"
|
||||
}
|
||||
|
||||
@ -242,7 +244,7 @@ merge_or_rebase() {
|
||||
Could not 'git stash' in ${DIR}!
|
||||
Please stash/commit manually if you need to keep your changes or, if not, run:
|
||||
cd ${DIR}
|
||||
git reset --hard origin/master
|
||||
git reset --hard origin/HEAD
|
||||
EOS
|
||||
fi
|
||||
git reset --hard "${QUIET_ARGS[@]}"
|
||||
@ -260,10 +262,12 @@ EOS
|
||||
then
|
||||
git checkout --force "${UPSTREAM_BRANCH}" "${QUIET_ARGS[@]}"
|
||||
else
|
||||
if [[ -n "${UPSTREAM_TAG}" && "${UPSTREAM_BRANCH}" != "master" ]] &&
|
||||
[[ "${INITIAL_BRANCH}" != "master" ]]
|
||||
if [[ -n "${UPSTREAM_TAG}" && "${UPSTREAM_BRANCH}" != "master" && "${UPSTREAM_BRANCH}" != "main" ]] &&
|
||||
[[ "${INITIAL_BRANCH}" != "master" && "${INITIAL_BRANCH}" != "main" ]]
|
||||
then
|
||||
git branch --force "master" "origin/master" "${QUIET_ARGS[@]}"
|
||||
local detected_upstream_branch
|
||||
detected_upstream_branch="$(upstream_branch)"
|
||||
git branch --force "${detected_upstream_branch}" "origin/${detected_upstream_branch}" "${QUIET_ARGS[@]}"
|
||||
fi
|
||||
|
||||
git checkout --force -B "${UPSTREAM_BRANCH}" "${REMOTE_REF}" "${QUIET_ARGS[@]}"
|
||||
@ -541,7 +545,8 @@ EOS
|
||||
echo "HOMEBREW_CORE_GIT_REMOTE set: using ${HOMEBREW_CORE_GIT_REMOTE} as the Homebrew/homebrew-core Git remote."
|
||||
git remote set-url origin "${HOMEBREW_CORE_GIT_REMOTE}"
|
||||
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
|
||||
git fetch --force origin refs/heads/master:refs/remotes/origin/master
|
||||
git config fetch.prune true
|
||||
git fetch --force origin
|
||||
SKIP_FETCH_CORE_REPOSITORY=1
|
||||
fi
|
||||
|
||||
@ -642,9 +647,9 @@ EOS
|
||||
UPDATING_MESSAGE_SHOWN=1
|
||||
fi
|
||||
|
||||
# The upstream repository's default branch may not be master;
|
||||
# The upstream repository's default branch may not be main or master;
|
||||
# check refs/remotes/origin/HEAD to see what the default
|
||||
# origin branch name is, and use that. If not set, fall back to "master".
|
||||
# origin branch name is, and use that. If not set, fall back to "main".
|
||||
# the refspec ensures that the default upstream branch gets updated
|
||||
(
|
||||
UPSTREAM_REPOSITORY_URL="$(git config remote.origin.url)"
|
||||
@ -732,9 +737,9 @@ EOS
|
||||
then
|
||||
local git_errors
|
||||
git_errors="$(cat "${tmp_failure_file}")"
|
||||
# Attempt migration from master to main branch.
|
||||
if [[ "${git_errors}" == "fatal: couldn't find remote ref refs/heads/master" ]]
|
||||
then
|
||||
# Attempt migration from master to main branch.
|
||||
if git fetch --tags --force "${QUIET_ARGS[@]}" origin \
|
||||
"refs/heads/main:refs/remotes/origin/main" 2>>"${tmp_failure_file}"
|
||||
then
|
||||
|
@ -1,12 +1,12 @@
|
||||
{
|
||||
"$schema" : "https://json-schema.org/draft/2019-09/schema",
|
||||
"$id" : "http://spdx.org/rdf/terms/2.3",
|
||||
"title" : "SPDX 2.3",
|
||||
"title" : "SPDX 2.3.1-dev",
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"$schema": {
|
||||
"type": "string",
|
||||
"description": "Reference the SPDX 2.3 JSON schema."
|
||||
"description": "Reference the SPDX 2.3.1 JSON schema."
|
||||
},
|
||||
"SPDXID" : {
|
||||
"type" : "string",
|
||||
@ -90,7 +90,7 @@
|
||||
"enum" : [ "SHA1", "BLAKE3", "SHA3-384", "SHA256", "SHA384", "BLAKE2b-512", "BLAKE2b-256", "SHA3-512", "MD2", "ADLER32", "MD4", "SHA3-256", "BLAKE2b-384", "SHA512", "MD6", "MD5", "SHA224" ]
|
||||
},
|
||||
"checksumValue" : {
|
||||
"description" : "The checksumValue property provides a lower case hexidecimal encoded digest value produced using a specific algorithm.",
|
||||
"description" : "The checksumValue property provides a lower case hexadecimal encoded digest value produced using a specific algorithm.",
|
||||
"type" : "string"
|
||||
}
|
||||
},
|
||||
@ -270,10 +270,10 @@
|
||||
}
|
||||
},
|
||||
"attributionTexts" : {
|
||||
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
|
||||
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConcluded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
|
||||
"type" : "array",
|
||||
"items" : {
|
||||
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
|
||||
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConcluded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
|
||||
"type" : "string"
|
||||
}
|
||||
},
|
||||
@ -293,7 +293,7 @@
|
||||
"enum" : [ "SHA1", "BLAKE3", "SHA3-384", "SHA256", "SHA384", "BLAKE2b-512", "BLAKE2b-256", "SHA3-512", "MD2", "ADLER32", "MD4", "SHA3-256", "BLAKE2b-384", "SHA512", "MD6", "MD5", "SHA224" ]
|
||||
},
|
||||
"checksumValue" : {
|
||||
"description" : "The checksumValue property provides a lower case hexidecimal encoded digest value produced using a specific algorithm.",
|
||||
"description" : "The checksumValue property provides a lower case hexadecimal encoded digest value produced using a specific algorithm.",
|
||||
"type" : "string"
|
||||
}
|
||||
},
|
||||
@ -375,10 +375,10 @@
|
||||
"type" : "string"
|
||||
},
|
||||
"licenseInfoFromFiles" : {
|
||||
"description" : "The licensing information that was discovered directly within the package. There will be an instance of this property for each distinct value of alllicenseInfoInFile properties of all files contained in the package.\n\nIf the licenseInfoFromFiles field is not present for a package and filesAnalyzed property for that same package is true or omitted, it implies an equivalent meaning to NOASSERTION.",
|
||||
"description" : "The licensing information that was discovered directly within the package. There will be an instance of this property for each distinct value of all licenseInfoInFile properties of all files contained in the package.\n\nIf the licenseInfoFromFiles field is not present for a package and filesAnalyzed property for that same package is true or omitted, it implies an equivalent meaning to NOASSERTION.",
|
||||
"type" : "array",
|
||||
"items" : {
|
||||
"description" : "License expression for licenseInfoFromFiles. See SPDX Annex D for the license expression syntax. The licensing information that was discovered directly within the package. There will be an instance of this property for each distinct value of alllicenseInfoInFile properties of all files contained in the package.\n\nIf the licenseInfoFromFiles field is not present for a package and filesAnalyzed property for that same package is true or omitted, it implies an equivalent meaning to NOASSERTION.",
|
||||
"description" : "License expression for licenseInfoFromFiles. See SPDX Annex D for the license expression syntax. The licensing information that was discovered directly within the package. There will be an instance of this property for each distinct value of all licenseInfoInFile properties of all files contained in the package.\n\nIf the licenseInfoFromFiles field is not present for a package and filesAnalyzed property for that same package is true or omitted, it implies an equivalent meaning to NOASSERTION.",
|
||||
"type" : "string"
|
||||
}
|
||||
},
|
||||
@ -417,7 +417,7 @@
|
||||
"primaryPackagePurpose" : {
|
||||
"description" : "This field provides information about the primary purpose of the identified package. Package Purpose is intrinsic to how the package is being used rather than the content of the package.",
|
||||
"type" : "string",
|
||||
"enum" : [ "OTHER", "INSTALL", "ARCHIVE", "FIRMWARE", "APPLICATION", "FRAMEWORK", "LIBRARY", "CONTAINER", "SOURCE", "DEVICE", "OPERATING_SYSTEM", "FILE" ]
|
||||
"enum" : [ "OTHER", "INSTALL", "ARCHIVE", "FIRMWARE", "APPLICATION", "FRAMEWORK", "LIBRARY", "CONTAINER", "SOURCE", "DEVICE", "OPERATING-SYSTEM", "FILE" ]
|
||||
},
|
||||
"releaseDate" : {
|
||||
"description" : "This field provides a place for recording the date the package was released.",
|
||||
@ -494,10 +494,10 @@
|
||||
}
|
||||
},
|
||||
"attributionTexts" : {
|
||||
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
|
||||
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConcluded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
|
||||
"type" : "array",
|
||||
"items" : {
|
||||
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
|
||||
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConcluded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
|
||||
"type" : "string"
|
||||
}
|
||||
},
|
||||
@ -514,7 +514,7 @@
|
||||
"enum" : [ "SHA1", "BLAKE3", "SHA3-384", "SHA256", "SHA384", "BLAKE2b-512", "BLAKE2b-256", "SHA3-512", "MD2", "ADLER32", "MD4", "SHA3-256", "BLAKE2b-384", "SHA512", "MD6", "MD5", "SHA224" ]
|
||||
},
|
||||
"checksumValue" : {
|
||||
"description" : "The checksumValue property provides a lower case hexidecimal encoded digest value produced using a specific algorithm.",
|
||||
"description" : "The checksumValue property provides a lower case hexadecimal encoded digest value produced using a specific algorithm.",
|
||||
"type" : "string"
|
||||
}
|
||||
},
|
||||
@ -624,10 +624,10 @@
|
||||
}
|
||||
},
|
||||
"attributionTexts" : {
|
||||
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
|
||||
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConcluded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
|
||||
"type" : "array",
|
||||
"items" : {
|
||||
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConculded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
|
||||
"description" : "This field provides a place for the SPDX data creator to record acknowledgements that may be required to be communicated in some contexts. This is not meant to include the actual complete license text (see licenseConcluded and licenseDeclared), and may or may not include copyright notices (see also copyrightText). The SPDX data creator may use this field to record other acknowledgements, such as particular clauses from license texts, which may be necessary or desirable to reproduce.",
|
||||
"type" : "string"
|
||||
}
|
||||
},
|
||||
@ -709,7 +709,7 @@
|
||||
}
|
||||
},
|
||||
"snippetFromFile" : {
|
||||
"description" : "SPDX ID for File. File containing the SPDX element (e.g. the file contaning a snippet).",
|
||||
"description" : "SPDX ID for File. File containing the SPDX element (e.g. the file containing a snippet).",
|
||||
"type" : "string"
|
||||
}
|
||||
},
|
||||
|
@ -1,13 +1,15 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "irb"
|
||||
|
||||
module IRB
|
||||
sig { params(binding: Binding).void }
|
||||
def self.start_within(binding)
|
||||
old_stdout_sync = $stdout.sync
|
||||
$stdout.sync = true
|
||||
|
||||
@setup_done ||= T.let(false, T.nilable(T::Boolean))
|
||||
unless @setup_done
|
||||
setup(nil, argv: [])
|
||||
@setup_done = true
|
||||
|
@ -190,7 +190,7 @@ module Homebrew
|
||||
def generate_system_options(cask)
|
||||
current_os = Homebrew::SimulateSystem.current_os
|
||||
current_os_is_macos = MacOSVersion::SYMBOLS.include?(current_os)
|
||||
newest_macos = MacOSVersion::SYMBOLS.keys.first
|
||||
newest_macos = MacOSVersion.new(HOMEBREW_MACOS_NEWEST_SUPPORTED).to_sym
|
||||
|
||||
depends_on_archs = cask.depends_on.arch&.filter_map { |arch| arch[:type] }&.uniq
|
||||
|
||||
|
@ -399,7 +399,7 @@ module Homebrew
|
||||
nil
|
||||
end
|
||||
|
||||
if github_release_data.present?
|
||||
if github_release_data.present? && github_release_data["body"].present?
|
||||
pre = "pre" if github_release_data["prerelease"].present?
|
||||
# maximum length of PR body is 65,536 characters so let's truncate release notes to half of that.
|
||||
body = Formatter.truncate(github_release_data["body"], max: 32_768)
|
||||
|
@ -183,41 +183,42 @@ module Homebrew
|
||||
:zig
|
||||
end
|
||||
|
||||
fc = FormulaCreator.new(
|
||||
args.set_name,
|
||||
args.set_version,
|
||||
tap: args.tap,
|
||||
formula_creator = FormulaCreator.new(
|
||||
url: args.named.fetch(0),
|
||||
name: args.set_name,
|
||||
version: args.set_version,
|
||||
tap: args.tap,
|
||||
mode:,
|
||||
license: args.set_license,
|
||||
fetch: !args.no_fetch?,
|
||||
head: args.HEAD?,
|
||||
)
|
||||
fc.parse_url
|
||||
|
||||
# ask for confirmation if name wasn't passed explicitly
|
||||
if args.set_name.blank?
|
||||
print "Formula name [#{fc.name}]: "
|
||||
fc.name = __gets || fc.name
|
||||
print "Formula name [#{formula_creator.name}]: "
|
||||
confirmed_name = __gets
|
||||
formula_creator.name = confirmed_name if confirmed_name.present?
|
||||
end
|
||||
|
||||
fc.verify
|
||||
formula_creator.verify_tap_available!
|
||||
|
||||
# Check for disallowed formula, or names that shadow aliases,
|
||||
# unless --force is specified.
|
||||
unless args.force?
|
||||
if (reason = MissingFormula.disallowed_reason(fc.name))
|
||||
if (reason = MissingFormula.disallowed_reason(formula_creator.name))
|
||||
odie <<~EOS
|
||||
The formula '#{fc.name}' is not allowed to be created.
|
||||
The formula '#{formula_creator.name}' is not allowed to be created.
|
||||
#{reason}
|
||||
If you really want to create this formula use `--force`.
|
||||
EOS
|
||||
end
|
||||
|
||||
Homebrew.with_no_api_env do
|
||||
if Formula.aliases.include? fc.name
|
||||
realname = Formulary.canonical_name(fc.name)
|
||||
if Formula.aliases.include?(formula_creator.name)
|
||||
realname = Formulary.canonical_name(formula_creator.name)
|
||||
odie <<~EOS
|
||||
The formula '#{realname}' is already aliased to '#{fc.name}'.
|
||||
The formula '#{realname}' is already aliased to '#{formula_creator.name}'.
|
||||
Please check that you are not creating a duplicate.
|
||||
To force creation use `--force`.
|
||||
EOS
|
||||
@ -225,19 +226,19 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
path = fc.write_formula!
|
||||
path = formula_creator.write_formula!
|
||||
|
||||
formula = Homebrew.with_no_api_env do
|
||||
CoreTap.instance.clear_cache
|
||||
Formula[fc.name]
|
||||
Formula[formula_creator.name]
|
||||
end
|
||||
PyPI.update_python_resources! formula, ignore_non_pypi_packages: true if args.python?
|
||||
|
||||
puts <<~EOS
|
||||
Please audit and test formula before submitting:
|
||||
HOMEBREW_NO_INSTALL_FROM_API=1 brew audit --new #{fc.name}
|
||||
HOMEBREW_NO_INSTALL_FROM_API=1 brew install --build-from-source --verbose --debug #{fc.name}
|
||||
HOMEBREW_NO_INSTALL_FROM_API=1 brew test #{fc.name}
|
||||
HOMEBREW_NO_INSTALL_FROM_API=1 brew audit --new #{formula_creator.name}
|
||||
HOMEBREW_NO_INSTALL_FROM_API=1 brew install --build-from-source --verbose --debug #{formula_creator.name}
|
||||
HOMEBREW_NO_INSTALL_FROM_API=1 brew test #{formula_creator.name}
|
||||
EOS
|
||||
path
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:disable Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "abstract_command"
|
||||
@ -172,7 +172,8 @@ module Homebrew
|
||||
with_monkey_patch { Formulary.from_contents(name, file, contents, ignore_errors: true) }
|
||||
end
|
||||
|
||||
def with_monkey_patch
|
||||
sig { params(_block: T.proc.void).returns(T.untyped) }
|
||||
def with_monkey_patch(&_block)
|
||||
# Since `method_defined?` is not a supported type guard, the use of `alias_method` below is not typesafe:
|
||||
BottleSpecification.class_eval do
|
||||
T.unsafe(self).alias_method :old_method_missing, :method_missing if method_defined?(:method_missing)
|
||||
@ -210,28 +211,28 @@ module Homebrew
|
||||
BottleSpecification.class_eval do
|
||||
if method_defined?(:old_method_missing)
|
||||
T.unsafe(self).alias_method :method_missing, :old_method_missing
|
||||
undef :old_method_missing
|
||||
T.unsafe(self).undef :old_method_missing
|
||||
end
|
||||
end
|
||||
|
||||
Module.class_eval do
|
||||
if method_defined?(:old_method_missing)
|
||||
T.unsafe(self).alias_method :method_missing, :old_method_missing
|
||||
undef :old_method_missing
|
||||
T.unsafe(self).undef :old_method_missing
|
||||
end
|
||||
end
|
||||
|
||||
Resource.class_eval do
|
||||
if method_defined?(:old_method_missing)
|
||||
T.unsafe(self).alias_method :method_missing, :old_method_missing
|
||||
undef :old_method_missing
|
||||
T.unsafe(self).undef :old_method_missing
|
||||
end
|
||||
end
|
||||
|
||||
DependencyCollector.class_eval do
|
||||
if method_defined?(:old_parse_symbol_spec)
|
||||
T.unsafe(self).alias_method :parse_symbol_spec, :old_parse_symbol_spec
|
||||
undef :old_parse_symbol_spec
|
||||
T.unsafe(self).undef :old_parse_symbol_spec
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -45,7 +45,7 @@ module Homebrew
|
||||
Cask::Cask.generating_hash!
|
||||
|
||||
all_casks = {}
|
||||
latest_macos = MacOSVersion.new((HOMEBREW_MACOS_NEWEST_UNSUPPORTED.to_i - 1).to_s).to_sym
|
||||
latest_macos = MacOSVersion.new(HOMEBREW_MACOS_NEWEST_SUPPORTED).to_sym
|
||||
Homebrew::SimulateSystem.with(os: latest_macos, arch: :arm) do
|
||||
tap.cask_files.each do |path|
|
||||
cask = Cask::CaskLoader.load(path)
|
||||
|
@ -67,8 +67,8 @@ module Homebrew
|
||||
end
|
||||
raise UsageError, "Only one url can be specified" if pr_url&.count&.> 1
|
||||
|
||||
labels = if pr_url
|
||||
pr = GitHub::API.open_rest(pr_url.first)
|
||||
labels = if pr_url && (first_pr_url = pr_url.first)
|
||||
pr = GitHub::API.open_rest(first_pr_url)
|
||||
pr.fetch("labels").map { |l| l.fetch("name") }
|
||||
else
|
||||
[]
|
||||
@ -263,11 +263,10 @@ module Homebrew
|
||||
audit_exceptions << %w[homepage_https_availability] if labels.include?("ci-skip-homepage")
|
||||
|
||||
if labels.include?("ci-skip-livecheck")
|
||||
audit_exceptions << %w[hosting_with_livecheck livecheck_https_availability
|
||||
livecheck_min_os livecheck_version]
|
||||
audit_exceptions << %w[hosting_with_livecheck livecheck_https_availability livecheck_version min_os]
|
||||
end
|
||||
|
||||
audit_exceptions << "livecheck_min_os" if labels.include?("ci-skip-livecheck-min-os")
|
||||
audit_exceptions << "min_os" if labels.include?("ci-skip-livecheck-min-os")
|
||||
|
||||
if labels.include?("ci-skip-repository")
|
||||
audit_exceptions << %w[github_repository github_prerelease_version
|
||||
|
@ -44,12 +44,11 @@ module Homebrew
|
||||
titleized_repository = tap.repository.dup
|
||||
titleized_user[0] = titleized_user[0].upcase
|
||||
titleized_repository[0] = titleized_repository[0].upcase
|
||||
root_url = GitHubPackages.root_url(tap.user, "homebrew-#{tap.repository}") if args.github_packages?
|
||||
# Duplicate assignment to silence `assigned but unused variable` warning
|
||||
root_url = root_url = GitHubPackages.root_url(tap.user, "homebrew-#{tap.repository}") if args.github_packages?
|
||||
|
||||
(tap.path/"Formula").mkpath
|
||||
|
||||
# FIXME: https://github.com/errata-ai/vale/issues/818
|
||||
# <!-- vale off -->
|
||||
readme = <<~MARKDOWN
|
||||
# #{titleized_user} #{titleized_repository}
|
||||
|
||||
@ -70,7 +69,6 @@ module Homebrew
|
||||
|
||||
`brew help`, `man brew` or check [Homebrew's documentation](https://docs.brew.sh).
|
||||
MARKDOWN
|
||||
# <!-- vale on -->
|
||||
write_path(tap, "README.md", readme)
|
||||
|
||||
tests_yml = <<~ERB
|
||||
@ -99,7 +97,7 @@ module Homebrew
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
|
||||
@ -164,12 +162,12 @@ module Homebrew
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Set up Homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
uses: Homebrew/actions/setup-homebrew@main
|
||||
with:
|
||||
token: ${{ github.token }}
|
||||
|
||||
- name: Set up git
|
||||
uses: Homebrew/actions/git-user-config@master
|
||||
uses: Homebrew/actions/git-user-config@main
|
||||
|
||||
- name: Pull bottles
|
||||
env:
|
||||
@ -182,7 +180,7 @@ module Homebrew
|
||||
run: brew pr-pull --debug --tap="$GITHUB_REPOSITORY" "$PULL_REQUEST"
|
||||
|
||||
- name: Push commits
|
||||
uses: Homebrew/actions/git-try-push@master
|
||||
uses: Homebrew/actions/git-try-push@main
|
||||
with:
|
||||
branch: <%= branch %>
|
||||
|
||||
|
@ -51,6 +51,11 @@ module Homebrew
|
||||
HOMEBREW_LIBRARY_PATH.cd do
|
||||
setup_environment!
|
||||
|
||||
# Needs required here, after `setup_environment!`, so that
|
||||
# `HOMEBREW_TEST_GENERIC_OS` is set and `OS.linux?` and `OS.mac?` both
|
||||
# `return false`.
|
||||
require "extend/os/dev-cmd/tests"
|
||||
|
||||
parallel = !args.no_parallel?
|
||||
|
||||
only = args.only
|
||||
@ -267,5 +272,3 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require "extend/os/dev-cmd/tests"
|
||||
|
@ -142,6 +142,7 @@ module Homebrew
|
||||
|
||||
private
|
||||
|
||||
sig { returns(String) }
|
||||
def git_tags
|
||||
tags = Utils.popen_read("git", "tag", "--list", "--sort=-version:refname")
|
||||
if tags.blank?
|
||||
|
@ -350,7 +350,6 @@ module Homebrew
|
||||
sudo chmod +t #{HOMEBREW_TEMP}
|
||||
EOS
|
||||
end
|
||||
alias generic_check_tmpdir_sticky_bit check_tmpdir_sticky_bit
|
||||
|
||||
def check_exist_directories
|
||||
return if HOMEBREW_PREFIX.writable?
|
||||
|
@ -54,8 +54,6 @@ module SharedEnvExtension
|
||||
@debug_symbols = debug_symbols
|
||||
reset
|
||||
end
|
||||
alias generic_shared_setup_build_environment setup_build_environment
|
||||
private :generic_shared_setup_build_environment
|
||||
|
||||
sig { void }
|
||||
def reset
|
||||
|
@ -68,7 +68,6 @@ module Stdenv
|
||||
gcc_formula = gcc_version_formula(cc)
|
||||
append_path "PATH", gcc_formula.opt_bin.to_s
|
||||
end
|
||||
alias generic_setup_build_environment setup_build_environment
|
||||
|
||||
sig { returns(T.nilable(PATH)) }
|
||||
def determine_pkg_config_libdir
|
||||
|
@ -125,7 +125,6 @@ module Superenv
|
||||
# These flags will also be present:
|
||||
# a - apply fix for apr-1-config path
|
||||
end
|
||||
alias generic_setup_build_environment setup_build_environment
|
||||
|
||||
private
|
||||
|
||||
@ -152,7 +151,6 @@ module Superenv
|
||||
.reverse
|
||||
.map { |d| d.opt_libexec/"bin" }
|
||||
end
|
||||
alias generic_homebrew_extra_paths homebrew_extra_paths
|
||||
|
||||
sig { returns(T.nilable(PATH)) }
|
||||
def determine_path
|
||||
@ -372,8 +370,8 @@ module Superenv
|
||||
append_to_cccfg "O"
|
||||
end
|
||||
|
||||
# This is an exception where we want to use this method name format.
|
||||
# rubocop: disable Naming/MethodName
|
||||
# Fixes style error `Naming/MethodName: Use snake_case for method names.`
|
||||
sig { params(block: T.nilable(T.proc.void)).void }
|
||||
def O0(&block)
|
||||
if block
|
||||
|
@ -15,6 +15,11 @@ module OS
|
||||
def os_bundle_args(bundle_args)
|
||||
non_macos_bundle_args(bundle_args)
|
||||
end
|
||||
|
||||
sig { params(files: T::Array[String]).returns(T::Array[String]) }
|
||||
def os_files(files)
|
||||
non_macos_files(files)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,19 +1,19 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Homebrew
|
||||
module DevCmd
|
||||
class UpdateTest < AbstractCommand
|
||||
alias generic_git_tags git_tags
|
||||
module OS
|
||||
module Linux
|
||||
module DevCmd
|
||||
module UpdateTest
|
||||
private
|
||||
|
||||
private
|
||||
|
||||
sig { returns(String) }
|
||||
def git_tags
|
||||
tags = generic_git_tags
|
||||
tags = Utils.popen_read("git tag --list | sort -rV") if tags.blank?
|
||||
tags
|
||||
sig { returns(String) }
|
||||
def git_tags
|
||||
super.presence || Utils.popen_read("git tag --list | sort -rV")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Homebrew::DevCmd::UpdateTest.prepend(OS::Linux::DevCmd::UpdateTest)
|
||||
|
@ -62,7 +62,7 @@ module OS
|
||||
def build_system_info
|
||||
super.merge({
|
||||
"glibc_version" => OS::Linux::Glibc.version.to_s.presence,
|
||||
"oldest_cpu_family" => Hardware.oldest_cpu.to_s,
|
||||
"oldest_cpu_family" => ::Hardware.oldest_cpu.to_s,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
@ -32,7 +32,7 @@ module OS
|
||||
end
|
||||
|
||||
def check_tmpdir_sticky_bit
|
||||
message = generic_check_tmpdir_sticky_bit
|
||||
message = super
|
||||
return if message.nil?
|
||||
|
||||
message + <<~EOS
|
||||
@ -74,11 +74,11 @@ module OS
|
||||
end
|
||||
|
||||
def check_supported_architecture
|
||||
return if Hardware::CPU.intel?
|
||||
return if Homebrew::EnvConfig.developer? && ENV["HOMEBREW_ARM64_TESTING"].present? && Hardware::CPU.arm?
|
||||
return if ::Hardware::CPU.intel?
|
||||
return if Homebrew::EnvConfig.developer? && ENV["HOMEBREW_ARM64_TESTING"].present? && ::Hardware::CPU.arm?
|
||||
|
||||
<<~EOS
|
||||
Your CPU architecture (#{Hardware::CPU.arch}) is not supported. We only support
|
||||
Your CPU architecture (#{::Hardware::CPU.arch}) is not supported. We only support
|
||||
x86_64 CPU architectures. You will be unable to use binary packages (bottles).
|
||||
|
||||
#{support_tier_message(tier: 2)}
|
||||
|
@ -1,16 +1,22 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SharedEnvExtension
|
||||
def effective_arch
|
||||
if @build_bottle && @bottle_arch
|
||||
@bottle_arch.to_sym
|
||||
elsif @build_bottle
|
||||
Hardware.oldest_cpu
|
||||
elsif Hardware::CPU.intel? || Hardware::CPU.arm?
|
||||
:native
|
||||
else
|
||||
:dunno
|
||||
module OS
|
||||
module Linux
|
||||
module SharedEnvExtension
|
||||
def effective_arch
|
||||
if @build_bottle && @bottle_arch
|
||||
@bottle_arch.to_sym
|
||||
elsif @build_bottle
|
||||
::Hardware.oldest_cpu
|
||||
elsif ::Hardware::CPU.intel? || ::Hardware::CPU.arm?
|
||||
:native
|
||||
else
|
||||
:dunno
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SharedEnvExtension.prepend(OS::Linux::SharedEnvExtension)
|
||||
|
@ -1,36 +1,45 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Stdenv
|
||||
sig {
|
||||
params(
|
||||
formula: T.nilable(Formula),
|
||||
cc: T.nilable(String),
|
||||
build_bottle: T.nilable(T::Boolean),
|
||||
bottle_arch: T.nilable(String),
|
||||
testing_formula: T::Boolean,
|
||||
debug_symbols: T.nilable(T::Boolean),
|
||||
).void
|
||||
}
|
||||
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false,
|
||||
debug_symbols: false)
|
||||
generic_setup_build_environment(formula:, cc:, build_bottle:, bottle_arch:,
|
||||
testing_formula:, debug_symbols:)
|
||||
module OS
|
||||
module Linux
|
||||
module Stdenv
|
||||
extend T::Helpers
|
||||
|
||||
prepend_path "CPATH", HOMEBREW_PREFIX/"include"
|
||||
prepend_path "LIBRARY_PATH", HOMEBREW_PREFIX/"lib"
|
||||
prepend_path "LD_RUN_PATH", HOMEBREW_PREFIX/"lib"
|
||||
requires_ancestor { ::SharedEnvExtension }
|
||||
|
||||
return unless @formula
|
||||
sig {
|
||||
params(
|
||||
formula: T.nilable(::Formula),
|
||||
cc: T.nilable(String),
|
||||
build_bottle: T.nilable(T::Boolean),
|
||||
bottle_arch: T.nilable(String),
|
||||
testing_formula: T::Boolean,
|
||||
debug_symbols: T.nilable(T::Boolean),
|
||||
).void
|
||||
}
|
||||
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil,
|
||||
testing_formula: false, debug_symbols: false)
|
||||
super
|
||||
|
||||
prepend_path "CPATH", @formula.include
|
||||
prepend_path "LIBRARY_PATH", @formula.lib
|
||||
prepend_path "LD_RUN_PATH", @formula.lib
|
||||
end
|
||||
prepend_path "CPATH", HOMEBREW_PREFIX/"include"
|
||||
prepend_path "LIBRARY_PATH", HOMEBREW_PREFIX/"lib"
|
||||
prepend_path "LD_RUN_PATH", HOMEBREW_PREFIX/"lib"
|
||||
|
||||
def libxml2
|
||||
append "CPPFLAGS", "-I#{Formula["libxml2"].include/"libxml2"}"
|
||||
rescue FormulaUnavailableError
|
||||
nil
|
||||
return unless @formula
|
||||
|
||||
prepend_path "CPATH", @formula.include
|
||||
prepend_path "LIBRARY_PATH", @formula.lib
|
||||
prepend_path "LD_RUN_PATH", @formula.lib
|
||||
end
|
||||
|
||||
def libxml2
|
||||
append "CPPFLAGS", "-I#{::Formula["libxml2"].include/"libxml2"}"
|
||||
rescue FormulaUnavailableError
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Stdenv.prepend(OS::Linux::Stdenv)
|
||||
|
@ -1,79 +1,93 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Superenv
|
||||
sig { returns(Pathname) }
|
||||
def self.shims_path
|
||||
HOMEBREW_SHIMS_PATH/"linux/super"
|
||||
end
|
||||
module OS
|
||||
module Linux
|
||||
module Superenv
|
||||
extend T::Helpers
|
||||
|
||||
sig { returns(T.nilable(Pathname)) }
|
||||
def self.bin
|
||||
shims_path.realpath
|
||||
end
|
||||
requires_ancestor { SharedEnvExtension }
|
||||
requires_ancestor { ::Superenv }
|
||||
|
||||
sig {
|
||||
params(
|
||||
formula: T.nilable(Formula),
|
||||
cc: T.nilable(String),
|
||||
build_bottle: T.nilable(T::Boolean),
|
||||
bottle_arch: T.nilable(String),
|
||||
testing_formula: T::Boolean,
|
||||
debug_symbols: T.nilable(T::Boolean),
|
||||
).void
|
||||
}
|
||||
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false,
|
||||
debug_symbols: false)
|
||||
generic_setup_build_environment(formula:, cc:, build_bottle:, bottle_arch:,
|
||||
testing_formula:, debug_symbols:)
|
||||
self["HOMEBREW_OPTIMIZATION_LEVEL"] = "O2"
|
||||
self["HOMEBREW_DYNAMIC_LINKER"] = determine_dynamic_linker_path
|
||||
self["HOMEBREW_RPATH_PATHS"] = determine_rpath_paths(@formula)
|
||||
m4_path_deps = ["libtool", "bison"]
|
||||
self["M4"] = "#{HOMEBREW_PREFIX}/opt/m4/bin/m4" if deps.any? { m4_path_deps.include?(_1.name) }
|
||||
module ClassMethods
|
||||
sig { returns(Pathname) }
|
||||
def shims_path
|
||||
HOMEBREW_SHIMS_PATH/"linux/super"
|
||||
end
|
||||
|
||||
# Pointer authentication and BTI are hardening techniques most distros
|
||||
# use by default on their packages. arm64 Linux we're packaging
|
||||
# everything from scratch so the entire dependency tree can have it.
|
||||
append_to_cccfg "b" if Hardware::CPU.arch == :arm64 && DevelopmentTools.gcc_version("gcc") >= 9
|
||||
end
|
||||
sig { returns(T.nilable(Pathname)) }
|
||||
def bin
|
||||
shims_path.realpath
|
||||
end
|
||||
end
|
||||
|
||||
def homebrew_extra_paths
|
||||
paths = generic_homebrew_extra_paths
|
||||
paths += %w[binutils make].filter_map do |f|
|
||||
bin = Formulary.factory(f).opt_bin
|
||||
bin if bin.directory?
|
||||
rescue FormulaUnavailableError
|
||||
nil
|
||||
sig {
|
||||
params(
|
||||
formula: T.nilable(Formula),
|
||||
cc: T.nilable(String),
|
||||
build_bottle: T.nilable(T::Boolean),
|
||||
bottle_arch: T.nilable(String),
|
||||
testing_formula: T::Boolean,
|
||||
debug_symbols: T.nilable(T::Boolean),
|
||||
).void
|
||||
}
|
||||
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil,
|
||||
testing_formula: false, debug_symbols: false)
|
||||
super
|
||||
|
||||
self["HOMEBREW_OPTIMIZATION_LEVEL"] = "O2"
|
||||
self["HOMEBREW_DYNAMIC_LINKER"] = determine_dynamic_linker_path
|
||||
self["HOMEBREW_RPATH_PATHS"] = determine_rpath_paths(@formula)
|
||||
m4_path_deps = ["libtool", "bison"]
|
||||
self["M4"] = "#{HOMEBREW_PREFIX}/opt/m4/bin/m4" if deps.any? { m4_path_deps.include?(_1.name) }
|
||||
|
||||
# Pointer authentication and BTI are hardening techniques most distros
|
||||
# use by default on their packages. arm64 Linux we're packaging
|
||||
# everything from scratch so the entire dependency tree can have it.
|
||||
append_to_cccfg "b" if ::Hardware::CPU.arch == :arm64 && ::DevelopmentTools.gcc_version("gcc") >= 9
|
||||
end
|
||||
|
||||
def homebrew_extra_paths
|
||||
paths = super
|
||||
paths += %w[binutils make].filter_map do |f|
|
||||
bin = Formulary.factory(f).opt_bin
|
||||
bin if bin.directory?
|
||||
rescue FormulaUnavailableError
|
||||
nil
|
||||
end
|
||||
paths
|
||||
end
|
||||
|
||||
def homebrew_extra_isystem_paths
|
||||
paths = []
|
||||
# Add paths for GCC headers when building against versioned glibc because we have to use -nostdinc.
|
||||
if deps.any? { |d| d.name.match?(/^glibc@.+$/) }
|
||||
gcc_include_dir = Utils.safe_popen_read(cc, "--print-file-name=include").chomp
|
||||
gcc_include_fixed_dir = Utils.safe_popen_read(cc, "--print-file-name=include-fixed").chomp
|
||||
paths << gcc_include_dir << gcc_include_fixed_dir
|
||||
end
|
||||
paths
|
||||
end
|
||||
|
||||
def determine_rpath_paths(formula)
|
||||
PATH.new(
|
||||
*formula&.lib,
|
||||
"#{HOMEBREW_PREFIX}/opt/gcc/lib/gcc/current",
|
||||
PATH.new(run_time_deps.map { |dep| dep.opt_lib.to_s }).existing,
|
||||
"#{HOMEBREW_PREFIX}/lib",
|
||||
)
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(String)) }
|
||||
def determine_dynamic_linker_path
|
||||
path = "#{HOMEBREW_PREFIX}/lib/ld.so"
|
||||
return unless File.readable? path
|
||||
|
||||
path
|
||||
end
|
||||
end
|
||||
paths
|
||||
end
|
||||
|
||||
def homebrew_extra_isystem_paths
|
||||
paths = []
|
||||
# Add paths for GCC headers when building against versioned glibc because we have to use -nostdinc.
|
||||
if deps.any? { |d| d.name.match?(/^glibc@.+$/) }
|
||||
gcc_include_dir = Utils.safe_popen_read(cc, "--print-file-name=include").chomp
|
||||
gcc_include_fixed_dir = Utils.safe_popen_read(cc, "--print-file-name=include-fixed").chomp
|
||||
paths << gcc_include_dir << gcc_include_fixed_dir
|
||||
end
|
||||
paths
|
||||
end
|
||||
|
||||
def determine_rpath_paths(formula)
|
||||
PATH.new(
|
||||
*formula&.lib,
|
||||
"#{HOMEBREW_PREFIX}/opt/gcc/lib/gcc/current",
|
||||
PATH.new(run_time_deps.map { |dep| dep.opt_lib.to_s }).existing,
|
||||
"#{HOMEBREW_PREFIX}/lib",
|
||||
)
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(String)) }
|
||||
def determine_dynamic_linker_path
|
||||
path = "#{HOMEBREW_PREFIX}/lib/ld.so"
|
||||
return unless File.readable? path
|
||||
|
||||
path
|
||||
end
|
||||
end
|
||||
|
||||
Superenv.singleton_class.prepend(OS::Linux::Superenv::ClassMethods)
|
||||
Superenv.prepend(OS::Linux::Superenv)
|
||||
|
@ -1,9 +1,15 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
module FormulaCellarChecks
|
||||
sig { params(filename: Pathname).returns(T::Boolean) }
|
||||
def valid_library_extension?(filename)
|
||||
generic_valid_library_extension?(filename) || filename.basename.to_s.include?(".so.")
|
||||
module OS
|
||||
module Linux
|
||||
module FormulaCellarChecks
|
||||
sig { params(filename: Pathname).returns(T::Boolean) }
|
||||
def valid_library_extension?(filename)
|
||||
super || filename.basename.to_s.include?(".so.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
FormulaCellarChecks.prepend(OS::Linux::FormulaCellarChecks)
|
||||
|
@ -1,161 +1,171 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Hardware
|
||||
class CPU
|
||||
class << self
|
||||
def optimization_flags
|
||||
@optimization_flags ||= begin
|
||||
flags = generic_optimization_flags.dup
|
||||
flags[:native] = arch_flag(Homebrew::EnvConfig.arch)
|
||||
flags
|
||||
end
|
||||
end
|
||||
module OS
|
||||
module Linux
|
||||
module Hardware
|
||||
module CPU
|
||||
module ClassMethods
|
||||
extend T::Helpers
|
||||
|
||||
def family
|
||||
return :arm if arm?
|
||||
return :ppc if ppc?
|
||||
return :dunno unless intel?
|
||||
requires_ancestor { T.class_of(::Hardware::CPU) }
|
||||
|
||||
# See https://software.intel.com/en-us/articles/intel-architecture-and-processor-identification-with-cpuid-model-and-family-numbers
|
||||
# and https://github.com/llvm/llvm-project/blob/main/llvm/lib/TargetParser/Host.cpp
|
||||
# and https://en.wikipedia.org/wiki/List_of_Intel_CPU_microarchitectures#Roadmap
|
||||
vendor_id = cpuinfo[/^vendor_id\s*: (.*)/, 1]
|
||||
cpu_family = cpuinfo[/^cpu family\s*: ([0-9]+)/, 1].to_i
|
||||
cpu_model = cpuinfo[/^model\s*: ([0-9]+)/, 1].to_i
|
||||
unknown = :"unknown_0x#{cpu_family.to_s(16)}_0x#{cpu_model.to_s(16)}"
|
||||
case vendor_id
|
||||
when "GenuineIntel"
|
||||
intel_family(cpu_family, cpu_model)
|
||||
when "AuthenticAMD"
|
||||
amd_family(cpu_family, cpu_model)
|
||||
end || unknown
|
||||
end
|
||||
|
||||
def intel_family(family, cpu_model)
|
||||
case family
|
||||
when 0x06
|
||||
case cpu_model
|
||||
when 0x3a, 0x3e
|
||||
:ivybridge
|
||||
when 0x2a, 0x2d
|
||||
:sandybridge
|
||||
when 0x25, 0x2c, 0x2f
|
||||
:westmere
|
||||
when 0x1a, 0x1e, 0x1f, 0x2e
|
||||
:nehalem
|
||||
when 0x17, 0x1d
|
||||
:penryn
|
||||
when 0x0f, 0x16
|
||||
:merom
|
||||
when 0x0d
|
||||
:dothan
|
||||
when 0x1c, 0x26, 0x27, 0x35, 0x36
|
||||
:atom
|
||||
when 0x3c, 0x3f, 0x45, 0x46
|
||||
:haswell
|
||||
when 0x3d, 0x47, 0x4f, 0x56
|
||||
:broadwell
|
||||
when 0x4e, 0x5e, 0x8e, 0x9e, 0xa5, 0xa6
|
||||
:skylake
|
||||
when 0x66
|
||||
:cannonlake
|
||||
when 0x6a, 0x6c, 0x7d, 0x7e
|
||||
:icelake
|
||||
when 0xa7
|
||||
:rocketlake
|
||||
when 0x8c, 0x8d
|
||||
:tigerlake
|
||||
when 0x97, 0x9a, 0xbe, 0xb7, 0xba, 0xbf, 0xaa, 0xac
|
||||
:alderlake
|
||||
when 0xc5, 0xb5, 0xc6, 0xbd
|
||||
:arrowlake
|
||||
when 0xcc
|
||||
:pantherlake
|
||||
when 0xad, 0xae
|
||||
:graniterapids
|
||||
when 0xcf, 0x8f
|
||||
:sapphirerapids
|
||||
def optimization_flags
|
||||
@optimization_flags ||= begin
|
||||
flags = super.dup
|
||||
flags[:native] = arch_flag(Homebrew::EnvConfig.arch)
|
||||
flags
|
||||
end
|
||||
end
|
||||
when 0x0f
|
||||
case cpu_model
|
||||
when 0x06
|
||||
:presler
|
||||
when 0x03, 0x04
|
||||
:prescott
|
||||
|
||||
def family
|
||||
return :arm if arm?
|
||||
return :ppc if ppc?
|
||||
return :dunno unless intel?
|
||||
|
||||
# See https://software.intel.com/en-us/articles/intel-architecture-and-processor-identification-with-cpuid-model-and-family-numbers
|
||||
# and https://github.com/llvm/llvm-project/blob/main/llvm/lib/TargetParser/Host.cpp
|
||||
# and https://en.wikipedia.org/wiki/List_of_Intel_CPU_microarchitectures#Roadmap
|
||||
vendor_id = cpuinfo[/^vendor_id\s*: (.*)/, 1]
|
||||
cpu_family = cpuinfo[/^cpu family\s*: ([0-9]+)/, 1].to_i
|
||||
cpu_model = cpuinfo[/^model\s*: ([0-9]+)/, 1].to_i
|
||||
unknown = :"unknown_0x#{cpu_family.to_s(16)}_0x#{cpu_model.to_s(16)}"
|
||||
case vendor_id
|
||||
when "GenuineIntel"
|
||||
intel_family(cpu_family, cpu_model)
|
||||
when "AuthenticAMD"
|
||||
amd_family(cpu_family, cpu_model)
|
||||
end || unknown
|
||||
end
|
||||
|
||||
def intel_family(family, cpu_model)
|
||||
case family
|
||||
when 0x06
|
||||
case cpu_model
|
||||
when 0x3a, 0x3e
|
||||
:ivybridge
|
||||
when 0x2a, 0x2d
|
||||
:sandybridge
|
||||
when 0x25, 0x2c, 0x2f
|
||||
:westmere
|
||||
when 0x1a, 0x1e, 0x1f, 0x2e
|
||||
:nehalem
|
||||
when 0x17, 0x1d
|
||||
:penryn
|
||||
when 0x0f, 0x16
|
||||
:merom
|
||||
when 0x0d
|
||||
:dothan
|
||||
when 0x1c, 0x26, 0x27, 0x35, 0x36
|
||||
:atom
|
||||
when 0x3c, 0x3f, 0x45, 0x46
|
||||
:haswell
|
||||
when 0x3d, 0x47, 0x4f, 0x56
|
||||
:broadwell
|
||||
when 0x4e, 0x5e, 0x8e, 0x9e, 0xa5, 0xa6
|
||||
:skylake
|
||||
when 0x66
|
||||
:cannonlake
|
||||
when 0x6a, 0x6c, 0x7d, 0x7e
|
||||
:icelake
|
||||
when 0xa7
|
||||
:rocketlake
|
||||
when 0x8c, 0x8d
|
||||
:tigerlake
|
||||
when 0x97, 0x9a, 0xbe, 0xb7, 0xba, 0xbf, 0xaa, 0xac
|
||||
:alderlake
|
||||
when 0xc5, 0xb5, 0xc6, 0xbd
|
||||
:arrowlake
|
||||
when 0xcc
|
||||
:pantherlake
|
||||
when 0xad, 0xae
|
||||
:graniterapids
|
||||
when 0xcf, 0x8f
|
||||
:sapphirerapids
|
||||
end
|
||||
when 0x0f
|
||||
case cpu_model
|
||||
when 0x06
|
||||
:presler
|
||||
when 0x03, 0x04
|
||||
:prescott
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def amd_family(family, cpu_model)
|
||||
case family
|
||||
when 0x06
|
||||
:amd_k7
|
||||
when 0x0f
|
||||
:amd_k8
|
||||
when 0x10
|
||||
:amd_k10
|
||||
when 0x11
|
||||
:amd_k8_k10_hybrid
|
||||
when 0x12
|
||||
:amd_k10_llano
|
||||
when 0x14
|
||||
:bobcat
|
||||
when 0x15
|
||||
:bulldozer
|
||||
when 0x16
|
||||
:jaguar
|
||||
when 0x17
|
||||
case cpu_model
|
||||
when 0x10..0x2f
|
||||
:zen
|
||||
when 0x30..0x3f, 0x47, 0x60..0x7f, 0x84..0x87, 0x90..0xaf
|
||||
:zen2
|
||||
end
|
||||
when 0x19
|
||||
case cpu_model
|
||||
when ..0x0f, 0x20..0x5f
|
||||
:zen3
|
||||
when 0x10..0x1f, 0x60..0x7f, 0xa0..0xaf
|
||||
:zen4
|
||||
end
|
||||
when 0x1a
|
||||
:zen5
|
||||
end
|
||||
end
|
||||
|
||||
# Supported CPU instructions
|
||||
def flags
|
||||
@flags ||= cpuinfo[/^(?:flags|Features)\s*: (.*)/, 1]&.split
|
||||
@flags ||= []
|
||||
end
|
||||
|
||||
# Compatibility with Mac method, which returns lowercase symbols
|
||||
# instead of strings.
|
||||
def features
|
||||
@features ||= flags[1..].map(&:intern)
|
||||
end
|
||||
|
||||
%w[aes altivec avx avx2 lm ssse3 sse4_2].each do |flag|
|
||||
define_method(:"#{flag}?") do
|
||||
T.bind(self, OS::Linux::Hardware::CPU::ClassMethods)
|
||||
flags.include? flag
|
||||
end
|
||||
end
|
||||
|
||||
def sse3?
|
||||
flags.include?("pni") || flags.include?("sse3")
|
||||
end
|
||||
|
||||
def sse4?
|
||||
flags.include? "sse4_1"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def cpuinfo
|
||||
@cpuinfo ||= File.read("/proc/cpuinfo")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def amd_family(family, cpu_model)
|
||||
case family
|
||||
when 0x06
|
||||
:amd_k7
|
||||
when 0x0f
|
||||
:amd_k8
|
||||
when 0x10
|
||||
:amd_k10
|
||||
when 0x11
|
||||
:amd_k8_k10_hybrid
|
||||
when 0x12
|
||||
:amd_k10_llano
|
||||
when 0x14
|
||||
:bobcat
|
||||
when 0x15
|
||||
:bulldozer
|
||||
when 0x16
|
||||
:jaguar
|
||||
when 0x17
|
||||
case cpu_model
|
||||
when 0x10..0x2f
|
||||
:zen
|
||||
when 0x30..0x3f, 0x47, 0x60..0x7f, 0x84..0x87, 0x90..0xaf
|
||||
:zen2
|
||||
end
|
||||
when 0x19
|
||||
case cpu_model
|
||||
when ..0x0f, 0x20..0x5f
|
||||
:zen3
|
||||
when 0x10..0x1f, 0x60..0x7f, 0xa0..0xaf
|
||||
:zen4
|
||||
end
|
||||
when 0x1a
|
||||
:zen5
|
||||
end
|
||||
end
|
||||
|
||||
# Supported CPU instructions
|
||||
def flags
|
||||
@flags ||= cpuinfo[/^(?:flags|Features)\s*: (.*)/, 1]&.split
|
||||
@flags ||= []
|
||||
end
|
||||
|
||||
# Compatibility with Mac method, which returns lowercase symbols
|
||||
# instead of strings.
|
||||
def features
|
||||
@features ||= flags[1..].map(&:intern)
|
||||
end
|
||||
|
||||
%w[aes altivec avx avx2 lm ssse3 sse4_2].each do |flag|
|
||||
define_method(:"#{flag}?") do
|
||||
T.bind(self, T.class_of(Hardware::CPU))
|
||||
flags.include? flag
|
||||
end
|
||||
end
|
||||
|
||||
def sse3?
|
||||
flags.include?("pni") || flags.include?("sse3")
|
||||
end
|
||||
|
||||
def sse4?
|
||||
flags.include? "sse4_1"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def cpuinfo
|
||||
@cpuinfo ||= File.read("/proc/cpuinfo")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Hardware::CPU.singleton_class.prepend(OS::Linux::Hardware::CPU::ClassMethods)
|
||||
|
@ -1,132 +1,132 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Homebrew
|
||||
module Install
|
||||
# This is a list of known paths to the host dynamic linker on Linux if
|
||||
# the host glibc is new enough. The symlink_ld_so method will fail if
|
||||
# the host linker cannot be found in this list.
|
||||
DYNAMIC_LINKERS = %w[
|
||||
/lib64/ld-linux-x86-64.so.2
|
||||
/lib64/ld64.so.2
|
||||
/lib/ld-linux.so.3
|
||||
/lib/ld-linux.so.2
|
||||
/lib/ld-linux-aarch64.so.1
|
||||
/lib/ld-linux-armhf.so.3
|
||||
/system/bin/linker64
|
||||
/system/bin/linker
|
||||
].freeze
|
||||
private_constant :DYNAMIC_LINKERS
|
||||
module OS
|
||||
module Linux
|
||||
module Install
|
||||
module ClassMethods
|
||||
# This is a list of known paths to the host dynamic linker on Linux if
|
||||
# the host glibc is new enough. The symlink_ld_so method will fail if
|
||||
# the host linker cannot be found in this list.
|
||||
DYNAMIC_LINKERS = %w[
|
||||
/lib64/ld-linux-x86-64.so.2
|
||||
/lib64/ld64.so.2
|
||||
/lib/ld-linux.so.3
|
||||
/lib/ld-linux.so.2
|
||||
/lib/ld-linux-aarch64.so.1
|
||||
/lib/ld-linux-armhf.so.3
|
||||
/system/bin/linker64
|
||||
/system/bin/linker
|
||||
].freeze
|
||||
|
||||
# We link GCC runtime libraries that are not specifically used for Fortran,
|
||||
# which are linked by the GCC formula. We only use the versioned shared libraries
|
||||
# as the other shared and static libraries are only used at build time where
|
||||
# GCC can find its own libraries.
|
||||
GCC_RUNTIME_LIBS = %w[
|
||||
libatomic.so.1
|
||||
libgcc_s.so.1
|
||||
libgomp.so.1
|
||||
libstdc++.so.6
|
||||
].freeze
|
||||
private_constant :GCC_RUNTIME_LIBS
|
||||
# We link GCC runtime libraries that are not specifically used for Fortran,
|
||||
# which are linked by the GCC formula. We only use the versioned shared libraries
|
||||
# as the other shared and static libraries are only used at build time where
|
||||
# GCC can find its own libraries.
|
||||
GCC_RUNTIME_LIBS = %w[
|
||||
libatomic.so.1
|
||||
libgcc_s.so.1
|
||||
libgomp.so.1
|
||||
libstdc++.so.6
|
||||
].freeze
|
||||
|
||||
def self.perform_preinstall_checks(all_fatal: false)
|
||||
generic_perform_preinstall_checks(all_fatal:)
|
||||
symlink_ld_so
|
||||
setup_preferred_gcc_libs
|
||||
end
|
||||
private_class_method :perform_preinstall_checks
|
||||
|
||||
def self.global_post_install
|
||||
generic_global_post_install
|
||||
symlink_ld_so
|
||||
setup_preferred_gcc_libs
|
||||
end
|
||||
|
||||
def self.check_cpu
|
||||
return if Hardware::CPU.intel? && Hardware::CPU.is_64_bit?
|
||||
return if Hardware::CPU.arm?
|
||||
|
||||
message = "Sorry, Homebrew does not support your computer's CPU architecture!"
|
||||
if Hardware::CPU.ppc64le?
|
||||
message += <<~EOS
|
||||
For OpenPOWER Linux (PPC64LE) support, see:
|
||||
#{Formatter.url("https://github.com/homebrew-ppc64le/brew")}
|
||||
EOS
|
||||
end
|
||||
abort message
|
||||
end
|
||||
private_class_method :check_cpu
|
||||
|
||||
def self.symlink_ld_so
|
||||
brew_ld_so = HOMEBREW_PREFIX/"lib/ld.so"
|
||||
|
||||
ld_so = HOMEBREW_PREFIX/"opt/glibc/bin/ld.so"
|
||||
unless ld_so.readable?
|
||||
ld_so = DYNAMIC_LINKERS.find { |s| File.executable? s }
|
||||
if ld_so.blank?
|
||||
raise "Unable to locate the system's dynamic linker" unless brew_ld_so.readable?
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return if brew_ld_so.readable? && (brew_ld_so.readlink == ld_so)
|
||||
|
||||
FileUtils.mkdir_p HOMEBREW_PREFIX/"lib"
|
||||
FileUtils.ln_sf ld_so, brew_ld_so
|
||||
end
|
||||
private_class_method :symlink_ld_so
|
||||
|
||||
def self.setup_preferred_gcc_libs
|
||||
gcc_opt_prefix = HOMEBREW_PREFIX/"opt/#{OS::LINUX_PREFERRED_GCC_RUNTIME_FORMULA}"
|
||||
glibc_installed = (HOMEBREW_PREFIX/"opt/glibc/bin/ld.so").readable?
|
||||
|
||||
return unless gcc_opt_prefix.readable?
|
||||
|
||||
if glibc_installed
|
||||
ld_so_conf_d = HOMEBREW_PREFIX/"etc/ld.so.conf.d"
|
||||
unless ld_so_conf_d.exist?
|
||||
ld_so_conf_d.mkpath
|
||||
FileUtils.chmod "go-w", ld_so_conf_d
|
||||
def perform_preinstall_checks(all_fatal: false)
|
||||
super
|
||||
symlink_ld_so
|
||||
setup_preferred_gcc_libs
|
||||
end
|
||||
|
||||
# Add gcc to ld search paths
|
||||
ld_gcc_conf = ld_so_conf_d/"50-homebrew-preferred-gcc.conf"
|
||||
ld_gcc_conf_content = <<~EOS
|
||||
# This file is generated by Homebrew. Do not modify.
|
||||
#{gcc_opt_prefix}/lib/gcc/current
|
||||
EOS
|
||||
|
||||
if !ld_gcc_conf.exist? || (ld_gcc_conf.read != ld_gcc_conf_content)
|
||||
ld_gcc_conf.atomic_write ld_gcc_conf_content
|
||||
FileUtils.chmod "u=rw,go-wx", ld_gcc_conf
|
||||
|
||||
FileUtils.rm_f HOMEBREW_PREFIX/"etc/ld.so.cache"
|
||||
system HOMEBREW_PREFIX/"opt/glibc/sbin/ldconfig"
|
||||
def global_post_install
|
||||
super
|
||||
symlink_ld_so
|
||||
setup_preferred_gcc_libs
|
||||
end
|
||||
else
|
||||
odie "#{HOMEBREW_PREFIX}/lib does not exist!" unless (HOMEBREW_PREFIX/"lib").readable?
|
||||
end
|
||||
|
||||
GCC_RUNTIME_LIBS.each do |library|
|
||||
gcc_library_symlink = HOMEBREW_PREFIX/"lib/#{library}"
|
||||
def check_cpu
|
||||
return if ::Hardware::CPU.intel? && ::Hardware::CPU.is_64_bit?
|
||||
return if ::Hardware::CPU.arm?
|
||||
|
||||
if glibc_installed
|
||||
# Remove legacy symlinks
|
||||
FileUtils.rm gcc_library_symlink if gcc_library_symlink.symlink?
|
||||
else
|
||||
gcc_library = gcc_opt_prefix/"lib/gcc/current/#{library}"
|
||||
# Skip if the link target doesn't exist.
|
||||
next unless gcc_library.readable?
|
||||
message = "Sorry, Homebrew does not support your computer's CPU architecture!"
|
||||
if ::Hardware::CPU.ppc64le?
|
||||
message += <<~EOS
|
||||
For OpenPOWER Linux (PPC64LE) support, see:
|
||||
#{Formatter.url("https://github.com/homebrew-ppc64le/brew")}
|
||||
EOS
|
||||
end
|
||||
::Kernel.abort message
|
||||
end
|
||||
|
||||
# Also skip if the symlink already exists.
|
||||
next if gcc_library_symlink.readable? && (gcc_library_symlink.readlink == gcc_library)
|
||||
def symlink_ld_so
|
||||
brew_ld_so = HOMEBREW_PREFIX/"lib/ld.so"
|
||||
|
||||
FileUtils.ln_sf gcc_library, gcc_library_symlink
|
||||
ld_so = HOMEBREW_PREFIX/"opt/glibc/bin/ld.so"
|
||||
unless ld_so.readable?
|
||||
ld_so = DYNAMIC_LINKERS.find { |s| File.executable? s }
|
||||
if ld_so.blank?
|
||||
::Kernel.raise "Unable to locate the system's dynamic linker" unless brew_ld_so.readable?
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return if brew_ld_so.readable? && (brew_ld_so.readlink == ld_so)
|
||||
|
||||
FileUtils.mkdir_p HOMEBREW_PREFIX/"lib"
|
||||
FileUtils.ln_sf ld_so, brew_ld_so
|
||||
end
|
||||
|
||||
def setup_preferred_gcc_libs
|
||||
gcc_opt_prefix = HOMEBREW_PREFIX/"opt/#{OS::LINUX_PREFERRED_GCC_RUNTIME_FORMULA}"
|
||||
glibc_installed = (HOMEBREW_PREFIX/"opt/glibc/bin/ld.so").readable?
|
||||
|
||||
return unless gcc_opt_prefix.readable?
|
||||
|
||||
if glibc_installed
|
||||
ld_so_conf_d = HOMEBREW_PREFIX/"etc/ld.so.conf.d"
|
||||
unless ld_so_conf_d.exist?
|
||||
ld_so_conf_d.mkpath
|
||||
FileUtils.chmod "go-w", ld_so_conf_d
|
||||
end
|
||||
|
||||
# Add gcc to ld search paths
|
||||
ld_gcc_conf = ld_so_conf_d/"50-homebrew-preferred-gcc.conf"
|
||||
ld_gcc_conf_content = <<~EOS
|
||||
# This file is generated by Homebrew. Do not modify.
|
||||
#{gcc_opt_prefix}/lib/gcc/current
|
||||
EOS
|
||||
|
||||
if !ld_gcc_conf.exist? || (ld_gcc_conf.read != ld_gcc_conf_content)
|
||||
ld_gcc_conf.atomic_write ld_gcc_conf_content
|
||||
FileUtils.chmod "u=rw,go-wx", ld_gcc_conf
|
||||
|
||||
FileUtils.rm_f HOMEBREW_PREFIX/"etc/ld.so.cache"
|
||||
::Kernel.system HOMEBREW_PREFIX/"opt/glibc/sbin/ldconfig"
|
||||
end
|
||||
else
|
||||
::Kernel.odie "#{HOMEBREW_PREFIX}/lib does not exist!" unless (HOMEBREW_PREFIX/"lib").readable?
|
||||
end
|
||||
|
||||
GCC_RUNTIME_LIBS.each do |library|
|
||||
gcc_library_symlink = HOMEBREW_PREFIX/"lib/#{library}"
|
||||
|
||||
if glibc_installed
|
||||
# Remove legacy symlinks
|
||||
FileUtils.rm gcc_library_symlink if gcc_library_symlink.symlink?
|
||||
else
|
||||
gcc_library = gcc_opt_prefix/"lib/gcc/current/#{library}"
|
||||
# Skip if the link target doesn't exist.
|
||||
next unless gcc_library.readable?
|
||||
|
||||
# Also skip if the symlink already exists.
|
||||
next if gcc_library_symlink.readable? && (gcc_library_symlink.readlink == gcc_library)
|
||||
|
||||
FileUtils.ln_sf gcc_library, gcc_library_symlink
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
private_class_method :setup_preferred_gcc_libs
|
||||
end
|
||||
end
|
||||
|
||||
Homebrew::Install.singleton_class.prepend(OS::Linux::Install::ClassMethods)
|
||||
|
@ -3,48 +3,55 @@
|
||||
|
||||
require "compilers"
|
||||
|
||||
class LinkageChecker
|
||||
# Libraries provided by glibc and gcc.
|
||||
SYSTEM_LIBRARY_ALLOWLIST = %w[
|
||||
ld-linux-x86-64.so.2
|
||||
ld-linux-aarch64.so.1
|
||||
libanl.so.1
|
||||
libatomic.so.1
|
||||
libc.so.6
|
||||
libdl.so.2
|
||||
libm.so.6
|
||||
libmvec.so.1
|
||||
libnss_files.so.2
|
||||
libpthread.so.0
|
||||
libresolv.so.2
|
||||
librt.so.1
|
||||
libthread_db.so.1
|
||||
libutil.so.1
|
||||
libgcc_s.so.1
|
||||
libgomp.so.1
|
||||
libstdc++.so.6
|
||||
libquadmath.so.0
|
||||
].freeze
|
||||
module OS
|
||||
module Linux
|
||||
module LinkageChecker
|
||||
# Libraries provided by glibc and gcc.
|
||||
SYSTEM_LIBRARY_ALLOWLIST = %w[
|
||||
ld-linux-x86-64.so.2
|
||||
ld-linux-aarch64.so.1
|
||||
libanl.so.1
|
||||
libatomic.so.1
|
||||
libc.so.6
|
||||
libdl.so.2
|
||||
libm.so.6
|
||||
libmvec.so.1
|
||||
libnss_files.so.2
|
||||
libpthread.so.0
|
||||
libresolv.so.2
|
||||
librt.so.1
|
||||
libthread_db.so.1
|
||||
libutil.so.1
|
||||
libgcc_s.so.1
|
||||
libgomp.so.1
|
||||
libstdc++.so.6
|
||||
libquadmath.so.0
|
||||
].freeze
|
||||
|
||||
private
|
||||
private
|
||||
|
||||
def check_dylibs(rebuild_cache:)
|
||||
generic_check_dylibs(rebuild_cache:)
|
||||
def check_dylibs(rebuild_cache:)
|
||||
super
|
||||
|
||||
# glibc and gcc are implicit dependencies.
|
||||
# No other linkage to system libraries is expected or desired.
|
||||
@unwanted_system_dylibs = @system_dylibs.reject do |s|
|
||||
SYSTEM_LIBRARY_ALLOWLIST.include? File.basename(s)
|
||||
# glibc and gcc are implicit dependencies.
|
||||
# No other linkage to system libraries is expected or desired.
|
||||
@unwanted_system_dylibs = @system_dylibs.reject do |s|
|
||||
SYSTEM_LIBRARY_ALLOWLIST.include? File.basename(s)
|
||||
end
|
||||
|
||||
# We build all formulae with an RPATH that includes the gcc formula's runtime lib directory.
|
||||
# See: https://github.com/Homebrew/brew/blob/e689cc07/Library/Homebrew/extend/os/linux/extend/ENV/super.rb#L53
|
||||
# This results in formulae showing linkage with gcc whenever it is installed, even if no dependency is
|
||||
# declared.
|
||||
# See discussions at:
|
||||
# https://github.com/Homebrew/brew/pull/13659
|
||||
# https://github.com/Homebrew/brew/pull/13796
|
||||
# TODO: Find a nicer way to handle this. (e.g. examining the ELF file to determine the required libstdc++.)
|
||||
@undeclared_deps.delete("gcc")
|
||||
@indirect_deps.delete("gcc")
|
||||
end
|
||||
end
|
||||
|
||||
# We build all formulae with an RPATH that includes the gcc formula's runtime lib directory.
|
||||
# See: https://github.com/Homebrew/brew/blob/e689cc07/Library/Homebrew/extend/os/linux/extend/ENV/super.rb#L53
|
||||
# This results in formulae showing linkage with gcc whenever it is installed, even if no dependency is declared.
|
||||
# See discussions at:
|
||||
# https://github.com/Homebrew/brew/pull/13659
|
||||
# https://github.com/Homebrew/brew/pull/13796
|
||||
# TODO: Find a nicer way to handle this. (e.g. examining the ELF file to determine the required libstdc++.)
|
||||
@undeclared_deps.delete("gcc")
|
||||
@indirect_deps.delete("gcc")
|
||||
end
|
||||
end
|
||||
|
||||
LinkageChecker.prepend(OS::Linux::LinkageChecker)
|
||||
|
@ -5,53 +5,59 @@ require "compilers"
|
||||
require "os/linux/glibc"
|
||||
require "system_command"
|
||||
|
||||
module SystemConfig
|
||||
include SystemCommand::Mixin
|
||||
module OS
|
||||
module Linux
|
||||
module SystemConfig
|
||||
module ClassMethods
|
||||
include SystemCommand::Mixin
|
||||
|
||||
HOST_RUBY_PATH = "/usr/bin/ruby"
|
||||
HOST_RUBY_PATH = "/usr/bin/ruby"
|
||||
|
||||
class << self
|
||||
def host_glibc_version
|
||||
version = OS::Linux::Glibc.system_version
|
||||
return "N/A" if version.null?
|
||||
def host_glibc_version
|
||||
version = OS::Linux::Glibc.system_version
|
||||
return "N/A" if version.null?
|
||||
|
||||
version
|
||||
end
|
||||
version
|
||||
end
|
||||
|
||||
def host_gcc_version
|
||||
gcc = DevelopmentTools.host_gcc_path
|
||||
return "N/A" unless gcc.executable?
|
||||
def host_gcc_version
|
||||
gcc = ::DevelopmentTools.host_gcc_path
|
||||
return "N/A" unless gcc.executable?
|
||||
|
||||
`#{gcc} --version 2>/dev/null`[/ (\d+\.\d+\.\d+)/, 1]
|
||||
end
|
||||
Utils.popen_read(gcc, "--version")[/ (\d+\.\d+\.\d+)/, 1]
|
||||
end
|
||||
|
||||
def formula_linked_version(formula)
|
||||
return "N/A" if Homebrew::EnvConfig.no_install_from_api? && !CoreTap.instance.installed?
|
||||
def formula_linked_version(formula)
|
||||
return "N/A" if Homebrew::EnvConfig.no_install_from_api? && !CoreTap.instance.installed?
|
||||
|
||||
Formulary.factory(formula).any_installed_version || "N/A"
|
||||
rescue FormulaUnavailableError
|
||||
"N/A"
|
||||
end
|
||||
Formulary.factory(formula).any_installed_version || "N/A"
|
||||
rescue FormulaUnavailableError
|
||||
"N/A"
|
||||
end
|
||||
|
||||
def host_ruby_version
|
||||
out, _, status = system_command(HOST_RUBY_PATH, args: ["-e", "puts RUBY_VERSION"], print_stderr: false)
|
||||
return "N/A" unless status.success?
|
||||
def host_ruby_version
|
||||
out, _, status = system_command(HOST_RUBY_PATH, args: ["-e", "puts RUBY_VERSION"], print_stderr: false)
|
||||
return "N/A" unless status.success?
|
||||
|
||||
out
|
||||
end
|
||||
out
|
||||
end
|
||||
|
||||
def dump_verbose_config(out = $stdout)
|
||||
kernel = Utils.safe_popen_read("uname", "-mors").chomp
|
||||
dump_generic_verbose_config(out)
|
||||
out.puts "Kernel: #{kernel}"
|
||||
out.puts "OS: #{OS::Linux.os_version}"
|
||||
out.puts "WSL: #{OS::Linux.wsl_version}" if OS::Linux.wsl?
|
||||
out.puts "Host glibc: #{host_glibc_version}"
|
||||
out.puts "#{DevelopmentTools.host_gcc_path}: #{host_gcc_version}"
|
||||
out.puts "/usr/bin/ruby: #{host_ruby_version}" if RUBY_PATH != HOST_RUBY_PATH
|
||||
["glibc", CompilerSelector.preferred_gcc, OS::LINUX_PREFERRED_GCC_RUNTIME_FORMULA, "xorg"].each do |f|
|
||||
out.puts "#{f}: #{formula_linked_version(f)}"
|
||||
def dump_verbose_config(out = $stdout)
|
||||
kernel = Utils.safe_popen_read("uname", "-mors").chomp
|
||||
super
|
||||
out.puts "Kernel: #{kernel}"
|
||||
out.puts "OS: #{OS::Linux.os_version}"
|
||||
out.puts "WSL: #{OS::Linux.wsl_version}" if OS::Linux.wsl?
|
||||
out.puts "Host glibc: #{host_glibc_version}"
|
||||
out.puts "#{::DevelopmentTools.host_gcc_path}: #{host_gcc_version}"
|
||||
out.puts "/usr/bin/ruby: #{host_ruby_version}" if RUBY_PATH != HOST_RUBY_PATH
|
||||
["glibc", CompilerSelector.preferred_gcc, OS::LINUX_PREFERRED_GCC_RUNTIME_FORMULA, "xorg"].each do |f|
|
||||
out.puts "#{f}: #{formula_linked_version(f)}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SystemConfig.singleton_class.prepend(OS::Linux::SystemConfig::ClassMethods)
|
||||
|
@ -15,6 +15,11 @@ module OS
|
||||
def os_bundle_args(bundle_args)
|
||||
non_linux_bundle_args(bundle_args)
|
||||
end
|
||||
|
||||
sig { params(files: T::Array[String]).returns(T::Array[String]) }
|
||||
def os_files(files)
|
||||
non_linux_files(files)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,42 +1,50 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SharedEnvExtension
|
||||
sig {
|
||||
params(
|
||||
formula: T.nilable(Formula),
|
||||
cc: T.nilable(String),
|
||||
build_bottle: T.nilable(T::Boolean),
|
||||
bottle_arch: T.nilable(String),
|
||||
testing_formula: T::Boolean,
|
||||
debug_symbols: T.nilable(T::Boolean),
|
||||
).void
|
||||
}
|
||||
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false,
|
||||
debug_symbols: false)
|
||||
generic_shared_setup_build_environment(formula:, cc:, build_bottle:,
|
||||
bottle_arch:, testing_formula:,
|
||||
debug_symbols:)
|
||||
module OS
|
||||
module Mac
|
||||
module SharedEnvExtension
|
||||
extend T::Helpers
|
||||
|
||||
# Normalise the system Perl version used, where multiple may be available
|
||||
self["VERSIONER_PERL_VERSION"] = MacOS.preferred_perl_version
|
||||
end
|
||||
requires_ancestor { ::SharedEnvExtension }
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def no_weak_imports_support?
|
||||
return false if compiler != :clang
|
||||
sig {
|
||||
params(
|
||||
formula: T.nilable(::Formula),
|
||||
cc: T.nilable(String),
|
||||
build_bottle: T.nilable(T::Boolean),
|
||||
bottle_arch: T.nilable(String),
|
||||
testing_formula: T::Boolean,
|
||||
debug_symbols: T.nilable(T::Boolean),
|
||||
).void
|
||||
}
|
||||
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil,
|
||||
testing_formula: false, debug_symbols: false)
|
||||
super
|
||||
|
||||
return false if !MacOS::Xcode.version.null? && MacOS::Xcode.version < "8.0"
|
||||
return false if !MacOS::CLT.version.null? && MacOS::CLT.version < "8.0"
|
||||
# Normalise the system Perl version used, where multiple may be available
|
||||
self["VERSIONER_PERL_VERSION"] = MacOS.preferred_perl_version
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
sig { returns(T::Boolean) }
|
||||
def no_weak_imports_support?
|
||||
return false if compiler != :clang
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def no_fixup_chains_support?
|
||||
# This is supported starting Xcode 13, which ships ld64-711.
|
||||
# https://developer.apple.com/documentation/xcode-release-notes/xcode-13-release-notes
|
||||
# https://en.wikipedia.org/wiki/Xcode#Xcode_11.0_-_14.x_(since_SwiftUI_framework)_2
|
||||
OS::Mac::DevelopmentTools.ld64_version >= 711
|
||||
return false if !MacOS::Xcode.version.null? && MacOS::Xcode.version < "8.0"
|
||||
return false if !MacOS::CLT.version.null? && MacOS::CLT.version < "8.0"
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def no_fixup_chains_support?
|
||||
# This is supported starting Xcode 13, which ships ld64-711.
|
||||
# https://developer.apple.com/documentation/xcode-release-notes/xcode-13-release-notes
|
||||
# https://en.wikipedia.org/wiki/Xcode#Xcode_11.0_-_14.x_(since_SwiftUI_framework)_2
|
||||
OS::Mac::DevelopmentTools.ld64_version >= 711
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SharedEnvExtension.prepend(OS::Mac::SharedEnvExtension)
|
||||
|
@ -1,117 +1,125 @@
|
||||
# typed: true # rubocop:disable Sorbet/StrictSigil
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Stdenv
|
||||
undef homebrew_extra_pkg_config_paths
|
||||
module OS
|
||||
module Mac
|
||||
module Stdenv
|
||||
extend T::Helpers
|
||||
|
||||
sig { returns(T::Array[Pathname]) }
|
||||
def homebrew_extra_pkg_config_paths
|
||||
[Pathname("#{HOMEBREW_LIBRARY}/Homebrew/os/mac/pkgconfig/#{MacOS.version}")]
|
||||
end
|
||||
private :homebrew_extra_pkg_config_paths
|
||||
requires_ancestor { SharedEnvExtension }
|
||||
requires_ancestor { ::Stdenv }
|
||||
|
||||
sig {
|
||||
params(
|
||||
formula: T.nilable(Formula),
|
||||
cc: T.nilable(String),
|
||||
build_bottle: T.nilable(T::Boolean),
|
||||
bottle_arch: T.nilable(String),
|
||||
testing_formula: T::Boolean,
|
||||
debug_symbols: T.nilable(T::Boolean),
|
||||
).void
|
||||
}
|
||||
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false,
|
||||
debug_symbols: false)
|
||||
generic_setup_build_environment(formula:, cc:, build_bottle:, bottle_arch:,
|
||||
testing_formula:, debug_symbols:)
|
||||
sig { returns(T::Array[Pathname]) }
|
||||
def homebrew_extra_pkg_config_paths
|
||||
[Pathname("#{HOMEBREW_LIBRARY}/Homebrew/os/mac/pkgconfig/#{MacOS.version}")]
|
||||
end
|
||||
private :homebrew_extra_pkg_config_paths
|
||||
|
||||
append "LDFLAGS", "-Wl,-headerpad_max_install_names"
|
||||
sig {
|
||||
params(
|
||||
formula: T.nilable(Formula),
|
||||
cc: T.nilable(String),
|
||||
build_bottle: T.nilable(T::Boolean),
|
||||
bottle_arch: T.nilable(String),
|
||||
testing_formula: T::Boolean,
|
||||
debug_symbols: T.nilable(T::Boolean),
|
||||
).void
|
||||
}
|
||||
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil,
|
||||
testing_formula: false, debug_symbols: false)
|
||||
super
|
||||
|
||||
# `sed` is strict and errors out when it encounters files with mixed character sets.
|
||||
delete("LC_ALL")
|
||||
self["LC_CTYPE"] = "C"
|
||||
append "LDFLAGS", "-Wl,-headerpad_max_install_names"
|
||||
|
||||
# Add `lib` and `include` etc. from the current `macosxsdk` to compiler flags:
|
||||
macosxsdk(formula: @formula, testing_formula:)
|
||||
# `sed` is strict and errors out when it encounters files with mixed character sets.
|
||||
delete("LC_ALL")
|
||||
self["LC_CTYPE"] = "C"
|
||||
|
||||
return unless MacOS::Xcode.without_clt?
|
||||
# Add `lib` and `include` etc. from the current `macosxsdk` to compiler flags:
|
||||
macosxsdk(formula: @formula, testing_formula:)
|
||||
|
||||
append_path "PATH", "#{MacOS::Xcode.prefix}/usr/bin"
|
||||
append_path "PATH", "#{MacOS::Xcode.toolchain_path}/usr/bin"
|
||||
end
|
||||
return unless MacOS::Xcode.without_clt?
|
||||
|
||||
def remove_macosxsdk(version = nil)
|
||||
# Clear all `lib` and `include` dirs from `CFLAGS`, `CPPFLAGS`, `LDFLAGS` that were
|
||||
# previously added by `macosxsdk`.
|
||||
remove_from_cflags(/ ?-mmacosx-version-min=\d+\.\d+/)
|
||||
delete("CPATH")
|
||||
remove "LDFLAGS", "-L#{HOMEBREW_PREFIX}/lib"
|
||||
append_path "PATH", "#{MacOS::Xcode.prefix}/usr/bin"
|
||||
append_path "PATH", "#{MacOS::Xcode.toolchain_path}/usr/bin"
|
||||
end
|
||||
|
||||
sdk = self["SDKROOT"] || MacOS.sdk_path_if_needed(version)
|
||||
return unless sdk
|
||||
def remove_macosxsdk(version = nil)
|
||||
# Clear all `lib` and `include` dirs from `CFLAGS`, `CPPFLAGS`, `LDFLAGS` that were
|
||||
# previously added by `macosxsdk`.
|
||||
remove_from_cflags(/ ?-mmacosx-version-min=\d+\.\d+/)
|
||||
delete("CPATH")
|
||||
remove "LDFLAGS", "-L#{HOMEBREW_PREFIX}/lib"
|
||||
|
||||
delete("SDKROOT")
|
||||
remove_from_cflags "-isysroot#{sdk}"
|
||||
remove "CPPFLAGS", "-isysroot#{sdk}"
|
||||
remove "LDFLAGS", "-isysroot#{sdk}"
|
||||
if HOMEBREW_PREFIX.to_s == "/usr/local"
|
||||
delete("CMAKE_PREFIX_PATH")
|
||||
else
|
||||
# It was set in `setup_build_environment`, so we have to restore it here.
|
||||
self["CMAKE_PREFIX_PATH"] = HOMEBREW_PREFIX.to_s
|
||||
sdk = self["SDKROOT"] || MacOS.sdk_path_if_needed(version)
|
||||
return unless sdk
|
||||
|
||||
delete("SDKROOT")
|
||||
remove_from_cflags "-isysroot#{sdk}"
|
||||
remove "CPPFLAGS", "-isysroot#{sdk}"
|
||||
remove "LDFLAGS", "-isysroot#{sdk}"
|
||||
if HOMEBREW_PREFIX.to_s == "/usr/local"
|
||||
delete("CMAKE_PREFIX_PATH")
|
||||
else
|
||||
# It was set in `setup_build_environment`, so we have to restore it here.
|
||||
self["CMAKE_PREFIX_PATH"] = HOMEBREW_PREFIX.to_s
|
||||
end
|
||||
remove "CMAKE_FRAMEWORK_PATH", "#{sdk}/System/Library/Frameworks"
|
||||
end
|
||||
|
||||
def macosxsdk(version = nil, formula: nil, testing_formula: false)
|
||||
# Sets all needed `lib` and `include` dirs to `CFLAGS`, `CPPFLAGS`, `LDFLAGS`.
|
||||
remove_macosxsdk
|
||||
min_version = version || MacOS.version
|
||||
append_to_cflags("-mmacosx-version-min=#{min_version}")
|
||||
self["CPATH"] = "#{HOMEBREW_PREFIX}/include"
|
||||
prepend "LDFLAGS", "-L#{HOMEBREW_PREFIX}/lib"
|
||||
|
||||
sdk = if formula
|
||||
MacOS.sdk_for_formula(formula, version, check_only_runtime_requirements: testing_formula)
|
||||
else
|
||||
MacOS.sdk(version)
|
||||
end
|
||||
return if !MacOS.sdk_root_needed? && sdk&.source != :xcode
|
||||
|
||||
Homebrew::Diagnostic.checks(:fatal_setup_build_environment_checks)
|
||||
sdk = sdk.path
|
||||
|
||||
# Extra setup to support Xcode 4.3+ without CLT.
|
||||
self["SDKROOT"] = sdk
|
||||
# Tell clang/gcc where system include's are:
|
||||
append_path "CPATH", "#{sdk}/usr/include"
|
||||
# The -isysroot is needed, too, because of the Frameworks
|
||||
append_to_cflags "-isysroot#{sdk}"
|
||||
append "CPPFLAGS", "-isysroot#{sdk}"
|
||||
# And the linker needs to find sdk/usr/lib
|
||||
append "LDFLAGS", "-isysroot#{sdk}"
|
||||
# Needed to build cmake itself and perhaps some cmake projects:
|
||||
append_path "CMAKE_PREFIX_PATH", "#{sdk}/usr"
|
||||
append_path "CMAKE_FRAMEWORK_PATH", "#{sdk}/System/Library/Frameworks"
|
||||
end
|
||||
|
||||
# Some configure scripts won't find libxml2 without help.
|
||||
# This is a no-op with macOS SDK 10.15.4 and later.
|
||||
def libxml2
|
||||
sdk = self["SDKROOT"] || MacOS.sdk_path_if_needed
|
||||
if !sdk
|
||||
append "CPPFLAGS", "-I/usr/include/libxml2"
|
||||
elsif !Pathname("#{sdk}/usr/include/libxml").directory?
|
||||
# Use the includes form the sdk
|
||||
append "CPPFLAGS", "-I#{sdk}/usr/include/libxml2"
|
||||
end
|
||||
end
|
||||
|
||||
def no_weak_imports
|
||||
append "LDFLAGS", "-Wl,-no_weak_imports" if no_weak_imports_support?
|
||||
end
|
||||
|
||||
def no_fixup_chains
|
||||
append "LDFLAGS", "-Wl,-no_fixup_chains" if no_fixup_chains_support?
|
||||
end
|
||||
end
|
||||
remove "CMAKE_FRAMEWORK_PATH", "#{sdk}/System/Library/Frameworks"
|
||||
end
|
||||
|
||||
def macosxsdk(version = nil, formula: nil, testing_formula: false)
|
||||
# Sets all needed `lib` and `include` dirs to `CFLAGS`, `CPPFLAGS`, `LDFLAGS`.
|
||||
remove_macosxsdk
|
||||
min_version = version || MacOS.version
|
||||
append_to_cflags("-mmacosx-version-min=#{min_version}")
|
||||
self["CPATH"] = "#{HOMEBREW_PREFIX}/include"
|
||||
prepend "LDFLAGS", "-L#{HOMEBREW_PREFIX}/lib"
|
||||
|
||||
sdk = if formula
|
||||
MacOS.sdk_for_formula(formula, version, check_only_runtime_requirements: testing_formula)
|
||||
else
|
||||
MacOS.sdk(version)
|
||||
end
|
||||
return if !MacOS.sdk_root_needed? && sdk&.source != :xcode
|
||||
|
||||
Homebrew::Diagnostic.checks(:fatal_setup_build_environment_checks)
|
||||
sdk = sdk.path
|
||||
|
||||
# Extra setup to support Xcode 4.3+ without CLT.
|
||||
self["SDKROOT"] = sdk
|
||||
# Tell clang/gcc where system include's are:
|
||||
append_path "CPATH", "#{sdk}/usr/include"
|
||||
# The -isysroot is needed, too, because of the Frameworks
|
||||
append_to_cflags "-isysroot#{sdk}"
|
||||
append "CPPFLAGS", "-isysroot#{sdk}"
|
||||
# And the linker needs to find sdk/usr/lib
|
||||
append "LDFLAGS", "-isysroot#{sdk}"
|
||||
# Needed to build cmake itself and perhaps some cmake projects:
|
||||
append_path "CMAKE_PREFIX_PATH", "#{sdk}/usr"
|
||||
append_path "CMAKE_FRAMEWORK_PATH", "#{sdk}/System/Library/Frameworks"
|
||||
end
|
||||
|
||||
# Some configure scripts won't find libxml2 without help.
|
||||
# This is a no-op with macOS SDK 10.15.4 and later.
|
||||
def libxml2
|
||||
sdk = self["SDKROOT"] || MacOS.sdk_path_if_needed
|
||||
if !sdk
|
||||
append "CPPFLAGS", "-I/usr/include/libxml2"
|
||||
elsif !Pathname("#{sdk}/usr/include/libxml").directory?
|
||||
# Use the includes form the sdk
|
||||
append "CPPFLAGS", "-I#{sdk}/usr/include/libxml2"
|
||||
end
|
||||
end
|
||||
|
||||
def no_weak_imports
|
||||
append "LDFLAGS", "-Wl,-no_weak_imports" if no_weak_imports_support?
|
||||
end
|
||||
|
||||
def no_fixup_chains
|
||||
append "LDFLAGS", "-Wl,-no_fixup_chains" if no_fixup_chains_support?
|
||||
end
|
||||
end
|
||||
|
||||
Stdenv.prepend(OS::Mac::Stdenv)
|
||||
|
@ -1,171 +1,173 @@
|
||||
# typed: true # rubocop:disable Sorbet/StrictSigil
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Superenv
|
||||
class << self
|
||||
# The location of Homebrew's shims on macOS.
|
||||
def shims_path
|
||||
HOMEBREW_SHIMS_PATH/"mac/super"
|
||||
end
|
||||
module OS
|
||||
module Mac
|
||||
module Superenv
|
||||
extend T::Helpers
|
||||
|
||||
undef bin
|
||||
requires_ancestor { SharedEnvExtension }
|
||||
requires_ancestor { ::Superenv }
|
||||
|
||||
def bin
|
||||
return unless DevelopmentTools.installed?
|
||||
module ClassMethods
|
||||
sig { returns(Pathname) }
|
||||
def shims_path
|
||||
HOMEBREW_SHIMS_PATH/"mac/super"
|
||||
end
|
||||
|
||||
shims_path.realpath
|
||||
end
|
||||
end
|
||||
sig { returns(T.nilable(Pathname)) }
|
||||
def bin
|
||||
return unless ::DevelopmentTools.installed?
|
||||
|
||||
undef homebrew_extra_pkg_config_paths,
|
||||
homebrew_extra_isystem_paths, homebrew_extra_library_paths,
|
||||
homebrew_extra_cmake_include_paths,
|
||||
homebrew_extra_cmake_library_paths,
|
||||
homebrew_extra_cmake_frameworks_paths,
|
||||
determine_cccfg
|
||||
|
||||
sig { returns(T::Array[Pathname]) }
|
||||
def homebrew_extra_pkg_config_paths
|
||||
[Pathname("/usr/lib/pkgconfig"), Pathname("#{HOMEBREW_LIBRARY}/Homebrew/os/mac/pkgconfig/#{MacOS.version}")]
|
||||
end
|
||||
private :homebrew_extra_pkg_config_paths
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def libxml2_include_needed?
|
||||
return false if deps.any? { |d| d.name == "libxml2" }
|
||||
return false if Pathname("#{self["HOMEBREW_SDKROOT"]}/usr/include/libxml").directory?
|
||||
|
||||
true
|
||||
end
|
||||
private :libxml2_include_needed?
|
||||
|
||||
def homebrew_extra_isystem_paths
|
||||
paths = []
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/usr/include/libxml2" if libxml2_include_needed?
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/usr/include/apache2" if MacOS::Xcode.without_clt?
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Headers"
|
||||
paths
|
||||
end
|
||||
|
||||
def homebrew_extra_library_paths
|
||||
paths = []
|
||||
if compiler == :llvm_clang
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/usr/lib"
|
||||
paths << Formula["llvm"].opt_lib.to_s
|
||||
end
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries"
|
||||
paths
|
||||
end
|
||||
|
||||
def homebrew_extra_cmake_include_paths
|
||||
paths = []
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/usr/include/libxml2" if libxml2_include_needed?
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/usr/include/apache2" if MacOS::Xcode.without_clt?
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Headers"
|
||||
paths
|
||||
end
|
||||
|
||||
def homebrew_extra_cmake_library_paths
|
||||
[Pathname("#{self["HOMEBREW_SDKROOT"]}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries")]
|
||||
end
|
||||
|
||||
def homebrew_extra_cmake_frameworks_paths
|
||||
paths = []
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/System/Library/Frameworks" if MacOS::Xcode.without_clt?
|
||||
paths
|
||||
end
|
||||
|
||||
def determine_cccfg
|
||||
s = +""
|
||||
# Fix issue with >= Mountain Lion apr-1-config having broken paths
|
||||
s << "a"
|
||||
s.freeze
|
||||
end
|
||||
|
||||
# @private
|
||||
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false,
|
||||
debug_symbols: false)
|
||||
sdk = formula ? MacOS.sdk_for_formula(formula) : MacOS.sdk
|
||||
is_xcode_sdk = sdk&.source == :xcode
|
||||
|
||||
if is_xcode_sdk || MacOS.sdk_root_needed?
|
||||
Homebrew::Diagnostic.checks(:fatal_setup_build_environment_checks)
|
||||
self["HOMEBREW_SDKROOT"] = sdk.path if sdk
|
||||
end
|
||||
|
||||
self["HOMEBREW_DEVELOPER_DIR"] = if is_xcode_sdk
|
||||
MacOS::Xcode.prefix.to_s
|
||||
else
|
||||
MacOS::CLT::PKG_PATH
|
||||
end
|
||||
|
||||
# This is a workaround for the missing `m4` in Xcode CLT 15.3, which was
|
||||
# reported in FB13679972. Apple has fixed this in Xcode CLT 16.0.
|
||||
# See https://github.com/Homebrew/homebrew-core/issues/165388
|
||||
if deps.none? { |d| d.name == "m4" } &&
|
||||
MacOS.active_developer_dir == MacOS::CLT::PKG_PATH &&
|
||||
!File.exist?("#{MacOS::CLT::PKG_PATH}/usr/bin/m4") &&
|
||||
(gm4 = DevelopmentTools.locate("gm4").to_s).present?
|
||||
self["M4"] = gm4
|
||||
end
|
||||
|
||||
generic_setup_build_environment(formula:, cc:, build_bottle:, bottle_arch:,
|
||||
testing_formula:, debug_symbols:)
|
||||
|
||||
# Filter out symbols known not to be defined since GNU Autotools can't
|
||||
# reliably figure this out with Xcode 8 and above.
|
||||
if MacOS.version == "10.12" && MacOS::Xcode.version >= "9.0"
|
||||
%w[fmemopen futimens open_memstream utimensat].each do |s|
|
||||
ENV["ac_cv_func_#{s}"] = "no"
|
||||
end
|
||||
elsif MacOS.version == "10.11" && MacOS::Xcode.version >= "8.0"
|
||||
%w[basename_r clock_getres clock_gettime clock_settime dirname_r
|
||||
getentropy mkostemp mkostemps timingsafe_bcmp].each do |s|
|
||||
ENV["ac_cv_func_#{s}"] = "no"
|
||||
shims_path.realpath
|
||||
end
|
||||
end
|
||||
|
||||
ENV["ac_cv_search_clock_gettime"] = "no"
|
||||
sig { returns(T::Array[Pathname]) }
|
||||
def homebrew_extra_pkg_config_paths
|
||||
[Pathname("/usr/lib/pkgconfig"), Pathname("#{HOMEBREW_LIBRARY}/Homebrew/os/mac/pkgconfig/#{MacOS.version}")]
|
||||
end
|
||||
|
||||
# works around libev.m4 unsetting ac_cv_func_clock_gettime
|
||||
ENV["ac_have_clock_syscall"] = "no"
|
||||
sig { returns(T::Boolean) }
|
||||
def libxml2_include_needed?
|
||||
return false if deps.any? { |d| d.name == "libxml2" }
|
||||
return false if Pathname("#{self["HOMEBREW_SDKROOT"]}/usr/include/libxml").directory?
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def homebrew_extra_isystem_paths
|
||||
paths = []
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/usr/include/libxml2" if libxml2_include_needed?
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/usr/include/apache2" if MacOS::Xcode.without_clt?
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Headers"
|
||||
paths
|
||||
end
|
||||
|
||||
def homebrew_extra_library_paths
|
||||
paths = []
|
||||
if compiler == :llvm_clang
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/usr/lib"
|
||||
paths << ::Formula["llvm"].opt_lib.to_s
|
||||
end
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries"
|
||||
paths
|
||||
end
|
||||
|
||||
def homebrew_extra_cmake_include_paths
|
||||
paths = []
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/usr/include/libxml2" if libxml2_include_needed?
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/usr/include/apache2" if MacOS::Xcode.without_clt?
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Headers"
|
||||
paths
|
||||
end
|
||||
|
||||
def homebrew_extra_cmake_library_paths
|
||||
brew_sdkroot = self["HOMEBREW_SDKROOT"]
|
||||
[Pathname("#{brew_sdkroot}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries")]
|
||||
end
|
||||
|
||||
def homebrew_extra_cmake_frameworks_paths
|
||||
paths = []
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/System/Library/Frameworks" if MacOS::Xcode.without_clt?
|
||||
paths
|
||||
end
|
||||
|
||||
def determine_cccfg
|
||||
s = +""
|
||||
# Fix issue with >= Mountain Lion apr-1-config having broken paths
|
||||
s << "a"
|
||||
s.freeze
|
||||
end
|
||||
|
||||
# @private
|
||||
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil,
|
||||
testing_formula: false, debug_symbols: false)
|
||||
sdk = formula ? MacOS.sdk_for_formula(formula) : MacOS.sdk
|
||||
is_xcode_sdk = sdk&.source == :xcode
|
||||
|
||||
if is_xcode_sdk || MacOS.sdk_root_needed?
|
||||
Homebrew::Diagnostic.checks(:fatal_setup_build_environment_checks)
|
||||
self["HOMEBREW_SDKROOT"] = sdk.path if sdk
|
||||
end
|
||||
|
||||
self["HOMEBREW_DEVELOPER_DIR"] = if is_xcode_sdk
|
||||
MacOS::Xcode.prefix.to_s
|
||||
else
|
||||
MacOS::CLT::PKG_PATH
|
||||
end
|
||||
|
||||
# This is a workaround for the missing `m4` in Xcode CLT 15.3, which was
|
||||
# reported in FB13679972. Apple has fixed this in Xcode CLT 16.0.
|
||||
# See https://github.com/Homebrew/homebrew-core/issues/165388
|
||||
if deps.none? { |d| d.name == "m4" } &&
|
||||
MacOS.active_developer_dir == MacOS::CLT::PKG_PATH &&
|
||||
!File.exist?("#{MacOS::CLT::PKG_PATH}/usr/bin/m4") &&
|
||||
(gm4 = ::DevelopmentTools.locate("gm4").to_s).present?
|
||||
self["M4"] = gm4
|
||||
end
|
||||
|
||||
super
|
||||
|
||||
# Filter out symbols known not to be defined since GNU Autotools can't
|
||||
# reliably figure this out with Xcode 8 and above.
|
||||
if MacOS.version == "10.12" && MacOS::Xcode.version >= "9.0"
|
||||
%w[fmemopen futimens open_memstream utimensat].each do |s|
|
||||
ENV["ac_cv_func_#{s}"] = "no"
|
||||
end
|
||||
elsif MacOS.version == "10.11" && MacOS::Xcode.version >= "8.0"
|
||||
%w[basename_r clock_getres clock_gettime clock_settime dirname_r
|
||||
getentropy mkostemp mkostemps timingsafe_bcmp].each do |s|
|
||||
ENV["ac_cv_func_#{s}"] = "no"
|
||||
end
|
||||
|
||||
ENV["ac_cv_search_clock_gettime"] = "no"
|
||||
|
||||
# works around libev.m4 unsetting ac_cv_func_clock_gettime
|
||||
ENV["ac_have_clock_syscall"] = "no"
|
||||
end
|
||||
|
||||
# On macOS Sonoma (at least release candidate), iconv() is generally
|
||||
# present and working, but has a minor regression that defeats the
|
||||
# test implemented in gettext's configure script (and used by many
|
||||
# gettext dependents).
|
||||
ENV["am_cv_func_iconv_works"] = "yes" if MacOS.version == "14"
|
||||
|
||||
# The tools in /usr/bin proxy to the active developer directory.
|
||||
# This means we can use them for any combination of CLT and Xcode.
|
||||
self["HOMEBREW_PREFER_CLT_PROXIES"] = "1"
|
||||
|
||||
# Deterministic timestamping.
|
||||
# This can work on older Xcode versions, but they contain some bugs.
|
||||
# Notably, Xcode 10.2 fixes issues where ZERO_AR_DATE affected file mtimes.
|
||||
# Xcode 11.0 contains fixes for lldb reading things built with ZERO_AR_DATE.
|
||||
self["ZERO_AR_DATE"] = "1" if MacOS::Xcode.version >= "11.0" || MacOS::CLT.version >= "11.0"
|
||||
|
||||
# Pass `-no_fixup_chains` whenever the linker is invoked with `-undefined dynamic_lookup`.
|
||||
# See: https://github.com/python/cpython/issues/97524
|
||||
# https://github.com/pybind/pybind11/pull/4301
|
||||
no_fixup_chains
|
||||
|
||||
# Strip build prefixes from linker where supported, for deterministic builds.
|
||||
append_to_cccfg "o" if OS::Mac::DevelopmentTools.ld64_version >= 512
|
||||
|
||||
# Pass `-ld_classic` whenever the linker is invoked with `-dead_strip_dylibs`
|
||||
# on `ld` versions that don't properly handle that option.
|
||||
return unless OS::Mac::DevelopmentTools.ld64_version.between?("1015.7", "1022.1")
|
||||
|
||||
append_to_cccfg "c"
|
||||
end
|
||||
|
||||
def no_weak_imports
|
||||
append_to_cccfg "w" if no_weak_imports_support?
|
||||
end
|
||||
|
||||
def no_fixup_chains
|
||||
append_to_cccfg "f" if no_fixup_chains_support?
|
||||
end
|
||||
end
|
||||
|
||||
# On macOS Sonoma (at least release candidate), iconv() is generally
|
||||
# present and working, but has a minor regression that defeats the
|
||||
# test implemented in gettext's configure script (and used by many
|
||||
# gettext dependents).
|
||||
ENV["am_cv_func_iconv_works"] = "yes" if MacOS.version == "14"
|
||||
|
||||
# The tools in /usr/bin proxy to the active developer directory.
|
||||
# This means we can use them for any combination of CLT and Xcode.
|
||||
self["HOMEBREW_PREFER_CLT_PROXIES"] = "1"
|
||||
|
||||
# Deterministic timestamping.
|
||||
# This can work on older Xcode versions, but they contain some bugs.
|
||||
# Notably, Xcode 10.2 fixes issues where ZERO_AR_DATE affected file mtimes.
|
||||
# Xcode 11.0 contains fixes for lldb reading things built with ZERO_AR_DATE.
|
||||
self["ZERO_AR_DATE"] = "1" if MacOS::Xcode.version >= "11.0" || MacOS::CLT.version >= "11.0"
|
||||
|
||||
# Pass `-no_fixup_chains` whenever the linker is invoked with `-undefined dynamic_lookup`.
|
||||
# See: https://github.com/python/cpython/issues/97524
|
||||
# https://github.com/pybind/pybind11/pull/4301
|
||||
no_fixup_chains
|
||||
|
||||
# Strip build prefixes from linker where supported, for deterministic builds.
|
||||
append_to_cccfg "o" if OS::Mac::DevelopmentTools.ld64_version >= 512
|
||||
|
||||
# Pass `-ld_classic` whenever the linker is invoked with `-dead_strip_dylibs`
|
||||
# on `ld` versions that don't properly handle that option.
|
||||
return unless OS::Mac::DevelopmentTools.ld64_version.between?("1015.7", "1022.1")
|
||||
|
||||
append_to_cccfg "c"
|
||||
end
|
||||
|
||||
def no_weak_imports
|
||||
append_to_cccfg "w" if no_weak_imports_support?
|
||||
end
|
||||
|
||||
def no_fixup_chains
|
||||
append_to_cccfg "f" if no_fixup_chains_support?
|
||||
end
|
||||
end
|
||||
|
||||
Superenv.singleton_class.prepend(OS::Mac::Superenv::ClassMethods)
|
||||
Superenv.prepend(OS::Mac::Superenv)
|
||||
|
@ -4,133 +4,145 @@
|
||||
require "cache_store"
|
||||
require "linkage_checker"
|
||||
|
||||
module FormulaCellarChecks
|
||||
sig { returns(T.nilable(String)) }
|
||||
def check_shadowed_headers
|
||||
return if ["libtool", "subversion", "berkeley-db"].any? do |formula_name|
|
||||
formula.name.start_with?(formula_name)
|
||||
end
|
||||
module OS
|
||||
module Mac
|
||||
module FormulaCellarChecks
|
||||
extend T::Helpers
|
||||
|
||||
return if formula.name.match?(Version.formula_optionally_versioned_regex(:php))
|
||||
return if formula.keg_only? || !formula.include.directory?
|
||||
requires_ancestor { Homebrew::FormulaAuditor }
|
||||
requires_ancestor { ::FormulaCellarChecks }
|
||||
|
||||
files = relative_glob(formula.include, "**/*.h")
|
||||
files &= relative_glob("#{MacOS.sdk_path}/usr/include", "**/*.h")
|
||||
files.map! { |p| File.join(formula.include, p) }
|
||||
sig { returns(T.nilable(String)) }
|
||||
def check_shadowed_headers
|
||||
return if ["libtool", "subversion", "berkeley-db"].any? do |formula_name|
|
||||
formula.name.start_with?(formula_name)
|
||||
end
|
||||
|
||||
return if files.empty?
|
||||
return if formula.name.match?(Version.formula_optionally_versioned_regex(:php))
|
||||
return if formula.keg_only? || !formula.include.directory?
|
||||
|
||||
<<~EOS
|
||||
Header files that shadow system header files were installed to "#{formula.include}"
|
||||
The offending files are:
|
||||
#{files * "\n "}
|
||||
EOS
|
||||
end
|
||||
files = relative_glob(formula.include, "**/*.h")
|
||||
files &= relative_glob("#{MacOS.sdk_path}/usr/include", "**/*.h")
|
||||
files.map! { |p| File.join(formula.include, p) }
|
||||
|
||||
sig { returns(T.nilable(String)) }
|
||||
def check_openssl_links
|
||||
return unless formula.prefix.directory?
|
||||
return if files.empty?
|
||||
|
||||
keg = Keg.new(formula.prefix)
|
||||
system_openssl = keg.mach_o_files.select do |obj|
|
||||
dlls = obj.dynamically_linked_libraries
|
||||
dlls.any? { |dll| %r{/usr/lib/lib(crypto|ssl|tls)\..*dylib}.match? dll }
|
||||
end
|
||||
return if system_openssl.empty?
|
||||
|
||||
<<~EOS
|
||||
object files were linked against system openssl
|
||||
These object files were linked against the deprecated system OpenSSL or
|
||||
the system's private LibreSSL.
|
||||
Adding `depends_on "openssl"` to the formula may help.
|
||||
#{system_openssl * "\n "}
|
||||
EOS
|
||||
end
|
||||
|
||||
sig { params(lib: Pathname).returns(T.nilable(String)) }
|
||||
def check_python_framework_links(lib)
|
||||
python_modules = Pathname.glob lib/"python*/site-packages/**/*.so"
|
||||
framework_links = python_modules.select do |obj|
|
||||
dlls = obj.dynamically_linked_libraries
|
||||
dlls.any? { |dll| dll.include?("Python.framework") }
|
||||
end
|
||||
return if framework_links.empty?
|
||||
|
||||
<<~EOS
|
||||
python modules have explicit framework links
|
||||
These python extension modules were linked directly to a Python
|
||||
framework binary. They should be linked with -undefined dynamic_lookup
|
||||
instead of -lpython or -framework Python.
|
||||
#{framework_links * "\n "}
|
||||
EOS
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def check_linkage
|
||||
return unless formula.prefix.directory?
|
||||
|
||||
keg = Keg.new(formula.prefix)
|
||||
|
||||
CacheStoreDatabase.use(:linkage) do |db|
|
||||
checker = LinkageChecker.new(keg, formula, cache_db: db)
|
||||
next unless checker.broken_library_linkage?
|
||||
|
||||
output = <<~EOS
|
||||
#{formula} has broken dynamic library links:
|
||||
#{checker.display_test_output}
|
||||
EOS
|
||||
|
||||
tab = keg.tab
|
||||
if tab.poured_from_bottle
|
||||
output += <<~EOS
|
||||
Rebuild this from source with:
|
||||
brew reinstall --build-from-source #{formula}
|
||||
If that's successful, file an issue#{formula.tap ? " here:\n #{T.must(formula.tap).issues_url}" : "."}
|
||||
<<~EOS
|
||||
Header files that shadow system header files were installed to "#{formula.include}"
|
||||
The offending files are:
|
||||
#{files * "\n "}
|
||||
EOS
|
||||
end
|
||||
problem_if_output output
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(formula: Formula).returns(T.nilable(String)) }
|
||||
def check_flat_namespace(formula)
|
||||
return unless formula.prefix.directory?
|
||||
return if formula.tap&.audit_exception(:flat_namespace_allowlist, formula.name)
|
||||
sig { returns(T.nilable(String)) }
|
||||
def check_openssl_links
|
||||
return unless formula.prefix.directory?
|
||||
|
||||
keg = ::Keg.new(formula.prefix)
|
||||
flat_namespace_files = keg.mach_o_files.reject do |file|
|
||||
next true unless file.dylib?
|
||||
keg = ::Keg.new(formula.prefix)
|
||||
system_openssl = keg.mach_o_files.select do |obj|
|
||||
dlls = obj.dynamically_linked_libraries
|
||||
dlls.any? { |dll| %r{/usr/lib/lib(crypto|ssl|tls)\..*dylib}.match? dll }
|
||||
end
|
||||
return if system_openssl.empty?
|
||||
|
||||
macho = MachO.open(file)
|
||||
if MachO::Utils.fat_magic?(macho.magic)
|
||||
macho.machos.map(&:header).all? { |h| h.flag? :MH_TWOLEVEL }
|
||||
else
|
||||
macho.header.flag? :MH_TWOLEVEL
|
||||
<<~EOS
|
||||
object files were linked against system openssl
|
||||
These object files were linked against the deprecated system OpenSSL or
|
||||
the system's private LibreSSL.
|
||||
Adding `depends_on "openssl"` to the formula may help.
|
||||
#{system_openssl * "\n "}
|
||||
EOS
|
||||
end
|
||||
|
||||
sig { params(lib: Pathname).returns(T.nilable(String)) }
|
||||
def check_python_framework_links(lib)
|
||||
python_modules = Pathname.glob lib/"python*/site-packages/**/*.so"
|
||||
framework_links = python_modules.select do |obj|
|
||||
dlls = obj.dynamically_linked_libraries
|
||||
dlls.any? { |dll| dll.include?("Python.framework") }
|
||||
end
|
||||
return if framework_links.empty?
|
||||
|
||||
<<~EOS
|
||||
python modules have explicit framework links
|
||||
These python extension modules were linked directly to a Python
|
||||
framework binary. They should be linked with -undefined dynamic_lookup
|
||||
instead of -lpython or -framework Python.
|
||||
#{framework_links * "\n "}
|
||||
EOS
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def check_linkage
|
||||
return unless formula.prefix.directory?
|
||||
|
||||
keg = ::Keg.new(formula.prefix)
|
||||
|
||||
CacheStoreDatabase.use(:linkage) do |db|
|
||||
checker = ::LinkageChecker.new(keg, formula, cache_db: db)
|
||||
next unless checker.broken_library_linkage?
|
||||
|
||||
output = <<~EOS
|
||||
#{formula} has broken dynamic library links:
|
||||
#{checker.display_test_output}
|
||||
EOS
|
||||
|
||||
tab = keg.tab
|
||||
if tab.poured_from_bottle
|
||||
output += <<~EOS
|
||||
Rebuild this from source with:
|
||||
brew reinstall --build-from-source #{formula}
|
||||
If that's successful, file an issue#{formula.tap ? " here:\n #{formula.tap.issues_url}" : "."}
|
||||
EOS
|
||||
end
|
||||
problem_if_output output
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(formula: ::Formula).returns(T.nilable(String)) }
|
||||
def check_flat_namespace(formula)
|
||||
return unless formula.prefix.directory?
|
||||
return if formula.tap&.audit_exception(:flat_namespace_allowlist, formula.name)
|
||||
|
||||
keg = ::Keg.new(formula.prefix)
|
||||
flat_namespace_files = keg.mach_o_files.reject do |file|
|
||||
next true unless file.dylib?
|
||||
|
||||
macho = MachO.open(file)
|
||||
if MachO::Utils.fat_magic?(macho.magic)
|
||||
macho.machos.map(&:header).all? { |h| h.flag? :MH_TWOLEVEL }
|
||||
else
|
||||
macho.header.flag? :MH_TWOLEVEL
|
||||
end
|
||||
end
|
||||
return if flat_namespace_files.empty?
|
||||
|
||||
<<~EOS
|
||||
Libraries were compiled with a flat namespace.
|
||||
This can cause linker errors due to name collisions and
|
||||
is often due to a bug in detecting the macOS version.
|
||||
#{flat_namespace_files * "\n "}
|
||||
EOS
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def audit_installed
|
||||
super
|
||||
problem_if_output(check_shadowed_headers)
|
||||
problem_if_output(check_openssl_links)
|
||||
problem_if_output(check_python_framework_links(formula.lib))
|
||||
check_linkage
|
||||
problem_if_output(check_flat_namespace(formula))
|
||||
end
|
||||
|
||||
MACOS_LIB_EXTENSIONS = %w[.dylib .framework].freeze
|
||||
|
||||
sig { params(filename: Pathname).returns(T::Boolean) }
|
||||
def valid_library_extension?(filename)
|
||||
super || MACOS_LIB_EXTENSIONS.include?(filename.extname)
|
||||
end
|
||||
end
|
||||
return if flat_namespace_files.empty?
|
||||
|
||||
<<~EOS
|
||||
Libraries were compiled with a flat namespace.
|
||||
This can cause linker errors due to name collisions and
|
||||
is often due to a bug in detecting the macOS version.
|
||||
#{flat_namespace_files * "\n "}
|
||||
EOS
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def audit_installed
|
||||
generic_audit_installed
|
||||
problem_if_output(check_shadowed_headers)
|
||||
problem_if_output(check_openssl_links)
|
||||
problem_if_output(check_python_framework_links(formula.lib))
|
||||
check_linkage
|
||||
problem_if_output(check_flat_namespace(formula))
|
||||
end
|
||||
|
||||
sig { params(filename: Pathname).returns(T::Boolean) }
|
||||
def valid_library_extension?(filename)
|
||||
macos_lib_extensions = %w[.dylib .framework]
|
||||
generic_valid_library_extension?(filename) || macos_lib_extensions.include?(filename.extname)
|
||||
end
|
||||
end
|
||||
|
||||
FormulaCellarChecks.prepend(OS::Mac::FormulaCellarChecks)
|
||||
|
@ -1,25 +1,33 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Hardware
|
||||
sig { params(version: T.nilable(Version)).returns(Symbol) }
|
||||
def self.oldest_cpu(version = nil)
|
||||
version = if version
|
||||
MacOSVersion.new(version.to_s)
|
||||
else
|
||||
MacOS.version
|
||||
end
|
||||
if CPU.arch == :arm64
|
||||
:arm_vortex_tempest
|
||||
# This cannot use a newer CPU e.g. haswell because Rosetta 2 does not
|
||||
# support AVX instructions in bottles:
|
||||
# https://github.com/Homebrew/homebrew-core/issues/67713
|
||||
elsif version >= :ventura
|
||||
:westmere
|
||||
elsif version >= :mojave
|
||||
:nehalem
|
||||
else
|
||||
generic_oldest_cpu
|
||||
module OS
|
||||
module Mac
|
||||
module Hardware
|
||||
module ClassMethods
|
||||
sig { params(version: T.nilable(MacOSVersion)).returns(Symbol) }
|
||||
def oldest_cpu(version = nil)
|
||||
version = if version
|
||||
MacOSVersion.new(version.to_s)
|
||||
else
|
||||
MacOS.version
|
||||
end
|
||||
if ::Hardware::CPU.arch == :arm64
|
||||
:arm_vortex_tempest
|
||||
# This cannot use a newer CPU e.g. haswell because Rosetta 2 does not
|
||||
# support AVX instructions in bottles:
|
||||
# https://github.com/Homebrew/homebrew-core/issues/67713
|
||||
elsif version >= :ventura
|
||||
:westmere
|
||||
elsif version >= :mojave
|
||||
:nehalem
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Hardware.singleton_class.prepend(OS::Mac::Hardware::ClassMethods)
|
||||
|
@ -95,7 +95,7 @@ module OS
|
||||
end
|
||||
end
|
||||
|
||||
generic_fix_dynamic_linkage
|
||||
super
|
||||
end
|
||||
|
||||
def loader_name_for(file, target)
|
||||
@ -199,7 +199,7 @@ module OS
|
||||
end
|
||||
|
||||
def prepare_relocation_to_locations
|
||||
relocation = generic_prepare_relocation_to_locations
|
||||
relocation = super
|
||||
|
||||
brewed_perl = runtime_dependencies&.any? { |dep| dep["full_name"] == "perl" && dep["declared_directly"] }
|
||||
perl_path = if brewed_perl || name == "perl"
|
||||
|
@ -5,55 +5,59 @@ require "cask/info"
|
||||
require "cask/cask_loader"
|
||||
require "cask/caskroom"
|
||||
|
||||
module Homebrew
|
||||
module MissingFormula
|
||||
class << self
|
||||
sig { params(name: String).returns(T.nilable(String)) }
|
||||
def disallowed_reason(name)
|
||||
case name.downcase
|
||||
when "xcode"
|
||||
<<~EOS
|
||||
Xcode can be installed from the App Store.
|
||||
EOS
|
||||
else
|
||||
generic_disallowed_reason(name)
|
||||
module OS
|
||||
module Mac
|
||||
module MissingFormula
|
||||
module ClassMethods
|
||||
sig { params(name: String).returns(T.nilable(String)) }
|
||||
def disallowed_reason(name)
|
||||
case name.downcase
|
||||
when "xcode"
|
||||
<<~EOS
|
||||
Xcode can be installed from the App Store.
|
||||
EOS
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(name: String, silent: T::Boolean, show_info: T::Boolean).returns(T.nilable(String)) }
|
||||
def cask_reason(name, silent: false, show_info: false)
|
||||
return if silent
|
||||
sig { params(name: String, silent: T::Boolean, show_info: T::Boolean).returns(T.nilable(String)) }
|
||||
def cask_reason(name, silent: false, show_info: false)
|
||||
return if silent
|
||||
|
||||
suggest_command(name, show_info ? "info" : "install")
|
||||
end
|
||||
suggest_command(name, show_info ? "info" : "install")
|
||||
end
|
||||
|
||||
sig { params(name: String, command: String).returns(T.nilable(String)) }
|
||||
def suggest_command(name, command)
|
||||
suggestion = <<~EOS
|
||||
Found a cask named "#{name}" instead. Try
|
||||
brew #{command} --cask #{name}
|
||||
|
||||
EOS
|
||||
case command
|
||||
when "install"
|
||||
Cask::CaskLoader.load(name)
|
||||
when "uninstall"
|
||||
cask = Cask::Caskroom.casks.find { |installed_cask| installed_cask.to_s == name }
|
||||
raise Cask::CaskUnavailableError, name if cask.nil?
|
||||
when "info"
|
||||
cask = Cask::CaskLoader.load(name)
|
||||
sig { params(name: String, command: String).returns(T.nilable(String)) }
|
||||
def suggest_command(name, command)
|
||||
suggestion = <<~EOS
|
||||
Found a cask named "#{name}" instead.
|
||||
Found a cask named "#{name}" instead. Try
|
||||
brew #{command} --cask #{name}
|
||||
|
||||
#{Cask::Info.get_info(cask)}
|
||||
EOS
|
||||
else
|
||||
return
|
||||
case command
|
||||
when "install"
|
||||
::Cask::CaskLoader.load(name)
|
||||
when "uninstall"
|
||||
cask = ::Cask::Caskroom.casks.find { |installed_cask| installed_cask.to_s == name }
|
||||
Kernel.raise ::Cask::CaskUnavailableError, name if cask.nil?
|
||||
when "info"
|
||||
cask = ::Cask::CaskLoader.load(name)
|
||||
suggestion = <<~EOS
|
||||
Found a cask named "#{name}" instead.
|
||||
|
||||
#{::Cask::Info.get_info(cask)}
|
||||
EOS
|
||||
else
|
||||
return
|
||||
end
|
||||
suggestion
|
||||
rescue ::Cask::CaskUnavailableError
|
||||
nil
|
||||
end
|
||||
suggestion
|
||||
rescue Cask::CaskUnavailableError
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Homebrew::MissingFormula.singleton_class.prepend(OS::Mac::MissingFormula::ClassMethods)
|
||||
|
@ -6,46 +6,45 @@ require "system_command"
|
||||
module OS
|
||||
module Mac
|
||||
module SystemConfig
|
||||
sig { returns(String) }
|
||||
def describe_clang
|
||||
return "N/A" if ::SystemConfig.clang.null?
|
||||
module ClassMethods
|
||||
extend T::Helpers
|
||||
|
||||
clang_build_info = ::SystemConfig.clang_build.null? ? "(parse error)" : ::SystemConfig.clang_build
|
||||
"#{::SystemConfig.clang} build #{clang_build_info}"
|
||||
requires_ancestor { T.class_of(::SystemConfig) }
|
||||
|
||||
sig { returns(String) }
|
||||
def describe_clang
|
||||
return "N/A" if ::SystemConfig.clang.null?
|
||||
|
||||
clang_build_info = ::SystemConfig.clang_build.null? ? "(parse error)" : ::SystemConfig.clang_build
|
||||
"#{::SystemConfig.clang} build #{clang_build_info}"
|
||||
end
|
||||
|
||||
def xcode
|
||||
@xcode ||= if MacOS::Xcode.installed?
|
||||
xcode = MacOS::Xcode.version.to_s
|
||||
xcode += " => #{MacOS::Xcode.prefix}" unless MacOS::Xcode.default_prefix?
|
||||
xcode
|
||||
end
|
||||
end
|
||||
|
||||
def clt
|
||||
@clt ||= MacOS::CLT.version if MacOS::CLT.installed?
|
||||
end
|
||||
|
||||
def core_tap_config(out = $stdout)
|
||||
dump_tap_config(CoreTap.instance, out)
|
||||
dump_tap_config(CoreCaskTap.instance, out)
|
||||
end
|
||||
|
||||
def dump_verbose_config(out = $stdout)
|
||||
super
|
||||
out.puts "macOS: #{MacOS.full_version}-#{kernel}"
|
||||
out.puts "CLT: #{clt || "N/A"}"
|
||||
out.puts "Xcode: #{xcode || "N/A"}"
|
||||
out.puts "Rosetta 2: #{::Hardware::CPU.in_rosetta2?}" if ::Hardware::CPU.physical_cpu_arm64?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SystemConfig.prepend(OS::Mac::SystemConfig)
|
||||
|
||||
module SystemConfig
|
||||
class << self
|
||||
include SystemCommand::Mixin
|
||||
|
||||
def xcode
|
||||
@xcode ||= if MacOS::Xcode.installed?
|
||||
xcode = MacOS::Xcode.version.to_s
|
||||
xcode += " => #{MacOS::Xcode.prefix}" unless MacOS::Xcode.default_prefix?
|
||||
xcode
|
||||
end
|
||||
end
|
||||
|
||||
def clt
|
||||
@clt ||= MacOS::CLT.version if MacOS::CLT.installed?
|
||||
end
|
||||
|
||||
def core_tap_config(out = $stdout)
|
||||
dump_tap_config(CoreTap.instance, out)
|
||||
dump_tap_config(CoreCaskTap.instance, out)
|
||||
end
|
||||
|
||||
def dump_verbose_config(out = $stdout)
|
||||
dump_generic_verbose_config(out)
|
||||
out.puts "macOS: #{MacOS.full_version}-#{kernel}"
|
||||
out.puts "CLT: #{clt || "N/A"}"
|
||||
out.puts "Xcode: #{xcode || "N/A"}"
|
||||
out.puts "Rosetta 2: #{Hardware::CPU.in_rosetta2?}" if Hardware::CPU.physical_cpu_arm64?
|
||||
end
|
||||
end
|
||||
end
|
||||
SystemConfig.singleton_class.prepend(OS::Mac::SystemConfig::ClassMethods)
|
||||
|
@ -1,59 +1,66 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Utils
|
||||
module Bottles
|
||||
class << self
|
||||
module MacOSOverride
|
||||
sig { params(tag: T.nilable(T.any(Symbol, Tag))).returns(Tag) }
|
||||
module OS
|
||||
module Mac
|
||||
module Bottles
|
||||
module ClassMethods
|
||||
sig { params(tag: T.nilable(T.any(Symbol, Utils::Bottles::Tag))).returns(Utils::Bottles::Tag) }
|
||||
def tag(tag = nil)
|
||||
return Tag.new(system: MacOS.version.to_sym, arch: Hardware::CPU.arch) if tag.nil?
|
||||
|
||||
super
|
||||
if tag.nil?
|
||||
Utils::Bottles::Tag.new(system: MacOS.version.to_sym, arch: ::Hardware::CPU.arch)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
prepend MacOSOverride
|
||||
end
|
||||
module Collector
|
||||
extend T::Helpers
|
||||
|
||||
class Collector
|
||||
private
|
||||
requires_ancestor { Utils::Bottles::Collector }
|
||||
|
||||
alias generic_find_matching_tag find_matching_tag
|
||||
private
|
||||
|
||||
sig { params(tag: Utils::Bottles::Tag, no_older_versions: T::Boolean).returns(T.nilable(Utils::Bottles::Tag)) }
|
||||
def find_matching_tag(tag, no_older_versions: false)
|
||||
# Used primarily by developers testing beta macOS releases.
|
||||
if no_older_versions ||
|
||||
(OS::Mac.version.prerelease? &&
|
||||
Homebrew::EnvConfig.developer? &&
|
||||
Homebrew::EnvConfig.skip_or_later_bottles?)
|
||||
generic_find_matching_tag(tag)
|
||||
else
|
||||
generic_find_matching_tag(tag) ||
|
||||
find_older_compatible_tag(tag)
|
||||
end
|
||||
end
|
||||
|
||||
# Find a bottle built for a previous version of macOS.
|
||||
sig { params(tag: Utils::Bottles::Tag).returns(T.nilable(Utils::Bottles::Tag)) }
|
||||
def find_older_compatible_tag(tag)
|
||||
tag_version = begin
|
||||
tag.to_macos_version
|
||||
rescue MacOSVersion::Error
|
||||
nil
|
||||
sig {
|
||||
params(tag: Utils::Bottles::Tag,
|
||||
no_older_versions: T::Boolean).returns(T.nilable(Utils::Bottles::Tag))
|
||||
}
|
||||
def find_matching_tag(tag, no_older_versions: false)
|
||||
# Used primarily by developers testing beta macOS releases.
|
||||
if no_older_versions ||
|
||||
(OS::Mac.version.prerelease? &&
|
||||
Homebrew::EnvConfig.developer? &&
|
||||
Homebrew::EnvConfig.skip_or_later_bottles?)
|
||||
super(tag)
|
||||
else
|
||||
super(tag) || find_older_compatible_tag(tag)
|
||||
end
|
||||
end
|
||||
|
||||
return if tag_version.blank?
|
||||
# Find a bottle built for a previous version of macOS.
|
||||
sig { params(tag: Utils::Bottles::Tag).returns(T.nilable(Utils::Bottles::Tag)) }
|
||||
def find_older_compatible_tag(tag)
|
||||
tag_version = begin
|
||||
tag.to_macos_version
|
||||
rescue MacOSVersion::Error
|
||||
nil
|
||||
end
|
||||
|
||||
tags.find do |candidate|
|
||||
next if candidate.standardized_arch != tag.standardized_arch
|
||||
return if tag_version.blank?
|
||||
|
||||
candidate.to_macos_version <= tag_version
|
||||
rescue MacOSVersion::Error
|
||||
false
|
||||
tags.find do |candidate|
|
||||
next if candidate.standardized_arch != tag.standardized_arch
|
||||
|
||||
candidate.to_macos_version <= tag_version
|
||||
rescue MacOSVersion::Error
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Utils::Bottles.singleton_class.prepend(OS::Mac::Bottles::ClassMethods)
|
||||
Utils::Bottles::Collector.prepend(OS::Mac::Bottles::Collector)
|
||||
|
@ -84,7 +84,6 @@ module FormulaCellarChecks
|
||||
def valid_library_extension?(filename)
|
||||
VALID_LIBRARY_EXTENSIONS.include? filename.extname
|
||||
end
|
||||
alias generic_valid_library_extension? valid_library_extension?
|
||||
|
||||
sig { returns(T.nilable(String)) }
|
||||
def check_non_libraries
|
||||
@ -437,7 +436,6 @@ module FormulaCellarChecks
|
||||
problem_if_output(check_cpuid_instruction(formula))
|
||||
problem_if_output(check_binary_arches(formula))
|
||||
end
|
||||
alias generic_audit_installed audit_installed
|
||||
|
||||
private
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "digest"
|
||||
@ -7,62 +7,81 @@ require "erb"
|
||||
module Homebrew
|
||||
# Class for generating a formula from a template.
|
||||
class FormulaCreator
|
||||
sig { returns(String) }
|
||||
attr_accessor :name
|
||||
|
||||
sig { returns(Version) }
|
||||
attr_reader :version
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
attr_reader :head
|
||||
|
||||
sig {
|
||||
params(name: T.nilable(String), version: T.nilable(String), tap: T.nilable(String), url: String,
|
||||
params(url: String, name: T.nilable(String), version: T.nilable(String), tap: T.nilable(String),
|
||||
mode: T.nilable(Symbol), license: T.nilable(String), fetch: T::Boolean, head: T::Boolean).void
|
||||
}
|
||||
def initialize(name, version, tap:, url:, mode:, license:, fetch:, head:)
|
||||
@name = name
|
||||
@version = Version.new(version) if version
|
||||
@tap = Tap.fetch(tap || "homebrew/core")
|
||||
def initialize(url:, name: nil, version: nil, tap: nil, mode: nil, license: nil, fetch: false, head: false)
|
||||
@url = url
|
||||
@mode = mode
|
||||
@license = license
|
||||
@fetch = fetch
|
||||
@head = head
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def verify
|
||||
raise TapUnavailableError, @tap.name unless @tap.installed?
|
||||
end
|
||||
|
||||
sig { params(url: String).returns(T.nilable(String)) }
|
||||
def self.name_from_url(url)
|
||||
stem = Pathname.new(url).stem
|
||||
# special cases first
|
||||
if stem.start_with? "index.cgi"
|
||||
# gitweb URLs e.g. http://www.codesrc.com/gitweb/index.cgi?p=libzipper.git;a=summary
|
||||
stem.rpartition("=").last
|
||||
elsif url =~ %r{github\.com/\S+/(\S+)/(archive|releases)/}
|
||||
# e.g. https://github.com/stella-emu/stella/releases/download/6.7/stella-6.7-src.tar.xz
|
||||
Regexp.last_match(1)
|
||||
else
|
||||
# e.g. http://digit-labs.org/files/tools/synscan/releases/synscan-5.02.tar.gz
|
||||
pathver = Version.parse(stem).to_s
|
||||
stem.sub(/[-_.]?#{Regexp.escape(pathver)}$/, "")
|
||||
if name.blank?
|
||||
stem = Pathname.new(url).stem
|
||||
name = if stem.start_with?("index.cgi") && stem.include?("=")
|
||||
# special cases first
|
||||
# gitweb URLs e.g. http://www.codesrc.com/gitweb/index.cgi?p=libzipper.git;a=summary
|
||||
stem.rpartition("=").last
|
||||
elsif url =~ %r{github\.com/\S+/(\S+)/(archive|releases)/}
|
||||
# e.g. https://github.com/stella-emu/stella/releases/download/6.7/stella-6.7-src.tar.xz
|
||||
T.must(Regexp.last_match(1))
|
||||
else
|
||||
# e.g. http://digit-labs.org/files/tools/synscan/releases/synscan-5.02.tar.gz
|
||||
pathver = Version.parse(stem).to_s
|
||||
stem.sub(/[-_.]?#{Regexp.escape(pathver)}$/, "")
|
||||
end
|
||||
odebug "name from url: #{name}"
|
||||
end
|
||||
end
|
||||
@name = T.let(name, String)
|
||||
|
||||
sig { void }
|
||||
def parse_url
|
||||
@name = FormulaCreator.name_from_url(@url) if @name.blank?
|
||||
odebug "name_from_url: #{@name}"
|
||||
@version = Version.detect(@url) if @version.nil?
|
||||
version = if version.present?
|
||||
Version.new(version)
|
||||
else
|
||||
Version.detect(url)
|
||||
end
|
||||
@version = T.let(version, Version)
|
||||
|
||||
case @url
|
||||
tap = if tap.blank?
|
||||
CoreTap.instance
|
||||
else
|
||||
Tap.fetch(tap)
|
||||
end
|
||||
@tap = T.let(tap, Tap)
|
||||
|
||||
@mode = T.let(mode.presence, T.nilable(Symbol))
|
||||
@license = T.let(license.presence, T.nilable(String))
|
||||
@fetch = fetch
|
||||
|
||||
case url
|
||||
when %r{github\.com/(\S+)/(\S+)\.git}
|
||||
@head = true
|
||||
head = true
|
||||
user = Regexp.last_match(1)
|
||||
repo = Regexp.last_match(2)
|
||||
@github = GitHub.repository(user, repo) if @fetch
|
||||
repository = Regexp.last_match(2)
|
||||
github = GitHub.repository(user, repository) if fetch
|
||||
when %r{github\.com/(\S+)/(\S+)/(archive|releases)/}
|
||||
user = Regexp.last_match(1)
|
||||
repo = Regexp.last_match(2)
|
||||
@github = GitHub.repository(user, repo) if @fetch
|
||||
repository = Regexp.last_match(2)
|
||||
github = GitHub.repository(user, repository) if fetch
|
||||
end
|
||||
@head = head
|
||||
@github = T.let(github, T.untyped)
|
||||
|
||||
@sha256 = T.let(nil, T.nilable(String))
|
||||
@desc = T.let(nil, T.nilable(String))
|
||||
@homepage = T.let(nil, T.nilable(String))
|
||||
@license = T.let(nil, T.nilable(String))
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def verify_tap_available!
|
||||
raise TapUnavailableError, @tap.name unless @tap.installed?
|
||||
end
|
||||
|
||||
sig { returns(Pathname) }
|
||||
@ -91,7 +110,7 @@ module Homebrew
|
||||
raise "Downloaded URL is not archive"
|
||||
end
|
||||
|
||||
@sha256 = filepath.sha256
|
||||
@sha256 = T.let(filepath.sha256, T.nilable(String))
|
||||
end
|
||||
|
||||
if @github
|
||||
@ -106,6 +125,8 @@ module Homebrew
|
||||
path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
sig { params(name: String).returns(String) }
|
||||
def latest_versioned_formula(name)
|
||||
name_prefix = "#{name}@"
|
||||
@ -116,8 +137,6 @@ module Homebrew
|
||||
|
||||
sig { returns(String) }
|
||||
def template
|
||||
# FIXME: https://github.com/errata-ai/vale/issues/818
|
||||
# <!-- vale off -->
|
||||
<<~ERB
|
||||
# Documentation: https://docs.brew.sh/Formula-Cookbook
|
||||
# https://rubydoc.brew.sh/Formula
|
||||
@ -261,7 +280,6 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
ERB
|
||||
# <!-- vale on -->
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -51,6 +51,7 @@ HOMEBREW_HOME_PLACEHOLDER = "/$HOME"
|
||||
HOMEBREW_CASK_APPDIR_PLACEHOLDER = "$APPDIR"
|
||||
|
||||
HOMEBREW_MACOS_NEWEST_UNSUPPORTED = ENV.fetch("HOMEBREW_MACOS_NEWEST_UNSUPPORTED").freeze
|
||||
HOMEBREW_MACOS_NEWEST_SUPPORTED = ENV.fetch("HOMEBREW_MACOS_NEWEST_SUPPORTED").freeze
|
||||
HOMEBREW_MACOS_OLDEST_SUPPORTED = ENV.fetch("HOMEBREW_MACOS_OLDEST_SUPPORTED").freeze
|
||||
HOMEBREW_MACOS_OLDEST_ALLOWED = ENV.fetch("HOMEBREW_MACOS_OLDEST_ALLOWED").freeze
|
||||
|
||||
|
@ -42,7 +42,6 @@ module Hardware
|
||||
ppc64le: "-mcpu=powerpc64le",
|
||||
}.freeze, T.nilable(T::Hash[Symbol, String]))
|
||||
end
|
||||
alias generic_optimization_flags optimization_flags
|
||||
|
||||
sig { returns(Symbol) }
|
||||
def arch_32_bit
|
||||
@ -219,6 +218,7 @@ module Hardware
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(_version: T.nilable(MacOSVersion)).returns(Symbol) }
|
||||
def oldest_cpu(_version = nil)
|
||||
if Hardware::CPU.intel?
|
||||
if Hardware::CPU.is_64_bit?
|
||||
@ -242,7 +242,6 @@ module Hardware
|
||||
Hardware::CPU.family
|
||||
end
|
||||
end
|
||||
alias generic_oldest_cpu oldest_cpu
|
||||
|
||||
# Returns a Rust flag to set the target CPU if necessary.
|
||||
# Defaults to nil.
|
||||
|
@ -37,7 +37,6 @@ module Homebrew
|
||||
end
|
||||
|
||||
def global_post_install; end
|
||||
alias generic_global_post_install global_post_install
|
||||
|
||||
def check_prefix
|
||||
if (Hardware::CPU.intel? || Hardware::CPU.in_rosetta2?) &&
|
||||
@ -399,7 +398,6 @@ module Homebrew
|
||||
Diagnostic.checks(:supported_configuration_checks, fatal: all_fatal)
|
||||
Diagnostic.checks(:fatal_preinstall_checks)
|
||||
end
|
||||
alias generic_perform_preinstall_checks perform_preinstall_checks
|
||||
|
||||
def attempt_directory_creation
|
||||
Keg.must_exist_directories.each do |dir|
|
||||
|
@ -77,7 +77,6 @@ class Keg
|
||||
FileUtils.ln_s(new_src, file)
|
||||
end
|
||||
end
|
||||
alias generic_fix_dynamic_linkage fix_dynamic_linkage
|
||||
|
||||
def relocate_dynamic_linkage(_relocation)
|
||||
[]
|
||||
@ -102,7 +101,6 @@ class Keg
|
||||
|
||||
relocation
|
||||
end
|
||||
alias generic_prepare_relocation_to_placeholders prepare_relocation_to_placeholders
|
||||
|
||||
def replace_locations_with_placeholders
|
||||
relocation = prepare_relocation_to_placeholders.freeze
|
||||
@ -123,7 +121,6 @@ class Keg
|
||||
|
||||
relocation
|
||||
end
|
||||
alias generic_prepare_relocation_to_locations prepare_relocation_to_locations
|
||||
|
||||
def replace_placeholders_with_locations(files, skip_linkage: false)
|
||||
relocation = prepare_relocation_to_locations.freeze
|
||||
@ -221,7 +218,6 @@ class Keg
|
||||
|
||||
[grep_bin, grep_args]
|
||||
end
|
||||
alias generic_egrep_args egrep_args
|
||||
|
||||
def each_unique_file_matching(string)
|
||||
Utils.popen_read("fgrep", recursive_fgrep_args, string, to_s) do |io|
|
||||
|
@ -188,12 +188,10 @@ class LinkageChecker
|
||||
|
||||
store&.update!(keg_files_dylibs:)
|
||||
end
|
||||
alias generic_check_dylibs check_dylibs
|
||||
|
||||
def system_libraries_exist_in_cache?
|
||||
false
|
||||
end
|
||||
alias generic_system_libraries_exist_in_cache? system_libraries_exist_in_cache?
|
||||
|
||||
def dylib_found_in_shared_cache?(dylib)
|
||||
@dyld_shared_cache_contains_path ||= begin
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strong
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "version"
|
||||
@ -10,6 +10,7 @@ class MacOSVersion < Version
|
||||
sig { returns(T.nilable(T.any(String, Symbol))) }
|
||||
attr_reader :version
|
||||
|
||||
sig { params(version: T.nilable(T.any(String, Symbol))).void }
|
||||
def initialize(version)
|
||||
@version = version
|
||||
super "unknown or unsupported macOS version: #{version.inspect}"
|
||||
@ -18,7 +19,7 @@ class MacOSVersion < Version
|
||||
|
||||
# NOTE: When removing symbols here, ensure that they are added
|
||||
# to `DEPRECATED_MACOS_VERSIONS` in `MacOSRequirement`.
|
||||
SYMBOLS = {
|
||||
SYMBOLS = T.let({
|
||||
tahoe: "26",
|
||||
sequoia: "15",
|
||||
sonoma: "14",
|
||||
@ -30,7 +31,7 @@ class MacOSVersion < Version
|
||||
high_sierra: "10.13",
|
||||
sierra: "10.12",
|
||||
el_capitan: "10.11",
|
||||
}.freeze
|
||||
}.freeze, T::Hash[Symbol, String])
|
||||
|
||||
sig { params(macos_version: MacOSVersion).returns(Version) }
|
||||
def self.kernel_major_version(macos_version)
|
||||
@ -57,7 +58,9 @@ class MacOSVersion < Version
|
||||
|
||||
super(T.must(version))
|
||||
|
||||
@comparison_cache = {}
|
||||
@comparison_cache = T.let({}, T::Hash[T.untyped, T.nilable(Integer)])
|
||||
@pretty_name = T.let(nil, T.nilable(String))
|
||||
@sym = T.let(nil, T.nilable(Symbol))
|
||||
end
|
||||
|
||||
sig { override.params(other: T.untyped).returns(T.nilable(Integer)) }
|
||||
@ -95,7 +98,7 @@ class MacOSVersion < Version
|
||||
|
||||
sig { returns(Symbol) }
|
||||
def to_sym
|
||||
return @sym if defined?(@sym)
|
||||
return @sym if @sym
|
||||
|
||||
sym = SYMBOLS.invert.fetch(strip_patch.to_s, :dunno)
|
||||
|
||||
@ -106,7 +109,7 @@ class MacOSVersion < Version
|
||||
|
||||
sig { returns(String) }
|
||||
def pretty_name
|
||||
return @pretty_name if defined?(@pretty_name)
|
||||
return @pretty_name if @pretty_name
|
||||
|
||||
pretty_name = to_sym.to_s.split("_").map(&:capitalize).join(" ").freeze
|
||||
|
||||
@ -154,5 +157,7 @@ class MacOSVersion < Version
|
||||
# Represents the absence of a version.
|
||||
#
|
||||
# NOTE: Constructor needs to called with an arbitrary macOS-like version which is then set to `nil`.
|
||||
NULL = MacOSVersion.new("10.0").tap { |v| v.instance_variable_set(:@version, nil) }.freeze
|
||||
NULL = T.let(MacOSVersion.new("10.0").tap do |v|
|
||||
T.let(v, MacOSVersion).instance_variable_set(:@version, nil)
|
||||
end.freeze, MacOSVersion)
|
||||
end
|
||||
|
@ -93,7 +93,6 @@ module Homebrew
|
||||
EOS
|
||||
end
|
||||
end
|
||||
alias generic_disallowed_reason disallowed_reason
|
||||
|
||||
sig { params(name: String).returns(T.nilable(String)) }
|
||||
def tap_migration_reason(name)
|
||||
@ -195,8 +194,10 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(name: String, silent: T::Boolean, show_info: T::Boolean).returns(T.nilable(String)) }
|
||||
def cask_reason(name, silent: false, show_info: false); end
|
||||
|
||||
sig { params(name: String, command: String).returns(T.nilable(String)) }
|
||||
def suggest_command(name, command); end
|
||||
|
||||
require "extend/os/missing_formula"
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "requirement"
|
||||
@ -7,10 +7,14 @@ require "requirement"
|
||||
class ArchRequirement < Requirement
|
||||
fatal true
|
||||
|
||||
@arch = T.let(nil, T.nilable(Symbol))
|
||||
|
||||
sig { returns(T.nilable(Symbol)) }
|
||||
attr_reader :arch
|
||||
|
||||
sig { params(tags: T::Array[Symbol]).void }
|
||||
def initialize(tags)
|
||||
@arch = tags.shift
|
||||
@arch = T.let(tags.shift, T.nilable(Symbol))
|
||||
super
|
||||
end
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "requirement"
|
||||
@ -7,6 +7,7 @@ require "requirement"
|
||||
class XcodeRequirement < Requirement
|
||||
fatal true
|
||||
|
||||
sig { returns(T.nilable(String)) }
|
||||
attr_reader :version
|
||||
|
||||
satisfy(build_env: false) do
|
||||
@ -14,8 +15,10 @@ class XcodeRequirement < Requirement
|
||||
xcode_installed_version
|
||||
end
|
||||
|
||||
sig { params(tags: T::Array[String]).void }
|
||||
def initialize(tags = [])
|
||||
@version = tags.shift if tags.first.to_s.match?(/(\d\.)+\d/)
|
||||
version = tags.shift if tags.first.to_s.match?(/(\d\.)+\d/)
|
||||
@version = T.let(version, T.nilable(String))
|
||||
super
|
||||
end
|
||||
|
||||
@ -53,6 +56,7 @@ class XcodeRequirement < Requirement
|
||||
"#<#{self.class.name}: version>=#{@version.inspect} #{tags.inspect}>"
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def display_s
|
||||
return "#{name.capitalize} (on macOS)" unless @version
|
||||
|
||||
|
3
Library/Homebrew/sorbet/rbi/dsl/cask/cask.rbi
generated
3
Library/Homebrew/sorbet/rbi/dsl/cask/cask.rbi
generated
@ -9,9 +9,6 @@ class Cask::Cask
|
||||
sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) }
|
||||
def app(*args, &block); end
|
||||
|
||||
sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) }
|
||||
def appcast(*args, &block); end
|
||||
|
||||
sig { params(args: T.untyped, block: T.untyped).returns(T.untyped) }
|
||||
def appdir(*args, &block); end
|
||||
|
||||
|
58
Library/Homebrew/sorbet/rbi/dsl/cask/config.rbi
generated
Normal file
58
Library/Homebrew/sorbet/rbi/dsl/cask/config.rbi
generated
Normal file
@ -0,0 +1,58 @@
|
||||
# typed: true
|
||||
|
||||
# DO NOT EDIT MANUALLY
|
||||
# This is an autogenerated file for dynamic methods in `Cask::Config`.
|
||||
# Please instead update this file by running `bin/tapioca dsl Cask::Config`.
|
||||
|
||||
|
||||
module Cask
|
||||
class Config
|
||||
sig { returns(String) }
|
||||
def appdir; end
|
||||
|
||||
sig { returns(String) }
|
||||
def audio_unit_plugindir; end
|
||||
|
||||
sig { returns(String) }
|
||||
def colorpickerdir; end
|
||||
|
||||
sig { returns(String) }
|
||||
def dictionarydir; end
|
||||
|
||||
sig { returns(String) }
|
||||
def fontdir; end
|
||||
|
||||
sig { returns(String) }
|
||||
def input_methoddir; end
|
||||
|
||||
sig { returns(String) }
|
||||
def internet_plugindir; end
|
||||
|
||||
sig { returns(String) }
|
||||
def keyboard_layoutdir; end
|
||||
|
||||
sig { returns(T::Array[String]) }
|
||||
def languages; end
|
||||
|
||||
sig { returns(String) }
|
||||
def mdimporterdir; end
|
||||
|
||||
sig { returns(String) }
|
||||
def prefpanedir; end
|
||||
|
||||
sig { returns(String) }
|
||||
def qlplugindir; end
|
||||
|
||||
sig { returns(String) }
|
||||
def screen_saverdir; end
|
||||
|
||||
sig { returns(String) }
|
||||
def servicedir; end
|
||||
|
||||
sig { returns(String) }
|
||||
def vst3_plugindir; end
|
||||
|
||||
sig { returns(String) }
|
||||
def vst_plugindir; end
|
||||
end
|
||||
end
|
@ -23,9 +23,6 @@ class Homebrew::Cmd::TapCmd::Args < Homebrew::CLI::Args
|
||||
sig { returns(T::Boolean) }
|
||||
def force?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def force_auto_update?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def repair?; end
|
||||
end
|
||||
|
37
Library/Homebrew/sorbet/tapioca/compilers/cask/config.rb
Normal file
37
Library/Homebrew/sorbet/tapioca/compilers/cask/config.rb
Normal file
@ -0,0 +1,37 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative "../../../../global"
|
||||
require "cask/config"
|
||||
|
||||
module Tapioca
|
||||
module Compilers
|
||||
class CaskConfig < Tapioca::Dsl::Compiler
|
||||
ConstantType = type_member { { fixed: Module } }
|
||||
|
||||
sig { override.returns(T::Enumerable[Module]) }
|
||||
def self.gather_constants = [Cask::Config]
|
||||
|
||||
sig { override.void }
|
||||
def decorate
|
||||
root.create_module("Cask") do |mod|
|
||||
mod.create_class("Config") do |klass|
|
||||
Cask::Config.defaults.each do |key, value|
|
||||
return_type = if key == :languages
|
||||
# :languages is a `LazyObject`, so it lazily evaluates to an
|
||||
# array of strings when a method is called on it.
|
||||
"T::Array[String]"
|
||||
elsif key.end_with?("?")
|
||||
"T::Boolean"
|
||||
else
|
||||
value.class.to_s
|
||||
end
|
||||
|
||||
klass.create_method(key.to_s, return_type:, class_method: false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -128,10 +128,12 @@ module SystemConfig
|
||||
out.puts "#{tap_name} origin: #{tap.remote}" if tap.remote != tap.default_remote
|
||||
out.puts "#{tap_name} HEAD: #{tap.git_head || "(none)"}"
|
||||
out.puts "#{tap_name} last commit: #{tap.git_last_commit || "never"}"
|
||||
out.puts "#{tap_name} branch: #{tap.git_branch || "(none)"}" if tap.git_branch != "master"
|
||||
default_branches = %w[main master].freeze
|
||||
out.puts "#{tap_name} branch: #{tap.git_branch || "(none)"}" if default_branches.exclude?(tap.git_branch)
|
||||
end
|
||||
|
||||
if (json_file = Homebrew::API::HOMEBREW_CACHE_API/json_file_name) && json_file.exist?
|
||||
json_file = Homebrew::API::HOMEBREW_CACHE_API/json_file_name
|
||||
if json_file.exist?
|
||||
out.puts "#{tap_name} JSON: #{json_file.mtime.utc.strftime("%d %b %H:%M UTC")}"
|
||||
elsif !tap.installed?
|
||||
out.puts "#{tap_name}: N/A"
|
||||
@ -194,7 +196,6 @@ module SystemConfig
|
||||
out.puts hardware if hardware
|
||||
host_software_config(out)
|
||||
end
|
||||
alias dump_generic_verbose_config dump_verbose_config
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -15,7 +15,7 @@ RSpec.describe Homebrew::Bundle::Dsl do
|
||||
cask_args appdir: '/Applications'
|
||||
tap 'homebrew/cask'
|
||||
tap 'telemachus/brew', 'https://telemachus@bitbucket.org/telemachus/brew.git'
|
||||
tap 'auto/update', 'https://bitbucket.org/auto/update.git', force_auto_update: true
|
||||
tap 'auto/update', 'https://bitbucket.org/auto/update.git'
|
||||
brew 'imagemagick'
|
||||
brew 'mysql@5.6', restart_service: true, link: true, conflicts_with: ['mysql']
|
||||
brew 'emacs', args: ['with-cocoa', 'with-gnutls'], link: :overwrite
|
||||
@ -40,10 +40,7 @@ RSpec.describe Homebrew::Bundle::Dsl do
|
||||
expect(dsl.entries[0].name).to eql("homebrew/cask")
|
||||
expect(dsl.entries[1].name).to eql("telemachus/brew")
|
||||
expect(dsl.entries[1].options).to eql(clone_target: "https://telemachus@bitbucket.org/telemachus/brew.git")
|
||||
expect(dsl.entries[2].options).to eql(
|
||||
clone_target: "https://bitbucket.org/auto/update.git",
|
||||
force_auto_update: true,
|
||||
)
|
||||
expect(dsl.entries[2].options).to eql(clone_target: "https://bitbucket.org/auto/update.git")
|
||||
expect(dsl.entries[3].name).to eql("imagemagick")
|
||||
expect(dsl.entries[4].name).to eql("mysql@5.6")
|
||||
expect(dsl.entries[4].options).to eql(restart_service: true, link: true, conflicts_with: ["mysql"])
|
||||
|
@ -55,25 +55,5 @@ RSpec.describe Homebrew::Bundle::TapInstaller do
|
||||
expect(described_class.install("homebrew/cask", clone_target: "clone_target_path")).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
context "with force_auto_update" do
|
||||
it "taps" do
|
||||
expect(Homebrew::Bundle).to receive(:system).with(HOMEBREW_BREW_FILE, "tap", "homebrew/cask",
|
||||
"--force-auto-update",
|
||||
verbose: false)
|
||||
.and_return(true)
|
||||
expect(described_class.preinstall("homebrew/cask", force_auto_update: true)).to be(true)
|
||||
expect(described_class.install("homebrew/cask", force_auto_update: true)).to be(true)
|
||||
end
|
||||
|
||||
it "fails" do
|
||||
expect(Homebrew::Bundle).to receive(:system).with(HOMEBREW_BREW_FILE, "tap", "homebrew/cask",
|
||||
"--force-auto-update",
|
||||
verbose: false)
|
||||
.and_return(false)
|
||||
expect(described_class.preinstall("homebrew/cask", force_auto_update: true)).to be(true)
|
||||
expect(described_class.install("homebrew/cask", force_auto_update: true)).to be(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -19,7 +19,7 @@ RSpec.describe Cask::Artifact::Artifact, :cask do
|
||||
end
|
||||
|
||||
context "without target" do
|
||||
it "fails to load" do
|
||||
it "fails to load", :no_api do
|
||||
expect do
|
||||
Cask::CaskLoader.load("invalid-generic-artifact-no-target")
|
||||
end.to raise_error(Cask::CaskInvalidError, /Generic Artifact.*requires.*target/)
|
||||
|
@ -6,7 +6,7 @@ RSpec.describe Cask::Artifact::Manpage, :cask do
|
||||
context "without section" do
|
||||
let(:cask_token) { "invalid-manpage-no-section" }
|
||||
|
||||
it "fails to load a cask without section" do
|
||||
it "fails to load a cask without section", :no_api do
|
||||
expect { cask }.to raise_error(Cask::CaskInvalidError, /is not a valid man page name/)
|
||||
end
|
||||
end
|
||||
|
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