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 OS
|
||||
module Linux
|
||||
module DevCmd
|
||||
class UpdateTest < AbstractCommand
|
||||
alias generic_git_tags git_tags
|
||||
|
||||
module UpdateTest
|
||||
private
|
||||
|
||||
sig { returns(String) }
|
||||
def git_tags
|
||||
tags = generic_git_tags
|
||||
tags = Utils.popen_read("git tag --list | sort -rV") if tags.blank?
|
||||
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
|
||||
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?
|
||||
::Hardware.oldest_cpu
|
||||
elsif ::Hardware::CPU.intel? || ::Hardware::CPU.arm?
|
||||
:native
|
||||
else
|
||||
:dunno
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SharedEnvExtension.prepend(OS::Linux::SharedEnvExtension)
|
||||
|
@ -1,10 +1,16 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Stdenv
|
||||
module OS
|
||||
module Linux
|
||||
module Stdenv
|
||||
extend T::Helpers
|
||||
|
||||
requires_ancestor { ::SharedEnvExtension }
|
||||
|
||||
sig {
|
||||
params(
|
||||
formula: T.nilable(Formula),
|
||||
formula: T.nilable(::Formula),
|
||||
cc: T.nilable(String),
|
||||
build_bottle: T.nilable(T::Boolean),
|
||||
bottle_arch: T.nilable(String),
|
||||
@ -12,10 +18,9 @@ module Stdenv
|
||||
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:)
|
||||
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil,
|
||||
testing_formula: false, debug_symbols: false)
|
||||
super
|
||||
|
||||
prepend_path "CPATH", HOMEBREW_PREFIX/"include"
|
||||
prepend_path "LIBRARY_PATH", HOMEBREW_PREFIX/"lib"
|
||||
@ -29,8 +34,12 @@ module Stdenv
|
||||
end
|
||||
|
||||
def libxml2
|
||||
append "CPPFLAGS", "-I#{Formula["libxml2"].include/"libxml2"}"
|
||||
append "CPPFLAGS", "-I#{::Formula["libxml2"].include/"libxml2"}"
|
||||
rescue FormulaUnavailableError
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Stdenv.prepend(OS::Linux::Stdenv)
|
||||
|
@ -1,16 +1,25 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Superenv
|
||||
module OS
|
||||
module Linux
|
||||
module Superenv
|
||||
extend T::Helpers
|
||||
|
||||
requires_ancestor { SharedEnvExtension }
|
||||
requires_ancestor { ::Superenv }
|
||||
|
||||
module ClassMethods
|
||||
sig { returns(Pathname) }
|
||||
def self.shims_path
|
||||
def shims_path
|
||||
HOMEBREW_SHIMS_PATH/"linux/super"
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(Pathname)) }
|
||||
def self.bin
|
||||
def bin
|
||||
shims_path.realpath
|
||||
end
|
||||
end
|
||||
|
||||
sig {
|
||||
params(
|
||||
@ -22,10 +31,10 @@ module Superenv
|
||||
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:)
|
||||
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)
|
||||
@ -35,11 +44,11 @@ module Superenv
|
||||
# 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
|
||||
append_to_cccfg "b" if ::Hardware::CPU.arch == :arm64 && ::DevelopmentTools.gcc_version("gcc") >= 9
|
||||
end
|
||||
|
||||
def homebrew_extra_paths
|
||||
paths = generic_homebrew_extra_paths
|
||||
paths = super
|
||||
paths += %w[binutils make].filter_map do |f|
|
||||
bin = Formulary.factory(f).opt_bin
|
||||
bin if bin.directory?
|
||||
@ -76,4 +85,9 @@ module Superenv
|
||||
|
||||
path
|
||||
end
|
||||
end
|
||||
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
|
||||
module OS
|
||||
module Linux
|
||||
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.")
|
||||
super || filename.basename.to_s.include?(".so.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
FormulaCellarChecks.prepend(OS::Linux::FormulaCellarChecks)
|
||||
|
@ -1,12 +1,18 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Hardware
|
||||
class CPU
|
||||
class << self
|
||||
module OS
|
||||
module Linux
|
||||
module Hardware
|
||||
module CPU
|
||||
module ClassMethods
|
||||
extend T::Helpers
|
||||
|
||||
requires_ancestor { T.class_of(::Hardware::CPU) }
|
||||
|
||||
def optimization_flags
|
||||
@optimization_flags ||= begin
|
||||
flags = generic_optimization_flags.dup
|
||||
flags = super.dup
|
||||
flags[:native] = arch_flag(Homebrew::EnvConfig.arch)
|
||||
flags
|
||||
end
|
||||
@ -138,7 +144,7 @@ module Hardware
|
||||
|
||||
%w[aes altivec avx avx2 lm ssse3 sse4_2].each do |flag|
|
||||
define_method(:"#{flag}?") do
|
||||
T.bind(self, T.class_of(Hardware::CPU))
|
||||
T.bind(self, OS::Linux::Hardware::CPU::ClassMethods)
|
||||
flags.include? flag
|
||||
end
|
||||
end
|
||||
@ -158,4 +164,8 @@ module Hardware
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Hardware::CPU.singleton_class.prepend(OS::Linux::Hardware::CPU::ClassMethods)
|
||||
|
@ -1,8 +1,10 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Homebrew
|
||||
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.
|
||||
@ -16,7 +18,6 @@ module Homebrew
|
||||
/system/bin/linker64
|
||||
/system/bin/linker
|
||||
].freeze
|
||||
private_constant :DYNAMIC_LINKERS
|
||||
|
||||
# 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
|
||||
@ -28,44 +29,41 @@ module Homebrew
|
||||
libgomp.so.1
|
||||
libstdc++.so.6
|
||||
].freeze
|
||||
private_constant :GCC_RUNTIME_LIBS
|
||||
|
||||
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
|
||||
def perform_preinstall_checks(all_fatal: false)
|
||||
super
|
||||
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?
|
||||
def global_post_install
|
||||
super
|
||||
symlink_ld_so
|
||||
setup_preferred_gcc_libs
|
||||
end
|
||||
|
||||
def 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?
|
||||
if ::Hardware::CPU.ppc64le?
|
||||
message += <<~EOS
|
||||
For OpenPOWER Linux (PPC64LE) support, see:
|
||||
#{Formatter.url("https://github.com/homebrew-ppc64le/brew")}
|
||||
EOS
|
||||
end
|
||||
abort message
|
||||
::Kernel.abort message
|
||||
end
|
||||
private_class_method :check_cpu
|
||||
|
||||
def self.symlink_ld_so
|
||||
def 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?
|
||||
::Kernel.raise "Unable to locate the system's dynamic linker" unless brew_ld_so.readable?
|
||||
|
||||
return
|
||||
end
|
||||
@ -76,9 +74,8 @@ module Homebrew
|
||||
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
|
||||
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?
|
||||
|
||||
@ -103,10 +100,10 @@ module Homebrew
|
||||
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"
|
||||
::Kernel.system HOMEBREW_PREFIX/"opt/glibc/sbin/ldconfig"
|
||||
end
|
||||
else
|
||||
odie "#{HOMEBREW_PREFIX}/lib does not exist!" unless (HOMEBREW_PREFIX/"lib").readable?
|
||||
::Kernel.odie "#{HOMEBREW_PREFIX}/lib does not exist!" unless (HOMEBREW_PREFIX/"lib").readable?
|
||||
end
|
||||
|
||||
GCC_RUNTIME_LIBS.each do |library|
|
||||
@ -127,6 +124,9 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
end
|
||||
private_class_method :setup_preferred_gcc_libs
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Homebrew::Install.singleton_class.prepend(OS::Linux::Install::ClassMethods)
|
||||
|
@ -3,7 +3,9 @@
|
||||
|
||||
require "compilers"
|
||||
|
||||
class LinkageChecker
|
||||
module OS
|
||||
module Linux
|
||||
module LinkageChecker
|
||||
# Libraries provided by glibc and gcc.
|
||||
SYSTEM_LIBRARY_ALLOWLIST = %w[
|
||||
ld-linux-x86-64.so.2
|
||||
@ -29,7 +31,7 @@ class LinkageChecker
|
||||
private
|
||||
|
||||
def check_dylibs(rebuild_cache:)
|
||||
generic_check_dylibs(rebuild_cache:)
|
||||
super
|
||||
|
||||
# glibc and gcc are implicit dependencies.
|
||||
# No other linkage to system libraries is expected or desired.
|
||||
@ -39,7 +41,8 @@ class LinkageChecker
|
||||
|
||||
# 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.
|
||||
# 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
|
||||
@ -47,4 +50,8 @@ class LinkageChecker
|
||||
@undeclared_deps.delete("gcc")
|
||||
@indirect_deps.delete("gcc")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
LinkageChecker.prepend(OS::Linux::LinkageChecker)
|
||||
|
@ -5,12 +5,14 @@ require "compilers"
|
||||
require "os/linux/glibc"
|
||||
require "system_command"
|
||||
|
||||
module SystemConfig
|
||||
module OS
|
||||
module Linux
|
||||
module SystemConfig
|
||||
module ClassMethods
|
||||
include SystemCommand::Mixin
|
||||
|
||||
HOST_RUBY_PATH = "/usr/bin/ruby"
|
||||
|
||||
class << self
|
||||
def host_glibc_version
|
||||
version = OS::Linux::Glibc.system_version
|
||||
return "N/A" if version.null?
|
||||
@ -19,10 +21,10 @@ module SystemConfig
|
||||
end
|
||||
|
||||
def host_gcc_version
|
||||
gcc = DevelopmentTools.host_gcc_path
|
||||
gcc = ::DevelopmentTools.host_gcc_path
|
||||
return "N/A" unless gcc.executable?
|
||||
|
||||
`#{gcc} --version 2>/dev/null`[/ (\d+\.\d+\.\d+)/, 1]
|
||||
Utils.popen_read(gcc, "--version")[/ (\d+\.\d+\.\d+)/, 1]
|
||||
end
|
||||
|
||||
def formula_linked_version(formula)
|
||||
@ -42,16 +44,20 @@ module SystemConfig
|
||||
|
||||
def dump_verbose_config(out = $stdout)
|
||||
kernel = Utils.safe_popen_read("uname", "-mors").chomp
|
||||
dump_generic_verbose_config(out)
|
||||
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 "#{::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,10 +1,16 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
module SharedEnvExtension
|
||||
module OS
|
||||
module Mac
|
||||
module SharedEnvExtension
|
||||
extend T::Helpers
|
||||
|
||||
requires_ancestor { ::SharedEnvExtension }
|
||||
|
||||
sig {
|
||||
params(
|
||||
formula: T.nilable(Formula),
|
||||
formula: T.nilable(::Formula),
|
||||
cc: T.nilable(String),
|
||||
build_bottle: T.nilable(T::Boolean),
|
||||
bottle_arch: T.nilable(String),
|
||||
@ -12,11 +18,9 @@ module SharedEnvExtension
|
||||
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:)
|
||||
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil,
|
||||
testing_formula: false, debug_symbols: false)
|
||||
super
|
||||
|
||||
# Normalise the system Perl version used, where multiple may be available
|
||||
self["VERSIONER_PERL_VERSION"] = MacOS.preferred_perl_version
|
||||
@ -39,4 +43,8 @@ module SharedEnvExtension
|
||||
# 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,8 +1,13 @@
|
||||
# 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
|
||||
|
||||
requires_ancestor { SharedEnvExtension }
|
||||
requires_ancestor { ::Stdenv }
|
||||
|
||||
sig { returns(T::Array[Pathname]) }
|
||||
def homebrew_extra_pkg_config_paths
|
||||
@ -20,10 +25,9 @@ module Stdenv
|
||||
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:)
|
||||
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil,
|
||||
testing_formula: false, debug_symbols: false)
|
||||
super
|
||||
|
||||
append "LDFLAGS", "-Wl,-headerpad_max_install_names"
|
||||
|
||||
@ -114,4 +118,8 @@ module Stdenv
|
||||
def no_fixup_chains
|
||||
append "LDFLAGS", "-Wl,-no_fixup_chains" if no_fixup_chains_support?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Stdenv.prepend(OS::Mac::Stdenv)
|
||||
|
@ -1,34 +1,32 @@
|
||||
# typed: true # rubocop:disable Sorbet/StrictSigil
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Superenv
|
||||
class << self
|
||||
# The location of Homebrew's shims on macOS.
|
||||
module OS
|
||||
module Mac
|
||||
module Superenv
|
||||
extend T::Helpers
|
||||
|
||||
requires_ancestor { SharedEnvExtension }
|
||||
requires_ancestor { ::Superenv }
|
||||
|
||||
module ClassMethods
|
||||
sig { returns(Pathname) }
|
||||
def shims_path
|
||||
HOMEBREW_SHIMS_PATH/"mac/super"
|
||||
end
|
||||
|
||||
undef bin
|
||||
|
||||
sig { returns(T.nilable(Pathname)) }
|
||||
def bin
|
||||
return unless DevelopmentTools.installed?
|
||||
return unless ::DevelopmentTools.installed?
|
||||
|
||||
shims_path.realpath
|
||||
end
|
||||
end
|
||||
|
||||
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?
|
||||
@ -37,7 +35,6 @@ module Superenv
|
||||
|
||||
true
|
||||
end
|
||||
private :libxml2_include_needed?
|
||||
|
||||
def homebrew_extra_isystem_paths
|
||||
paths = []
|
||||
@ -51,7 +48,7 @@ module Superenv
|
||||
paths = []
|
||||
if compiler == :llvm_clang
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/usr/lib"
|
||||
paths << Formula["llvm"].opt_lib.to_s
|
||||
paths << ::Formula["llvm"].opt_lib.to_s
|
||||
end
|
||||
paths << "#{self["HOMEBREW_SDKROOT"]}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries"
|
||||
paths
|
||||
@ -66,7 +63,8 @@ module Superenv
|
||||
end
|
||||
|
||||
def homebrew_extra_cmake_library_paths
|
||||
[Pathname("#{self["HOMEBREW_SDKROOT"]}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries")]
|
||||
brew_sdkroot = self["HOMEBREW_SDKROOT"]
|
||||
[Pathname("#{brew_sdkroot}/System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries")]
|
||||
end
|
||||
|
||||
def homebrew_extra_cmake_frameworks_paths
|
||||
@ -83,8 +81,8 @@ module Superenv
|
||||
end
|
||||
|
||||
# @private
|
||||
def setup_build_environment(formula: nil, cc: nil, build_bottle: false, bottle_arch: nil, testing_formula: false,
|
||||
debug_symbols: false)
|
||||
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
|
||||
|
||||
@ -105,12 +103,11 @@ module Superenv
|
||||
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?
|
||||
(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:)
|
||||
super
|
||||
|
||||
# Filter out symbols known not to be defined since GNU Autotools can't
|
||||
# reliably figure this out with Xcode 8 and above.
|
||||
@ -168,4 +165,9 @@ module Superenv
|
||||
def no_fixup_chains
|
||||
append_to_cccfg "f" if no_fixup_chains_support?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Superenv.singleton_class.prepend(OS::Mac::Superenv::ClassMethods)
|
||||
Superenv.prepend(OS::Mac::Superenv)
|
||||
|
@ -4,7 +4,14 @@
|
||||
require "cache_store"
|
||||
require "linkage_checker"
|
||||
|
||||
module FormulaCellarChecks
|
||||
module OS
|
||||
module Mac
|
||||
module FormulaCellarChecks
|
||||
extend T::Helpers
|
||||
|
||||
requires_ancestor { Homebrew::FormulaAuditor }
|
||||
requires_ancestor { ::FormulaCellarChecks }
|
||||
|
||||
sig { returns(T.nilable(String)) }
|
||||
def check_shadowed_headers
|
||||
return if ["libtool", "subversion", "berkeley-db"].any? do |formula_name|
|
||||
@ -31,7 +38,7 @@ module FormulaCellarChecks
|
||||
def check_openssl_links
|
||||
return unless formula.prefix.directory?
|
||||
|
||||
keg = Keg.new(formula.prefix)
|
||||
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 }
|
||||
@ -69,10 +76,10 @@ module FormulaCellarChecks
|
||||
def check_linkage
|
||||
return unless formula.prefix.directory?
|
||||
|
||||
keg = Keg.new(formula.prefix)
|
||||
keg = ::Keg.new(formula.prefix)
|
||||
|
||||
CacheStoreDatabase.use(:linkage) do |db|
|
||||
checker = LinkageChecker.new(keg, formula, cache_db: db)
|
||||
checker = ::LinkageChecker.new(keg, formula, cache_db: db)
|
||||
next unless checker.broken_library_linkage?
|
||||
|
||||
output = <<~EOS
|
||||
@ -85,14 +92,14 @@ module FormulaCellarChecks
|
||||
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}" : "."}
|
||||
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)) }
|
||||
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)
|
||||
@ -120,7 +127,7 @@ module FormulaCellarChecks
|
||||
|
||||
sig { void }
|
||||
def audit_installed
|
||||
generic_audit_installed
|
||||
super
|
||||
problem_if_output(check_shadowed_headers)
|
||||
problem_if_output(check_openssl_links)
|
||||
problem_if_output(check_python_framework_links(formula.lib))
|
||||
@ -128,9 +135,14 @@ module FormulaCellarChecks
|
||||
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)
|
||||
macos_lib_extensions = %w[.dylib .framework]
|
||||
generic_valid_library_extension?(filename) || macos_lib_extensions.include?(filename.extname)
|
||||
super || MACOS_LIB_EXTENSIONS.include?(filename.extname)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
FormulaCellarChecks.prepend(OS::Mac::FormulaCellarChecks)
|
||||
|
@ -1,15 +1,18 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Hardware
|
||||
sig { params(version: T.nilable(Version)).returns(Symbol) }
|
||||
def self.oldest_cpu(version = nil)
|
||||
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 CPU.arch == :arm64
|
||||
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:
|
||||
@ -19,7 +22,12 @@ module Hardware
|
||||
elsif version >= :mojave
|
||||
:nehalem
|
||||
else
|
||||
generic_oldest_cpu
|
||||
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,9 +5,10 @@ require "cask/info"
|
||||
require "cask/cask_loader"
|
||||
require "cask/caskroom"
|
||||
|
||||
module Homebrew
|
||||
module OS
|
||||
module Mac
|
||||
module MissingFormula
|
||||
class << self
|
||||
module ClassMethods
|
||||
sig { params(name: String).returns(T.nilable(String)) }
|
||||
def disallowed_reason(name)
|
||||
case name.downcase
|
||||
@ -16,7 +17,7 @@ module Homebrew
|
||||
Xcode can be installed from the App Store.
|
||||
EOS
|
||||
else
|
||||
generic_disallowed_reason(name)
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
@ -36,24 +37,27 @@ module Homebrew
|
||||
EOS
|
||||
case command
|
||||
when "install"
|
||||
Cask::CaskLoader.load(name)
|
||||
::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?
|
||||
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)
|
||||
cask = ::Cask::CaskLoader.load(name)
|
||||
suggestion = <<~EOS
|
||||
Found a cask named "#{name}" instead.
|
||||
|
||||
#{Cask::Info.get_info(cask)}
|
||||
#{::Cask::Info.get_info(cask)}
|
||||
EOS
|
||||
else
|
||||
return
|
||||
end
|
||||
suggestion
|
||||
rescue Cask::CaskUnavailableError
|
||||
rescue ::Cask::CaskUnavailableError
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Homebrew::MissingFormula.singleton_class.prepend(OS::Mac::MissingFormula::ClassMethods)
|
||||
|
@ -6,6 +6,11 @@ require "system_command"
|
||||
module OS
|
||||
module Mac
|
||||
module SystemConfig
|
||||
module ClassMethods
|
||||
extend T::Helpers
|
||||
|
||||
requires_ancestor { T.class_of(::SystemConfig) }
|
||||
|
||||
sig { returns(String) }
|
||||
def describe_clang
|
||||
return "N/A" if ::SystemConfig.clang.null?
|
||||
@ -13,15 +18,6 @@ module OS
|
||||
clang_build_info = ::SystemConfig.clang_build.null? ? "(parse error)" : ::SystemConfig.clang_build
|
||||
"#{::SystemConfig.clang} build #{clang_build_info}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
SystemConfig.prepend(OS::Mac::SystemConfig)
|
||||
|
||||
module SystemConfig
|
||||
class << self
|
||||
include SystemCommand::Mixin
|
||||
|
||||
def xcode
|
||||
@xcode ||= if MacOS::Xcode.installed?
|
||||
@ -41,11 +37,14 @@ module SystemConfig
|
||||
end
|
||||
|
||||
def dump_verbose_config(out = $stdout)
|
||||
dump_generic_verbose_config(out)
|
||||
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?
|
||||
out.puts "Rosetta 2: #{::Hardware::CPU.in_rosetta2?}" if ::Hardware::CPU.physical_cpu_arm64?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
SystemConfig.singleton_class.prepend(OS::Mac::SystemConfig::ClassMethods)
|
||||
|
@ -1,37 +1,40 @@
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Utils
|
||||
module OS
|
||||
module Mac
|
||||
module Bottles
|
||||
class << self
|
||||
module MacOSOverride
|
||||
sig { params(tag: T.nilable(T.any(Symbol, Tag))).returns(Tag) }
|
||||
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?
|
||||
|
||||
if tag.nil?
|
||||
Utils::Bottles::Tag.new(system: MacOS.version.to_sym, arch: ::Hardware::CPU.arch)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
prepend MacOSOverride
|
||||
end
|
||||
|
||||
class Collector
|
||||
module Collector
|
||||
extend T::Helpers
|
||||
|
||||
requires_ancestor { Utils::Bottles::Collector }
|
||||
|
||||
private
|
||||
|
||||
alias generic_find_matching_tag find_matching_tag
|
||||
|
||||
sig { params(tag: Utils::Bottles::Tag, no_older_versions: T::Boolean).returns(T.nilable(Utils::Bottles::Tag)) }
|
||||
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)
|
||||
super(tag)
|
||||
else
|
||||
generic_find_matching_tag(tag) ||
|
||||
find_older_compatible_tag(tag)
|
||||
super(tag) || find_older_compatible_tag(tag)
|
||||
end
|
||||
end
|
||||
|
||||
@ -56,4 +59,8 @@ module Utils
|
||||
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)
|
||||
if name.blank?
|
||||
stem = Pathname.new(url).stem
|
||||
name = if stem.start_with?("index.cgi") && stem.include?("=")
|
||||
# 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)
|
||||
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
|
||||
@name = T.let(name, String)
|
||||
|
||||
version = if version.present?
|
||||
Version.new(version)
|
||||
else
|
||||
Version.detect(url)
|
||||
end
|
||||
@version = T.let(version, Version)
|
||||
|
||||
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
|
||||
user = Regexp.last_match(1)
|
||||
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)
|
||||
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 parse_url
|
||||
@name = FormulaCreator.name_from_url(@url) if @name.blank?
|
||||
odebug "name_from_url: #{@name}"
|
||||
@version = Version.detect(@url) if @version.nil?
|
||||
|
||||
case @url
|
||||
when %r{github\.com/(\S+)/(\S+)\.git}
|
||||
@head = true
|
||||
user = Regexp.last_match(1)
|
||||
repo = Regexp.last_match(2)
|
||||
@github = GitHub.repository(user, repo) 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
|
||||
end
|
||||
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
|
||||
|
||||
|
@ -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
Normal file
58
Library/Homebrew/sorbet/rbi/dsl/cask/config.rbi
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