Compare commits
128 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 24055498d7 | |||
| 71c842d2ed | |||
| 779dcd65bb | |||
| f698ac0247 | |||
| adbdc580ee | |||
| d6e4dfda55 | |||
|
|
6c44d1a8f1 | ||
|
|
5f1241b953 | ||
|
|
6cb3473e9e | ||
|
|
263ca54e7a | ||
|
|
41198d866f | ||
|
|
8304edbf2c | ||
|
|
96048f0a5a | ||
|
|
a9cc3c49f5 | ||
|
|
c834a862ab | ||
|
|
57578cf91a | ||
|
|
47b7bf378e | ||
|
|
d7c0052e78 | ||
|
|
f5c11fa342 | ||
|
|
f1aa78993c | ||
|
|
e63c885033 | ||
|
|
d3e7e6bde5 | ||
|
|
c35fe04c91 | ||
|
|
8567e8bcd3 | ||
|
|
eda9e78529 | ||
|
|
5f4e42a2c8 | ||
|
|
852574dedf | ||
|
|
3e413b4521 | ||
|
|
2d9e9ce5d1 | ||
|
|
2fe1076281 | ||
|
|
05985fabc3 | ||
|
|
6297f98d06 | ||
|
|
07091cfbea | ||
|
|
00a49bf8e1 | ||
|
|
1019f9ef21 | ||
|
|
e88ceb8178 | ||
|
|
2d8ba1e209 | ||
|
|
675a588f6c | ||
|
|
0a7a60f506 | ||
|
|
9b364ad25b | ||
|
|
613d6466a9 | ||
|
|
99456ee150 | ||
|
|
29270a8858 | ||
|
|
3fb55a1577 | ||
|
|
3d80dfadd1 | ||
|
|
f233244ab7 | ||
|
|
e4ac3bfeed | ||
|
|
610c67b715 | ||
|
|
6d548f784b | ||
|
|
b2539d37fe | ||
|
|
1cc4d0bc25 | ||
|
|
89d36e0dd5 | ||
|
|
deb6666f32 | ||
|
|
66f8afa734 | ||
|
|
34be1486e2 | ||
|
|
ccda7a5de1 | ||
|
|
0d8da983d8 | ||
|
|
3023e6dcad | ||
|
|
843fc7c97a | ||
|
|
a31fb2a6c2 | ||
|
|
8ef7a9dbd4 | ||
|
|
67f4be419b | ||
|
|
51a98eb950 | ||
|
|
055c87e47e | ||
|
|
bc2c12c742 | ||
|
|
0adf85970d | ||
|
|
28761d8756 | ||
|
|
289fed93b4 | ||
|
|
744e2452d8 | ||
|
|
80f9e6714f | ||
|
|
971ca17180 | ||
|
|
4d36861ad0 | ||
|
|
14d7942c95 | ||
|
|
5453c0a74c | ||
|
|
6e6c06f5a9 | ||
|
|
b54695d6e5 | ||
|
|
b827a1337a | ||
|
|
2f827242aa | ||
|
|
f68908d492 | ||
|
|
3541b4989f | ||
|
|
afcaae3be8 | ||
|
|
c5b8cc906e | ||
|
|
78d34b45af | ||
|
|
efc036f75a | ||
|
|
31fb2adc84 | ||
|
|
bbca610601 | ||
|
|
3f11702fb1 | ||
|
|
e2f02bcfbf | ||
|
|
b22d2328b7 | ||
|
|
1da17b8fde | ||
|
|
83c1ed68f3 | ||
|
|
62a3b5e43e | ||
|
|
896edb4451 | ||
|
|
5b003154e5 | ||
|
|
74095ab480 | ||
|
|
0e81158e3a | ||
|
|
ffc3c4bd6a | ||
|
|
f26e296cbb | ||
|
|
0264a1e2ee | ||
|
|
faf936a589 | ||
|
|
1c4cb6936e | ||
|
|
09452ed3c7 | ||
|
|
cba6e40e77 | ||
|
|
24e7d8f0e0 | ||
|
|
32a5e9f779 | ||
|
|
6e9da0ba4c | ||
|
|
c73538ac03 | ||
|
|
5fb96d9d8a | ||
|
|
08181692f3 | ||
|
|
1c959c22ce | ||
|
|
00f960174f | ||
|
|
bd57ad891d | ||
|
|
f23b84897c | ||
|
|
dce220e518 | ||
|
|
4343324468 | ||
|
|
31cf8b43a9 | ||
|
|
6c98d2bf1b | ||
|
|
de8ff312e6 | ||
|
|
ce8ae46054 | ||
|
|
fb6c51da07 | ||
|
|
ab980dc3b7 | ||
|
|
89f3c76cd7 | ||
|
|
e28fe444a5 | ||
|
|
45a642c363 | ||
|
|
75350b48a3 | ||
|
|
bfb0a55347 | ||
|
|
dc28719c8e | ||
|
|
3eb57bc41d |
2
.github/workflows/actionlint.yml
vendored
2
.github/workflows/actionlint.yml
vendored
@ -93,7 +93,7 @@ jobs:
|
|||||||
path: results.sarif
|
path: results.sarif
|
||||||
|
|
||||||
- name: Upload SARIF file
|
- name: Upload SARIF file
|
||||||
uses: github/codeql-action/upload-sarif@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11
|
uses: github/codeql-action/upload-sarif@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
sarif_file: results.sarif
|
||||||
category: zizmor
|
category: zizmor
|
||||||
|
|||||||
4
.github/workflows/codeql-analysis.yml
vendored
4
.github/workflows/codeql-analysis.yml
vendored
@ -27,7 +27,7 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11
|
uses: github/codeql-action/init@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3
|
||||||
with:
|
with:
|
||||||
languages: ruby
|
languages: ruby
|
||||||
config: |
|
config: |
|
||||||
@ -35,4 +35,4 @@ jobs:
|
|||||||
- Library/Homebrew/vendor
|
- Library/Homebrew/vendor
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@3c3833e0f8c1c83d449a7478aa59c036a9165498 # v3.29.11
|
uses: github/codeql-action/analyze@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3
|
||||||
|
|||||||
2
.github/workflows/docs.yml
vendored
2
.github/workflows/docs.yml
vendored
@ -52,7 +52,7 @@ jobs:
|
|||||||
run: vale docs/
|
run: vale docs/
|
||||||
|
|
||||||
- name: Install Ruby
|
- name: Install Ruby
|
||||||
uses: ruby/setup-ruby@efbf473cab83af4468e8606cc33eca9281bb213f # v1.256.0
|
uses: ruby/setup-ruby@44511735964dcb71245e7e55f72539531f7bc0eb # v1.257.0
|
||||||
with:
|
with:
|
||||||
bundler-cache: true
|
bundler-cache: true
|
||||||
working-directory: docs
|
working-directory: docs
|
||||||
|
|||||||
6
.github/workflows/pkg-installer.yml
vendored
6
.github/workflows/pkg-installer.yml
vendored
@ -32,7 +32,7 @@ jobs:
|
|||||||
TEMPORARY_CERTIFICATE_FILE: 'homebrew_developer_id_installer_certificate.p12'
|
TEMPORARY_CERTIFICATE_FILE: 'homebrew_developer_id_installer_certificate.p12'
|
||||||
TEMPORARY_KEYCHAIN_FILE: 'homebrew_installer_signing.keychain-db'
|
TEMPORARY_KEYCHAIN_FILE: 'homebrew_installer_signing.keychain-db'
|
||||||
# Set to the oldest supported version of macOS
|
# Set to the oldest supported version of macOS
|
||||||
HOMEBREW_MACOS_OLDEST_SUPPORTED: '13.0'
|
HOMEBREW_MACOS_OLDEST_SUPPORTED: '14.0'
|
||||||
permissions:
|
permissions:
|
||||||
contents: read # for code access
|
contents: read # for code access
|
||||||
attestations: write # for actions/attest-build-provenance
|
attestations: write # for actions/attest-build-provenance
|
||||||
@ -152,10 +152,6 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
# Intel
|
|
||||||
- runner: macos-13
|
|
||||||
name: macos-13-x86_64
|
|
||||||
# Apple Silicon
|
|
||||||
- runner: macos-14
|
- runner: macos-14
|
||||||
name: macos-14-arm64
|
name: macos-14-arm64
|
||||||
- runner: macos-15
|
- runner: macos-15
|
||||||
|
|||||||
2
.github/workflows/rubydoc.yml
vendored
2
.github/workflows/rubydoc.yml
vendored
@ -43,7 +43,7 @@ jobs:
|
|||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- name: Install Ruby
|
- name: Install Ruby
|
||||||
uses: ruby/setup-ruby@efbf473cab83af4468e8606cc33eca9281bb213f # v1.256.0
|
uses: ruby/setup-ruby@44511735964dcb71245e7e55f72539531f7bc0eb # v1.257.0
|
||||||
with:
|
with:
|
||||||
bundler-cache: true
|
bundler-cache: true
|
||||||
working-directory: rubydoc
|
working-directory: rubydoc
|
||||||
|
|||||||
4
.github/workflows/stale-issues.yml
vendored
4
.github/workflows/stale-issues.yml
vendored
@ -38,7 +38,7 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- name: Mark/Close Stale Issues and Pull Requests
|
- name: Mark/Close Stale Issues and Pull Requests
|
||||||
uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0
|
uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
days-before-stale: 21
|
days-before-stale: 21
|
||||||
@ -68,7 +68,7 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- name: Mark/Close Stale `bump-formula-pr` and `bump-cask-pr` Pull Requests
|
- name: Mark/Close Stale `bump-formula-pr` and `bump-cask-pr` Pull Requests
|
||||||
uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0
|
uses: actions/stale@3a9db7e6a41a89f618792c92c0e97cc736e1b13f # v10.0.0
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
days-before-stale: 2
|
days-before-stale: 2
|
||||||
|
|||||||
6
.github/workflows/tests.yml
vendored
6
.github/workflows/tests.yml
vendored
@ -104,7 +104,7 @@ jobs:
|
|||||||
- name: Cache style cache
|
- name: Cache style cache
|
||||||
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/Homebrew/style
|
path: ~/Library/Caches/Homebrew/style
|
||||||
key: tap-syntax-style-cache-${{ github.sha }}
|
key: tap-syntax-style-cache-${{ github.sha }}
|
||||||
restore-keys: tap-syntax-style-cache-
|
restore-keys: tap-syntax-style-cache-
|
||||||
|
|
||||||
@ -331,7 +331,7 @@ jobs:
|
|||||||
disable_search: true
|
disable_search: true
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
|
||||||
- uses: codecov/codecov-action@fdcc8476540edceab3de004e990f80d881c6cc00 # v5.5.0
|
- uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # v5.5.1
|
||||||
with:
|
with:
|
||||||
working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
|
working-directory: ${{ steps.set-up-homebrew.outputs.repository-path }}
|
||||||
files: Library/Homebrew/test/coverage/coverage.xml
|
files: Library/Homebrew/test/coverage/coverage.xml
|
||||||
@ -495,7 +495,7 @@ jobs:
|
|||||||
uses: Homebrew/actions/setup-homebrew@main
|
uses: Homebrew/actions/setup-homebrew@main
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
|
||||||
with:
|
with:
|
||||||
python-version-file: ${{ steps.set-up-homebrew.outputs.repository-path }}/Library/Homebrew/formula-analytics/.python-version
|
python-version-file: ${{ steps.set-up-homebrew.outputs.repository-path }}/Library/Homebrew/formula-analytics/.python-version
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ GEM
|
|||||||
ast (2.4.3)
|
ast (2.4.3)
|
||||||
base64 (0.3.0)
|
base64 (0.3.0)
|
||||||
benchmark (0.4.1)
|
benchmark (0.4.1)
|
||||||
bigdecimal (3.2.2)
|
bigdecimal (3.2.3)
|
||||||
bindata (2.5.1)
|
bindata (2.5.1)
|
||||||
coderay (1.1.3)
|
coderay (1.1.3)
|
||||||
concurrent-ruby (1.3.5)
|
concurrent-ruby (1.3.5)
|
||||||
@ -57,7 +57,7 @@ GEM
|
|||||||
redcarpet (3.6.1)
|
redcarpet (3.6.1)
|
||||||
regexp_parser (2.11.2)
|
regexp_parser (2.11.2)
|
||||||
require-hooks (0.2.2)
|
require-hooks (0.2.2)
|
||||||
rexml (3.4.2)
|
rexml (3.4.4)
|
||||||
rspec (3.13.1)
|
rspec (3.13.1)
|
||||||
rspec-core (~> 3.13.0)
|
rspec-core (~> 3.13.0)
|
||||||
rspec-expectations (~> 3.13.0)
|
rspec-expectations (~> 3.13.0)
|
||||||
@ -79,7 +79,7 @@ GEM
|
|||||||
rspec-support (3.13.5)
|
rspec-support (3.13.5)
|
||||||
rspec_junit_formatter (0.6.0)
|
rspec_junit_formatter (0.6.0)
|
||||||
rspec-core (>= 2, < 4, != 2.12.0)
|
rspec-core (>= 2, < 4, != 2.12.0)
|
||||||
rubocop (1.80.1)
|
rubocop (1.80.2)
|
||||||
json (~> 2.3)
|
json (~> 2.3)
|
||||||
language_server-protocol (~> 3.17.0.2)
|
language_server-protocol (~> 3.17.0.2)
|
||||||
lint_roller (~> 1.1.0)
|
lint_roller (~> 1.1.0)
|
||||||
@ -96,11 +96,11 @@ GEM
|
|||||||
rubocop-md (2.0.2)
|
rubocop-md (2.0.2)
|
||||||
lint_roller (~> 1.1)
|
lint_roller (~> 1.1)
|
||||||
rubocop (>= 1.72.1)
|
rubocop (>= 1.72.1)
|
||||||
rubocop-performance (1.25.0)
|
rubocop-performance (1.26.0)
|
||||||
lint_roller (~> 1.1)
|
lint_roller (~> 1.1)
|
||||||
rubocop (>= 1.75.0, < 2.0)
|
rubocop (>= 1.75.0, < 2.0)
|
||||||
rubocop-ast (>= 1.38.0, < 2.0)
|
rubocop-ast (>= 1.44.0, < 2.0)
|
||||||
rubocop-rspec (3.6.0)
|
rubocop-rspec (3.7.0)
|
||||||
lint_roller (~> 1.1)
|
lint_roller (~> 1.1)
|
||||||
rubocop (~> 1.72, >= 1.72.1)
|
rubocop (~> 1.72, >= 1.72.1)
|
||||||
rubocop-sorbet (0.10.5)
|
rubocop-sorbet (0.10.5)
|
||||||
@ -124,15 +124,15 @@ GEM
|
|||||||
simplecov-html (0.13.2)
|
simplecov-html (0.13.2)
|
||||||
simplecov_json_formatter (0.1.4)
|
simplecov_json_formatter (0.1.4)
|
||||||
simpleidn (0.2.3)
|
simpleidn (0.2.3)
|
||||||
sorbet (0.6.12466)
|
sorbet (0.6.12521)
|
||||||
sorbet-static (= 0.6.12466)
|
sorbet-static (= 0.6.12521)
|
||||||
sorbet-runtime (0.6.12466)
|
sorbet-runtime (0.6.12521)
|
||||||
sorbet-static (0.6.12466-aarch64-linux)
|
sorbet-static (0.6.12521-aarch64-linux)
|
||||||
sorbet-static (0.6.12466-universal-darwin)
|
sorbet-static (0.6.12521-universal-darwin)
|
||||||
sorbet-static (0.6.12466-x86_64-linux)
|
sorbet-static (0.6.12521-x86_64-linux)
|
||||||
sorbet-static-and-runtime (0.6.12466)
|
sorbet-static-and-runtime (0.6.12521)
|
||||||
sorbet (= 0.6.12466)
|
sorbet (= 0.6.12521)
|
||||||
sorbet-runtime (= 0.6.12466)
|
sorbet-runtime (= 0.6.12521)
|
||||||
spoom (1.7.6)
|
spoom (1.7.6)
|
||||||
erubi (>= 1.10.0)
|
erubi (>= 1.10.0)
|
||||||
prism (>= 0.28.0)
|
prism (>= 0.28.0)
|
||||||
@ -154,9 +154,9 @@ GEM
|
|||||||
thor (>= 1.2.0)
|
thor (>= 1.2.0)
|
||||||
yard-sorbet
|
yard-sorbet
|
||||||
thor (1.4.0)
|
thor (1.4.0)
|
||||||
unicode-display_width (3.1.5)
|
unicode-display_width (3.2.0)
|
||||||
unicode-emoji (~> 4.0, >= 4.0.4)
|
unicode-emoji (~> 4.1)
|
||||||
unicode-emoji (4.0.4)
|
unicode-emoji (4.1.0)
|
||||||
vernier (1.8.0)
|
vernier (1.8.0)
|
||||||
warning (1.5.0)
|
warning (1.5.0)
|
||||||
yard (0.9.37)
|
yard (0.9.37)
|
||||||
|
|||||||
@ -17,7 +17,7 @@ module Homebrew
|
|||||||
|
|
||||||
HOMEBREW_CACHE_API = T.let((HOMEBREW_CACHE/"api").freeze, Pathname)
|
HOMEBREW_CACHE_API = T.let((HOMEBREW_CACHE/"api").freeze, Pathname)
|
||||||
HOMEBREW_CACHE_API_SOURCE = T.let((HOMEBREW_CACHE/"api-source").freeze, Pathname)
|
HOMEBREW_CACHE_API_SOURCE = T.let((HOMEBREW_CACHE/"api-source").freeze, Pathname)
|
||||||
TAP_MIGRATIONS_STALE_SECONDS = T.let(86400, Integer) # 1 day
|
DEFAULT_API_STALE_SECONDS = T.let(86400, Integer) # 1 day
|
||||||
|
|
||||||
sig { params(endpoint: String).returns(T::Hash[String, T.untyped]) }
|
sig { params(endpoint: String).returns(T::Hash[String, T.untyped]) }
|
||||||
def self.fetch(endpoint)
|
def self.fetch(endpoint)
|
||||||
@ -37,12 +37,25 @@ module Homebrew
|
|||||||
raise ArgumentError, "Invalid JSON file: #{Tty.underline}#{api_url}#{Tty.reset}"
|
raise ArgumentError, "Invalid JSON file: #{Tty.underline}#{api_url}#{Tty.reset}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(target: Pathname, stale_seconds: T.nilable(Integer)).returns(T::Boolean) }
|
||||||
|
def self.skip_download?(target:, stale_seconds:)
|
||||||
|
return true if Homebrew.running_as_root_but_not_owned_by_root?
|
||||||
|
return false if !target.exist? || target.empty?
|
||||||
|
return true unless stale_seconds
|
||||||
|
|
||||||
|
(Time.now - stale_seconds) < target.mtime
|
||||||
|
end
|
||||||
|
|
||||||
sig {
|
sig {
|
||||||
params(endpoint: String, target: Pathname, stale_seconds: Integer, download_queue: T.nilable(DownloadQueue))
|
params(
|
||||||
.returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
|
endpoint: String,
|
||||||
|
target: Pathname,
|
||||||
|
stale_seconds: T.nilable(Integer),
|
||||||
|
download_queue: T.nilable(DownloadQueue),
|
||||||
|
).returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
|
||||||
}
|
}
|
||||||
def self.fetch_json_api_file(endpoint, target: HOMEBREW_CACHE_API/endpoint,
|
def self.fetch_json_api_file(endpoint, target: HOMEBREW_CACHE_API/endpoint,
|
||||||
stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i, download_queue: nil)
|
stale_seconds: nil, download_queue: nil)
|
||||||
# Lazy-load dependency.
|
# Lazy-load dependency.
|
||||||
require "development_tools"
|
require "development_tools"
|
||||||
|
|
||||||
@ -63,12 +76,7 @@ module Homebrew
|
|||||||
|
|
||||||
insecure_download = DevelopmentTools.ca_file_substitution_required? ||
|
insecure_download = DevelopmentTools.ca_file_substitution_required? ||
|
||||||
DevelopmentTools.curl_substitution_required?
|
DevelopmentTools.curl_substitution_required?
|
||||||
skip_download = target.exist? &&
|
skip_download = skip_download?(target:, stale_seconds:)
|
||||||
!target.empty? &&
|
|
||||||
(!Homebrew.auto_update_command? ||
|
|
||||||
(Homebrew::EnvConfig.no_auto_update? && !Homebrew::EnvConfig.force_api_auto_update?) ||
|
|
||||||
((Time.now - stale_seconds) < target.mtime))
|
|
||||||
skip_download ||= Homebrew.running_as_root_but_not_owned_by_root?
|
|
||||||
|
|
||||||
if download_queue
|
if download_queue
|
||||||
unless skip_download
|
unless skip_download
|
||||||
@ -161,17 +169,28 @@ module Homebrew
|
|||||||
require "download_queue"
|
require "download_queue"
|
||||||
Homebrew::DownloadQueue.new
|
Homebrew::DownloadQueue.new
|
||||||
end
|
end
|
||||||
stale_seconds = 86400 # 1 day
|
|
||||||
|
stale_seconds = if ENV["HOMEBREW_API_UPDATED"].present? ||
|
||||||
|
(Homebrew::EnvConfig.no_auto_update? && !Homebrew::EnvConfig.force_api_auto_update?)
|
||||||
|
nil
|
||||||
|
elsif Homebrew.auto_update_command?
|
||||||
|
Homebrew::EnvConfig.api_auto_update_secs.to_i
|
||||||
|
else
|
||||||
|
DEFAULT_API_STALE_SECONDS
|
||||||
|
end
|
||||||
|
|
||||||
if Homebrew::EnvConfig.use_internal_api?
|
if Homebrew::EnvConfig.use_internal_api?
|
||||||
Homebrew::API::Internal.fetch_formula_api!(download_queue:, stale_seconds:)
|
Homebrew::API::Internal.fetch_formula_api!(download_queue:, stale_seconds:)
|
||||||
Homebrew::API::Internal.fetch_cask_api!(download_queue:, stale_seconds:)
|
Homebrew::API::Internal.fetch_cask_api!(download_queue:, stale_seconds:)
|
||||||
else
|
else
|
||||||
Homebrew::API::Formula.fetch_api!(download_queue:, stale_seconds:)
|
Homebrew::API::Formula.fetch_api!(download_queue:, stale_seconds:)
|
||||||
Homebrew::API::Formula.fetch_tap_migrations!(download_queue:, stale_seconds:)
|
Homebrew::API::Formula.fetch_tap_migrations!(download_queue:, stale_seconds: DEFAULT_API_STALE_SECONDS)
|
||||||
Homebrew::API::Cask.fetch_api!(download_queue:, stale_seconds:)
|
Homebrew::API::Cask.fetch_api!(download_queue:, stale_seconds:)
|
||||||
Homebrew::API::Cask.fetch_tap_migrations!(download_queue:, stale_seconds:)
|
Homebrew::API::Cask.fetch_tap_migrations!(download_queue:, stale_seconds: DEFAULT_API_STALE_SECONDS)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
ENV["HOMEBREW_API_UPDATED"] = "1"
|
||||||
|
|
||||||
return unless download_queue
|
return unless download_queue
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|||||||
@ -75,18 +75,18 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
sig {
|
sig {
|
||||||
params(download_queue: T.nilable(::Homebrew::DownloadQueue), stale_seconds: Integer)
|
params(download_queue: T.nilable(::Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer))
|
||||||
.returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
|
.returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
|
||||||
}
|
}
|
||||||
def self.fetch_api!(download_queue: nil, stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i)
|
def self.fetch_api!(download_queue: nil, stale_seconds: nil)
|
||||||
Homebrew::API.fetch_json_api_file DEFAULT_API_FILENAME, stale_seconds:, download_queue:
|
Homebrew::API.fetch_json_api_file DEFAULT_API_FILENAME, stale_seconds:, download_queue:
|
||||||
end
|
end
|
||||||
|
|
||||||
sig {
|
sig {
|
||||||
params(download_queue: T.nilable(::Homebrew::DownloadQueue), stale_seconds: Integer)
|
params(download_queue: T.nilable(::Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer))
|
||||||
.returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
|
.returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
|
||||||
}
|
}
|
||||||
def self.fetch_tap_migrations!(download_queue: nil, stale_seconds: Homebrew::API::TAP_MIGRATIONS_STALE_SECONDS)
|
def self.fetch_tap_migrations!(download_queue: nil, stale_seconds: nil)
|
||||||
Homebrew::API.fetch_json_api_file "cask_tap_migrations.jws.json", stale_seconds:, download_queue:
|
Homebrew::API.fetch_json_api_file "cask_tap_migrations.jws.json", stale_seconds:, download_queue:
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -74,18 +74,18 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
sig {
|
sig {
|
||||||
params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: Integer)
|
params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer))
|
||||||
.returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
|
.returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
|
||||||
}
|
}
|
||||||
def self.fetch_api!(download_queue: nil, stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i)
|
def self.fetch_api!(download_queue: nil, stale_seconds: nil)
|
||||||
Homebrew::API.fetch_json_api_file DEFAULT_API_FILENAME, stale_seconds:, download_queue:
|
Homebrew::API.fetch_json_api_file DEFAULT_API_FILENAME, stale_seconds:, download_queue:
|
||||||
end
|
end
|
||||||
|
|
||||||
sig {
|
sig {
|
||||||
params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: Integer)
|
params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer))
|
||||||
.returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
|
.returns([T.any(T::Array[T.untyped], T::Hash[String, T.untyped]), T::Boolean])
|
||||||
}
|
}
|
||||||
def self.fetch_tap_migrations!(download_queue: nil, stale_seconds: Homebrew::API::TAP_MIGRATIONS_STALE_SECONDS)
|
def self.fetch_tap_migrations!(download_queue: nil, stale_seconds: nil)
|
||||||
Homebrew::API.fetch_json_api_file "formula_tap_migrations.jws.json", stale_seconds:, download_queue:
|
Homebrew::API.fetch_json_api_file "formula_tap_migrations.jws.json", stale_seconds:, download_queue:
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -56,20 +56,20 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
sig {
|
sig {
|
||||||
params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: Integer)
|
params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer))
|
||||||
.returns([T::Hash[String, T.untyped], T::Boolean])
|
.returns([T::Hash[String, T.untyped], T::Boolean])
|
||||||
}
|
}
|
||||||
def self.fetch_formula_api!(download_queue: nil, stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i)
|
def self.fetch_formula_api!(download_queue: nil, stale_seconds: nil)
|
||||||
json_contents, updated = (Homebrew::API.fetch_json_api_file formula_endpoint, stale_seconds:, download_queue:)
|
json_contents, updated = Homebrew::API.fetch_json_api_file(formula_endpoint, stale_seconds:, download_queue:)
|
||||||
[T.cast(json_contents, T::Hash[String, T.untyped]), updated]
|
[T.cast(json_contents, T::Hash[String, T.untyped]), updated]
|
||||||
end
|
end
|
||||||
|
|
||||||
sig {
|
sig {
|
||||||
params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: Integer)
|
params(download_queue: T.nilable(Homebrew::DownloadQueue), stale_seconds: T.nilable(Integer))
|
||||||
.returns([T::Hash[String, T.untyped], T::Boolean])
|
.returns([T::Hash[String, T.untyped], T::Boolean])
|
||||||
}
|
}
|
||||||
def self.fetch_cask_api!(download_queue: nil, stale_seconds: Homebrew::EnvConfig.api_auto_update_secs.to_i)
|
def self.fetch_cask_api!(download_queue: nil, stale_seconds: nil)
|
||||||
json_contents, updated = (Homebrew::API.fetch_json_api_file cask_endpoint, stale_seconds:, download_queue:)
|
json_contents, updated = Homebrew::API.fetch_json_api_file(cask_endpoint, stale_seconds:, download_queue:)
|
||||||
[T.cast(json_contents, T::Hash[String, T.untyped]), updated]
|
[T.cast(json_contents, T::Hash[String, T.untyped]), updated]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -10,13 +10,13 @@ module Homebrew
|
|||||||
def initialize(url, name, version, **meta)
|
def initialize(url, name, version, **meta)
|
||||||
super
|
super
|
||||||
@target = T.let(meta.fetch(:target), Pathname)
|
@target = T.let(meta.fetch(:target), Pathname)
|
||||||
@stale_seconds = T.let(meta.fetch(:stale_seconds), Integer)
|
@stale_seconds = T.let(meta[:stale_seconds], T.nilable(Integer))
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { override.params(timeout: T.nilable(T.any(Integer, Float))).returns(Pathname) }
|
sig { override.params(timeout: T.nilable(T.any(Integer, Float))).returns(Pathname) }
|
||||||
def fetch(timeout: nil)
|
def fetch(timeout: nil)
|
||||||
with_context quiet: quiet? do
|
with_context quiet: quiet? do
|
||||||
Homebrew::API.fetch_json_api_file(url, target: cached_location, stale_seconds: meta.fetch(:stale_seconds))
|
Homebrew::API.fetch_json_api_file(url, target: cached_location, stale_seconds: meta[:stale_seconds])
|
||||||
end
|
end
|
||||||
cached_location
|
cached_location
|
||||||
end
|
end
|
||||||
@ -30,7 +30,7 @@ module Homebrew
|
|||||||
class JSONDownload
|
class JSONDownload
|
||||||
include Downloadable
|
include Downloadable
|
||||||
|
|
||||||
sig { params(url: String, target: Pathname, stale_seconds: Integer).void }
|
sig { params(url: String, target: Pathname, stale_seconds: T.nilable(Integer)).void }
|
||||||
def initialize(url, target:, stale_seconds:)
|
def initialize(url, target:, stale_seconds:)
|
||||||
super()
|
super()
|
||||||
@url = T.let(URL.new(url, using: API::JSONDownloadStrategy, target:, stale_seconds:), URL)
|
@url = T.let(URL.new(url, using: API::JSONDownloadStrategy, target:, stale_seconds:), URL)
|
||||||
|
|||||||
@ -576,18 +576,19 @@ esac
|
|||||||
# - docs/Installation.md
|
# - docs/Installation.md
|
||||||
# - https://github.com/Homebrew/install/blob/HEAD/install.sh
|
# - https://github.com/Homebrew/install/blob/HEAD/install.sh
|
||||||
# - Library/Homebrew/os/mac.rb (latest_sdk_version)
|
# - Library/Homebrew/os/mac.rb (latest_sdk_version)
|
||||||
|
# - Library/Homebrew/os/mac/xcode.rb (latest_version), (minimum_version)
|
||||||
# and, if needed:
|
# and, if needed:
|
||||||
# - MacOSVersion::SYMBOLS
|
# - MacOSVersion::SYMBOLS
|
||||||
HOMEBREW_MACOS_NEWEST_UNSUPPORTED="16"
|
HOMEBREW_MACOS_NEWEST_UNSUPPORTED="27"
|
||||||
# TODO: bump version when new macOS is released
|
# TODO: bump version when new macOS is released
|
||||||
HOMEBREW_MACOS_NEWEST_SUPPORTED="15"
|
HOMEBREW_MACOS_NEWEST_SUPPORTED="26"
|
||||||
# TODO: bump version when new macOS is released and update references in:
|
# TODO: bump version when new macOS is released and update references in:
|
||||||
# - docs/Installation.md
|
# - docs/Installation.md
|
||||||
# - HOMEBREW_MACOS_OLDEST_SUPPORTED in .github/workflows/pkg-installer.yml
|
# - HOMEBREW_MACOS_OLDEST_SUPPORTED in .github/workflows/pkg-installer.yml
|
||||||
# - `os-version min` in package/Distribution.xml
|
# - `os-version min` in package/Distribution.xml
|
||||||
# - https://github.com/Homebrew/install/blob/HEAD/install.sh
|
# - https://github.com/Homebrew/install/blob/HEAD/install.sh
|
||||||
HOMEBREW_MACOS_OLDEST_SUPPORTED="13"
|
HOMEBREW_MACOS_OLDEST_SUPPORTED="14"
|
||||||
HOMEBREW_MACOS_OLDEST_ALLOWED="10.11"
|
HOMEBREW_MACOS_OLDEST_ALLOWED="10.15"
|
||||||
|
|
||||||
if [[ -n "${HOMEBREW_MACOS}" ]]
|
if [[ -n "${HOMEBREW_MACOS}" ]]
|
||||||
then
|
then
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# This script is loaded by formula_installer as a separate instance.
|
# This script is loaded by formula_installer as a separate instance.
|
||||||
@ -23,28 +23,40 @@ require "extend/pathname/write_mkpath_extension"
|
|||||||
class Build
|
class Build
|
||||||
include Utils::Output::Mixin
|
include Utils::Output::Mixin
|
||||||
|
|
||||||
attr_reader :formula, :deps, :reqs, :args
|
sig { returns(Formula) }
|
||||||
|
attr_reader :formula
|
||||||
|
|
||||||
|
sig { returns(T::Array[Dependency]) }
|
||||||
|
attr_reader :deps
|
||||||
|
|
||||||
|
sig { returns(Requirements) }
|
||||||
|
attr_reader :reqs
|
||||||
|
|
||||||
|
sig { returns(Homebrew::Cmd::InstallCmd::Args) }
|
||||||
|
attr_reader :args
|
||||||
|
|
||||||
|
sig { params(formula: Formula, options: Options, args: Homebrew::Cmd::InstallCmd::Args).void }
|
||||||
def initialize(formula, options, args:)
|
def initialize(formula, options, args:)
|
||||||
@formula = formula
|
@formula = formula
|
||||||
@formula.build = BuildOptions.new(options, formula.options)
|
@formula.build = BuildOptions.new(options, formula.options)
|
||||||
@args = args
|
@args = T.let(args, Homebrew::Cmd::InstallCmd::Args)
|
||||||
|
@deps = T.let([], T::Array[Dependency])
|
||||||
|
@reqs = T.let(Requirements.new, Requirements)
|
||||||
|
|
||||||
|
return if args.ignore_dependencies?
|
||||||
|
|
||||||
if args.ignore_dependencies?
|
|
||||||
@deps = []
|
|
||||||
@reqs = []
|
|
||||||
else
|
|
||||||
@deps = expand_deps
|
@deps = expand_deps
|
||||||
@reqs = expand_reqs
|
@reqs = expand_reqs
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
|
sig { params(dependent: Formula).returns(BuildOptions) }
|
||||||
def effective_build_options_for(dependent)
|
def effective_build_options_for(dependent)
|
||||||
args = dependent.build.used_options
|
args = dependent.build.used_options
|
||||||
args |= Tab.for_formula(dependent).used_options
|
args |= Tab.for_formula(dependent).used_options
|
||||||
BuildOptions.new(args, dependent.options)
|
BuildOptions.new(args, dependent.options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(Requirements) }
|
||||||
def expand_reqs
|
def expand_reqs
|
||||||
formula.recursive_requirements do |dependent, req|
|
formula.recursive_requirements do |dependent, req|
|
||||||
build = effective_build_options_for(dependent)
|
build = effective_build_options_for(dependent)
|
||||||
@ -54,6 +66,7 @@ class Build
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Array[Dependency]) }
|
||||||
def expand_deps
|
def expand_deps
|
||||||
formula.recursive_dependencies do |dependent, dep|
|
formula.recursive_dependencies do |dependent, dep|
|
||||||
build = effective_build_options_for(dependent)
|
build = effective_build_options_for(dependent)
|
||||||
@ -67,6 +80,7 @@ class Build
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { void }
|
||||||
def install
|
def install
|
||||||
formula_deps = deps.map(&:to_formula)
|
formula_deps = deps.map(&:to_formula)
|
||||||
keg_only_deps = formula_deps.select(&:keg_only?)
|
keg_only_deps = formula_deps.select(&:keg_only?)
|
||||||
@ -79,7 +93,7 @@ class Build
|
|||||||
ENV.activate_extensions!(env: args.env)
|
ENV.activate_extensions!(env: args.env)
|
||||||
|
|
||||||
if superenv?(args.env)
|
if superenv?(args.env)
|
||||||
superenv = T.cast(ENV, Superenv)
|
superenv = ENV
|
||||||
superenv.keg_only_deps = keg_only_deps
|
superenv.keg_only_deps = keg_only_deps
|
||||||
superenv.deps = formula_deps
|
superenv.deps = formula_deps
|
||||||
superenv.run_time_deps = run_time_deps
|
superenv.run_time_deps = run_time_deps
|
||||||
@ -183,6 +197,8 @@ class Build
|
|||||||
|
|
||||||
(formula.logs/"00.options.out").write \
|
(formula.logs/"00.options.out").write \
|
||||||
"#{formula.full_name} #{formula.build.used_options.sort.join(" ")}".strip
|
"#{formula.full_name} #{formula.build.used_options.sort.join(" ")}".strip
|
||||||
|
|
||||||
|
Pathname.prepend WriteMkpathExtension
|
||||||
formula.install
|
formula.install
|
||||||
|
|
||||||
stdlibs = detect_stdlibs
|
stdlibs = detect_stdlibs
|
||||||
@ -190,7 +206,7 @@ class Build
|
|||||||
tab.write
|
tab.write
|
||||||
|
|
||||||
# Find and link metafiles
|
# Find and link metafiles
|
||||||
formula.prefix.install_metafiles formula.buildpath
|
formula.prefix.install_metafiles T.must(formula.buildpath)
|
||||||
formula.prefix.install_metafiles formula.libexec if formula.libexec.exist?
|
formula.prefix.install_metafiles formula.libexec if formula.libexec.exist?
|
||||||
|
|
||||||
normalize_pod2man_outputs!(formula)
|
normalize_pod2man_outputs!(formula)
|
||||||
@ -200,6 +216,7 @@ class Build
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Array[Symbol]) }
|
||||||
def detect_stdlibs
|
def detect_stdlibs
|
||||||
keg = Keg.new(formula.prefix)
|
keg = Keg.new(formula.prefix)
|
||||||
|
|
||||||
@ -209,13 +226,15 @@ class Build
|
|||||||
keg.detect_cxx_stdlibs(skip_executables: true)
|
keg.detect_cxx_stdlibs(skip_executables: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(formula: Formula).void }
|
||||||
def fixopt(formula)
|
def fixopt(formula)
|
||||||
path = if formula.linked_keg.directory? && formula.linked_keg.symlink?
|
path = if formula.linked_keg.directory? && formula.linked_keg.symlink?
|
||||||
formula.linked_keg.resolved_path
|
formula.linked_keg.resolved_path
|
||||||
elsif formula.prefix.directory?
|
elsif formula.prefix.directory?
|
||||||
formula.prefix
|
formula.prefix
|
||||||
elsif (kids = formula.rack.children).size == 1 && kids.first.directory?
|
elsif (children = formula.rack.children.presence) && children.size == 1 &&
|
||||||
kids.first
|
(first_child = children.first.presence) && first_child.directory?
|
||||||
|
first_child
|
||||||
else
|
else
|
||||||
raise
|
raise
|
||||||
end
|
end
|
||||||
@ -224,6 +243,7 @@ class Build
|
|||||||
raise "#{formula.opt_prefix} not present or broken\nPlease reinstall #{formula.full_name}. Sorry :("
|
raise "#{formula.opt_prefix} not present or broken\nPlease reinstall #{formula.full_name}. Sorry :("
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(formula: Formula).void }
|
||||||
def normalize_pod2man_outputs!(formula)
|
def normalize_pod2man_outputs!(formula)
|
||||||
keg = Keg.new(formula.prefix)
|
keg = Keg.new(formula.prefix)
|
||||||
keg.normalize_pod2man_outputs!
|
keg.normalize_pod2man_outputs!
|
||||||
@ -243,12 +263,10 @@ begin
|
|||||||
|
|
||||||
trap("INT", old_trap)
|
trap("INT", old_trap)
|
||||||
|
|
||||||
formula = args.named.to_formulae.first
|
formula = args.named.to_formulae.fetch(0)
|
||||||
options = Options.create(args.flags_only)
|
options = Options.create(args.flags_only)
|
||||||
build = Build.new(formula, options, args:)
|
build = Build.new(formula, options, args:)
|
||||||
|
|
||||||
Pathname.prepend WriteMkpathExtension
|
|
||||||
|
|
||||||
build.install
|
build.install
|
||||||
# Any exception means the build did not complete.
|
# Any exception means the build did not complete.
|
||||||
# The `case` for what to do per-exception class is further down.
|
# The `case` for what to do per-exception class is further down.
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# Settings for the build environment.
|
# Settings for the build environment.
|
||||||
class BuildEnvironment
|
class BuildEnvironment
|
||||||
sig { params(settings: Symbol).void }
|
sig { params(settings: Symbol).void }
|
||||||
def initialize(*settings)
|
def initialize(*settings)
|
||||||
@settings = Set.new(settings)
|
@settings = T.let(Set.new(settings), T::Set[Symbol])
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(args: T::Enumerable[Symbol]).returns(T.self_type) }
|
sig { params(args: T::Enumerable[Symbol]).returns(T.self_type) }
|
||||||
@ -29,16 +29,17 @@ class BuildEnvironment
|
|||||||
module DSL
|
module DSL
|
||||||
# Initialise @env for each class which may use this DSL (e.g. each formula subclass).
|
# Initialise @env for each class which may use this DSL (e.g. each formula subclass).
|
||||||
# `env` may never be called and it needs to be initialised before the class is frozen.
|
# `env` may never be called and it needs to be initialised before the class is frozen.
|
||||||
|
sig { params(child: T.untyped).void }
|
||||||
def inherited(child)
|
def inherited(child)
|
||||||
super
|
super
|
||||||
child.instance_eval do
|
child.instance_eval do
|
||||||
@env = BuildEnvironment.new
|
@env = T.let(BuildEnvironment.new, T.nilable(BuildEnvironment))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(settings: Symbol).returns(BuildEnvironment) }
|
sig { params(settings: Symbol).returns(BuildEnvironment) }
|
||||||
def env(*settings)
|
def env(*settings)
|
||||||
@env.merge(settings)
|
T.must(@env).merge(settings)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,12 @@
|
|||||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# Options for a formula build.
|
# Options for a formula build.
|
||||||
class BuildOptions
|
class BuildOptions
|
||||||
|
sig { params(args: Options, options: Options).void }
|
||||||
def initialize(args, options)
|
def initialize(args, options)
|
||||||
@args = args
|
@args = T.let(args, Options)
|
||||||
@options = options
|
@options = T.let(options, Options)
|
||||||
end
|
end
|
||||||
|
|
||||||
# True if a {Formula} is being built with a specific option.
|
# True if a {Formula} is being built with a specific option.
|
||||||
@ -29,8 +30,13 @@ class BuildOptions
|
|||||||
# args << "--with-example1"
|
# args << "--with-example1"
|
||||||
# end
|
# end
|
||||||
# ```
|
# ```
|
||||||
|
sig { params(val: T.any(String, Requirement, Dependency)).returns(T::Boolean) }
|
||||||
def with?(val)
|
def with?(val)
|
||||||
option_names = val.respond_to?(:option_names) ? val.option_names : [val]
|
option_names = if val.is_a?(String)
|
||||||
|
[val]
|
||||||
|
else
|
||||||
|
val.option_names
|
||||||
|
end
|
||||||
|
|
||||||
option_names.any? do |name|
|
option_names.any? do |name|
|
||||||
if option_defined? "with-#{name}"
|
if option_defined? "with-#{name}"
|
||||||
@ -50,11 +56,13 @@ class BuildOptions
|
|||||||
# ```ruby
|
# ```ruby
|
||||||
# args << "--no-spam-plz" if build.without? "spam"
|
# args << "--no-spam-plz" if build.without? "spam"
|
||||||
# ```
|
# ```
|
||||||
|
sig { params(val: T.any(String, Requirement, Dependency)).returns(T::Boolean) }
|
||||||
def without?(val)
|
def without?(val)
|
||||||
!with?(val)
|
!with?(val)
|
||||||
end
|
end
|
||||||
|
|
||||||
# True if a {Formula} is being built as a bottle (i.e. binary package).
|
# True if a {Formula} is being built as a bottle (i.e. binary package).
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def bottle?
|
def bottle?
|
||||||
include? "build-bottle"
|
include? "build-bottle"
|
||||||
end
|
end
|
||||||
@ -75,6 +83,7 @@ class BuildOptions
|
|||||||
# args << "--and-a-cold-beer" if build.with? "cold-beer"
|
# args << "--and-a-cold-beer" if build.with? "cold-beer"
|
||||||
# end
|
# end
|
||||||
# ```
|
# ```
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def head?
|
def head?
|
||||||
include? "HEAD"
|
include? "HEAD"
|
||||||
end
|
end
|
||||||
@ -87,29 +96,35 @@ class BuildOptions
|
|||||||
# ```ruby
|
# ```ruby
|
||||||
# args << "--some-feature" if build.stable?
|
# args << "--some-feature" if build.stable?
|
||||||
# ```
|
# ```
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def stable?
|
def stable?
|
||||||
!head?
|
!head?
|
||||||
end
|
end
|
||||||
|
|
||||||
# True if the build has any arguments or options specified.
|
# True if the build has any arguments or options specified.
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def any_args_or_options?
|
def any_args_or_options?
|
||||||
!@args.empty? || !@options.empty?
|
!@args.empty? || !@options.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(Options) }
|
||||||
def used_options
|
def used_options
|
||||||
@options & @args
|
@options & @args
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(Options) }
|
||||||
def unused_options
|
def unused_options
|
||||||
@options - @args
|
@options - @args
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
sig { params(name: String).returns(T::Boolean) }
|
||||||
def include?(name)
|
def include?(name)
|
||||||
@args.include?("--#{name}")
|
@args.include?("--#{name}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(name: String).returns(T::Boolean) }
|
||||||
def option_defined?(name)
|
def option_defined?(name)
|
||||||
@options.include? name
|
@options.include? name
|
||||||
end
|
end
|
||||||
|
|||||||
@ -4,6 +4,8 @@
|
|||||||
module Homebrew
|
module Homebrew
|
||||||
# Class handling architecture-specific version information.
|
# Class handling architecture-specific version information.
|
||||||
class BumpVersionParser
|
class BumpVersionParser
|
||||||
|
VERSION_SYMBOLS = [:general, :arm, :intel].freeze
|
||||||
|
|
||||||
sig { returns(T.nilable(T.any(Version, Cask::DSL::Version))) }
|
sig { returns(T.nilable(T.any(Version, Cask::DSL::Version))) }
|
||||||
attr_reader :arm, :general, :intel
|
attr_reader :arm, :general, :intel
|
||||||
|
|
||||||
|
|||||||
@ -183,7 +183,7 @@ module Homebrew
|
|||||||
require "bundle/tap_dumper"
|
require "bundle/tap_dumper"
|
||||||
|
|
||||||
@dsl ||= Brewfile.read(global:, file:)
|
@dsl ||= Brewfile.read(global:, file:)
|
||||||
kept_formulae = self.kept_formulae(global:, file:).filter_map(&method(:lookup_formula))
|
kept_formulae = self.kept_formulae(global:, file:).filter_map { lookup_formula(_1) }
|
||||||
kept_taps = @dsl.entries.select { |e| e.type == :tap }.map(&:name)
|
kept_taps = @dsl.entries.select { |e| e.type == :tap }.map(&:name)
|
||||||
kept_taps += kept_formulae.filter_map(&:tap).map(&:name)
|
kept_taps += kept_formulae.filter_map(&:tap).map(&:name)
|
||||||
current_taps = Homebrew::Bundle::TapDumper.tap_names
|
current_taps = Homebrew::Bundle::TapDumper.tap_names
|
||||||
|
|||||||
@ -40,7 +40,7 @@ module Homebrew
|
|||||||
@formulae_by_full_name ||= {}
|
@formulae_by_full_name ||= {}
|
||||||
|
|
||||||
if name.nil?
|
if name.nil?
|
||||||
formulae = Formula.installed.map(&method(:add_formula))
|
formulae = Formula.installed.map { add_formula(_1) }
|
||||||
sort!(formulae)
|
sort!(formulae)
|
||||||
return @formulae_by_full_name
|
return @formulae_by_full_name
|
||||||
end
|
end
|
||||||
|
|||||||
@ -172,7 +172,7 @@ module Cask
|
|||||||
.stdout.lines.drop(1) # skip stdout column headers
|
.stdout.lines.drop(1) # skip stdout column headers
|
||||||
.filter_map do |line|
|
.filter_map do |line|
|
||||||
pid, _state, id = line.chomp.split(/\s+/)
|
pid, _state, id = line.chomp.split(/\s+/)
|
||||||
id if pid.to_i.nonzero? && id.match?(regex)
|
id if pid.to_i.nonzero? && T.must(id).match?(regex)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -460,9 +460,9 @@ module Cask
|
|||||||
def trash_paths(*paths, command: nil, **_)
|
def trash_paths(*paths, command: nil, **_)
|
||||||
return if paths.empty?
|
return if paths.empty?
|
||||||
|
|
||||||
stdout, = system_command HOMEBREW_LIBRARY_PATH/"cask/utils/trash.swift",
|
stdout = system_command(HOMEBREW_LIBRARY_PATH/"cask/utils/trash.swift",
|
||||||
args: paths,
|
args: paths,
|
||||||
print_stderr: Homebrew::EnvConfig.developer?
|
print_stderr: Homebrew::EnvConfig.developer?).stdout
|
||||||
|
|
||||||
trashed, _, untrashable = stdout.partition("\n")
|
trashed, _, untrashable = stdout.partition("\n")
|
||||||
trashed = trashed.split(":")
|
trashed = trashed.split(":")
|
||||||
|
|||||||
@ -79,8 +79,9 @@ module Cask
|
|||||||
# Try to make the asset searchable under the target name. Spotlight
|
# Try to make the asset searchable under the target name. Spotlight
|
||||||
# respects this attribute for many filetypes, but ignores it for App
|
# respects this attribute for many filetypes, but ignores it for App
|
||||||
# bundles. Alfred 2.2 respects it even for App bundles.
|
# bundles. Alfred 2.2 respects it even for App bundles.
|
||||||
def add_altname_metadata(file, altname, command: nil)
|
sig { params(file: Pathname, altname: Pathname, command: T.class_of(SystemCommand)).returns(T.nilable(SystemCommand::Result)) }
|
||||||
return if altname.to_s.casecmp(file.basename.to_s).zero?
|
def add_altname_metadata(file, altname, command:)
|
||||||
|
return if altname.to_s.casecmp(file.basename.to_s)&.zero?
|
||||||
|
|
||||||
odebug "Adding #{ALT_NAME_ATTRIBUTE} metadata"
|
odebug "Adding #{ALT_NAME_ATTRIBUTE} metadata"
|
||||||
altnames = command.run("/usr/bin/xattr",
|
altnames = command.run("/usr/bin/xattr",
|
||||||
@ -108,3 +109,5 @@ module Cask
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require "extend/os/cask/artifact/relocated"
|
||||||
|
|||||||
@ -543,6 +543,7 @@ module Cask
|
|||||||
print_stderr: false)
|
print_stderr: false)
|
||||||
else
|
else
|
||||||
add_error "Unknown artifact type: #{artifact.class}", location: url.location
|
add_error "Unknown artifact type: #{artifact.class}", location: url.location
|
||||||
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
next false if result.success?
|
next false if result.success?
|
||||||
@ -622,15 +623,17 @@ module Cask
|
|||||||
}.compact
|
}.compact
|
||||||
|
|
||||||
Homebrew::Install.perform_preinstall_checks_once
|
Homebrew::Install.perform_preinstall_checks_once
|
||||||
valid_formula_installers = Homebrew::Install.fetch_formulae(primary_container.dependencies)
|
formula_installers = primary_container.dependencies.map do |dep|
|
||||||
|
FormulaInstaller.new(
|
||||||
primary_container.dependencies.each do |dep|
|
|
||||||
next unless valid_formula_installers.include?(dep)
|
|
||||||
|
|
||||||
fi = FormulaInstaller.new(
|
|
||||||
dep,
|
dep,
|
||||||
**install_options,
|
**install_options,
|
||||||
)
|
)
|
||||||
|
end
|
||||||
|
valid_formula_installers = Homebrew::Install.fetch_formulae(formula_installers)
|
||||||
|
|
||||||
|
formula_installers.each do |fi|
|
||||||
|
next unless valid_formula_installers.include?(fi)
|
||||||
|
|
||||||
fi.install
|
fi.install
|
||||||
fi.finish
|
fi.finish
|
||||||
end
|
end
|
||||||
@ -695,7 +698,7 @@ module Cask
|
|||||||
add_error "No binaries in App: #{artifact.source}", location: url.location if files.empty?
|
add_error "No binaries in App: #{artifact.source}", location: url.location if files.empty?
|
||||||
|
|
||||||
main_binary = get_plist_main_binary(path)
|
main_binary = get_plist_main_binary(path)
|
||||||
main_binary ||= files.first
|
main_binary ||= files.fetch(0)
|
||||||
|
|
||||||
system_command("lipo", args: ["-archs", main_binary], print_stderr: false)
|
system_command("lipo", args: ["-archs", main_binary], print_stderr: false)
|
||||||
when Artifact::Binary
|
when Artifact::Binary
|
||||||
@ -753,9 +756,9 @@ module Cask
|
|||||||
latest_version = Homebrew::Livecheck.latest_version(
|
latest_version = Homebrew::Livecheck.latest_version(
|
||||||
cask,
|
cask,
|
||||||
referenced_formula_or_cask: referenced_cask,
|
referenced_formula_or_cask: referenced_cask,
|
||||||
)&.fetch(:latest)
|
)&.fetch(:latest, nil)
|
||||||
|
|
||||||
return :auto_detected if cask.version.to_s == latest_version.to_s
|
return :auto_detected if latest_version && (cask.version.to_s == latest_version.to_s)
|
||||||
|
|
||||||
add_error "Version '#{cask.version}' differs from '#{latest_version}' retrieved by livecheck."
|
add_error "Version '#{cask.version}' differs from '#{latest_version}' retrieved by livecheck."
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ require "cask/cask"
|
|||||||
require "uri"
|
require "uri"
|
||||||
require "utils/curl"
|
require "utils/curl"
|
||||||
require "utils/output"
|
require "utils/output"
|
||||||
|
require "utils/path"
|
||||||
require "extend/hash/keys"
|
require "extend/hash/keys"
|
||||||
require "api"
|
require "api"
|
||||||
|
|
||||||
@ -112,9 +113,7 @@ module Cask
|
|||||||
|
|
||||||
return unless path.expand_path.exist?
|
return unless path.expand_path.exist?
|
||||||
return if invalid_path?(path)
|
return if invalid_path?(path)
|
||||||
|
return unless ::Utils::Path.loadable_package_path?(path, :cask)
|
||||||
return if Homebrew::EnvConfig.forbid_packages_from_paths? &&
|
|
||||||
!path.realpath.to_s.start_with?("#{Caskroom.path}/", "#{HOMEBREW_LIBRARY}/Taps/")
|
|
||||||
|
|
||||||
new(path)
|
new(path)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -49,7 +49,7 @@ module Cask
|
|||||||
|
|
||||||
SystemCommand.run("/bin/mkdir", args: ["-p", path], sudo:)
|
SystemCommand.run("/bin/mkdir", args: ["-p", path], sudo:)
|
||||||
SystemCommand.run("/bin/chmod", args: ["g+rwx", path], sudo:)
|
SystemCommand.run("/bin/chmod", args: ["g+rwx", path], sudo:)
|
||||||
SystemCommand.run("/usr/sbin/chown", args: [User.current, path], sudo:)
|
SystemCommand.run("/usr/sbin/chown", args: [User.current.to_s, path], sudo:)
|
||||||
SystemCommand.run("/usr/bin/chgrp", args: ["admin", path], sudo:)
|
SystemCommand.run("/usr/bin/chgrp", args: ["admin", path], sudo:)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -733,7 +733,7 @@ module Homebrew
|
|||||||
formulae_names = removable_formulae.map(&:full_name).sort
|
formulae_names = removable_formulae.map(&:full_name).sort
|
||||||
|
|
||||||
verb = dry_run ? "Would autoremove" : "Autoremoving"
|
verb = dry_run ? "Would autoremove" : "Autoremoving"
|
||||||
oh1 "#{verb} #{formulae_names.count} unneeded #{Utils.pluralize("formula", formulae_names.count, plural: "e")}:"
|
oh1 "#{verb} #{formulae_names.count} unneeded #{Utils.pluralize("formula", formulae_names.count)}:"
|
||||||
puts formulae_names.join("\n")
|
puts formulae_names.join("\n")
|
||||||
return if dry_run
|
return if dry_run
|
||||||
|
|
||||||
|
|||||||
@ -127,7 +127,7 @@ module Homebrew
|
|||||||
conflicts "--all", "--no-vscode"
|
conflicts "--all", "--no-vscode"
|
||||||
conflicts "--vscode", "--no-vscode"
|
conflicts "--vscode", "--no-vscode"
|
||||||
conflicts "--install", "--upgrade"
|
conflicts "--install", "--upgrade"
|
||||||
conflicts "--file=", "--global"
|
conflicts "--file", "--global"
|
||||||
|
|
||||||
named_args %w[install dump cleanup check exec list sh env edit]
|
named_args %w[install dump cleanup check exec list sh env edit]
|
||||||
end
|
end
|
||||||
|
|||||||
@ -77,7 +77,6 @@ module Homebrew
|
|||||||
description: "Show the size of installed formulae and casks."
|
description: "Show the size of installed formulae and casks."
|
||||||
|
|
||||||
conflicts "--installed", "--eval-all"
|
conflicts "--installed", "--eval-all"
|
||||||
conflicts "--installed", "--all"
|
|
||||||
conflicts "--formula", "--cask"
|
conflicts "--formula", "--cask"
|
||||||
conflicts "--fetch-manifest", "--cask"
|
conflicts "--fetch-manifest", "--cask"
|
||||||
conflicts "--fetch-manifest", "--json"
|
conflicts "--fetch-manifest", "--json"
|
||||||
|
|||||||
@ -233,8 +233,8 @@ module Homebrew
|
|||||||
.map(&:name)
|
.map(&:name)
|
||||||
next if dep_names.blank?
|
next if dep_names.blank?
|
||||||
|
|
||||||
ohai "Would install #{::Utils.pluralize("dependenc", dep_names.count, plural: "ies", singular: "y",
|
ohai "Would install #{::Utils.pluralize("dependency", dep_names.count, include_count: true)} " \
|
||||||
include_count: true)} for #{cask.full_name}:"
|
"for #{cask.full_name}:"
|
||||||
puts dep_names.join(" ")
|
puts dep_names.join(" ")
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
|
|||||||
@ -23,7 +23,7 @@ module Homebrew
|
|||||||
flag "--command=",
|
flag "--command=",
|
||||||
description: "Show options for the specified <command>."
|
description: "Show options for the specified <command>."
|
||||||
|
|
||||||
conflicts "--installed", "--all", "--command"
|
conflicts "--command", "--installed", "--eval-all"
|
||||||
|
|
||||||
named_args :formula
|
named_args :formula
|
||||||
end
|
end
|
||||||
@ -47,7 +47,7 @@ module Homebrew
|
|||||||
puts
|
puts
|
||||||
end
|
end
|
||||||
elsif args.no_named?
|
elsif args.no_named?
|
||||||
raise FormulaUnspecifiedError
|
raise UsageError, "`brew options` needs a formula or `--eval-all` passed or `HOMEBREW_EVAL_ALL=1` set!"
|
||||||
else
|
else
|
||||||
puts_options args.named.to_formulae
|
puts_options args.named.to_formulae
|
||||||
end
|
end
|
||||||
|
|||||||
@ -37,8 +37,7 @@ module Homebrew
|
|||||||
description: "Search for casks."
|
description: "Search for casks."
|
||||||
switch "--desc",
|
switch "--desc",
|
||||||
description: "Search for formulae with a description matching <text> and casks with " \
|
description: "Search for formulae with a description matching <text> and casks with " \
|
||||||
"a name or description matching <text>.",
|
"a name or description matching <text>."
|
||||||
depends_on: "--eval-all"
|
|
||||||
switch "--eval-all",
|
switch "--eval-all",
|
||||||
description: "Evaluate all available formulae and casks, whether installed or not, to search their " \
|
description: "Evaluate all available formulae and casks, whether installed or not, to search their " \
|
||||||
"descriptions.",
|
"descriptions.",
|
||||||
|
|||||||
@ -68,7 +68,7 @@ module Homebrew
|
|||||||
description: "Output as JSON."
|
description: "Output as JSON."
|
||||||
|
|
||||||
conflicts "--all", "--file"
|
conflicts "--all", "--file"
|
||||||
conflicts "--max-wait=", "--no-wait"
|
conflicts "--max-wait", "--no-wait"
|
||||||
|
|
||||||
named_args %w[list info run start stop kill restart cleanup]
|
named_args %w[list info run start stop kill restart cleanup]
|
||||||
end
|
end
|
||||||
|
|||||||
@ -50,7 +50,7 @@ homebrew-shellenv() {
|
|||||||
echo "setenv HOMEBREW_REPOSITORY ${HOMEBREW_REPOSITORY};"
|
echo "setenv HOMEBREW_REPOSITORY ${HOMEBREW_REPOSITORY};"
|
||||||
if [[ -n "${PATH_HELPER_ROOT}" ]]
|
if [[ -n "${PATH_HELPER_ROOT}" ]]
|
||||||
then
|
then
|
||||||
PATH_HELPER_ROOT="${PATH_HELPER_ROOT}" PATH="${HOMEBREW_PATH}" /usr/libexec/path_helper -c
|
echo "eval \`PATH_HELPER_ROOT=\"${PATH_HELPER_ROOT}\" /usr/libexec/path_helper -c\`;"
|
||||||
else
|
else
|
||||||
echo "setenv PATH ${HOMEBREW_PREFIX}/bin:${HOMEBREW_PREFIX}/sbin:\$PATH;"
|
echo "setenv PATH ${HOMEBREW_PREFIX}/bin:${HOMEBREW_PREFIX}/sbin:\$PATH;"
|
||||||
fi
|
fi
|
||||||
@ -75,7 +75,7 @@ homebrew-shellenv() {
|
|||||||
fi
|
fi
|
||||||
if [[ -n "${PATH_HELPER_ROOT}" ]]
|
if [[ -n "${PATH_HELPER_ROOT}" ]]
|
||||||
then
|
then
|
||||||
PATH_HELPER_ROOT="${PATH_HELPER_ROOT}" PATH="${HOMEBREW_PATH}" /usr/libexec/path_helper -s
|
echo "eval \"\$(PATH_HELPER_ROOT=\"${PATH_HELPER_ROOT}\" /usr/libexec/path_helper -s)\""
|
||||||
else
|
else
|
||||||
echo "export PATH=\"${HOMEBREW_PREFIX}/bin:${HOMEBREW_PREFIX}/sbin\${PATH+:\$PATH}\";"
|
echo "export PATH=\"${HOMEBREW_PREFIX}/bin:${HOMEBREW_PREFIX}/sbin\${PATH+:\$PATH}\";"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@ -57,7 +57,7 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
info = Utils.pluralize("tap", tap_count, include_count: true)
|
info = Utils.pluralize("tap", tap_count, include_count: true)
|
||||||
info += ", #{private_count} private"
|
info += ", #{private_count} private"
|
||||||
info += ", #{Utils.pluralize("formula", formula_count, plural: "e", include_count: true)}"
|
info += ", #{Utils.pluralize("formula", formula_count, include_count: true)}"
|
||||||
info += ", #{Utils.pluralize("command", command_count, include_count: true)}"
|
info += ", #{Utils.pluralize("command", command_count, include_count: true)}"
|
||||||
info += ", #{HOMEBREW_TAP_DIRECTORY.dup.abv}" if HOMEBREW_TAP_DIRECTORY.directory?
|
info += ", #{HOMEBREW_TAP_DIRECTORY.dup.abv}" if HOMEBREW_TAP_DIRECTORY.directory?
|
||||||
puts info
|
puts info
|
||||||
|
|||||||
@ -842,7 +842,7 @@ class ReporterHub
|
|||||||
msg = ""
|
msg = ""
|
||||||
|
|
||||||
if outdated_formulae.positive?
|
if outdated_formulae.positive?
|
||||||
noun = Utils.pluralize("formula", outdated_formulae, plural: "e")
|
noun = Utils.pluralize("formula", outdated_formulae)
|
||||||
msg += "#{Tty.bold}#{outdated_formulae}#{Tty.reset} outdated #{noun}"
|
msg += "#{Tty.bold}#{outdated_formulae}#{Tty.reset} outdated #{noun}"
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -974,7 +974,11 @@ class ReporterHub
|
|||||||
# Skip non-homebrew/core formulae for security.
|
# Skip non-homebrew/core formulae for security.
|
||||||
return if formula.include?("/")
|
return if formula.include?("/")
|
||||||
|
|
||||||
|
begin
|
||||||
Formula[formula].desc&.presence
|
Formula[formula].desc&.presence
|
||||||
|
rescue FormulaUnavailableError
|
||||||
|
nil
|
||||||
|
end
|
||||||
else
|
else
|
||||||
all_formula_json.find { |f| f["name"] == formula }
|
all_formula_json.find { |f| f["name"] == formula }
|
||||||
&.fetch("desc", nil)
|
&.fetch("desc", nil)
|
||||||
@ -988,7 +992,11 @@ class ReporterHub
|
|||||||
# Skip non-homebrew/cask formulae for security.
|
# Skip non-homebrew/cask formulae for security.
|
||||||
return if cask.include?("/")
|
return if cask.include?("/")
|
||||||
|
|
||||||
|
begin
|
||||||
Cask::CaskLoader.load(cask).desc&.presence
|
Cask::CaskLoader.load(cask).desc&.presence
|
||||||
|
rescue Cask::CaskError
|
||||||
|
nil
|
||||||
|
end
|
||||||
else
|
else
|
||||||
all_cask_json.find { |f| f["token"] == cask }
|
all_cask_json.find { |f| f["token"] == cask }
|
||||||
&.fetch("desc", nil)
|
&.fetch("desc", nil)
|
||||||
|
|||||||
@ -55,7 +55,7 @@ module Homebrew
|
|||||||
description: "Include only casks."
|
description: "Include only casks."
|
||||||
|
|
||||||
conflicts "--formula", "--cask"
|
conflicts "--formula", "--cask"
|
||||||
conflicts "--installed", "--all"
|
conflicts "--installed", "--eval-all"
|
||||||
conflicts "--missing", "--installed"
|
conflicts "--missing", "--installed"
|
||||||
|
|
||||||
named_args :formula, min: 1
|
named_args :formula, min: 1
|
||||||
|
|||||||
@ -128,7 +128,7 @@ module Commands
|
|||||||
OFFICIAL_CMD_TAPS.flat_map do |tap_name, cmds|
|
OFFICIAL_CMD_TAPS.flat_map do |tap_name, cmds|
|
||||||
tap = Tap.fetch(tap_name)
|
tap = Tap.fetch(tap_name)
|
||||||
tap.install(quiet:) unless tap.installed?
|
tap.install(quiet:) unless tap.installed?
|
||||||
cmds.map(&method(:external_ruby_v2_cmd_path)).compact
|
cmds.map { external_ruby_v2_cmd_path(_1) }.compact
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,7 @@ module DeprecateDisable
|
|||||||
no_longer_meets_criteria: "no longer meets the criteria for acceptable casks",
|
no_longer_meets_criteria: "no longer meets the criteria for acceptable casks",
|
||||||
unmaintained: "is not maintained upstream",
|
unmaintained: "is not maintained upstream",
|
||||||
fails_gatekeeper_check: "does not pass the macOS Gatekeeper check",
|
fails_gatekeeper_check: "does not pass the macOS Gatekeeper check",
|
||||||
|
unreachable: "is no longer reliably reachable upstream",
|
||||||
# odeprecate: remove the unsigned reason in a future release
|
# odeprecate: remove the unsigned reason in a future release
|
||||||
unsigned: "is unsigned or does not meet signature requirements",
|
unsigned: "is unsigned or does not meet signature requirements",
|
||||||
}.freeze, T::Hash[Symbol, String])
|
}.freeze, T::Hash[Symbol, String])
|
||||||
|
|||||||
@ -83,7 +83,7 @@ class DescriptionCacheStore < CacheStore
|
|||||||
def delete_from_formula_names!(formula_names)
|
def delete_from_formula_names!(formula_names)
|
||||||
return if database.empty?
|
return if database.empty?
|
||||||
|
|
||||||
formula_names.each(&method(:delete!))
|
formula_names.each { delete!(_1) }
|
||||||
end
|
end
|
||||||
alias delete_from_cask_tokens! delete_from_formula_names!
|
alias delete_from_cask_tokens! delete_from_formula_names!
|
||||||
|
|
||||||
|
|||||||
@ -93,11 +93,11 @@ module Homebrew
|
|||||||
switch "--cask", "--casks",
|
switch "--cask", "--casks",
|
||||||
description: "Treat all named arguments as casks."
|
description: "Treat all named arguments as casks."
|
||||||
|
|
||||||
|
conflicts "--installed", "--eval-all"
|
||||||
conflicts "--only", "--except"
|
conflicts "--only", "--except"
|
||||||
conflicts "--only-cops", "--except-cops", "--strict"
|
conflicts "--only-cops", "--except-cops", "--strict"
|
||||||
conflicts "--only-cops", "--except-cops", "--only"
|
conflicts "--only-cops", "--except-cops", "--only"
|
||||||
conflicts "--formula", "--cask"
|
conflicts "--formula", "--cask"
|
||||||
conflicts "--installed", "--all"
|
|
||||||
|
|
||||||
named_args [:formula, :cask], without_api: true
|
named_args [:formula, :cask], without_api: true
|
||||||
end
|
end
|
||||||
@ -294,9 +294,7 @@ module Homebrew
|
|||||||
errors_summary = Utils.pluralize("problem", total_problems_count, include_count: true)
|
errors_summary = Utils.pluralize("problem", total_problems_count, include_count: true)
|
||||||
|
|
||||||
error_sources = []
|
error_sources = []
|
||||||
if formula_count.positive?
|
error_sources << Utils.pluralize("formula", formula_count, include_count: true) if formula_count.positive?
|
||||||
error_sources << Utils.pluralize("formula", formula_count, plural: "e", include_count: true)
|
|
||||||
end
|
|
||||||
error_sources << Utils.pluralize("cask", cask_count, include_count: true) if cask_count.positive?
|
error_sources << Utils.pluralize("cask", cask_count, include_count: true) if cask_count.positive?
|
||||||
error_sources << Utils.pluralize("tap", tap_count, include_count: true) if tap_count.positive?
|
error_sources << Utils.pluralize("tap", tap_count, include_count: true) if tap_count.positive?
|
||||||
|
|
||||||
|
|||||||
@ -182,7 +182,8 @@ module Homebrew
|
|||||||
|
|
||||||
sig {
|
sig {
|
||||||
params(old_keys: T::Array[String], old_bottle_spec: BottleSpecification,
|
params(old_keys: T::Array[String], old_bottle_spec: BottleSpecification,
|
||||||
new_bottle_hash: T::Hash[String, T.untyped]).returns(T::Array[T::Array[String]])
|
new_bottle_hash: T::Hash[String, T.untyped])
|
||||||
|
.returns([T::Array[String], T::Array[T::Hash[Symbol, T.any(String, Symbol)]]])
|
||||||
}
|
}
|
||||||
def merge_bottle_spec(old_keys, old_bottle_spec, new_bottle_hash)
|
def merge_bottle_spec(old_keys, old_bottle_spec, new_bottle_hash)
|
||||||
mismatches = []
|
mismatches = []
|
||||||
@ -409,7 +410,7 @@ module Homebrew
|
|||||||
|
|
||||||
bottle_tag, rebuild = if local_bottle_json
|
bottle_tag, rebuild = if local_bottle_json
|
||||||
_, tag_string, rebuild_string = Utils::Bottles.extname_tag_rebuild(formula.local_bottle_path.to_s)
|
_, tag_string, rebuild_string = Utils::Bottles.extname_tag_rebuild(formula.local_bottle_path.to_s)
|
||||||
[tag_string.to_sym, rebuild_string.to_i]
|
[T.must(tag_string).to_sym, rebuild_string.to_i]
|
||||||
end
|
end
|
||||||
|
|
||||||
bottle_tag = if bottle_tag
|
bottle_tag = if bottle_tag
|
||||||
@ -860,8 +861,8 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
sig {
|
sig {
|
||||||
params(formula: Formula, formula_ast: Utils::AST::FormulaAST,
|
params(formula: Formula, formula_ast: Utils::AST::FormulaAST, bottle_hash: T::Hash[String, T.untyped])
|
||||||
bottle_hash: T::Hash[String, T.untyped]).returns(T.nilable(T::Array[String]))
|
.returns(T.nilable(T::Array[T::Hash[Symbol, T.any(String, Symbol)]]))
|
||||||
}
|
}
|
||||||
def old_checksums(formula, formula_ast, bottle_hash)
|
def old_checksums(formula, formula_ast, bottle_hash)
|
||||||
bottle_node = T.cast(formula_ast.bottle_block, T.nilable(RuboCop::AST::BlockNode))
|
bottle_node = T.cast(formula_ast.bottle_block, T.nilable(RuboCop::AST::BlockNode))
|
||||||
|
|||||||
@ -49,8 +49,8 @@ module Homebrew
|
|||||||
description: "Use the specified GitHub organization for forking."
|
description: "Use the specified GitHub organization for forking."
|
||||||
|
|
||||||
conflicts "--dry-run", "--write"
|
conflicts "--dry-run", "--write"
|
||||||
conflicts "--version=", "--version-arm="
|
conflicts "--version", "--version-arm"
|
||||||
conflicts "--version=", "--version-intel="
|
conflicts "--version", "--version-intel"
|
||||||
|
|
||||||
named_args :cask, number: 1, without_api: true
|
named_args :cask, number: 1, without_api: true
|
||||||
end
|
end
|
||||||
|
|||||||
@ -9,6 +9,8 @@ require "utils/repology"
|
|||||||
module Homebrew
|
module Homebrew
|
||||||
module DevCmd
|
module DevCmd
|
||||||
class Bump < AbstractCommand
|
class Bump < AbstractCommand
|
||||||
|
NEWER_THAN_UPSTREAM_MSG = " (newer than upstream)"
|
||||||
|
|
||||||
class VersionBumpInfo < T::Struct
|
class VersionBumpInfo < T::Struct
|
||||||
const :type, Symbol
|
const :type, Symbol
|
||||||
const :multiple_versions, T::Boolean
|
const :multiple_versions, T::Boolean
|
||||||
@ -16,6 +18,7 @@ module Homebrew
|
|||||||
const :current_version, BumpVersionParser
|
const :current_version, BumpVersionParser
|
||||||
const :repology_latest, T.any(String, Version)
|
const :repology_latest, T.any(String, Version)
|
||||||
const :new_version, BumpVersionParser
|
const :new_version, BumpVersionParser
|
||||||
|
const :newer_than_upstream, T::Hash[Symbol, T::Boolean], default: {}
|
||||||
const :duplicate_pull_requests, T.nilable(T.any(T::Array[String], String))
|
const :duplicate_pull_requests, T.nilable(T.any(T::Array[String], String))
|
||||||
const :maybe_duplicate_pull_requests, T.nilable(T.any(T::Array[String], String))
|
const :maybe_duplicate_pull_requests, T.nilable(T.any(T::Array[String], String))
|
||||||
end
|
end
|
||||||
@ -57,10 +60,10 @@ module Homebrew
|
|||||||
switch "--bump-synced",
|
switch "--bump-synced",
|
||||||
description: "Bump additional formulae marked as synced with the given formulae."
|
description: "Bump additional formulae marked as synced with the given formulae."
|
||||||
|
|
||||||
conflicts "--cask", "--formula"
|
conflicts "--formula", "--cask"
|
||||||
conflicts "--tap=", "--installed"
|
conflicts "--tap", "--installed"
|
||||||
conflicts "--tap=", "--no-autobump"
|
conflicts "--tap", "--no-autobump"
|
||||||
conflicts "--eval-all", "--installed"
|
conflicts "--installed", "--eval-all"
|
||||||
conflicts "--installed", "--auto"
|
conflicts "--installed", "--auto"
|
||||||
conflicts "--no-pull-requests", "--open-pr"
|
conflicts "--no-pull-requests", "--open-pr"
|
||||||
|
|
||||||
@ -315,6 +318,7 @@ module Homebrew
|
|||||||
new_versions = {}
|
new_versions = {}
|
||||||
|
|
||||||
repology_latest = repositories.present? ? Repology.latest_version(repositories) : "not found"
|
repology_latest = repositories.present? ? Repology.latest_version(repositories) : "not found"
|
||||||
|
repology_latest_is_a_version = repology_latest.is_a?(Version)
|
||||||
|
|
||||||
# When blocks are absent, arch is not relevant. For consistency, we simulate the arm architecture.
|
# When blocks are absent, arch is not relevant. For consistency, we simulate the arm architecture.
|
||||||
arch_options = is_cask_with_blocks ? OnSystem::ARCH_OPTIONS : [:arm]
|
arch_options = is_cask_with_blocks ? OnSystem::ARCH_OPTIONS : [:arm]
|
||||||
@ -331,23 +335,31 @@ module Homebrew
|
|||||||
loaded_formula_or_cask = Cask::CaskLoader.load(formula_or_cask.sourcefile_path)
|
loaded_formula_or_cask = Cask::CaskLoader.load(formula_or_cask.sourcefile_path)
|
||||||
current_version_value = Version.new(loaded_formula_or_cask.version)
|
current_version_value = Version.new(loaded_formula_or_cask.version)
|
||||||
end
|
end
|
||||||
|
formula_or_cask_has_livecheck = loaded_formula_or_cask.livecheck_defined?
|
||||||
|
|
||||||
livecheck_latest = livecheck_result(loaded_formula_or_cask)
|
livecheck_latest = livecheck_result(loaded_formula_or_cask)
|
||||||
|
livecheck_latest_is_a_version = livecheck_latest.is_a?(Version)
|
||||||
|
|
||||||
new_version_value = if (livecheck_latest.is_a?(Version) &&
|
new_version_value = if (livecheck_latest_is_a_version &&
|
||||||
Livecheck::LivecheckVersion.create(formula_or_cask, livecheck_latest) >=
|
Livecheck::LivecheckVersion.create(formula_or_cask, livecheck_latest) >=
|
||||||
Livecheck::LivecheckVersion.create(formula_or_cask, current_version_value)) ||
|
Livecheck::LivecheckVersion.create(formula_or_cask, current_version_value)) ||
|
||||||
current_version_value == "latest"
|
current_version_value == "latest"
|
||||||
livecheck_latest
|
livecheck_latest
|
||||||
elsif livecheck_latest.is_a?(String) && livecheck_latest.start_with?("skipped")
|
elsif livecheck_latest.is_a?(String) && livecheck_latest.start_with?("skipped")
|
||||||
"skipped"
|
"skipped"
|
||||||
elsif repology_latest.is_a?(Version) &&
|
elsif repology_latest_is_a_version &&
|
||||||
|
!formula_or_cask_has_livecheck &&
|
||||||
repology_latest > current_version_value &&
|
repology_latest > current_version_value &&
|
||||||
!loaded_formula_or_cask.livecheck_defined? &&
|
|
||||||
current_version_value != "latest"
|
current_version_value != "latest"
|
||||||
repology_latest
|
repology_latest
|
||||||
end.presence
|
end.presence
|
||||||
|
|
||||||
|
# Fall back to the upstream version if there isn't a new version
|
||||||
|
# value at this point, as this will allow us to surface an upstream
|
||||||
|
# version that's lower than the current version.
|
||||||
|
new_version_value ||= livecheck_latest if livecheck_latest_is_a_version
|
||||||
|
new_version_value ||= repology_latest if repology_latest_is_a_version && !formula_or_cask_has_livecheck
|
||||||
|
|
||||||
# Store old and new versions
|
# Store old and new versions
|
||||||
old_versions[version_key] = current_version_value
|
old_versions[version_key] = current_version_value
|
||||||
new_versions[version_key] = new_version_value
|
new_versions[version_key] = new_version_value
|
||||||
@ -380,10 +392,22 @@ module Homebrew
|
|||||||
new_version = BumpVersionParser.new(general: "unable to get versions")
|
new_version = BumpVersionParser.new(general: "unable to get versions")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
newer_than_upstream = {}
|
||||||
|
BumpVersionParser::VERSION_SYMBOLS.each do |version_type|
|
||||||
|
new_version_value = new_version.send(version_type)
|
||||||
|
next unless new_version_value.is_a?(Version)
|
||||||
|
|
||||||
|
newer_than_upstream[version_type] =
|
||||||
|
(current_version_value = current_version.send(version_type)).is_a?(Version) &&
|
||||||
|
(Livecheck::LivecheckVersion.create(formula_or_cask, current_version_value) >
|
||||||
|
Livecheck::LivecheckVersion.create(formula_or_cask, new_version_value))
|
||||||
|
end
|
||||||
|
|
||||||
if !args.no_pull_requests? &&
|
if !args.no_pull_requests? &&
|
||||||
(new_version.general != "unable to get versions") &&
|
(new_version.general != "unable to get versions") &&
|
||||||
(new_version.general != "skipped") &&
|
(new_version.general != "skipped") &&
|
||||||
(new_version != current_version)
|
(new_version != current_version) &&
|
||||||
|
!newer_than_upstream.all? { |_k, v| v == true }
|
||||||
# We use the ARM version for the pull request version. This is
|
# We use the ARM version for the pull request version. This is
|
||||||
# consistent with the behavior of bump-cask-pr.
|
# consistent with the behavior of bump-cask-pr.
|
||||||
pull_request_version = if multiple_versions
|
pull_request_version = if multiple_versions
|
||||||
@ -410,6 +434,7 @@ module Homebrew
|
|||||||
current_version:,
|
current_version:,
|
||||||
repology_latest:,
|
repology_latest:,
|
||||||
new_version:,
|
new_version:,
|
||||||
|
newer_than_upstream:,
|
||||||
duplicate_pull_requests:,
|
duplicate_pull_requests:,
|
||||||
maybe_duplicate_pull_requests:,
|
maybe_duplicate_pull_requests:,
|
||||||
)
|
)
|
||||||
@ -432,8 +457,8 @@ module Homebrew
|
|||||||
new_version = version_info.new_version
|
new_version = version_info.new_version
|
||||||
repology_latest = version_info.repology_latest
|
repology_latest = version_info.repology_latest
|
||||||
|
|
||||||
# Check if all versions are equal
|
|
||||||
versions_equal = (new_version == current_version)
|
versions_equal = (new_version == current_version)
|
||||||
|
all_newer_than_upstream = version_info.newer_than_upstream.all? { |_k, v| v == true }
|
||||||
|
|
||||||
title_name = ambiguous_cask ? "#{name} (cask)" : name
|
title_name = ambiguous_cask ? "#{name} (cask)" : name
|
||||||
title = if (repology_latest == current_version.general || !repology_latest.is_a?(Version)) && versions_equal
|
title = if (repology_latest == current_version.general || !repology_latest.is_a?(Version)) && versions_equal
|
||||||
@ -444,10 +469,13 @@ module Homebrew
|
|||||||
|
|
||||||
# Conditionally format output based on type of formula_or_cask
|
# Conditionally format output based on type of formula_or_cask
|
||||||
current_versions = if version_info.multiple_versions
|
current_versions = if version_info.multiple_versions
|
||||||
"arm: #{current_version.arm}
|
"arm: #{current_version.arm}" \
|
||||||
intel: #{current_version.intel}"
|
"#{NEWER_THAN_UPSTREAM_MSG if version_info.newer_than_upstream[:arm]}" \
|
||||||
|
"\n intel: #{current_version.intel}" \
|
||||||
|
"#{NEWER_THAN_UPSTREAM_MSG if version_info.newer_than_upstream[:intel]}"
|
||||||
else
|
else
|
||||||
current_version.general.to_s
|
newer_than_upstream_general = version_info.newer_than_upstream[:general]
|
||||||
|
"#{current_version.general}#{NEWER_THAN_UPSTREAM_MSG if newer_than_upstream_general}"
|
||||||
end
|
end
|
||||||
current_versions << " (deprecated)" if formula_or_cask.deprecated?
|
current_versions << " (deprecated)" if formula_or_cask.deprecated?
|
||||||
|
|
||||||
@ -482,7 +510,8 @@ module Homebrew
|
|||||||
if !args.no_pull_requests? &&
|
if !args.no_pull_requests? &&
|
||||||
(new_version.general != "unable to get versions") &&
|
(new_version.general != "unable to get versions") &&
|
||||||
(new_version.general != "skipped") &&
|
(new_version.general != "skipped") &&
|
||||||
!versions_equal
|
!versions_equal &&
|
||||||
|
!all_newer_than_upstream
|
||||||
if duplicate_pull_requests
|
if duplicate_pull_requests
|
||||||
duplicate_pull_requests_text = duplicate_pull_requests
|
duplicate_pull_requests_text = duplicate_pull_requests
|
||||||
elsif maybe_duplicate_pull_requests
|
elsif maybe_duplicate_pull_requests
|
||||||
@ -501,7 +530,8 @@ module Homebrew
|
|||||||
|
|
||||||
if !args.open_pr? ||
|
if !args.open_pr? ||
|
||||||
(new_version.general == "unable to get versions") ||
|
(new_version.general == "unable to get versions") ||
|
||||||
(new_version.general == "skipped")
|
(new_version.general == "skipped") ||
|
||||||
|
all_newer_than_upstream
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -6,13 +6,23 @@ require "abstract_command"
|
|||||||
module Homebrew
|
module Homebrew
|
||||||
module DevCmd
|
module DevCmd
|
||||||
class Contributions < AbstractCommand
|
class Contributions < AbstractCommand
|
||||||
PRIMARY_REPOS = T.let(%w[brew core cask].freeze, T::Array[String])
|
PRIMARY_REPOS = T.let(%w[
|
||||||
SUPPORTED_REPOS = T.let([
|
Homebrew/brew
|
||||||
PRIMARY_REPOS,
|
Homebrew/homebrew-core
|
||||||
OFFICIAL_CMD_TAPS.keys.map { |t| t.delete_prefix("homebrew/") },
|
Homebrew/homebrew-cask
|
||||||
OFFICIAL_CASK_TAPS.reject { |t| t == "cask" },
|
].freeze, T::Array[String])
|
||||||
].flatten.freeze, T::Array[String])
|
ALL_REPOS = T.let([
|
||||||
MAX_REPO_COMMITS = 1000
|
*PRIMARY_REPOS,
|
||||||
|
*OFFICIAL_CMD_TAPS.keys,
|
||||||
|
].freeze, T::Array[String])
|
||||||
|
CONTRIBUTION_TYPES = T.let({
|
||||||
|
merged_pr_author: "merged PR author",
|
||||||
|
approved_pr_review: "approved PR reviewer",
|
||||||
|
committer: "commit author or committer",
|
||||||
|
coauthor: "commit coauthor",
|
||||||
|
}.freeze, T::Hash[Symbol, String])
|
||||||
|
MAX_COMMITS = T.let(1000, Integer)
|
||||||
|
MAX_PR_SEARCH = T.let(100, Integer)
|
||||||
|
|
||||||
cmd_args do
|
cmd_args do
|
||||||
usage_banner "`contributions` [`--user=`] [`--repositories=`] [`--from=`] [`--to=`] [`--csv`]"
|
usage_banner "`contributions` [`--user=`] [`--repositories=`] [`--from=`] [`--to=`] [`--csv`]"
|
||||||
@ -24,10 +34,17 @@ module Homebrew
|
|||||||
"contributions from. Omitting this flag searches Homebrew maintainers."
|
"contributions from. Omitting this flag searches Homebrew maintainers."
|
||||||
comma_array "--repositories",
|
comma_array "--repositories",
|
||||||
description: "Specify a comma-separated list of repositories to search. " \
|
description: "Specify a comma-separated list of repositories to search. " \
|
||||||
"Supported repositories: #{SUPPORTED_REPOS.map { |t| "`#{t}`" }.to_sentence}. " \
|
"All repositories must be under the same user or organisation. " \
|
||||||
"Omitting this flag, or specifying `--repositories=primary`, searches only the " \
|
"Omitting this flag, or specifying `--repositories=primary`, searches only the " \
|
||||||
"main repositories: `brew`, `core`, `cask`. " \
|
"main repositories: `Homebrew/brew`, `Homebrew/homebrew-core`, " \
|
||||||
"Specifying `--repositories=all` searches all repositories. "
|
"`Homebrew/homebrew-cask`. Specifying `--repositories=all` searches all " \
|
||||||
|
"non-deprecated Homebrew repositories. "
|
||||||
|
flag "--organisation=", "--organization=", "--org=",
|
||||||
|
description: "Specify the organisation to populate sources repositories from. " \
|
||||||
|
"Omitting this flag searches the Homebrew primary repositories."
|
||||||
|
flag "--team=",
|
||||||
|
description: "Specify the team to populate users from. " \
|
||||||
|
"The first part of the team name will be used as the organisation."
|
||||||
flag "--from=",
|
flag "--from=",
|
||||||
description: "Date (ISO 8601 format) to start searching contributions. " \
|
description: "Date (ISO 8601 format) to start searching contributions. " \
|
||||||
"Omitting this flag searches the past year."
|
"Omitting this flag searches the past year."
|
||||||
@ -35,54 +52,93 @@ module Homebrew
|
|||||||
description: "Date (ISO 8601 format) to stop searching contributions."
|
description: "Date (ISO 8601 format) to stop searching contributions."
|
||||||
switch "--csv",
|
switch "--csv",
|
||||||
description: "Print a CSV of contributions across repositories over the time period."
|
description: "Print a CSV of contributions across repositories over the time period."
|
||||||
|
conflicts "--organisation", "--repositories"
|
||||||
|
conflicts "--organisation", "--team"
|
||||||
|
conflicts "--user", "--team"
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { override.void }
|
sig { override.void }
|
||||||
def run
|
def run
|
||||||
|
odie "Cannot get contributions as `$HOMEBREW_NO_GITHUB_API` is set!" if Homebrew::EnvConfig.no_github_api?
|
||||||
|
|
||||||
Homebrew.install_bundler_gems!(groups: ["contributions"]) if args.csv?
|
Homebrew.install_bundler_gems!(groups: ["contributions"]) if args.csv?
|
||||||
|
|
||||||
|
require "utils/github"
|
||||||
|
|
||||||
results = {}
|
results = {}
|
||||||
grand_totals = {}
|
grand_totals = {}
|
||||||
|
|
||||||
repos = T.must(
|
|
||||||
if args.repositories.blank? || args.repositories&.include?("primary")
|
|
||||||
PRIMARY_REPOS
|
|
||||||
elsif args.repositories&.include?("all")
|
|
||||||
SUPPORTED_REPOS
|
|
||||||
else
|
|
||||||
args.repositories
|
|
||||||
end,
|
|
||||||
)
|
|
||||||
|
|
||||||
repos.each do |repo|
|
|
||||||
if SUPPORTED_REPOS.exclude?(repo)
|
|
||||||
odie "Unsupported repository: #{repo}. Try one of #{SUPPORTED_REPOS.join(", ")}."
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
from = args.from.presence || Date.today.prev_year.iso8601
|
from = args.from.presence || Date.today.prev_year.iso8601
|
||||||
|
to = args.to.presence || (Date.today + 1).iso8601
|
||||||
|
organisation = nil
|
||||||
|
|
||||||
contribution_types = [:author, :committer, :coauthor, :review]
|
users = if (team = args.team.presence)
|
||||||
|
team_sections = team.split("/")
|
||||||
|
organisation = team_sections.first.presence
|
||||||
|
team_name = team_sections.last.presence
|
||||||
|
if team_sections.length != 2 || organisation.nil? || team_name.nil?
|
||||||
|
odie "Team must be in the format `organisation/team`!"
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "Getting members for #{organisation}/#{team_name}..." if args.verbose?
|
||||||
|
GitHub.members_by_team(organisation, team_name).keys
|
||||||
|
elsif (users = args.user.presence)
|
||||||
|
users
|
||||||
|
else
|
||||||
|
puts "Getting members for Homebrew/maintainers..." if args.verbose?
|
||||||
|
GitHub.members_by_team("Homebrew", "maintainers").keys
|
||||||
|
end
|
||||||
|
|
||||||
|
repositories = if (org = organisation.presence) || (org = args.organisation.presence)
|
||||||
|
organisation = org
|
||||||
|
puts "Getting repositories for #{organisation}..." if args.verbose?
|
||||||
|
GitHub.organisation_repositories(organisation, from, to, args.verbose?)
|
||||||
|
elsif (repos = args.repositories.presence) && repos.length == 1 && (first_repository = repos.first)
|
||||||
|
case first_repository
|
||||||
|
when "primary"
|
||||||
|
PRIMARY_REPOS
|
||||||
|
when "all"
|
||||||
|
ALL_REPOS
|
||||||
|
else
|
||||||
|
Array(first_repository)
|
||||||
|
end
|
||||||
|
elsif (repos = args.repositories.presence)
|
||||||
|
organisations = repos.map { |repository| repository.split("/").first }.uniq
|
||||||
|
odie "All repositories must be under the same user or organisation!" if organisations.length > 1
|
||||||
|
|
||||||
|
repos
|
||||||
|
else
|
||||||
|
PRIMARY_REPOS
|
||||||
|
end
|
||||||
|
organisation ||= T.must(repositories.fetch(0).split("/").first)
|
||||||
|
|
||||||
require "utils/github"
|
|
||||||
users = args.user.presence || GitHub.members_by_team("Homebrew", "maintainers").keys
|
|
||||||
users.each do |username|
|
users.each do |username|
|
||||||
# TODO: Using the GitHub username to scan the `git log` undercounts some
|
# TODO: Using the GitHub username to scan the `git log` undercounts some
|
||||||
# contributions as people might not always have configured their Git
|
# contributions as people might not always have configured their Git
|
||||||
# committer details to match the ones on GitHub.
|
# committer details to match the ones on GitHub.
|
||||||
# TODO: Switch to using the GitHub APIs instead of `git log` if
|
# TODO: Switch to using the GitHub APIs instead of `git log` if
|
||||||
# they ever support trailers.
|
# they ever support trailers.
|
||||||
results[username] = scan_repositories(repos, username, from:)
|
results[username] = scan_repositories(organisation, repositories, username, from:, to:)
|
||||||
grand_totals[username] = total(results[username])
|
grand_totals[username] = total(results[username])
|
||||||
|
|
||||||
contributions = contribution_types.filter_map do |type|
|
search_types = [:merged_pr_author, :approved_pr_review].freeze
|
||||||
|
greater_than_total = T.let(false, T::Boolean)
|
||||||
|
contributions = CONTRIBUTION_TYPES.keys.filter_map do |type|
|
||||||
type_count = grand_totals[username][type]
|
type_count = grand_totals[username][type]
|
||||||
next if type_count.to_i.zero?
|
next if type_count.zero?
|
||||||
|
|
||||||
"#{Utils.pluralize("time", type_count, include_count: true)} (#{type})"
|
count_prefix = ""
|
||||||
|
if (search_types.include?(type) && type_count == MAX_PR_SEARCH) ||
|
||||||
|
(type == :committer && type_count == MAX_COMMITS)
|
||||||
|
greater_than_total ||= true
|
||||||
|
count_prefix = ">="
|
||||||
end
|
end
|
||||||
contributions <<
|
|
||||||
"#{Utils.pluralize("time", grand_totals[username].values.sum, include_count: true)} (total)"
|
pretty_type = CONTRIBUTION_TYPES.fetch(type)
|
||||||
|
"#{count_prefix}#{Utils.pluralize("time", type_count, include_count: true)} (#{pretty_type})"
|
||||||
|
end
|
||||||
|
total = Utils.pluralize("time", grand_totals[username].values.sum, include_count: true)
|
||||||
|
total_prefix = ">=" if greater_than_total
|
||||||
|
contributions << "#{total_prefix}#{total} (total)"
|
||||||
|
|
||||||
contributions_string = [
|
contributions_string = [
|
||||||
"#{username} contributed",
|
"#{username} contributed",
|
||||||
@ -104,12 +160,16 @@ module Homebrew
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
sig { params(repo: String).returns(Pathname) }
|
sig { params(repository: String).returns([T.nilable(Pathname), T.nilable(Tap)]) }
|
||||||
def find_repo_path_for_repo(repo)
|
def repository_path_and_tap(repository)
|
||||||
return HOMEBREW_REPOSITORY if repo == "brew"
|
return [HOMEBREW_REPOSITORY, nil] if repository == "Homebrew/brew"
|
||||||
|
return [nil, nil] if repository.exclude?("/homebrew-")
|
||||||
|
|
||||||
require "tap"
|
require "tap"
|
||||||
Tap.fetch("homebrew", repo).path
|
tap = Tap.fetch(repository)
|
||||||
|
return [nil, nil] if tap.user == "Homebrew" && DEPRECATED_OFFICIAL_TAPS.include?(tap.repository)
|
||||||
|
|
||||||
|
[tap.path, tap]
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(from: T.nilable(String), to: T.nilable(String)).returns(String) }
|
sig { params(from: T.nilable(String), to: T.nilable(String)).returns(String) }
|
||||||
@ -130,7 +190,7 @@ module Homebrew
|
|||||||
require "csv"
|
require "csv"
|
||||||
|
|
||||||
CSV.generate do |csv|
|
CSV.generate do |csv|
|
||||||
csv << %w[user repo author committer coauthor review total]
|
csv << ["user", "repository", *CONTRIBUTION_TYPES.keys, "total"]
|
||||||
|
|
||||||
totals.sort_by { |_, v| -v.values.sum }.each do |user, total|
|
totals.sort_by { |_, v| -v.values.sum }.each do |user, total|
|
||||||
csv << grand_total_row(user, total)
|
csv << grand_total_row(user, total)
|
||||||
@ -138,63 +198,67 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
sig {
|
sig { params(user: String, grand_total: T::Hash[Symbol, Integer]).returns(T::Array[T.any(String, T.nilable(Integer))]) }
|
||||||
params(
|
|
||||||
user: String,
|
|
||||||
grand_total: T::Hash[Symbol, Integer],
|
|
||||||
).returns(
|
|
||||||
[String, String, T.nilable(Integer), T.nilable(Integer), T.nilable(Integer), T.nilable(Integer), Integer],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
def grand_total_row(user, grand_total)
|
def grand_total_row(user, grand_total)
|
||||||
[
|
grand_totals = grand_total.slice(*CONTRIBUTION_TYPES.keys).values
|
||||||
user,
|
[user, "all", *grand_totals, grand_totals.sum]
|
||||||
"all",
|
|
||||||
grand_total[:author],
|
|
||||||
grand_total[:committer],
|
|
||||||
grand_total[:coauthor],
|
|
||||||
grand_total[:review],
|
|
||||||
grand_total.values.sum,
|
|
||||||
]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
sig {
|
sig {
|
||||||
params(
|
params(
|
||||||
repos: T::Array[String],
|
organisation: String,
|
||||||
|
repositories: T::Array[String],
|
||||||
person: String,
|
person: String,
|
||||||
from: String,
|
from: String,
|
||||||
|
to: String,
|
||||||
).returns(T::Hash[Symbol, T.untyped])
|
).returns(T::Hash[Symbol, T.untyped])
|
||||||
}
|
}
|
||||||
def scan_repositories(repos, person, from:)
|
def scan_repositories(organisation, repositories, person, from:, to:)
|
||||||
data = {}
|
data = {}
|
||||||
return data if repos.blank?
|
return data if repositories.blank?
|
||||||
|
|
||||||
require "tap"
|
|
||||||
require "utils/github"
|
require "utils/github"
|
||||||
repos.each do |repo|
|
|
||||||
repo_path = find_repo_path_for_repo(repo)
|
max = MAX_COMMITS
|
||||||
tap = Tap.fetch("homebrew", repo)
|
verbose = args.verbose?
|
||||||
unless repo_path.exist?
|
|
||||||
opoo "Repository #{repo} not yet tapped! Tapping it now..."
|
puts "Querying pull requests for #{person} in #{organisation}..." if args.verbose?
|
||||||
|
organisation_merged_prs = \
|
||||||
|
GitHub.search_merged_pull_requests_in_user_or_organisation(organisation, person, from:, to:)
|
||||||
|
organisation_approved_reviews = \
|
||||||
|
GitHub.search_approved_pull_requests_in_user_or_organisation(organisation, person, from:, to:)
|
||||||
|
|
||||||
|
require "utils/git"
|
||||||
|
|
||||||
|
repositories.each do |repository|
|
||||||
|
repository_path, tap = repository_path_and_tap(repository)
|
||||||
|
if repository_path && tap && !repository_path.exist?
|
||||||
|
opoo "Repository #{repository} not yet tapped! Tapping it now..."
|
||||||
tap.install
|
tap.install
|
||||||
end
|
end
|
||||||
|
|
||||||
repo_full_name = if repo == "brew"
|
repository_full_name = tap&.full_name
|
||||||
"homebrew/brew"
|
repository_full_name ||= repository
|
||||||
else
|
|
||||||
tap.full_name
|
repository_api_url = "#{GitHub::API_URL}/repos/#{repository_full_name}"
|
||||||
|
|
||||||
|
puts "Determining contributions for #{person} on #{repository_full_name}..." if args.verbose?
|
||||||
|
|
||||||
|
merged_pr_author = organisation_merged_prs.count do |pr|
|
||||||
|
pr.fetch("repository_url") == repository_api_url
|
||||||
end
|
end
|
||||||
|
approved_pr_review = organisation_approved_reviews.count do |pr|
|
||||||
|
pr.fetch("repository_url") == repository_api_url
|
||||||
|
end
|
||||||
|
committer = GitHub.count_repository_commits(repository_full_name, person, max:, verbose:, from:, to:)
|
||||||
|
coauthor = Utils::Git.count_coauthors(repository_path, person, from:, to:)
|
||||||
|
|
||||||
puts "Determining contributions for #{person} on #{repo_full_name}..." if args.verbose?
|
data[repository] = { merged_pr_author:, approved_pr_review:, committer:, coauthor: }
|
||||||
|
rescue GitHub::API::RateLimitExceededError => e
|
||||||
author_commits, committer_commits = GitHub.count_repo_commits(repo_full_name, person,
|
sleep_seconds = e.reset - Time.now.to_i
|
||||||
from:, to: args.to, max: MAX_REPO_COMMITS)
|
opoo "GitHub rate limit exceeded, sleeping for #{sleep_seconds} seconds..."
|
||||||
data[repo] = {
|
sleep sleep_seconds
|
||||||
author: author_commits,
|
retry
|
||||||
committer: committer_commits,
|
|
||||||
coauthor: git_log_trailers_cmd(repo_path, person, "Co-authored-by", from:, to: args.to),
|
|
||||||
review: count_reviews(repo_full_name, person, from:, to: args.to),
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
data
|
data
|
||||||
@ -202,43 +266,17 @@ module Homebrew
|
|||||||
|
|
||||||
sig { params(results: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, Integer]) }
|
sig { params(results: T::Hash[Symbol, T.untyped]).returns(T::Hash[Symbol, Integer]) }
|
||||||
def total(results)
|
def total(results)
|
||||||
totals = { author: 0, committer: 0, coauthor: 0, review: 0 }
|
totals = {}
|
||||||
|
|
||||||
results.each_value do |counts|
|
results.each_value do |counts|
|
||||||
counts.each do |kind, count|
|
counts.each do |kind, count|
|
||||||
|
totals[kind] ||= 0
|
||||||
totals[kind] += count
|
totals[kind] += count
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
totals
|
totals
|
||||||
end
|
end
|
||||||
|
|
||||||
sig {
|
|
||||||
params(repo_path: Pathname, person: String, trailer: String, from: T.nilable(String),
|
|
||||||
to: T.nilable(String)).returns(Integer)
|
|
||||||
}
|
|
||||||
def git_log_trailers_cmd(repo_path, person, trailer, from:, to:)
|
|
||||||
cmd = ["git", "-C", repo_path, "log", "--oneline"]
|
|
||||||
cmd << "--format='%(trailers:key=#{trailer}:)'"
|
|
||||||
cmd << "--before=#{to}" if to
|
|
||||||
cmd << "--after=#{from}" if from
|
|
||||||
|
|
||||||
Utils.safe_popen_read(*cmd).lines.count { |l| l.include?(person) }
|
|
||||||
end
|
|
||||||
|
|
||||||
sig {
|
|
||||||
params(repo_full_name: String, person: String, from: T.nilable(String),
|
|
||||||
to: T.nilable(String)).returns(Integer)
|
|
||||||
}
|
|
||||||
def count_reviews(repo_full_name, person, from:, to:)
|
|
||||||
require "utils/github"
|
|
||||||
GitHub.count_issues("", is: "pr", repo: repo_full_name, reviewed_by: person, review: "approved", from:, to:)
|
|
||||||
rescue GitHub::API::ValidationFailedError
|
|
||||||
if args.verbose?
|
|
||||||
onoe "Couldn't search GitHub for PRs by #{person}. Their profile might be private. Defaulting to 0."
|
|
||||||
end
|
|
||||||
0 # Users who have made their contributions private are not searchable to determine counts.
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -41,9 +41,9 @@ module Homebrew
|
|||||||
switch "--autobump",
|
switch "--autobump",
|
||||||
description: "Include packages that are autobumped by BrewTestBot. By default these are skipped."
|
description: "Include packages that are autobumped by BrewTestBot. By default these are skipped."
|
||||||
|
|
||||||
conflicts "--debug", "--json"
|
conflicts "--tap", "--installed", "--eval-all"
|
||||||
conflicts "--tap=", "--eval-all", "--installed"
|
conflicts "--json", "--debug"
|
||||||
conflicts "--cask", "--formula"
|
conflicts "--formula", "--cask"
|
||||||
conflicts "--formula", "--extract-plist"
|
conflicts "--formula", "--extract-plist"
|
||||||
|
|
||||||
named_args [:formula, :cask], without_api: true
|
named_args [:formula, :cask], without_api: true
|
||||||
@ -78,9 +78,15 @@ module Homebrew
|
|||||||
formulae + casks
|
formulae + casks
|
||||||
elsif File.exist?(watchlist_path)
|
elsif File.exist?(watchlist_path)
|
||||||
begin
|
begin
|
||||||
|
# This removes blank lines, comment lines, and trailing comments
|
||||||
names = Pathname.new(watchlist_path).read.lines
|
names = Pathname.new(watchlist_path).read.lines
|
||||||
.reject { |line| line.start_with?("#") || line.blank? }
|
.filter_map do |line|
|
||||||
.map(&:strip)
|
comment_index = line.index("#")
|
||||||
|
next if comment_index&.zero?
|
||||||
|
|
||||||
|
line = line[0...comment_index] if comment_index
|
||||||
|
line&.strip.presence
|
||||||
|
end
|
||||||
|
|
||||||
named_args = CLI::NamedArgs.new(*names, parent: args)
|
named_args = CLI::NamedArgs.new(*names, parent: args)
|
||||||
named_args.to_formulae_and_casks(ignore_unavailable: true)
|
named_args.to_formulae_and_casks(ignore_unavailable: true)
|
||||||
|
|||||||
@ -208,8 +208,7 @@ module Homebrew
|
|||||||
if pull_request
|
if pull_request
|
||||||
# This is a tap pull request and approving reviewers should also sign-off.
|
# This is a tap pull request and approving reviewers should also sign-off.
|
||||||
tap = T.must(Tap.from_path(git_repo.pathname))
|
tap = T.must(Tap.from_path(git_repo.pathname))
|
||||||
review_trailers = GitHub.approved_reviews(tap.user, tap.full_name.split("/").last,
|
review_trailers = GitHub.repository_approved_reviews(tap.user, tap.full_repository, pull_request).map do |r|
|
||||||
pull_request).map do |r|
|
|
||||||
"Signed-off-by: #{r["name"]} <#{r["email"]}>"
|
"Signed-off-by: #{r["name"]} <#{r["email"]}>"
|
||||||
end
|
end
|
||||||
trailers = trailers.lines.concat(review_trailers).map(&:strip).uniq.join("\n")
|
trailers = trailers.lines.concat(review_trailers).map(&:strip).uniq.join("\n")
|
||||||
|
|||||||
@ -114,9 +114,9 @@ class DevelopmentTools
|
|||||||
|
|
||||||
# Get the GCC version.
|
# Get the GCC version.
|
||||||
#
|
#
|
||||||
# @api internal
|
# @api public
|
||||||
sig { params(cc: String).returns(Version) }
|
sig { params(cc: String).returns(Version) }
|
||||||
def gcc_version(cc)
|
def gcc_version(cc = host_gcc_path.to_s)
|
||||||
(@gcc_version ||= T.let({}, T.nilable(T::Hash[String, Version]))).fetch(cc) do
|
(@gcc_version ||= T.let({}, T.nilable(T::Hash[String, Version]))).fetch(cc) do
|
||||||
path = HOMEBREW_PREFIX/"opt/#{CompilerSelector.preferred_gcc}/bin"/cc
|
path = HOMEBREW_PREFIX/"opt/#{CompilerSelector.preferred_gcc}/bin"/cc
|
||||||
path = locate(cc) unless path.exist?
|
path = locate(cc) unless path.exist?
|
||||||
|
|||||||
@ -579,7 +579,7 @@ class UnbottledError < RuntimeError
|
|||||||
require "utils"
|
require "utils"
|
||||||
|
|
||||||
msg = <<~EOS
|
msg = <<~EOS
|
||||||
The following #{Utils.pluralize("formula", formulae.count, plural: "e")} cannot be installed from #{Utils.pluralize("bottle", formulae.count)} and must be
|
The following #{Utils.pluralize("formula", formulae.count)} cannot be installed from #{Utils.pluralize("bottle", formulae.count)} and must be
|
||||||
built from source.
|
built from source.
|
||||||
#{formulae.to_sentence}
|
#{formulae.to_sentence}
|
||||||
EOS
|
EOS
|
||||||
|
|||||||
4
Library/Homebrew/extend/os/cask/artifact/relocated.rb
Normal file
4
Library/Homebrew/extend/os/cask/artifact/relocated.rb
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# typed: strict
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "extend/os/linux/cask/artifact/relocated" if OS.linux?
|
||||||
23
Library/Homebrew/extend/os/linux/cask/artifact/relocated.rb
Normal file
23
Library/Homebrew/extend/os/linux/cask/artifact/relocated.rb
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# typed: strict
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module OS
|
||||||
|
module Linux
|
||||||
|
module Cask
|
||||||
|
module Artifact
|
||||||
|
module Relocated
|
||||||
|
extend T::Helpers
|
||||||
|
|
||||||
|
requires_ancestor { ::Cask::Artifact::Relocated }
|
||||||
|
|
||||||
|
sig { params(file: Pathname, altname: Pathname, command: T.class_of(SystemCommand)).returns(T.nilable(SystemCommand::Result)) }
|
||||||
|
def add_altname_metadata(file, altname, command:)
|
||||||
|
# no-op on Linux: /usr/bin/xattr for setting extended attributes is not available there.
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Cask::Artifact::Relocated.prepend(OS::Linux::Cask::Artifact::Relocated)
|
||||||
@ -42,14 +42,14 @@ module OS
|
|||||||
@needs_libc_formula ||= OS::Linux::Glibc.below_ci_version?
|
@needs_libc_formula ||= OS::Linux::Glibc.below_ci_version?
|
||||||
end
|
end
|
||||||
|
|
||||||
# Keep this method around for now to make it easier to add this functionality later.
|
|
||||||
# rubocop:disable Lint/UselessMethodDefinition
|
|
||||||
sig { returns(Pathname) }
|
sig { returns(Pathname) }
|
||||||
def host_gcc_path
|
def host_gcc_path
|
||||||
# TODO: override this if/when we to pick the GCC based on e.g. the Ubuntu version.
|
# Prioritise versioned path if installed
|
||||||
|
path = Pathname.new("/usr/bin/#{OS::LINUX_PREFERRED_GCC_COMPILER_FORMULA.tr("@", "-")}")
|
||||||
|
return path if path.exist?
|
||||||
|
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
# rubocop:enable Lint/UselessMethodDefinition
|
|
||||||
|
|
||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
def needs_compiler_formula?
|
def needs_compiler_formula?
|
||||||
@ -60,12 +60,7 @@ module OS
|
|||||||
# Undocumented environment variable to make it easier to test compiler
|
# Undocumented environment variable to make it easier to test compiler
|
||||||
# formula automatic installation.
|
# formula automatic installation.
|
||||||
@needs_compiler_formula = true if ENV["HOMEBREW_FORCE_COMPILER_FORMULA"]
|
@needs_compiler_formula = true if ENV["HOMEBREW_FORCE_COMPILER_FORMULA"]
|
||||||
|
@needs_compiler_formula ||= OS::Linux::Libstdcxx.below_ci_version?
|
||||||
@needs_compiler_formula ||= if host_gcc_path.exist?
|
|
||||||
::DevelopmentTools.gcc_version(host_gcc_path.to_s) < OS::LINUX_GCC_CI_VERSION
|
|
||||||
else
|
|
||||||
true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(T::Hash[String, T.nilable(String)]) }
|
sig { returns(T::Hash[String, T.nilable(String)]) }
|
||||||
|
|||||||
@ -40,6 +40,8 @@ module OS
|
|||||||
self["HOMEBREW_RPATH_PATHS"] = determine_rpath_paths(@formula)
|
self["HOMEBREW_RPATH_PATHS"] = determine_rpath_paths(@formula)
|
||||||
m4_path_deps = ["libtool", "bison"]
|
m4_path_deps = ["libtool", "bison"]
|
||||||
self["M4"] = "#{HOMEBREW_PREFIX}/opt/m4/bin/m4" if deps.any? { m4_path_deps.include?(_1.name) }
|
self["M4"] = "#{HOMEBREW_PREFIX}/opt/m4/bin/m4" if deps.any? { m4_path_deps.include?(_1.name) }
|
||||||
|
# Build jemalloc-sys rust crate on ARM64/AArch64 with support for page sizes up to 64K.
|
||||||
|
self["JEMALLOC_SYS_WITH_LG_PAGE"] = "16" if ::Hardware::CPU.arch == :arm64
|
||||||
|
|
||||||
# Pointer authentication and BTI are hardening techniques most distros
|
# Pointer authentication and BTI are hardening techniques most distros
|
||||||
# use by default on their packages. arm64 Linux we're packaging
|
# use by default on their packages. arm64 Linux we're packaging
|
||||||
|
|||||||
@ -1,36 +1,24 @@
|
|||||||
# typed: strict
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "os/linux/ld"
|
||||||
|
require "os/linux/libstdcxx"
|
||||||
require "utils/output"
|
require "utils/output"
|
||||||
|
|
||||||
module OS
|
module OS
|
||||||
module Linux
|
module Linux
|
||||||
module Install
|
module Install
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
# This is a list of known paths to the host dynamic linker on Linux if
|
|
||||||
# the host glibc is new enough. The symlink_ld_so method will fail if
|
|
||||||
# the host linker cannot be found in this list.
|
|
||||||
DYNAMIC_LINKERS = %w[
|
|
||||||
/lib64/ld-linux-x86-64.so.2
|
|
||||||
/lib64/ld64.so.2
|
|
||||||
/lib/ld-linux.so.3
|
|
||||||
/lib/ld-linux.so.2
|
|
||||||
/lib/ld-linux-aarch64.so.1
|
|
||||||
/lib/ld-linux-armhf.so.3
|
|
||||||
/system/bin/linker64
|
|
||||||
/system/bin/linker
|
|
||||||
].freeze
|
|
||||||
|
|
||||||
# We link GCC runtime libraries that are not specifically used for Fortran,
|
# 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
|
# which are linked by the GCC formula. We only use the versioned shared libraries
|
||||||
# as the other shared and static libraries are only used at build time where
|
# as the other shared and static libraries are only used at build time where
|
||||||
# GCC can find its own libraries.
|
# GCC can find its own libraries.
|
||||||
GCC_RUNTIME_LIBS = %w[
|
GCC_RUNTIME_LIBS = T.let(%W[
|
||||||
libatomic.so.1
|
libatomic.so.1
|
||||||
libgcc_s.so.1
|
libgcc_s.so.1
|
||||||
libgomp.so.1
|
libgomp.so.1
|
||||||
libstdc++.so.6
|
#{OS::Linux::Libstdcxx::SONAME}
|
||||||
].freeze
|
].freeze, T::Array[String])
|
||||||
|
|
||||||
sig { params(all_fatal: T::Boolean).void }
|
sig { params(all_fatal: T::Boolean).void }
|
||||||
def perform_preinstall_checks(all_fatal: false)
|
def perform_preinstall_checks(all_fatal: false)
|
||||||
@ -67,7 +55,7 @@ module OS
|
|||||||
|
|
||||||
ld_so = HOMEBREW_PREFIX/"opt/glibc/bin/ld.so"
|
ld_so = HOMEBREW_PREFIX/"opt/glibc/bin/ld.so"
|
||||||
unless ld_so.readable?
|
unless ld_so.readable?
|
||||||
ld_so = DYNAMIC_LINKERS.find { |s| File.executable? s }
|
ld_so = OS::Linux::Ld.system_ld_so
|
||||||
if ld_so.blank?
|
if ld_so.blank?
|
||||||
::Kernel.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?
|
||||||
|
|
||||||
|
|||||||
@ -2,12 +2,13 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "compilers"
|
require "compilers"
|
||||||
|
require "os/linux/libstdcxx"
|
||||||
|
|
||||||
module OS
|
module OS
|
||||||
module Linux
|
module Linux
|
||||||
module LinkageChecker
|
module LinkageChecker
|
||||||
# Libraries provided by glibc and gcc.
|
# Libraries provided by glibc and gcc.
|
||||||
SYSTEM_LIBRARY_ALLOWLIST = %w[
|
SYSTEM_LIBRARY_ALLOWLIST = %W[
|
||||||
ld-linux-x86-64.so.2
|
ld-linux-x86-64.so.2
|
||||||
ld-linux-aarch64.so.1
|
ld-linux-aarch64.so.1
|
||||||
libanl.so.1
|
libanl.so.1
|
||||||
@ -24,7 +25,7 @@ module OS
|
|||||||
libutil.so.1
|
libutil.so.1
|
||||||
libgcc_s.so.1
|
libgcc_s.so.1
|
||||||
libgomp.so.1
|
libgomp.so.1
|
||||||
libstdc++.so.6
|
#{OS::Linux::Libstdcxx::SONAME}
|
||||||
libquadmath.so.0
|
libquadmath.so.0
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
require "compilers"
|
require "compilers"
|
||||||
require "os/linux/glibc"
|
require "os/linux/glibc"
|
||||||
|
require "os/linux/libstdcxx"
|
||||||
require "system_command"
|
require "system_command"
|
||||||
|
|
||||||
module OS
|
module OS
|
||||||
@ -20,6 +21,13 @@ module OS
|
|||||||
version
|
version
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def host_libstdcxx_version
|
||||||
|
version = OS::Linux::Libstdcxx.system_version
|
||||||
|
return "N/A" if version.null?
|
||||||
|
|
||||||
|
version
|
||||||
|
end
|
||||||
|
|
||||||
def host_gcc_version
|
def host_gcc_version
|
||||||
gcc = ::DevelopmentTools.host_gcc_path
|
gcc = ::DevelopmentTools.host_gcc_path
|
||||||
return "N/A" unless gcc.executable?
|
return "N/A" unless gcc.executable?
|
||||||
@ -36,7 +44,7 @@ module OS
|
|||||||
end
|
end
|
||||||
|
|
||||||
def host_ruby_version
|
def host_ruby_version
|
||||||
out, _, status = system_command(HOST_RUBY_PATH, args: ["-e", "puts RUBY_VERSION"], print_stderr: false)
|
out, _, status = system_command(HOST_RUBY_PATH, args: ["-e", "puts RUBY_VERSION"], print_stderr: false).to_a
|
||||||
return "N/A" unless status.success?
|
return "N/A" unless status.success?
|
||||||
|
|
||||||
out
|
out
|
||||||
@ -49,6 +57,7 @@ module OS
|
|||||||
out.puts "OS: #{OS::Linux.os_version}"
|
out.puts "OS: #{OS::Linux.os_version}"
|
||||||
out.puts "WSL: #{OS::Linux.wsl_version}" if OS::Linux.wsl?
|
out.puts "WSL: #{OS::Linux.wsl_version}" if OS::Linux.wsl?
|
||||||
out.puts "Host glibc: #{host_glibc_version}"
|
out.puts "Host glibc: #{host_glibc_version}"
|
||||||
|
out.puts "Host libstdc++: #{host_libstdcxx_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
|
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|
|
["glibc", ::CompilerSelector.preferred_gcc, OS::LINUX_PREFERRED_GCC_RUNTIME_FORMULA, "xorg"].each do |f|
|
||||||
|
|||||||
@ -422,11 +422,13 @@ class Pathname
|
|||||||
|
|
||||||
sig { returns(T::Array[String]) }
|
sig { returns(T::Array[String]) }
|
||||||
def zipinfo
|
def zipinfo
|
||||||
@zipinfo ||= T.let(nil, T.nilable(String))
|
@zipinfo ||= T.let(
|
||||||
@zipinfo ||= system_command("zipinfo", args: ["-1", self], print_stderr: false)
|
system_command("zipinfo", args: ["-1", self], print_stderr: false)
|
||||||
.stdout
|
.stdout
|
||||||
.encode(Encoding::UTF_8, invalid: :replace)
|
.encode(Encoding::UTF_8, invalid: :replace)
|
||||||
.split("\n")
|
.split("\n"),
|
||||||
|
T.nilable(T::Array[String]),
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@ -749,7 +749,7 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
|
|
||||||
def audit_specs
|
def audit_specs
|
||||||
problem "HEAD-only (no stable download)" if head_only?(formula)
|
problem "HEAD-only (no stable download)" if head_only?(formula) && @core_tap
|
||||||
|
|
||||||
%w[Stable HEAD].each do |name|
|
%w[Stable HEAD].each do |name|
|
||||||
spec_name = name.downcase.to_sym
|
spec_name = name.downcase.to_sym
|
||||||
|
|||||||
@ -609,8 +609,8 @@ on_request: installed_on_request?, options:)
|
|||||||
clean
|
clean
|
||||||
|
|
||||||
# Store the formula used to build the keg in the keg.
|
# Store the formula used to build the keg in the keg.
|
||||||
formula_contents = if formula.local_bottle_path
|
formula_contents = if (local_bottle_path = formula.local_bottle_path)
|
||||||
Utils::Bottles.formula_contents formula.local_bottle_path, name: formula.name
|
Utils::Bottles.formula_contents local_bottle_path, name: formula.name
|
||||||
else
|
else
|
||||||
formula.path.read
|
formula.path.read
|
||||||
end
|
end
|
||||||
@ -1156,17 +1156,6 @@ on_request: installed_on_request?, options:)
|
|||||||
def link(keg)
|
def link(keg)
|
||||||
Formula.clear_cache
|
Formula.clear_cache
|
||||||
|
|
||||||
unless link_keg
|
|
||||||
begin
|
|
||||||
keg.optlink(verbose: verbose?, overwrite: overwrite?)
|
|
||||||
rescue Keg::LinkError => e
|
|
||||||
ofail "Failed to create #{formula.opt_prefix}"
|
|
||||||
puts "Things that depend on #{formula.full_name} will probably not build."
|
|
||||||
puts e
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
cask_installed_with_formula_name = begin
|
cask_installed_with_formula_name = begin
|
||||||
Cask::CaskLoader.load(formula.name, warn: false).installed?
|
Cask::CaskLoader.load(formula.name, warn: false).installed?
|
||||||
rescue Cask::CaskUnavailableError, Cask::CaskInvalidError
|
rescue Cask::CaskUnavailableError, Cask::CaskInvalidError
|
||||||
@ -1175,6 +1164,17 @@ on_request: installed_on_request?, options:)
|
|||||||
|
|
||||||
if cask_installed_with_formula_name
|
if cask_installed_with_formula_name
|
||||||
ohai "#{formula.name} cask is installed, skipping link."
|
ohai "#{formula.name} cask is installed, skipping link."
|
||||||
|
@link_keg = false
|
||||||
|
end
|
||||||
|
|
||||||
|
unless link_keg
|
||||||
|
begin
|
||||||
|
keg.optlink(verbose: verbose?, overwrite: overwrite?)
|
||||||
|
rescue Keg::LinkError => e
|
||||||
|
ofail "Failed to create #{formula.opt_prefix}"
|
||||||
|
puts "Things that depend on #{formula.full_name} will probably not build."
|
||||||
|
puts e
|
||||||
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ require "tab"
|
|||||||
require "utils"
|
require "utils"
|
||||||
require "utils/bottles"
|
require "utils/bottles"
|
||||||
require "utils/output"
|
require "utils/output"
|
||||||
|
require "utils/path"
|
||||||
require "service"
|
require "service"
|
||||||
require "utils/curl"
|
require "utils/curl"
|
||||||
require "deprecate_disable"
|
require "deprecate_disable"
|
||||||
@ -727,29 +728,7 @@ module Formulary
|
|||||||
end
|
end
|
||||||
|
|
||||||
return unless path.expand_path.exist?
|
return unless path.expand_path.exist?
|
||||||
|
return unless ::Utils::Path.loadable_package_path?(path, :formula)
|
||||||
if Homebrew::EnvConfig.forbid_packages_from_paths?
|
|
||||||
path_realpath = path.realpath.to_s
|
|
||||||
path_string = path.to_s
|
|
||||||
if (path_realpath.end_with?(".rb") || path_string.end_with?(".rb")) &&
|
|
||||||
!path_realpath.start_with?("#{HOMEBREW_CELLAR}/", "#{HOMEBREW_LIBRARY}/Taps/") &&
|
|
||||||
!path_string.start_with?("#{HOMEBREW_CELLAR}/", "#{HOMEBREW_LIBRARY}/Taps/")
|
|
||||||
if path_string.include?("./") || path_string.end_with?(".rb") || path_string.count("/") != 2
|
|
||||||
raise <<~WARNING
|
|
||||||
Homebrew requires formulae to be in a tap, rejecting:
|
|
||||||
#{path_string} (#{path_realpath})
|
|
||||||
|
|
||||||
To create a tap, run e.g.
|
|
||||||
brew tap-new <user|org>/<repository>
|
|
||||||
To create a formula in a tap run e.g.
|
|
||||||
brew create <url> --tap=<user|org>/<repository>
|
|
||||||
WARNING
|
|
||||||
elsif path_string.count("/") == 2
|
|
||||||
# Looks like a tap, let's quietly return but not error.
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if (tap = Tap.from_path(path))
|
if (tap = Tap.from_path(path))
|
||||||
# Only treat symlinks in taps as aliases.
|
# Only treat symlinks in taps as aliases.
|
||||||
|
|||||||
@ -9,8 +9,8 @@ class GitHubRunnerMatrix
|
|||||||
# on homebrew/core and tag the first commit with a bottle e.g.
|
# on homebrew/core and tag the first commit with a bottle e.g.
|
||||||
# `git tag 15-sequoia f42c4a659e4da887fc714f8f41cc26794a4bb320`
|
# `git tag 15-sequoia f42c4a659e4da887fc714f8f41cc26794a4bb320`
|
||||||
# to allow people to jump to specific commits based on their macOS version.
|
# to allow people to jump to specific commits based on their macOS version.
|
||||||
NEWEST_HOMEBREW_CORE_MACOS_RUNNER = :sequoia
|
NEWEST_HOMEBREW_CORE_MACOS_RUNNER = :tahoe
|
||||||
OLDEST_HOMEBREW_CORE_MACOS_RUNNER = :ventura
|
OLDEST_HOMEBREW_CORE_MACOS_RUNNER = :sonoma
|
||||||
NEWEST_HOMEBREW_CORE_INTEL_MACOS_RUNNER = :sonoma
|
NEWEST_HOMEBREW_CORE_INTEL_MACOS_RUNNER = :sonoma
|
||||||
|
|
||||||
RunnerSpec = T.type_alias { T.any(LinuxRunnerSpec, MacOSRunnerSpec) }
|
RunnerSpec = T.type_alias { T.any(LinuxRunnerSpec, MacOSRunnerSpec) }
|
||||||
|
|||||||
@ -405,8 +405,7 @@ module Homebrew
|
|||||||
return if formulae_names_to_install.empty?
|
return if formulae_names_to_install.empty?
|
||||||
|
|
||||||
if dry_run
|
if dry_run
|
||||||
ohai "Would install #{Utils.pluralize("formula", formulae_names_to_install.count,
|
ohai "Would install #{Utils.pluralize("formula", formulae_names_to_install.count, include_count: true)}:"
|
||||||
plural: "e", include_count: true)}:"
|
|
||||||
puts formulae_names_to_install.join(" ")
|
puts formulae_names_to_install.join(" ")
|
||||||
|
|
||||||
formula_installers.each do |fi|
|
formula_installers.each do |fi|
|
||||||
@ -429,8 +428,8 @@ module Homebrew
|
|||||||
def print_dry_run_dependencies(formula, dependencies)
|
def print_dry_run_dependencies(formula, dependencies)
|
||||||
return if dependencies.empty?
|
return if dependencies.empty?
|
||||||
|
|
||||||
ohai "Would install #{Utils.pluralize("dependenc", dependencies.count, plural: "ies", singular: "y",
|
ohai "Would install #{Utils.pluralize("dependency", dependencies.count, include_count: true)} " \
|
||||||
include_count: true)} for #{formula.name}:"
|
"for #{formula.name}:"
|
||||||
formula_names = dependencies.map { |(dep, _options)| yield dep.to_formula }
|
formula_names = dependencies.map { |(dep, _options)| yield dep.to_formula }
|
||||||
puts formula_names.join(" ")
|
puts formula_names.join(" ")
|
||||||
end
|
end
|
||||||
@ -446,7 +445,7 @@ module Homebrew
|
|||||||
|
|
||||||
sizes = compute_total_sizes(formulae, debug: args.debug?)
|
sizes = compute_total_sizes(formulae, debug: args.debug?)
|
||||||
|
|
||||||
puts "#{::Utils.pluralize("Formula", formulae.count, plural: "e")} \
|
puts "#{::Utils.pluralize("Formula", formulae.count)} \
|
||||||
(#{formulae.count}): #{formulae.join(", ")}\n\n"
|
(#{formulae.count}): #{formulae.join(", ")}\n\n"
|
||||||
puts "Download Size: #{disk_usage_readable(sizes.fetch(:download))}"
|
puts "Download Size: #{disk_usage_readable(sizes.fetch(:download))}"
|
||||||
puts "Install Size: #{disk_usage_readable(sizes.fetch(:installed))}"
|
puts "Install Size: #{disk_usage_readable(sizes.fetch(:installed))}"
|
||||||
|
|||||||
@ -113,6 +113,18 @@ class Keg
|
|||||||
old: "/usr/local/var/log/#{name}",
|
old: "/usr/local/var/log/#{name}",
|
||||||
new: "#{PREFIX_PLACEHOLDER}/var/log/#{name}",
|
new: "#{PREFIX_PLACEHOLDER}/var/log/#{name}",
|
||||||
},
|
},
|
||||||
|
var_run_name: {
|
||||||
|
old: "/usr/local/var/run/#{name}",
|
||||||
|
new: "#{PREFIX_PLACEHOLDER}/var/run/#{name}",
|
||||||
|
},
|
||||||
|
var_db_name: {
|
||||||
|
old: "/usr/local/var/db/#{name}",
|
||||||
|
new: "#{PREFIX_PLACEHOLDER}/var/db/#{name}",
|
||||||
|
},
|
||||||
|
share_name: {
|
||||||
|
old: "/usr/local/share/#{name}",
|
||||||
|
new: "#{PREFIX_PLACEHOLDER}/share/#{name}",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -198,8 +198,8 @@ module Homebrew
|
|||||||
FORMULA_CHECKS = T.let([
|
FORMULA_CHECKS = T.let([
|
||||||
:package_or_resource_skip,
|
:package_or_resource_skip,
|
||||||
:formula_head_only,
|
:formula_head_only,
|
||||||
:formula_deprecated,
|
|
||||||
:formula_disabled,
|
:formula_disabled,
|
||||||
|
:formula_deprecated,
|
||||||
:formula_versioned,
|
:formula_versioned,
|
||||||
].freeze, T::Array[Symbol])
|
].freeze, T::Array[Symbol])
|
||||||
private_constant :FORMULA_CHECKS
|
private_constant :FORMULA_CHECKS
|
||||||
@ -207,8 +207,8 @@ module Homebrew
|
|||||||
# Skip conditions for casks.
|
# Skip conditions for casks.
|
||||||
CASK_CHECKS = T.let([
|
CASK_CHECKS = T.let([
|
||||||
:package_or_resource_skip,
|
:package_or_resource_skip,
|
||||||
:cask_deprecated,
|
|
||||||
:cask_disabled,
|
:cask_disabled,
|
||||||
|
:cask_deprecated,
|
||||||
:cask_extract_plist,
|
:cask_extract_plist,
|
||||||
:cask_version_latest,
|
:cask_version_latest,
|
||||||
:cask_url_unversioned,
|
:cask_url_unversioned,
|
||||||
|
|||||||
@ -129,9 +129,9 @@ module Homebrew
|
|||||||
print_stderr: false,
|
print_stderr: false,
|
||||||
debug: false,
|
debug: false,
|
||||||
verbose: false,
|
verbose: false,
|
||||||
)
|
).to_a
|
||||||
|
|
||||||
tags_data = { tags: [] }
|
tags_data = { tags: T.let([], T::Array[String]) }
|
||||||
tags_data[:messages] = stderr.split("\n") if stderr.present?
|
tags_data[:messages] = stderr.split("\n") if stderr.present?
|
||||||
return tags_data if stdout.blank?
|
return tags_data if stdout.blank?
|
||||||
|
|
||||||
|
|||||||
@ -154,12 +154,6 @@ can take several different forms:
|
|||||||
You can still access these formulae by using a special syntax, e.g.
|
You can still access these formulae by using a special syntax, e.g.
|
||||||
`homebrew/dupes/vim` or `homebrew/versions/node4`.
|
`homebrew/dupes/vim` or `homebrew/versions/node4`.
|
||||||
|
|
||||||
* An arbitrary file:
|
|
||||||
Homebrew can install formulae from a local path. It can point to either a
|
|
||||||
formula file or a bottle.
|
|
||||||
Prefix relative paths with `./` to prevent them from being interpreted as a
|
|
||||||
formula or tap name.
|
|
||||||
|
|
||||||
## SPECIFYING CASKS
|
## SPECIFYING CASKS
|
||||||
|
|
||||||
Many Homebrew Cask commands accept one or more <cask> arguments. These can be
|
Many Homebrew Cask commands accept one or more <cask> arguments. These can be
|
||||||
|
|||||||
@ -23,6 +23,7 @@ DEPRECATED_OFFICIAL_TAPS = %w[
|
|||||||
devel-only
|
devel-only
|
||||||
dupes
|
dupes
|
||||||
emacs
|
emacs
|
||||||
|
formula-analytics
|
||||||
fuse
|
fuse
|
||||||
games
|
games
|
||||||
gui
|
gui
|
||||||
|
|||||||
@ -50,6 +50,7 @@ module OS
|
|||||||
LINUX_GLIBC_CI_VERSION = "2.35"
|
LINUX_GLIBC_CI_VERSION = "2.35"
|
||||||
LINUX_GLIBC_NEXT_CI_VERSION = "2.39"
|
LINUX_GLIBC_NEXT_CI_VERSION = "2.39"
|
||||||
LINUX_GCC_CI_VERSION = "11.0"
|
LINUX_GCC_CI_VERSION = "11.0"
|
||||||
|
LINUX_LIBSTDCXX_CI_VERSION = "6.0.30" # https://packages.ubuntu.com/jammy/libstdc++6
|
||||||
LINUX_PREFERRED_GCC_COMPILER_FORMULA = "gcc@11" # https://packages.ubuntu.com/jammy/gcc
|
LINUX_PREFERRED_GCC_COMPILER_FORMULA = "gcc@11" # https://packages.ubuntu.com/jammy/gcc
|
||||||
LINUX_PREFERRED_GCC_RUNTIME_FORMULA = "gcc"
|
LINUX_PREFERRED_GCC_RUNTIME_FORMULA = "gcc"
|
||||||
|
|
||||||
|
|||||||
@ -29,8 +29,6 @@ module OS
|
|||||||
else
|
else
|
||||||
"#{description} (#{codename})"
|
"#{description} (#{codename})"
|
||||||
end
|
end
|
||||||
elsif (redhat_release = Pathname.new("/etc/redhat-release")).readable?
|
|
||||||
redhat_release.read.chomp
|
|
||||||
elsif ::OS_VERSION.present?
|
elsif ::OS_VERSION.present?
|
||||||
::OS_VERSION
|
::OS_VERSION
|
||||||
else
|
else
|
||||||
|
|||||||
@ -5,37 +5,69 @@ module OS
|
|||||||
module Linux
|
module Linux
|
||||||
# Helper functions for querying `ld` information.
|
# Helper functions for querying `ld` information.
|
||||||
module Ld
|
module Ld
|
||||||
sig { returns(String) }
|
# This is a list of known paths to the host dynamic linker on Linux if
|
||||||
def self.brewed_ld_so_diagnostics
|
# the host glibc is new enough. Brew will fail to create a symlink for
|
||||||
@brewed_ld_so_diagnostics ||= T.let({}, T.nilable(T::Hash[Pathname, String]))
|
# ld.so if the host linker cannot be found in this list.
|
||||||
|
DYNAMIC_LINKERS = %w[
|
||||||
|
/lib64/ld-linux-x86-64.so.2
|
||||||
|
/lib64/ld64.so.2
|
||||||
|
/lib/ld-linux.so.3
|
||||||
|
/lib/ld-linux.so.2
|
||||||
|
/lib/ld-linux-aarch64.so.1
|
||||||
|
/lib/ld-linux-armhf.so.3
|
||||||
|
/system/bin/linker64
|
||||||
|
/system/bin/linker
|
||||||
|
].freeze
|
||||||
|
|
||||||
brewed_ld_so = HOMEBREW_PREFIX/"lib/ld.so"
|
# The path to the system's dynamic linker or `nil` if not found
|
||||||
return "" unless brewed_ld_so.exist?
|
sig { returns(T.nilable(Pathname)) }
|
||||||
|
def self.system_ld_so
|
||||||
|
@system_ld_so ||= T.let(nil, T.nilable(Pathname))
|
||||||
|
@system_ld_so ||= begin
|
||||||
|
linker = DYNAMIC_LINKERS.find { |s| File.executable? s }
|
||||||
|
Pathname(linker) if linker
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
brewed_ld_so_target = brewed_ld_so.readlink
|
sig { params(brewed: T::Boolean).returns(String) }
|
||||||
@brewed_ld_so_diagnostics[brewed_ld_so_target] ||= begin
|
def self.ld_so_diagnostics(brewed: true)
|
||||||
ld_so_output = Utils.popen_read(brewed_ld_so, "--list-diagnostics")
|
@ld_so_diagnostics ||= T.let({}, T.nilable(T::Hash[Pathname, String]))
|
||||||
|
|
||||||
|
ld_so_target = if brewed
|
||||||
|
ld_so = HOMEBREW_PREFIX/"lib/ld.so"
|
||||||
|
return "" unless ld_so.exist?
|
||||||
|
|
||||||
|
ld_so.readlink
|
||||||
|
else
|
||||||
|
ld_so = system_ld_so
|
||||||
|
return "" unless ld_so&.exist?
|
||||||
|
|
||||||
|
ld_so
|
||||||
|
end
|
||||||
|
|
||||||
|
@ld_so_diagnostics[ld_so_target] ||= begin
|
||||||
|
ld_so_output = Utils.popen_read(ld_so, "--list-diagnostics")
|
||||||
ld_so_output if $CHILD_STATUS.success?
|
ld_so_output if $CHILD_STATUS.success?
|
||||||
end
|
end
|
||||||
|
|
||||||
@brewed_ld_so_diagnostics[brewed_ld_so_target].to_s
|
@ld_so_diagnostics[ld_so_target].to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(String) }
|
sig { params(brewed: T::Boolean).returns(String) }
|
||||||
def self.sysconfdir
|
def self.sysconfdir(brewed: true)
|
||||||
fallback_sysconfdir = "/etc"
|
fallback_sysconfdir = "/etc"
|
||||||
|
|
||||||
match = brewed_ld_so_diagnostics.match(/path.sysconfdir="(.+)"/)
|
match = ld_so_diagnostics(brewed:).match(/path.sysconfdir="(.+)"/)
|
||||||
return fallback_sysconfdir unless match
|
return fallback_sysconfdir unless match
|
||||||
|
|
||||||
match.captures.compact.first || fallback_sysconfdir
|
match.captures.compact.first || fallback_sysconfdir
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(T::Array[String]) }
|
sig { params(brewed: T::Boolean).returns(T::Array[String]) }
|
||||||
def self.system_dirs
|
def self.system_dirs(brewed: true)
|
||||||
dirs = []
|
dirs = []
|
||||||
|
|
||||||
brewed_ld_so_diagnostics.split("\n").each do |line|
|
ld_so_diagnostics(brewed:).split("\n").each do |line|
|
||||||
match = line.match(/path.system_dirs\[0x.*\]="(.*)"/)
|
match = line.match(/path.system_dirs\[0x.*\]="(.*)"/)
|
||||||
next unless match
|
next unless match
|
||||||
|
|
||||||
@ -45,9 +77,9 @@ module OS
|
|||||||
dirs
|
dirs
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(conf_path: T.any(Pathname, String)).returns(T::Array[String]) }
|
sig { params(conf_path: T.any(Pathname, String), brewed: T::Boolean).returns(T::Array[String]) }
|
||||||
def self.library_paths(conf_path = Pathname(sysconfdir)/"ld.so.conf")
|
def self.library_paths(conf_path = "ld.so.conf", brewed: true)
|
||||||
conf_file = Pathname(conf_path)
|
conf_file = Pathname(sysconfdir(brewed:))/conf_path
|
||||||
return [] unless conf_file.exist?
|
return [] unless conf_file.exist?
|
||||||
return [] unless conf_file.file?
|
return [] unless conf_file.file?
|
||||||
return [] unless conf_file.readable?
|
return [] unless conf_file.readable?
|
||||||
@ -68,8 +100,7 @@ module OS
|
|||||||
line.sub!(/\s*#.*$/, "")
|
line.sub!(/\s*#.*$/, "")
|
||||||
|
|
||||||
if line.start_with?(/\s*include\s+/)
|
if line.start_with?(/\s*include\s+/)
|
||||||
include_path = Pathname(line.sub(/^\s*include\s+/, "")).expand_path
|
wildcard = Pathname(line.sub(/^\s*include\s+/, "")).expand_path(directory)
|
||||||
wildcard = include_path.absolute? ? include_path : directory/include_path
|
|
||||||
|
|
||||||
Dir.glob(wildcard.to_s).each do |include_file|
|
Dir.glob(wildcard.to_s).each do |include_file|
|
||||||
paths += library_paths(include_file)
|
paths += library_paths(include_file)
|
||||||
|
|||||||
47
Library/Homebrew/os/linux/libstdcxx.rb
Normal file
47
Library/Homebrew/os/linux/libstdcxx.rb
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# typed: strict
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "os/linux/ld"
|
||||||
|
|
||||||
|
module OS
|
||||||
|
module Linux
|
||||||
|
# Helper functions for querying `libstdc++` information.
|
||||||
|
module Libstdcxx
|
||||||
|
SOVERSION = 6
|
||||||
|
SONAME = T.let("libstdc++.so.#{SOVERSION}".freeze, String)
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
|
def self.below_ci_version?
|
||||||
|
system_version < LINUX_LIBSTDCXX_CI_VERSION
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { returns(Version) }
|
||||||
|
def self.system_version
|
||||||
|
@system_version ||= T.let(nil, T.nilable(Version))
|
||||||
|
@system_version ||= if (path = system_path)
|
||||||
|
Version.new("#{SOVERSION}#{path.realpath.basename.to_s.delete_prefix!(SONAME)}")
|
||||||
|
else
|
||||||
|
Version::NULL
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { returns(T.nilable(Pathname)) }
|
||||||
|
def self.system_path
|
||||||
|
@system_path ||= T.let(nil, T.nilable(Pathname))
|
||||||
|
@system_path ||= find_library(OS::Linux::Ld.library_paths(brewed: false))
|
||||||
|
@system_path ||= find_library(OS::Linux::Ld.system_dirs(brewed: false))
|
||||||
|
end
|
||||||
|
|
||||||
|
sig { params(paths: T::Array[String]).returns(T.nilable(Pathname)) }
|
||||||
|
private_class_method def self.find_library(paths)
|
||||||
|
paths.each do |path|
|
||||||
|
next if path.start_with?(HOMEBREW_PREFIX)
|
||||||
|
|
||||||
|
candidate = Pathname(path)/SONAME
|
||||||
|
return candidate if candidate.exist? && candidate.elf?
|
||||||
|
end
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -56,7 +56,7 @@ module OS
|
|||||||
def self.latest_sdk_version
|
def self.latest_sdk_version
|
||||||
# TODO: bump version when new Xcode macOS SDK is released
|
# TODO: bump version when new Xcode macOS SDK is released
|
||||||
# NOTE: We only track the major version of the SDK.
|
# NOTE: We only track the major version of the SDK.
|
||||||
::Version.new("15")
|
::Version.new("26")
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
|
|||||||
@ -1,7 +1,14 @@
|
|||||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Keg
|
class Keg
|
||||||
|
sig { params(path: Pathname).void }
|
||||||
|
def initialize(path)
|
||||||
|
super
|
||||||
|
|
||||||
|
@require_relocation = T.let(false, T::Boolean)
|
||||||
|
end
|
||||||
|
|
||||||
sig { params(id: String, file: Pathname).returns(T::Boolean) }
|
sig { params(id: String, file: Pathname).returns(T::Boolean) }
|
||||||
def change_dylib_id(id, file)
|
def change_dylib_id(id, file)
|
||||||
return false if file.dylib_id == id
|
return false if file.dylib_id == id
|
||||||
@ -36,6 +43,7 @@ class Keg
|
|||||||
raise
|
raise
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(old: String, new: String, file: Pathname).returns(T::Boolean) }
|
||||||
def change_rpath(old, new, file)
|
def change_rpath(old, new, file)
|
||||||
return false if old == new
|
return false if old == new
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "macho"
|
require "macho"
|
||||||
@ -12,25 +12,28 @@ module MachOShim
|
|||||||
|
|
||||||
delegate [:dylib_id] => :macho
|
delegate [:dylib_id] => :macho
|
||||||
|
|
||||||
|
sig { params(args: T.untyped).void }
|
||||||
def initialize(*args)
|
def initialize(*args)
|
||||||
@macho = T.let(nil, T.nilable(MachO::MachOFile))
|
@macho = T.let(nil, T.nilable(T.any(MachO::MachOFile, MachO::FatFile)))
|
||||||
@mach_data = T.let(nil, T.nilable(T::Array[T::Hash[Symbol, T.untyped]]))
|
@mach_data = T.let(nil, T.nilable(T::Array[T::Hash[Symbol, Symbol]]))
|
||||||
|
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T.any(MachO::MachOFile, MachO::FatFile)) }
|
||||||
def macho
|
def macho
|
||||||
@macho ||= MachO.open(to_s)
|
@macho ||= MachO.open(to_s)
|
||||||
end
|
end
|
||||||
private :macho
|
private :macho
|
||||||
|
|
||||||
sig { returns(T::Array[T::Hash[Symbol, T.untyped]]) }
|
sig { returns(T::Array[T::Hash[Symbol, Symbol]]) }
|
||||||
def mach_data
|
def mach_data
|
||||||
@mach_data ||= begin
|
@mach_data ||= begin
|
||||||
machos = []
|
machos = []
|
||||||
mach_data = []
|
mach_data = []
|
||||||
|
|
||||||
if MachO::Utils.fat_magic?(macho.magic)
|
case (macho = self.macho)
|
||||||
|
when MachO::FatFile
|
||||||
machos = macho.machos
|
machos = macho.machos
|
||||||
else
|
else
|
||||||
machos << macho
|
machos << macho
|
||||||
@ -68,34 +71,38 @@ module MachOShim
|
|||||||
|
|
||||||
# TODO: See if the `#write!` call can be delayed until
|
# TODO: See if the `#write!` call can be delayed until
|
||||||
# we know we're not making any changes to the rpaths.
|
# we know we're not making any changes to the rpaths.
|
||||||
def delete_rpath(rpath, **options)
|
sig { params(rpath: String, strict: T::Boolean).void }
|
||||||
|
def delete_rpath(rpath, strict: true)
|
||||||
candidates = rpaths(resolve_variable_references: false).select do |r|
|
candidates = rpaths(resolve_variable_references: false).select do |r|
|
||||||
resolve_variable_name(r) == resolve_variable_name(rpath)
|
resolve_variable_name(r) == resolve_variable_name(rpath)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Delete the last instance to avoid changing the order in which rpaths are searched.
|
# Delete the last instance to avoid changing the order in which rpaths are searched.
|
||||||
rpath_to_delete = candidates.last
|
rpath_to_delete = candidates.last
|
||||||
options[:last] = true
|
|
||||||
|
|
||||||
macho.delete_rpath(rpath_to_delete, options)
|
macho.delete_rpath(rpath_to_delete, { last: true, strict: })
|
||||||
macho.write!
|
macho.write!
|
||||||
end
|
end
|
||||||
|
|
||||||
def change_rpath(old, new, **options)
|
sig { params(old: String, new: String, uniq: T::Boolean, last: T::Boolean, strict: T::Boolean).void }
|
||||||
macho.change_rpath(old, new, options)
|
def change_rpath(old, new, uniq: false, last: false, strict: true)
|
||||||
|
macho.change_rpath(old, new, { uniq:, last:, strict: })
|
||||||
macho.write!
|
macho.write!
|
||||||
end
|
end
|
||||||
|
|
||||||
def change_dylib_id(id, **options)
|
sig { params(id: String, strict: T::Boolean).void }
|
||||||
macho.change_dylib_id(id, options)
|
def change_dylib_id(id, strict: true)
|
||||||
|
macho.change_dylib_id(id, { strict: })
|
||||||
macho.write!
|
macho.write!
|
||||||
end
|
end
|
||||||
|
|
||||||
def change_install_name(old, new, **options)
|
sig { params(old: String, new: String, strict: T::Boolean).void }
|
||||||
macho.change_install_name(old, new, options)
|
def change_install_name(old, new, strict: true)
|
||||||
|
macho.change_install_name(old, new, { strict: })
|
||||||
macho.write!
|
macho.write!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(except: Symbol, resolve_variable_references: T::Boolean).returns(T::Array[String]) }
|
||||||
def dynamically_linked_libraries(except: :none, resolve_variable_references: true)
|
def dynamically_linked_libraries(except: :none, resolve_variable_references: true)
|
||||||
lcs = macho.dylib_load_commands
|
lcs = macho.dylib_load_commands
|
||||||
lcs.reject! { |lc| lc.flag?(except) } if except != :none
|
lcs.reject! { |lc| lc.flag?(except) } if except != :none
|
||||||
@ -105,6 +112,7 @@ module MachOShim
|
|||||||
names
|
names
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(resolve_variable_references: T::Boolean).returns(T::Array[String]) }
|
||||||
def rpaths(resolve_variable_references: true)
|
def rpaths(resolve_variable_references: true)
|
||||||
names = macho.rpaths
|
names = macho.rpaths
|
||||||
# Don't recursively resolve rpaths to avoid infinite loops.
|
# Don't recursively resolve rpaths to avoid infinite loops.
|
||||||
@ -113,11 +121,12 @@ module MachOShim
|
|||||||
names
|
names
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(name: String, resolve_rpaths: T::Boolean).returns(String) }
|
||||||
def resolve_variable_name(name, resolve_rpaths: true)
|
def resolve_variable_name(name, resolve_rpaths: true)
|
||||||
if name.start_with? "@loader_path"
|
if name.start_with? "@loader_path"
|
||||||
Pathname(name.sub("@loader_path", dirname)).cleanpath.to_s
|
Pathname(name.sub("@loader_path", dirname.to_s)).cleanpath.to_s
|
||||||
elsif name.start_with?("@executable_path") && binary_executable?
|
elsif name.start_with?("@executable_path") && binary_executable?
|
||||||
Pathname(name.sub("@executable_path", dirname)).cleanpath.to_s
|
Pathname(name.sub("@executable_path", dirname.to_s)).cleanpath.to_s
|
||||||
elsif resolve_rpaths && name.start_with?("@rpath") && (target = resolve_rpath(name)).present?
|
elsif resolve_rpaths && name.start_with?("@rpath") && (target = resolve_rpath(name)).present?
|
||||||
target
|
target
|
||||||
else
|
else
|
||||||
@ -125,6 +134,7 @@ module MachOShim
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(name: String).returns(T.nilable(String)) }
|
||||||
def resolve_rpath(name)
|
def resolve_rpath(name)
|
||||||
target = T.let(nil, T.nilable(String))
|
target = T.let(nil, T.nilable(String))
|
||||||
return unless rpaths(resolve_variable_references: true).find do |rpath|
|
return unless rpaths(resolve_variable_references: true).find do |rpath|
|
||||||
@ -134,48 +144,58 @@ module MachOShim
|
|||||||
target
|
target
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Array[Symbol]) }
|
||||||
def archs
|
def archs
|
||||||
mach_data.map { |m| m.fetch :arch }
|
mach_data.map { |m| m.fetch :arch }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(Symbol) }
|
||||||
def arch
|
def arch
|
||||||
case archs.length
|
case archs.length
|
||||||
when 0 then :dunno
|
when 0 then :dunno
|
||||||
when 1 then archs.first
|
when 1 then archs.fetch(0)
|
||||||
else :universal
|
else :universal
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def universal?
|
def universal?
|
||||||
arch == :universal
|
arch == :universal
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def i386?
|
def i386?
|
||||||
arch == :i386
|
arch == :i386
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def x86_64?
|
def x86_64?
|
||||||
arch == :x86_64
|
arch == :x86_64
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def ppc7400?
|
def ppc7400?
|
||||||
arch == :ppc7400
|
arch == :ppc7400
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def ppc64?
|
def ppc64?
|
||||||
arch == :ppc64
|
arch == :ppc64
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def dylib?
|
def dylib?
|
||||||
mach_data.any? { |m| m.fetch(:type) == :dylib }
|
mach_data.any? { |m| m.fetch(:type) == :dylib }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def mach_o_executable?
|
def mach_o_executable?
|
||||||
mach_data.any? { |m| m.fetch(:type) == :executable }
|
mach_data.any? { |m| m.fetch(:type) == :executable }
|
||||||
end
|
end
|
||||||
|
|
||||||
alias binary_executable? mach_o_executable?
|
alias binary_executable? mach_o_executable?
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def mach_o_bundle?
|
def mach_o_bundle?
|
||||||
mach_data.any? { |m| m.fetch(:type) == :bundle }
|
mach_data.any? { |m| m.fetch(:type) == :bundle }
|
||||||
end
|
end
|
||||||
|
|||||||
@ -6,7 +6,7 @@ includedir=${prefix}/include
|
|||||||
|
|
||||||
Name: SQLite
|
Name: SQLite
|
||||||
Description: SQL database engine
|
Description: SQL database engine
|
||||||
Version: 3.48.0
|
Version: 3.51.0
|
||||||
Libs: -L${libdir} -lsqlite3
|
Libs: -L${libdir} -lsqlite3
|
||||||
Libs.private:
|
Libs.private:
|
||||||
Cflags:
|
Cflags:
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "system_command"
|
require "system_command"
|
||||||
@ -22,7 +22,7 @@ module OS
|
|||||||
sig { params(version: MacOSVersion, path: T.any(String, Pathname), source: Symbol).void }
|
sig { params(version: MacOSVersion, path: T.any(String, Pathname), source: Symbol).void }
|
||||||
def initialize(version, path, source)
|
def initialize(version, path, source)
|
||||||
@version = version
|
@version = version
|
||||||
@path = Pathname.new(path)
|
@path = T.let(Pathname(path), Pathname)
|
||||||
@source = source
|
@source = source
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -36,6 +36,12 @@ module OS
|
|||||||
|
|
||||||
class NoSDKError < StandardError; end
|
class NoSDKError < StandardError; end
|
||||||
|
|
||||||
|
sig { void }
|
||||||
|
def initialize
|
||||||
|
@all_sdks = T.let(nil, T.nilable(T::Array[SDK]))
|
||||||
|
@sdk_prefix = T.let(nil, T.nilable(String))
|
||||||
|
end
|
||||||
|
|
||||||
sig { params(version: MacOSVersion).returns(SDK) }
|
sig { params(version: MacOSVersion).returns(SDK) }
|
||||||
def sdk_for(version)
|
def sdk_for(version)
|
||||||
sdk = all_sdks.find { |s| s.version == version }
|
sdk = all_sdks.find { |s| s.version == version }
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module OS
|
module OS
|
||||||
module Mac
|
module Mac
|
||||||
# Helper module for querying Xcode information.
|
# Helper module for querying Xcode information.
|
||||||
module Xcode
|
module Xcode
|
||||||
DEFAULT_BUNDLE_PATH = Pathname("/Applications/Xcode.app").freeze
|
DEFAULT_BUNDLE_PATH = T.let(Pathname("/Applications/Xcode.app").freeze, Pathname)
|
||||||
BUNDLE_ID = "com.apple.dt.Xcode"
|
BUNDLE_ID = "com.apple.dt.Xcode"
|
||||||
OLD_BUNDLE_ID = "com.apple.Xcode"
|
OLD_BUNDLE_ID = "com.apple.Xcode"
|
||||||
APPLE_DEVELOPER_DOWNLOAD_URL = "https://developer.apple.com/download/all/"
|
APPLE_DEVELOPER_DOWNLOAD_URL = "https://developer.apple.com/download/all/"
|
||||||
@ -17,6 +17,7 @@ module OS
|
|||||||
def self.latest_version(macos: MacOS.version)
|
def self.latest_version(macos: MacOS.version)
|
||||||
macos = macos.strip_patch
|
macos = macos.strip_patch
|
||||||
case macos
|
case macos
|
||||||
|
when "26" then "26.0"
|
||||||
when "15" then "16.4"
|
when "15" then "16.4"
|
||||||
when "14" then "16.2"
|
when "14" then "16.2"
|
||||||
when "13" then "15.2"
|
when "13" then "15.2"
|
||||||
@ -43,6 +44,7 @@ module OS
|
|||||||
def self.minimum_version
|
def self.minimum_version
|
||||||
macos = MacOS.version
|
macos = MacOS.version
|
||||||
case macos
|
case macos
|
||||||
|
when "26" then "26.0"
|
||||||
when "15" then "16.0"
|
when "15" then "16.0"
|
||||||
when "14" then "15.0"
|
when "14" then "15.0"
|
||||||
when "13" then "14.1"
|
when "13" then "14.1"
|
||||||
@ -98,7 +100,7 @@ module OS
|
|||||||
# directory or nil if Xcode.app is not installed.
|
# directory or nil if Xcode.app is not installed.
|
||||||
sig { returns(T.nilable(Pathname)) }
|
sig { returns(T.nilable(Pathname)) }
|
||||||
def self.prefix
|
def self.prefix
|
||||||
@prefix ||= begin
|
@prefix ||= T.let(begin
|
||||||
dir = MacOS.active_developer_dir
|
dir = MacOS.active_developer_dir
|
||||||
|
|
||||||
if dir.empty? || dir == CLT::PKG_PATH || !File.directory?(dir)
|
if dir.empty? || dir == CLT::PKG_PATH || !File.directory?(dir)
|
||||||
@ -108,7 +110,7 @@ module OS
|
|||||||
# Use cleanpath to avoid pathological trailing slash
|
# Use cleanpath to avoid pathological trailing slash
|
||||||
Pathname.new(dir).cleanpath
|
Pathname.new(dir).cleanpath
|
||||||
end
|
end
|
||||||
end
|
end, T.nilable(Pathname))
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(Pathname) }
|
sig { returns(Pathname) }
|
||||||
@ -134,7 +136,7 @@ module OS
|
|||||||
|
|
||||||
sig { returns(XcodeSDKLocator) }
|
sig { returns(XcodeSDKLocator) }
|
||||||
def self.sdk_locator
|
def self.sdk_locator
|
||||||
@sdk_locator ||= XcodeSDKLocator.new
|
@sdk_locator ||= T.let(XcodeSDKLocator.new, T.nilable(OS::Mac::XcodeSDKLocator))
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(version: T.nilable(MacOSVersion)).returns(T.nilable(SDK)) }
|
sig { params(version: T.nilable(MacOSVersion)).returns(T.nilable(SDK)) }
|
||||||
@ -183,7 +185,7 @@ module OS
|
|||||||
# may return a version string
|
# may return a version string
|
||||||
# that is guessed based on the compiler, so do not
|
# that is guessed based on the compiler, so do not
|
||||||
# use it in order to check if Xcode is installed.
|
# use it in order to check if Xcode is installed.
|
||||||
if @version ||= detect_version
|
if @version ||= T.let(detect_version, T.nilable(String))
|
||||||
::Version.new @version
|
::Version.new @version
|
||||||
else
|
else
|
||||||
::Version::NULL
|
::Version::NULL
|
||||||
@ -293,7 +295,7 @@ module OS
|
|||||||
|
|
||||||
sig { returns(CLTSDKLocator) }
|
sig { returns(CLTSDKLocator) }
|
||||||
def self.sdk_locator
|
def self.sdk_locator
|
||||||
@sdk_locator ||= CLTSDKLocator.new
|
@sdk_locator ||= T.let(CLTSDKLocator.new, T.nilable(OS::Mac::CLTSDKLocator))
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(version: T.nilable(MacOSVersion)).returns(T.nilable(SDK)) }
|
sig { params(version: T.nilable(MacOSVersion)).returns(T.nilable(SDK)) }
|
||||||
@ -372,7 +374,7 @@ module OS
|
|||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def self.latest_clang_version
|
def self.latest_clang_version
|
||||||
case MacOS.version
|
case MacOS.version
|
||||||
when "26" then "1700.3.9.908"
|
when "26" then "1700.3.19.1"
|
||||||
when "15" then "1700.0.13.5"
|
when "15" then "1700.0.13.5"
|
||||||
when "14" then "1600.0.26.6"
|
when "14" then "1600.0.26.6"
|
||||||
when "13" then "1500.1.0.2.5"
|
when "13" then "1500.1.0.2.5"
|
||||||
@ -444,7 +446,7 @@ module OS
|
|||||||
# @api internal
|
# @api internal
|
||||||
sig { returns(::Version) }
|
sig { returns(::Version) }
|
||||||
def self.version
|
def self.version
|
||||||
if @version ||= detect_version
|
if @version ||= T.let(detect_version, T.nilable(String))
|
||||||
::Version.new @version
|
::Version.new @version
|
||||||
else
|
else
|
||||||
::Version::NULL
|
::Version::NULL
|
||||||
|
|||||||
@ -32,8 +32,8 @@ begin
|
|||||||
end
|
end
|
||||||
|
|
||||||
Pathname.prepend WriteMkpathExtension
|
Pathname.prepend WriteMkpathExtension
|
||||||
|
|
||||||
formula.run_post_install
|
formula.run_post_install
|
||||||
|
|
||||||
# Handle all possible exceptions.
|
# Handle all possible exceptions.
|
||||||
rescue Exception => e # rubocop:disable Lint/RescueException
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
||||||
error_pipe&.puts e.to_json
|
error_pipe&.puts e.to_json
|
||||||
|
|||||||
@ -125,7 +125,7 @@ module Readall
|
|||||||
sig { params(filename: Pathname).returns(T::Boolean) }
|
sig { params(filename: Pathname).returns(T::Boolean) }
|
||||||
private_class_method def self.syntax_errors_or_warnings?(filename)
|
private_class_method def self.syntax_errors_or_warnings?(filename)
|
||||||
# Retrieve messages about syntax errors/warnings printed to `$stderr`.
|
# Retrieve messages about syntax errors/warnings printed to `$stderr`.
|
||||||
_, err, status = system_command(RUBY_PATH, args: ["-c", "-w", filename], print_stderr: false)
|
_, err, status = system_command(RUBY_PATH, args: ["-c", "-w", filename], print_stderr: false).to_a
|
||||||
|
|
||||||
# Ignore unnecessary warning about named capture conflicts.
|
# Ignore unnecessary warning about named capture conflicts.
|
||||||
# See https://bugs.ruby-lang.org/issues/12359.
|
# See https://bugs.ruby-lang.org/issues/12359.
|
||||||
|
|||||||
@ -85,9 +85,6 @@ module Homebrew
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: Remove this exception for `lsr` after support for tangled.sh
|
|
||||||
# Git URLs is available in a brew release.
|
|
||||||
return if name == "lsr"
|
|
||||||
return if url_strategy != DownloadStrategyDetector.detect("", using)
|
return if url_strategy != DownloadStrategyDetector.detect("", using)
|
||||||
|
|
||||||
problem "Redundant `using:` value in URL"
|
problem "Redundant `using:` value in URL"
|
||||||
|
|||||||
@ -93,7 +93,7 @@ module Homebrew
|
|||||||
|
|
||||||
wait = 2 ** @try
|
wait = 2 ** @try
|
||||||
unless quiet
|
unless quiet
|
||||||
what = Utils.pluralize("tr", tries_remaining, plural: "ies", singular: "y")
|
what = Utils.pluralize("try", tries_remaining)
|
||||||
ohai "Retrying download in #{wait}s... (#{tries_remaining} #{what} left)"
|
ohai "Retrying download in #{wait}s... (#{tries_remaining} #{what} left)"
|
||||||
end
|
end
|
||||||
sleep wait
|
sleep wait
|
||||||
|
|||||||
@ -34,7 +34,7 @@ module Homebrew
|
|||||||
unofficial = Tap.all.sum { |tap| tap.official? ? 0 : tap.formula_files.size }
|
unofficial = Tap.all.sum { |tap| tap.official? ? 0 : tap.formula_files.size }
|
||||||
if unofficial.positive?
|
if unofficial.positive?
|
||||||
opoo "Use `--eval-all` to search #{unofficial} additional " \
|
opoo "Use `--eval-all` to search #{unofficial} additional " \
|
||||||
"#{Utils.pluralize("formula", unofficial, plural: "e")} in third party taps."
|
"#{Utils.pluralize("formula", unofficial)} in third party taps."
|
||||||
end
|
end
|
||||||
descriptions = Homebrew::API::Formula.all_formulae.transform_values { |data| data["desc"] }
|
descriptions = Homebrew::API::Formula.all_formulae.transform_values { |data| data["desc"] }
|
||||||
Descriptions.search(string_or_regex, search_type, descriptions, eval_all, cache_store_hash: true).print
|
Descriptions.search(string_or_regex, search_type, descriptions, eval_all, cache_store_hash: true).print
|
||||||
|
|||||||
@ -34,7 +34,7 @@ module Homebrew
|
|||||||
|
|
||||||
private_class_method def self._run(*args, mode:)
|
private_class_method def self._run(*args, mode:)
|
||||||
require "system_command"
|
require "system_command"
|
||||||
result = SystemCommand.run(executable,
|
result = SystemCommand.run(T.must(executable),
|
||||||
args: [scope, *args.map(&:to_s)],
|
args: [scope, *args.map(&:to_s)],
|
||||||
print_stdout: mode == :default,
|
print_stdout: mode == :default,
|
||||||
print_stderr: mode == :default,
|
print_stderr: mode == :default,
|
||||||
|
|||||||
@ -369,9 +369,13 @@ class Cmd
|
|||||||
end
|
end
|
||||||
args += rpath_flags("#{wl}-rpath=", rpath_paths)
|
args += rpath_flags("#{wl}-rpath=", rpath_paths)
|
||||||
args += ["#{wl}--dynamic-linker=#{dynamic_linker_path}"] if dynamic_linker_path
|
args += ["#{wl}--dynamic-linker=#{dynamic_linker_path}"] if dynamic_linker_path
|
||||||
# Use -rpath-link to make sure linker uses versioned glibc rather than the system glibc for indirect
|
# Use -rpath-link to make sure linker uses brew glibc rather than the system glibc for indirect
|
||||||
# dependencies because -L will only handle direct dependencies.
|
# dependencies because -L will only handle direct dependencies.
|
||||||
args << "#{wl}-rpath-link=#{@opt}/#{versioned_glibc_dep}/lib" if versioned_glibc_dep
|
if versioned_glibc_dep
|
||||||
|
args << "#{wl}-rpath-link=#{@opt}/#{versioned_glibc_dep}/lib"
|
||||||
|
else
|
||||||
|
args << "#{wl}-rpath-link=#{@opt}/glibc/lib"
|
||||||
|
end
|
||||||
args
|
args
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -17,9 +17,21 @@ class Homebrew::DevCmd::Contributions::Args < Homebrew::CLI::Args
|
|||||||
sig { returns(T.nilable(String)) }
|
sig { returns(T.nilable(String)) }
|
||||||
def from; end
|
def from; end
|
||||||
|
|
||||||
|
sig { returns(T.nilable(String)) }
|
||||||
|
def org; end
|
||||||
|
|
||||||
|
sig { returns(T.nilable(String)) }
|
||||||
|
def organisation; end
|
||||||
|
|
||||||
|
sig { returns(T.nilable(String)) }
|
||||||
|
def organization; end
|
||||||
|
|
||||||
sig { returns(T.nilable(T::Array[String])) }
|
sig { returns(T.nilable(T::Array[String])) }
|
||||||
def repositories; end
|
def repositories; end
|
||||||
|
|
||||||
|
sig { returns(T.nilable(String)) }
|
||||||
|
def team; end
|
||||||
|
|
||||||
sig { returns(T.nilable(String)) }
|
sig { returns(T.nilable(String)) }
|
||||||
def to; end
|
def to; end
|
||||||
|
|
||||||
|
|||||||
@ -988,38 +988,38 @@ RuboCop::Cop::RSpec::DescribeSymbol::RESTRICT_ON_SEND = T.let(T.unsafe(nil), Arr
|
|||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#71
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#76
|
||||||
class RuboCop::Cop::RSpec::DescribedClass < ::RuboCop::Cop::RSpec::Base
|
class RuboCop::Cop::RSpec::DescribedClass < ::RuboCop::Cop::RSpec::Base
|
||||||
include ::RuboCop::Cop::ConfigurableEnforcedStyle
|
include ::RuboCop::Cop::ConfigurableEnforcedStyle
|
||||||
include ::RuboCop::Cop::RSpec::Namespace
|
include ::RuboCop::Cop::RSpec::Namespace
|
||||||
extend ::RuboCop::Cop::AutoCorrector
|
extend ::RuboCop::Cop::AutoCorrector
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#80
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#85
|
||||||
def common_instance_exec_closure?(param0 = T.unsafe(nil)); end
|
def common_instance_exec_closure?(param0 = T.unsafe(nil)); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#97
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#108
|
||||||
def contains_described_class?(param0); end
|
def contains_described_class?(param0); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#92
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#103
|
||||||
def described_constant(param0 = T.unsafe(nil)); end
|
def described_constant(param0 = T.unsafe(nil)); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#100
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#111
|
||||||
def on_block(node); end
|
def on_block(node); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#85
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#96
|
||||||
def rspec_block?(param0 = T.unsafe(nil)); end
|
def rspec_block?(param0 = T.unsafe(nil)); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#89
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#100
|
||||||
def scope_changing_syntax?(param0 = T.unsafe(nil)); end
|
def scope_changing_syntax?(param0 = T.unsafe(nil)); end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#136
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#147
|
||||||
def allowed?(node); end
|
def allowed?(node); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#117
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#128
|
||||||
def autocorrect(corrector, match); end
|
def autocorrect(corrector, match); end
|
||||||
|
|
||||||
# @example
|
# @example
|
||||||
@ -1033,7 +1033,7 @@ class RuboCop::Cop::RSpec::DescribedClass < ::RuboCop::Cop::RSpec::Base
|
|||||||
# @param const [Array<Symbol>]
|
# @param const [Array<Symbol>]
|
||||||
# @return [Array<Symbol>]
|
# @return [Array<Symbol>]
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#202
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#213
|
||||||
def collapse_namespace(namespace, const); end
|
def collapse_namespace(namespace, const); end
|
||||||
|
|
||||||
# @example
|
# @example
|
||||||
@ -1043,50 +1043,50 @@ class RuboCop::Cop::RSpec::DescribedClass < ::RuboCop::Cop::RSpec::Base
|
|||||||
# @param node [RuboCop::AST::Node]
|
# @param node [RuboCop::AST::Node]
|
||||||
# @return [Array<Symbol>]
|
# @return [Array<Symbol>]
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#219
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#230
|
||||||
def const_name(node); end
|
def const_name(node); end
|
||||||
|
|
||||||
# @yield [node]
|
# @yield [node]
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#127
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#138
|
||||||
def find_usage(node, &block); end
|
def find_usage(node, &block); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#187
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#198
|
||||||
def full_const_name(node); end
|
def full_const_name(node); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#140
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#151
|
||||||
def message(offense); end
|
def message(offense); end
|
||||||
|
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#165
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#176
|
||||||
def offensive?(node); end
|
def offensive?(node); end
|
||||||
|
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#173
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#184
|
||||||
def offensive_described_class?(node); end
|
def offensive_described_class?(node); end
|
||||||
|
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#161
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#172
|
||||||
def only_static_constants?; end
|
def only_static_constants?; end
|
||||||
|
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#149
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#160
|
||||||
def scope_change?(node); end
|
def scope_change?(node); end
|
||||||
|
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#155
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#166
|
||||||
def skippable_block?(node); end
|
def skippable_block?(node); end
|
||||||
end
|
end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#76
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#81
|
||||||
RuboCop::Cop::RSpec::DescribedClass::DESCRIBED_CLASS = T.let(T.unsafe(nil), String)
|
RuboCop::Cop::RSpec::DescribedClass::DESCRIBED_CLASS = T.let(T.unsafe(nil), String)
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#77
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/described_class.rb#82
|
||||||
RuboCop::Cop::RSpec::DescribedClass::MSG = T.let(T.unsafe(nil), String)
|
RuboCop::Cop::RSpec::DescribedClass::MSG = T.let(T.unsafe(nil), String)
|
||||||
|
|
||||||
# Avoid opening modules and defining specs within them.
|
# Avoid opening modules and defining specs within them.
|
||||||
@ -1135,6 +1135,7 @@ RuboCop::Cop::RSpec::DescribedClassModuleWrapping::MSG = T.let(T.unsafe(nil), St
|
|||||||
# - let, let!
|
# - let, let!
|
||||||
# - subject, subject!
|
# - subject, subject!
|
||||||
# - expect, is_expected, expect_any_instance_of
|
# - expect, is_expected, expect_any_instance_of
|
||||||
|
# - raise_error, raise_exception
|
||||||
#
|
#
|
||||||
# By default all of the RSpec methods and aliases are allowed. By setting
|
# By default all of the RSpec methods and aliases are allowed. By setting
|
||||||
# a config like:
|
# a config like:
|
||||||
@ -1169,19 +1170,19 @@ RuboCop::Cop::RSpec::DescribedClassModuleWrapping::MSG = T.let(T.unsafe(nil), St
|
|||||||
# # ...
|
# # ...
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/dialect.rb#58
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/dialect.rb#59
|
||||||
class RuboCop::Cop::RSpec::Dialect < ::RuboCop::Cop::RSpec::Base
|
class RuboCop::Cop::RSpec::Dialect < ::RuboCop::Cop::RSpec::Base
|
||||||
include ::RuboCop::Cop::MethodPreference
|
include ::RuboCop::Cop::MethodPreference
|
||||||
extend ::RuboCop::Cop::AutoCorrector
|
extend ::RuboCop::Cop::AutoCorrector
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/dialect.rb#67
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/dialect.rb#68
|
||||||
def on_send(node); end
|
def on_send(node); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/dialect.rb#65
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/dialect.rb#66
|
||||||
def rspec_method?(param0 = T.unsafe(nil)); end
|
def rspec_method?(param0 = T.unsafe(nil)); end
|
||||||
end
|
end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/dialect.rb#62
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/dialect.rb#63
|
||||||
RuboCop::Cop::RSpec::Dialect::MSG = T.let(T.unsafe(nil), String)
|
RuboCop::Cop::RSpec::Dialect::MSG = T.let(T.unsafe(nil), String)
|
||||||
|
|
||||||
# Avoid duplicated metadata.
|
# Avoid duplicated metadata.
|
||||||
@ -1578,7 +1579,7 @@ class RuboCop::Cop::RSpec::EmptyLineAfterHook < ::RuboCop::Cop::RSpec::Base
|
|||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/empty_line_after_hook.rb#60
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/empty_line_after_hook.rb#60
|
||||||
def on_block(node); end
|
def on_block(node); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/empty_line_after_hook.rb#60
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/empty_line_after_hook.rb#70
|
||||||
def on_numblock(node); end
|
def on_numblock(node); end
|
||||||
|
|
||||||
private
|
private
|
||||||
@ -2189,7 +2190,7 @@ class RuboCop::Cop::RSpec::ExpectInHook < ::RuboCop::Cop::RSpec::Base
|
|||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/expect_in_hook.rb#30
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/expect_in_hook.rb#30
|
||||||
def on_block(node); end
|
def on_block(node); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/expect_in_hook.rb#30
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/expect_in_hook.rb#40
|
||||||
def on_numblock(node); end
|
def on_numblock(node); end
|
||||||
|
|
||||||
private
|
private
|
||||||
@ -2482,7 +2483,7 @@ class RuboCop::Cop::RSpec::HookArgument < ::RuboCop::Cop::RSpec::Base
|
|||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/hook_argument.rb#78
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/hook_argument.rb#78
|
||||||
def on_block(node); end
|
def on_block(node); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/hook_argument.rb#78
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/hook_argument.rb#91
|
||||||
def on_numblock(node); end
|
def on_numblock(node); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/hook_argument.rb#69
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/hook_argument.rb#69
|
||||||
@ -2546,7 +2547,7 @@ class RuboCop::Cop::RSpec::HooksBeforeExamples < ::RuboCop::Cop::RSpec::Base
|
|||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/hooks_before_examples.rb#41
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/hooks_before_examples.rb#41
|
||||||
def on_block(node); end
|
def on_block(node); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/hooks_before_examples.rb#41
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/hooks_before_examples.rb#47
|
||||||
def on_numblock(node); end
|
def on_numblock(node); end
|
||||||
|
|
||||||
private
|
private
|
||||||
@ -2838,18 +2839,18 @@ RuboCop::Cop::RSpec::ImplicitSubject::RESTRICT_ON_SEND = T.let(T.unsafe(nil), Ar
|
|||||||
# # good
|
# # good
|
||||||
# it_behaves_like 'examples'
|
# it_behaves_like 'examples'
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/include_examples.rb#22
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/include_examples.rb#73
|
||||||
class RuboCop::Cop::RSpec::IncludeExamples < ::RuboCop::Cop::RSpec::Base
|
class RuboCop::Cop::RSpec::IncludeExamples < ::RuboCop::Cop::RSpec::Base
|
||||||
extend ::RuboCop::Cop::AutoCorrector
|
extend ::RuboCop::Cop::AutoCorrector
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/include_examples.rb#29
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/include_examples.rb#80
|
||||||
def on_send(node); end
|
def on_send(node); end
|
||||||
end
|
end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/include_examples.rb#25
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/include_examples.rb#76
|
||||||
RuboCop::Cop::RSpec::IncludeExamples::MSG = T.let(T.unsafe(nil), String)
|
RuboCop::Cop::RSpec::IncludeExamples::MSG = T.let(T.unsafe(nil), String)
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/include_examples.rb#27
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/include_examples.rb#78
|
||||||
RuboCop::Cop::RSpec::IncludeExamples::RESTRICT_ON_SEND = T.let(T.unsafe(nil), Array)
|
RuboCop::Cop::RSpec::IncludeExamples::RESTRICT_ON_SEND = T.let(T.unsafe(nil), Array)
|
||||||
|
|
||||||
# Do not set up test data using indexes (e.g., `item_1`, `item_2`).
|
# Do not set up test data using indexes (e.g., `item_1`, `item_2`).
|
||||||
@ -3211,16 +3212,18 @@ RuboCop::Cop::RSpec::ItBehavesLike::RESTRICT_ON_SEND = T.let(T.unsafe(nil), Arra
|
|||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#19
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#19
|
||||||
class RuboCop::Cop::RSpec::IteratedExpectation < ::RuboCop::Cop::RSpec::Base
|
class RuboCop::Cop::RSpec::IteratedExpectation < ::RuboCop::Cop::RSpec::Base
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#24
|
extend ::RuboCop::Cop::AutoCorrector
|
||||||
|
|
||||||
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#26
|
||||||
def each?(param0 = T.unsafe(nil)); end
|
def each?(param0 = T.unsafe(nil)); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#33
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#35
|
||||||
def each_numblock?(param0 = T.unsafe(nil)); end
|
def each_numblock?(param0 = T.unsafe(nil)); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#40
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#42
|
||||||
def expectation?(param0 = T.unsafe(nil), param1); end
|
def expectation?(param0 = T.unsafe(nil), param1); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#44
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#46
|
||||||
def on_block(node); end
|
def on_block(node); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#52
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#52
|
||||||
@ -3228,18 +3231,29 @@ class RuboCop::Cop::RSpec::IteratedExpectation < ::RuboCop::Cop::RSpec::Base
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#60
|
||||||
|
def check_offense(node, argument); end
|
||||||
|
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#66
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#88
|
||||||
def only_expectations?(body, arg); end
|
def only_expectations?(body, arg); end
|
||||||
|
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#62
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#84
|
||||||
def single_expectation?(body, arg); end
|
def single_expectation?(body, arg); end
|
||||||
|
|
||||||
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#73
|
||||||
|
def single_expectation_replacement(node); end
|
||||||
|
|
||||||
|
# @return [Boolean]
|
||||||
|
#
|
||||||
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#80
|
||||||
|
def uses_argument_in_matcher?(node, argument); end
|
||||||
end
|
end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#20
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/iterated_expectation.rb#22
|
||||||
RuboCop::Cop::RSpec::IteratedExpectation::MSG = T.let(T.unsafe(nil), String)
|
RuboCop::Cop::RSpec::IteratedExpectation::MSG = T.let(T.unsafe(nil), String)
|
||||||
|
|
||||||
# Enforce that subject is the first definition in the test.
|
# Enforce that subject is the first definition in the test.
|
||||||
@ -3393,17 +3407,22 @@ class RuboCop::Cop::RSpec::LeakyConstantDeclaration < ::RuboCop::Cop::RSpec::Bas
|
|||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/leaky_constant_declaration.rb#101
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/leaky_constant_declaration.rb#101
|
||||||
def on_casgn(node); end
|
def on_casgn(node); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/leaky_constant_declaration.rb#107
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/leaky_constant_declaration.rb#108
|
||||||
def on_class(node); end
|
def on_class(node); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/leaky_constant_declaration.rb#113
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/leaky_constant_declaration.rb#115
|
||||||
def on_module(node); end
|
def on_module(node); end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/leaky_constant_declaration.rb#121
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/leaky_constant_declaration.rb#128
|
||||||
|
def explicit_namespace?(namespace); end
|
||||||
|
|
||||||
|
# @return [Boolean]
|
||||||
|
#
|
||||||
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/leaky_constant_declaration.rb#124
|
||||||
def inside_describe_block?(node); end
|
def inside_describe_block?(node); end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -3772,7 +3791,7 @@ module RuboCop::Cop::RSpec::Metadata
|
|||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/mixin/metadata.rb#43
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/mixin/metadata.rb#43
|
||||||
def on_metadata(_symbols, _hash); end
|
def on_metadata(_symbols, _hash); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/mixin/metadata.rb#30
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/mixin/metadata.rb#41
|
||||||
def on_numblock(node); end
|
def on_numblock(node); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/mixin/metadata.rb#21
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/mixin/metadata.rb#21
|
||||||
@ -4046,7 +4065,7 @@ class RuboCop::Cop::RSpec::MultipleExpectations < ::RuboCop::Cop::RSpec::Base
|
|||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/multiple_expectations.rb#86
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/multiple_expectations.rb#86
|
||||||
def expect?(param0 = T.unsafe(nil)); end
|
def expect?(param0 = T.unsafe(nil)); end
|
||||||
|
|
||||||
# source://rubocop/1.75.6/lib/rubocop/cop/exclude_limit.rb#11
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/multiple_expectations.rb#75
|
||||||
def max=(value); end
|
def max=(value); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/multiple_expectations.rb#93
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/multiple_expectations.rb#93
|
||||||
@ -4161,7 +4180,7 @@ RuboCop::Cop::RSpec::MultipleExpectations::TRUE_NODE = T.let(T.unsafe(nil), Proc
|
|||||||
class RuboCop::Cop::RSpec::MultipleMemoizedHelpers < ::RuboCop::Cop::RSpec::Base
|
class RuboCop::Cop::RSpec::MultipleMemoizedHelpers < ::RuboCop::Cop::RSpec::Base
|
||||||
include ::RuboCop::Cop::RSpec::Variable
|
include ::RuboCop::Cop::RSpec::Variable
|
||||||
|
|
||||||
# source://rubocop/1.75.6/lib/rubocop/cop/exclude_limit.rb#11
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/multiple_memoized_helpers.rb#89
|
||||||
def max=(value); end
|
def max=(value); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/multiple_memoized_helpers.rb#91
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/multiple_memoized_helpers.rb#91
|
||||||
@ -4503,7 +4522,7 @@ end
|
|||||||
class RuboCop::Cop::RSpec::NestedGroups < ::RuboCop::Cop::RSpec::Base
|
class RuboCop::Cop::RSpec::NestedGroups < ::RuboCop::Cop::RSpec::Base
|
||||||
include ::RuboCop::Cop::RSpec::TopLevelGroup
|
include ::RuboCop::Cop::RSpec::TopLevelGroup
|
||||||
|
|
||||||
# source://rubocop/1.75.6/lib/rubocop/cop/exclude_limit.rb#11
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/nested_groups.rb#105
|
||||||
def max=(value); end
|
def max=(value); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/nested_groups.rb#107
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/nested_groups.rb#107
|
||||||
@ -4617,7 +4636,7 @@ class RuboCop::Cop::RSpec::NoExpectationExample < ::RuboCop::Cop::RSpec::Base
|
|||||||
|
|
||||||
# @param node [RuboCop::AST::BlockNode]
|
# @param node [RuboCop::AST::BlockNode]
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/no_expectation_example.rb#89
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/no_expectation_example.rb#98
|
||||||
def on_numblock(node); end
|
def on_numblock(node); end
|
||||||
|
|
||||||
# @param node [RuboCop::AST::Node]
|
# @param node [RuboCop::AST::Node]
|
||||||
@ -4997,7 +5016,7 @@ RuboCop::Cop::RSpec::ReceiveCounts::MSG = T.let(T.unsafe(nil), String)
|
|||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/receive_counts.rb#30
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/receive_counts.rb#30
|
||||||
RuboCop::Cop::RSpec::ReceiveCounts::RESTRICT_ON_SEND = T.let(T.unsafe(nil), Array)
|
RuboCop::Cop::RSpec::ReceiveCounts::RESTRICT_ON_SEND = T.let(T.unsafe(nil), Array)
|
||||||
|
|
||||||
# Checks for multiple messages stubbed on the same object.
|
# Prefer `receive_messages` over multiple `receive`s on the same object.
|
||||||
#
|
#
|
||||||
# @example
|
# @example
|
||||||
# # bad
|
# # bad
|
||||||
@ -5140,7 +5159,7 @@ class RuboCop::Cop::RSpec::RedundantAround < ::RuboCop::Cop::RSpec::Base
|
|||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/redundant_around.rb#23
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/redundant_around.rb#23
|
||||||
def on_block(node); end
|
def on_block(node); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/redundant_around.rb#23
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/redundant_around.rb#30
|
||||||
def on_numblock(node); end
|
def on_numblock(node); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/redundant_around.rb#32
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/redundant_around.rb#32
|
||||||
@ -6126,7 +6145,7 @@ class RuboCop::Cop::RSpec::SkipBlockInsideExample < ::RuboCop::Cop::RSpec::Base
|
|||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/skip_block_inside_example.rb#29
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/skip_block_inside_example.rb#29
|
||||||
def on_block(node); end
|
def on_block(node); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/cop/rspec/skip_block_inside_example.rb#29
|
# source://rubocop-rspec//lib/rubocop/cop/rspec/skip_block_inside_example.rb#36
|
||||||
def on_numblock(node); end
|
def on_numblock(node); end
|
||||||
|
|
||||||
private
|
private
|
||||||
@ -7109,7 +7128,7 @@ class RuboCop::RSpec::Concept
|
|||||||
|
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/concept.rb#14
|
# source://rubocop-rspec//lib/rubocop/rspec/concept.rb#18
|
||||||
def ==(other); end
|
def ==(other); end
|
||||||
|
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
@ -7356,129 +7375,137 @@ end
|
|||||||
|
|
||||||
# This is used in Dialect and DescribeClass cops to detect RSpec blocks.
|
# This is used in Dialect and DescribeClass cops to detect RSpec blocks.
|
||||||
#
|
#
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#201
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#207
|
||||||
module RuboCop::RSpec::Language::ALL
|
module RuboCop::RSpec::Language::ALL
|
||||||
class << self
|
class << self
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#202
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#208
|
||||||
def all(element); end
|
def all(element); end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#75
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#75
|
||||||
|
module RuboCop::RSpec::Language::ErrorMatchers
|
||||||
|
class << self
|
||||||
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#76
|
||||||
|
def all(element); end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#81
|
||||||
module RuboCop::RSpec::Language::ExampleGroups
|
module RuboCop::RSpec::Language::ExampleGroups
|
||||||
class << self
|
class << self
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#77
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#83
|
||||||
def all(element); end
|
def all(element); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#87
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#93
|
||||||
def focused(element); end
|
def focused(element); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#83
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#89
|
||||||
def regular(element); end
|
def regular(element); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#91
|
|
||||||
def skipped(element); end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#97
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#97
|
||||||
module RuboCop::RSpec::Language::Examples
|
|
||||||
class << self
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#99
|
|
||||||
def all(element); end
|
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#110
|
|
||||||
def focused(element); end
|
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#118
|
|
||||||
def pending(element); end
|
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#106
|
|
||||||
def regular(element); end
|
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#114
|
|
||||||
def skipped(element); end
|
def skipped(element); end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#124
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#103
|
||||||
module RuboCop::RSpec::Language::Expectations
|
module RuboCop::RSpec::Language::Examples
|
||||||
class << self
|
class << self
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#125
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#105
|
||||||
def all(element); end
|
def all(element); end
|
||||||
|
|
||||||
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#116
|
||||||
|
def focused(element); end
|
||||||
|
|
||||||
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#124
|
||||||
|
def pending(element); end
|
||||||
|
|
||||||
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#112
|
||||||
|
def regular(element); end
|
||||||
|
|
||||||
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#120
|
||||||
|
def skipped(element); end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#130
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#130
|
||||||
module RuboCop::RSpec::Language::Helpers
|
module RuboCop::RSpec::Language::Expectations
|
||||||
class << self
|
class << self
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#131
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#131
|
||||||
def all(element); end
|
def all(element); end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#142
|
|
||||||
module RuboCop::RSpec::Language::HookScopes
|
|
||||||
class << self
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#144
|
|
||||||
def all(element); end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#143
|
|
||||||
RuboCop::RSpec::Language::HookScopes::ALL = T.let(T.unsafe(nil), Array)
|
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#136
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#136
|
||||||
module RuboCop::RSpec::Language::Hooks
|
module RuboCop::RSpec::Language::Helpers
|
||||||
class << self
|
class << self
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#137
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#137
|
||||||
def all(element); end
|
def all(element); end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#148
|
||||||
|
module RuboCop::RSpec::Language::HookScopes
|
||||||
|
class << self
|
||||||
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#150
|
||||||
|
def all(element); end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#149
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#149
|
||||||
|
RuboCop::RSpec::Language::HookScopes::ALL = T.let(T.unsafe(nil), Array)
|
||||||
|
|
||||||
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#142
|
||||||
|
module RuboCop::RSpec::Language::Hooks
|
||||||
|
class << self
|
||||||
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#143
|
||||||
|
def all(element); end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#155
|
||||||
module RuboCop::RSpec::Language::Includes
|
module RuboCop::RSpec::Language::Includes
|
||||||
class << self
|
class << self
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#151
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#157
|
||||||
def all(element); end
|
def all(element); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#160
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#166
|
||||||
def context(element); end
|
def context(element); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#156
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#162
|
||||||
def examples(element); end
|
def examples(element); end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#166
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#172
|
||||||
module RuboCop::RSpec::Language::Runners
|
module RuboCop::RSpec::Language::Runners
|
||||||
class << self
|
class << self
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#169
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#175
|
||||||
def all(element = T.unsafe(nil)); end
|
def all(element = T.unsafe(nil)); end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#167
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#173
|
||||||
RuboCop::RSpec::Language::Runners::ALL = T.let(T.unsafe(nil), Array)
|
RuboCop::RSpec::Language::Runners::ALL = T.let(T.unsafe(nil), Array)
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#177
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#183
|
||||||
module RuboCop::RSpec::Language::SharedGroups
|
module RuboCop::RSpec::Language::SharedGroups
|
||||||
class << self
|
class << self
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#179
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#185
|
||||||
def all(element); end
|
def all(element); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#188
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#194
|
||||||
def context(element); end
|
def context(element); end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#184
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#190
|
||||||
def examples(element); end
|
def examples(element); end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#194
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#200
|
||||||
module RuboCop::RSpec::Language::Subjects
|
module RuboCop::RSpec::Language::Subjects
|
||||||
class << self
|
class << self
|
||||||
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#195
|
# source://rubocop-rspec//lib/rubocop/rspec/language.rb#201
|
||||||
def all(element); end
|
def all(element); end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -49,7 +49,7 @@ module Homebrew
|
|||||||
ruby_files = T.let([], T::Array[Pathname])
|
ruby_files = T.let([], T::Array[Pathname])
|
||||||
shell_files = T.let([], T::Array[Pathname])
|
shell_files = T.let([], T::Array[Pathname])
|
||||||
actionlint_files = T.let([], T::Array[Pathname])
|
actionlint_files = T.let([], T::Array[Pathname])
|
||||||
Array(files).map(&method(:Pathname))
|
Array(files).map { Pathname(_1) }
|
||||||
.each do |path|
|
.each do |path|
|
||||||
case path.extname
|
case path.extname
|
||||||
when ".rb"
|
when ".rb"
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
# typed: strict
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require "plist"
|
require "plist"
|
||||||
@ -21,33 +21,121 @@ class SystemCommand
|
|||||||
# Run a fallible system command.
|
# Run a fallible system command.
|
||||||
#
|
#
|
||||||
# @api internal
|
# @api internal
|
||||||
def system_command(executable, **options)
|
sig {
|
||||||
SystemCommand.run(executable, **options)
|
params(
|
||||||
|
executable: T.any(String, Pathname),
|
||||||
|
args: T::Array[T.any(String, Integer, Float, Pathname, URI::Generic)],
|
||||||
|
sudo: T::Boolean,
|
||||||
|
sudo_as_root: T::Boolean,
|
||||||
|
env: T::Hash[String, String],
|
||||||
|
input: T.any(String, T::Array[String]),
|
||||||
|
must_succeed: T::Boolean,
|
||||||
|
print_stdout: T.any(T::Boolean, Symbol),
|
||||||
|
print_stderr: T.any(T::Boolean, Symbol),
|
||||||
|
debug: T.nilable(T::Boolean),
|
||||||
|
verbose: T.nilable(T::Boolean),
|
||||||
|
secrets: T.any(String, T::Array[String]),
|
||||||
|
chdir: T.any(String, Pathname),
|
||||||
|
reset_uid: T::Boolean,
|
||||||
|
timeout: T.nilable(T.any(Integer, Float)),
|
||||||
|
).returns(SystemCommand::Result)
|
||||||
|
}
|
||||||
|
def system_command(executable, args: [], sudo: false, sudo_as_root: false, env: {}, input: [],
|
||||||
|
must_succeed: false, print_stdout: false, print_stderr: true, debug: nil, verbose: nil,
|
||||||
|
secrets: [], chdir: T.unsafe(nil), reset_uid: false, timeout: nil)
|
||||||
|
SystemCommand.run(executable, args:, sudo:, sudo_as_root:, env:, input:, must_succeed:, print_stdout:,
|
||||||
|
print_stderr:, debug:, verbose:, secrets:, chdir:, reset_uid:, timeout:)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Run an infallible system command.
|
# Run an infallible system command.
|
||||||
#
|
#
|
||||||
# @api internal
|
# @api internal
|
||||||
def system_command!(command, **options)
|
sig {
|
||||||
SystemCommand.run!(command, **options)
|
params(
|
||||||
|
executable: T.any(String, Pathname),
|
||||||
|
args: T::Array[T.any(String, Integer, Float, Pathname, URI::Generic)],
|
||||||
|
sudo: T::Boolean,
|
||||||
|
sudo_as_root: T::Boolean,
|
||||||
|
env: T::Hash[String, String],
|
||||||
|
input: T.any(String, T::Array[String]),
|
||||||
|
print_stdout: T.any(T::Boolean, Symbol),
|
||||||
|
print_stderr: T.any(T::Boolean, Symbol),
|
||||||
|
debug: T.nilable(T::Boolean),
|
||||||
|
verbose: T.nilable(T::Boolean),
|
||||||
|
secrets: T.any(String, T::Array[String]),
|
||||||
|
chdir: T.any(String, Pathname),
|
||||||
|
reset_uid: T::Boolean,
|
||||||
|
timeout: T.nilable(T.any(Integer, Float)),
|
||||||
|
).returns(SystemCommand::Result)
|
||||||
|
}
|
||||||
|
def system_command!(executable, args: [], sudo: false, sudo_as_root: false, env: {}, input: [],
|
||||||
|
print_stdout: false, print_stderr: true, debug: nil, verbose: nil, secrets: [],
|
||||||
|
chdir: T.unsafe(nil), reset_uid: false, timeout: nil)
|
||||||
|
SystemCommand.run!(executable, args:, sudo:, sudo_as_root:, env:, input:, print_stdout:,
|
||||||
|
print_stderr:, debug:, verbose:, secrets:, chdir:, reset_uid:, timeout:)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
include Context
|
include Context
|
||||||
|
|
||||||
def self.run(executable, **options)
|
sig {
|
||||||
new(executable, **options).run!
|
params(
|
||||||
|
executable: T.any(String, Pathname),
|
||||||
|
args: T::Array[T.any(String, Integer, Float, Pathname, URI::Generic)],
|
||||||
|
sudo: T::Boolean,
|
||||||
|
sudo_as_root: T::Boolean,
|
||||||
|
env: T::Hash[String, String],
|
||||||
|
input: T.any(String, T::Array[String]),
|
||||||
|
must_succeed: T::Boolean,
|
||||||
|
print_stdout: T.any(T::Boolean, Symbol),
|
||||||
|
print_stderr: T.any(T::Boolean, Symbol),
|
||||||
|
debug: T.nilable(T::Boolean),
|
||||||
|
verbose: T.nilable(T::Boolean),
|
||||||
|
secrets: T.any(String, T::Array[String]),
|
||||||
|
chdir: T.any(NilClass, String, Pathname),
|
||||||
|
reset_uid: T::Boolean,
|
||||||
|
timeout: T.nilable(T.any(Integer, Float)),
|
||||||
|
).returns(SystemCommand::Result)
|
||||||
|
}
|
||||||
|
def self.run(executable, args: [], sudo: false, sudo_as_root: false, env: {}, input: [], must_succeed: false,
|
||||||
|
print_stdout: false, print_stderr: true, debug: nil, verbose: nil, secrets: [], chdir: nil,
|
||||||
|
reset_uid: false, timeout: nil)
|
||||||
|
new(executable, args:, sudo:, sudo_as_root:, env:, input:, must_succeed:, print_stdout:, print_stderr:, debug:,
|
||||||
|
verbose:, secrets:, chdir:, reset_uid:, timeout:).run!
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.run!(command, **options)
|
sig {
|
||||||
run(command, **options, must_succeed: true)
|
params(
|
||||||
|
executable: T.any(String, Pathname),
|
||||||
|
args: T::Array[T.any(String, Integer, Float, Pathname, URI::Generic)],
|
||||||
|
sudo: T::Boolean,
|
||||||
|
sudo_as_root: T::Boolean,
|
||||||
|
env: T::Hash[String, String],
|
||||||
|
input: T.any(String, T::Array[String]),
|
||||||
|
must_succeed: T::Boolean,
|
||||||
|
print_stdout: T.any(T::Boolean, Symbol),
|
||||||
|
print_stderr: T.any(T::Boolean, Symbol),
|
||||||
|
debug: T.nilable(T::Boolean),
|
||||||
|
verbose: T.nilable(T::Boolean),
|
||||||
|
secrets: T.any(String, T::Array[String]),
|
||||||
|
chdir: T.any(NilClass, String, Pathname),
|
||||||
|
reset_uid: T::Boolean,
|
||||||
|
timeout: T.nilable(T.any(Integer, Float)),
|
||||||
|
).returns(SystemCommand::Result)
|
||||||
|
}
|
||||||
|
def self.run!(executable, args: [], sudo: false, sudo_as_root: false, env: {}, input: [], must_succeed: true,
|
||||||
|
print_stdout: false, print_stderr: true, debug: nil, verbose: nil, secrets: [], chdir: nil,
|
||||||
|
reset_uid: false, timeout: nil)
|
||||||
|
run(executable, args:, sudo:, sudo_as_root:, env:, input:, must_succeed:, print_stdout:, print_stderr:,
|
||||||
|
debug:, verbose:, secrets:, chdir:, reset_uid:, timeout:)
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(SystemCommand::Result) }
|
sig { returns(SystemCommand::Result) }
|
||||||
def run!
|
def run!
|
||||||
$stderr.puts redact_secrets(command.shelljoin.gsub('\=', "="), @secrets) if verbose? && debug?
|
$stderr.puts redact_secrets(command.shelljoin.gsub('\=', "="), @secrets) if verbose? && debug?
|
||||||
|
|
||||||
@output = []
|
@output = T.let([], T.nilable(T::Array[[Symbol, String]]))
|
||||||
|
@output = T.must(@output)
|
||||||
|
|
||||||
each_output_line do |type, line|
|
each_output_line do |type, line|
|
||||||
case type
|
case type
|
||||||
@ -70,7 +158,7 @@ class SystemCommand
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
result = Result.new(command, @output, @status, secrets: @secrets)
|
result = Result.new(command, @output, T.must(@status), secrets: @secrets)
|
||||||
result.assert_success! if must_succeed?
|
result.assert_success! if must_succeed?
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
@ -78,7 +166,7 @@ class SystemCommand
|
|||||||
sig {
|
sig {
|
||||||
params(
|
params(
|
||||||
executable: T.any(String, Pathname),
|
executable: T.any(String, Pathname),
|
||||||
args: T::Array[T.any(String, Integer, Float, URI::Generic)],
|
args: T::Array[T.any(String, Integer, Float, Pathname, URI::Generic)],
|
||||||
sudo: T::Boolean,
|
sudo: T::Boolean,
|
||||||
sudo_as_root: T::Boolean,
|
sudo_as_root: T::Boolean,
|
||||||
env: T::Hash[String, String],
|
env: T::Hash[String, String],
|
||||||
@ -89,28 +177,14 @@ class SystemCommand
|
|||||||
debug: T.nilable(T::Boolean),
|
debug: T.nilable(T::Boolean),
|
||||||
verbose: T.nilable(T::Boolean),
|
verbose: T.nilable(T::Boolean),
|
||||||
secrets: T.any(String, T::Array[String]),
|
secrets: T.any(String, T::Array[String]),
|
||||||
chdir: T.any(String, Pathname),
|
chdir: T.any(NilClass, String, Pathname),
|
||||||
reset_uid: T::Boolean,
|
reset_uid: T::Boolean,
|
||||||
timeout: T.nilable(T.any(Integer, Float)),
|
timeout: T.nilable(T.any(Integer, Float)),
|
||||||
).void
|
).void
|
||||||
}
|
}
|
||||||
def initialize(
|
def initialize(executable, args: [], sudo: false, sudo_as_root: false, env: {}, input: [], must_succeed: false,
|
||||||
executable,
|
print_stdout: false, print_stderr: true, debug: nil, verbose: nil, secrets: [], chdir: nil,
|
||||||
args: [],
|
reset_uid: false, timeout: nil)
|
||||||
sudo: false,
|
|
||||||
sudo_as_root: false,
|
|
||||||
env: {},
|
|
||||||
input: [],
|
|
||||||
must_succeed: false,
|
|
||||||
print_stdout: false,
|
|
||||||
print_stderr: true,
|
|
||||||
debug: nil,
|
|
||||||
verbose: T.unsafe(nil),
|
|
||||||
secrets: [],
|
|
||||||
chdir: T.unsafe(nil),
|
|
||||||
reset_uid: false,
|
|
||||||
timeout: nil
|
|
||||||
)
|
|
||||||
require "extend/ENV"
|
require "extend/ENV"
|
||||||
@executable = executable
|
@executable = executable
|
||||||
@args = args
|
@args = args
|
||||||
@ -132,13 +206,13 @@ class SystemCommand
|
|||||||
raise ArgumentError, "Invalid variable name: #{name}"
|
raise ArgumentError, "Invalid variable name: #{name}"
|
||||||
end
|
end
|
||||||
@env = env
|
@env = env
|
||||||
@input = Array(input)
|
@input = T.let(Array(input), T::Array[String])
|
||||||
@must_succeed = must_succeed
|
@must_succeed = must_succeed
|
||||||
@print_stdout = print_stdout
|
@print_stdout = print_stdout
|
||||||
@print_stderr = print_stderr
|
@print_stderr = print_stderr
|
||||||
@debug = debug
|
@debug = debug
|
||||||
@verbose = verbose
|
@verbose = verbose
|
||||||
@secrets = (Array(secrets) + ENV.sensitive_environment.values).uniq
|
@secrets = T.let((Array(secrets) + ENV.sensitive_environment.values).uniq, T::Array[String])
|
||||||
@chdir = chdir
|
@chdir = chdir
|
||||||
@reset_uid = reset_uid
|
@reset_uid = reset_uid
|
||||||
@timeout = timeout
|
@timeout = timeout
|
||||||
@ -151,7 +225,20 @@ class SystemCommand
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
attr_reader :executable, :args, :input, :chdir, :env
|
sig { returns(T.any(Pathname, String)) }
|
||||||
|
attr_reader :executable
|
||||||
|
|
||||||
|
sig { returns(T::Array[T.any(String, Integer, Float, Pathname, URI::Generic)]) }
|
||||||
|
attr_reader :args
|
||||||
|
|
||||||
|
sig { returns(T::Array[String]) }
|
||||||
|
attr_reader :input
|
||||||
|
|
||||||
|
sig { returns(T.any(NilClass, String, Pathname)) }
|
||||||
|
attr_reader :chdir
|
||||||
|
|
||||||
|
sig { returns(T::Hash[String, String]) }
|
||||||
|
attr_reader :env
|
||||||
|
|
||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
def must_succeed? = @must_succeed
|
def must_succeed? = @must_succeed
|
||||||
@ -227,15 +314,13 @@ class SystemCommand
|
|||||||
|
|
||||||
sig { returns(T::Array[String]) }
|
sig { returns(T::Array[String]) }
|
||||||
def expanded_args
|
def expanded_args
|
||||||
@expanded_args ||= args.map do |arg|
|
@expanded_args ||= T.let(args.map do |arg|
|
||||||
if arg.respond_to?(:to_path)
|
if arg.is_a?(Pathname)
|
||||||
File.absolute_path(arg)
|
File.absolute_path(arg)
|
||||||
elsif arg.is_a?(Integer) || arg.is_a?(Float) || arg.is_a?(URI::Generic)
|
|
||||||
arg.to_s
|
|
||||||
else
|
else
|
||||||
arg.to_str
|
arg.to_s
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
end, T.nilable(T::Array[String]))
|
||||||
end
|
end
|
||||||
|
|
||||||
class ProcessTerminatedInterrupt < StandardError; end
|
class ProcessTerminatedInterrupt < StandardError; end
|
||||||
@ -275,7 +360,7 @@ class SystemCommand
|
|||||||
end_time = Time.now + @timeout if @timeout
|
end_time = Time.now + @timeout if @timeout
|
||||||
raise Timeout::Error if raw_wait_thr.join(Utils::Timer.remaining(end_time)).nil?
|
raise Timeout::Error if raw_wait_thr.join(Utils::Timer.remaining(end_time)).nil?
|
||||||
|
|
||||||
@status = raw_wait_thr.value
|
@status = T.let(raw_wait_thr.value, T.nilable(Process::Status))
|
||||||
rescue Interrupt
|
rescue Interrupt
|
||||||
Process.kill("INT", raw_wait_thr.pid) if raw_wait_thr && !sudo?
|
Process.kill("INT", raw_wait_thr.pid) if raw_wait_thr && !sudo?
|
||||||
raise Interrupt
|
raise Interrupt
|
||||||
@ -383,7 +468,14 @@ class SystemCommand
|
|||||||
include Context
|
include Context
|
||||||
include Utils::Output::Mixin
|
include Utils::Output::Mixin
|
||||||
|
|
||||||
attr_accessor :command, :status, :exit_status
|
sig { returns(T::Array[String]) }
|
||||||
|
attr_accessor :command
|
||||||
|
|
||||||
|
sig { returns(Process::Status) }
|
||||||
|
attr_accessor :status
|
||||||
|
|
||||||
|
sig { returns(T.nilable(Integer)) }
|
||||||
|
attr_accessor :exit_status
|
||||||
|
|
||||||
sig {
|
sig {
|
||||||
params(
|
params(
|
||||||
@ -397,7 +489,7 @@ class SystemCommand
|
|||||||
@command = command
|
@command = command
|
||||||
@output = output
|
@output = output
|
||||||
@status = status
|
@status = status
|
||||||
@exit_status = status.exitstatus
|
@exit_status = T.let(status.exitstatus, T.nilable(Integer))
|
||||||
@secrets = secrets
|
@secrets = secrets
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -410,22 +502,21 @@ class SystemCommand
|
|||||||
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def stdout
|
def stdout
|
||||||
@stdout ||= @output.select { |type,| type == :stdout }
|
@stdout ||= T.let(@output.select { |type,| type == :stdout }
|
||||||
.map { |_, line| line }
|
.map { |_, line| line }
|
||||||
.join
|
.join, T.nilable(String))
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def stderr
|
def stderr
|
||||||
@stderr ||= @output.select { |type,| type == :stderr }
|
@stderr ||= T.let(@output.select { |type,| type == :stderr }
|
||||||
.map { |_, line| line }
|
.map { |_, line| line }
|
||||||
.join
|
.join, T.nilable(String))
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def merged_output
|
def merged_output
|
||||||
@merged_output ||= @output.map { |_, line| line }
|
@merged_output ||= T.let(@output.map { |_, line| line }.join, T.nilable(String))
|
||||||
.join
|
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { returns(T::Boolean) }
|
sig { returns(T::Boolean) }
|
||||||
@ -439,10 +530,11 @@ class SystemCommand
|
|||||||
def to_ary
|
def to_ary
|
||||||
[stdout, stderr, status]
|
[stdout, stderr, status]
|
||||||
end
|
end
|
||||||
|
alias to_a to_ary
|
||||||
|
|
||||||
sig { returns(T.nilable(T.any(Array, Hash))) }
|
sig { returns(T.untyped) }
|
||||||
def plist
|
def plist
|
||||||
@plist ||= begin
|
@plist ||= T.let(begin
|
||||||
output = stdout
|
output = stdout
|
||||||
|
|
||||||
output = output.sub(/\A(.*?)(\s*<\?\s*xml)/m) do
|
output = output.sub(/\A(.*?)(\s*<\?\s*xml)/m) do
|
||||||
@ -456,7 +548,7 @@ class SystemCommand
|
|||||||
end
|
end
|
||||||
|
|
||||||
Plist.parse_xml(output, marshal: false)
|
Plist.parse_xml(output, marshal: false)
|
||||||
end
|
end, T.untyped)
|
||||||
end
|
end
|
||||||
|
|
||||||
sig { params(garbage: String).void }
|
sig { params(garbage: String).void }
|
||||||
|
|||||||
@ -102,7 +102,7 @@ module SystemConfig
|
|||||||
|
|
||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
def describe_curl
|
def describe_curl
|
||||||
out, = system_command(Utils::Curl.curl_executable, args: ["--version"], verbose: false)
|
out = system_command(Utils::Curl.curl_executable, args: ["--version"], verbose: false).stdout
|
||||||
|
|
||||||
match_data = /^curl (?<curl_version>[\d.]+)/.match(out)
|
match_data = /^curl (?<curl_version>[\d.]+)/.match(out)
|
||||||
if match_data
|
if match_data
|
||||||
|
|||||||
@ -169,6 +169,12 @@ class Tap
|
|||||||
sig { returns(String) }
|
sig { returns(String) }
|
||||||
attr_reader :repository
|
attr_reader :repository
|
||||||
|
|
||||||
|
# The repository name of this {Tap} including the leading `homebrew-`.
|
||||||
|
#
|
||||||
|
# @api public
|
||||||
|
sig { returns(String) }
|
||||||
|
attr_reader :full_repository
|
||||||
|
|
||||||
# The name of this {Tap}. It combines {#user} and {#repository} with a slash.
|
# The name of this {Tap}. It combines {#user} and {#repository} with a slash.
|
||||||
# {#name} is always in lowercase.
|
# {#name} is always in lowercase.
|
||||||
# e.g. `user/repository`
|
# e.g. `user/repository`
|
||||||
@ -210,7 +216,8 @@ class Tap
|
|||||||
@user = user
|
@user = user
|
||||||
@repository = repository
|
@repository = repository
|
||||||
@name = T.let("#{@user}/#{@repository}".downcase, String)
|
@name = T.let("#{@user}/#{@repository}".downcase, String)
|
||||||
@full_name = T.let("#{@user}/homebrew-#{@repository}", String)
|
@full_repository = T.let("homebrew-#{@repository}", String)
|
||||||
|
@full_name = T.let("#{@user}/#{@full_repository}", String)
|
||||||
@path = T.let(HOMEBREW_TAP_DIRECTORY/@full_name.downcase, Pathname)
|
@path = T.let(HOMEBREW_TAP_DIRECTORY/@full_name.downcase, Pathname)
|
||||||
@git_repository = T.let(GitRepository.new(@path), GitRepository)
|
@git_repository = T.let(GitRepository.new(@path), GitRepository)
|
||||||
end
|
end
|
||||||
@ -731,7 +738,7 @@ class Tap
|
|||||||
end
|
end
|
||||||
|
|
||||||
if (formula_count = formula_files.count).positive?
|
if (formula_count = formula_files.count).positive?
|
||||||
contents << Utils.pluralize("formula", formula_count, plural: "e", include_count: true)
|
contents << Utils.pluralize("formula", formula_count, include_count: true)
|
||||||
end
|
end
|
||||||
|
|
||||||
contents
|
contents
|
||||||
|
|||||||
@ -45,10 +45,9 @@ begin
|
|||||||
formula.extend(Debrew::Formula)
|
formula.extend(Debrew::Formula)
|
||||||
end
|
end
|
||||||
|
|
||||||
Pathname.prepend WriteMkpathExtension
|
|
||||||
|
|
||||||
ENV.extend(Stdenv)
|
ENV.extend(Stdenv)
|
||||||
ENV.setup_build_environment(formula:, testing_formula: true)
|
ENV.setup_build_environment(formula:, testing_formula: true)
|
||||||
|
Pathname.prepend WriteMkpathExtension
|
||||||
|
|
||||||
# tests can also return false to indicate failure
|
# tests can also return false to indicate failure
|
||||||
run_test = proc { |_ = nil| raise "test returned false" if formula.run_test(keep_tmp: args.keep_tmp?) == false }
|
run_test = proc { |_ = nil| raise "test returned false" if formula.run_test(keep_tmp: args.keep_tmp?) == false }
|
||||||
|
|||||||
52
Library/Homebrew/test/cask/artifact/relocated_spec.rb
Normal file
52
Library/Homebrew/test/cask/artifact/relocated_spec.rb
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "cask/artifact/relocated"
|
||||||
|
|
||||||
|
RSpec.describe Cask::Artifact::Relocated, :cask do
|
||||||
|
let(:cask) do
|
||||||
|
Cask::Cask.new("test-cask") do
|
||||||
|
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
|
||||||
|
homepage "https://brew.sh/"
|
||||||
|
version "1.0"
|
||||||
|
sha256 "67cdb8a02803ef37fdbf7e0be205863172e41a561ca446cd84f0d7ab35a99d94"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:command) { NeverSudoSystemCommand }
|
||||||
|
let(:artifact) { described_class.new(cask, "test_file.txt") }
|
||||||
|
|
||||||
|
describe "#add_altname_metadata" do
|
||||||
|
let(:file) { Pathname("/tmp/test_file.txt") }
|
||||||
|
let(:altname) { Pathname("alternate_name.txt") }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(file).to receive_messages(basename: Pathname("test_file.txt"), writable?: true, realpath: file)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when running on Linux", :needs_linux do
|
||||||
|
it "is a no-op and does not call xattr commands" do
|
||||||
|
expect(command).not_to receive(:run)
|
||||||
|
expect(command).not_to receive(:run!)
|
||||||
|
|
||||||
|
artifact.send(:add_altname_metadata, file, altname, command: command)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when running on macOS", :needs_macos do
|
||||||
|
before do
|
||||||
|
stdout_double = instance_double(SystemCommand::Result, stdout: "")
|
||||||
|
allow(command).to receive(:run).and_return(stdout_double)
|
||||||
|
allow(command).to receive(:run!)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "calls xattr commands to set metadata" do
|
||||||
|
expect(command).to receive(:run).with("/usr/bin/xattr",
|
||||||
|
args: ["-p", "com.apple.metadata:kMDItemAlternateNames", file],
|
||||||
|
print_stderr: false)
|
||||||
|
expect(command).to receive(:run!).twice
|
||||||
|
|
||||||
|
artifact.send(:add_altname_metadata, file, altname, command: command)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -236,4 +236,73 @@ RSpec.describe Cask::CaskLoader, :cask do
|
|||||||
expect(described_class.load_prefer_installed("test-cask").tap).to eq(foo_tap)
|
expect(described_class.load_prefer_installed("test-cask").tap).to eq(foo_tap)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "FromPathLoader with symlinked taps" do
|
||||||
|
let(:cask_token) { "testcask" }
|
||||||
|
let(:tmpdir) { mktmpdir }
|
||||||
|
let(:real_tap_path) { tmpdir / "real_tap" }
|
||||||
|
let(:homebrew_prefix) { tmpdir / "homebrew" }
|
||||||
|
let(:taps_dir) { homebrew_prefix / "Library" / "Taps" / "testuser" }
|
||||||
|
let(:symlinked_tap_path) { taps_dir / "homebrew-testtap" }
|
||||||
|
let(:cask_file_path) { symlinked_tap_path / "Casks" / "#{cask_token}.rb" }
|
||||||
|
let(:cask_content) do
|
||||||
|
<<~RUBY
|
||||||
|
cask "#{cask_token}" do
|
||||||
|
version "1.0.0"
|
||||||
|
sha256 "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
|
||||||
|
|
||||||
|
url "https://example.com/#{cask_token}-\#{version}.dmg"
|
||||||
|
name "Test Cask"
|
||||||
|
desc "A test cask for symlink testing"
|
||||||
|
homepage "https://example.com"
|
||||||
|
|
||||||
|
app "TestCask.app"
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
tmpdir.rmtree if tmpdir.exist?
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
# Create real tap directory structure
|
||||||
|
(real_tap_path / "Casks").mkpath
|
||||||
|
(real_tap_path / "Casks" / "#{cask_token}.rb").write(cask_content)
|
||||||
|
|
||||||
|
# Create homebrew prefix structure
|
||||||
|
taps_dir.mkpath
|
||||||
|
|
||||||
|
# Create symlink to the tap (this simulates what setup-homebrew does)
|
||||||
|
symlinked_tap_path.make_symlink(real_tap_path)
|
||||||
|
|
||||||
|
# Set HOMEBREW_LIBRARY to our test prefix for the security check
|
||||||
|
stub_const("HOMEBREW_LIBRARY", homebrew_prefix / "Library")
|
||||||
|
allow(Homebrew::EnvConfig).to receive(:forbid_packages_from_paths?).and_return(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when HOMEBREW_FORBID_PACKAGES_FROM_PATHS is enabled" do
|
||||||
|
it "allows loading casks from symlinked taps" do
|
||||||
|
loader = Cask::CaskLoader::FromPathLoader.try_new(cask_file_path)
|
||||||
|
expect(loader).not_to be_nil
|
||||||
|
expect(loader).to be_a(Cask::CaskLoader::FromPathLoader)
|
||||||
|
|
||||||
|
cask = loader.load(config: nil)
|
||||||
|
expect(cask.token).to eq(cask_token)
|
||||||
|
expect(cask.version).to eq(Version.new("1.0.0"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "when HOMEBREW_FORBID_PACKAGES_FROM_PATHS is disabled" do
|
||||||
|
before do
|
||||||
|
allow(Homebrew::EnvConfig).to receive(:forbid_packages_from_paths?).and_return(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "allows loading casks from symlinked taps" do
|
||||||
|
loader = Cask::CaskLoader::FromPathLoader.try_new(cask_file_path)
|
||||||
|
expect(loader).not_to be_nil
|
||||||
|
expect(loader).to be_a(Cask::CaskLoader::FromPathLoader)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -364,26 +364,6 @@ RSpec.describe Cask::Cask, :cask do
|
|||||||
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine/darwin/1.0.0/intel.zip",
|
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine/darwin/1.0.0/intel.zip",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"sha256": "1866dfa833b123bb8fe7fa7185ebf24d28d300d0643d75798bc23730af734216"
|
"sha256": "1866dfa833b123bb8fe7fa7185ebf24d28d300d0643d75798bc23730af734216"
|
||||||
},
|
|
||||||
"mojave": {
|
|
||||||
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine/darwin/1.0.0/intel.zip",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"sha256": "1866dfa833b123bb8fe7fa7185ebf24d28d300d0643d75798bc23730af734216"
|
|
||||||
},
|
|
||||||
"high_sierra": {
|
|
||||||
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine/darwin/1.0.0/intel.zip",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"sha256": "1866dfa833b123bb8fe7fa7185ebf24d28d300d0643d75798bc23730af734216"
|
|
||||||
},
|
|
||||||
"sierra": {
|
|
||||||
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine/darwin/1.0.0/intel.zip",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"sha256": "1866dfa833b123bb8fe7fa7185ebf24d28d300d0643d75798bc23730af734216"
|
|
||||||
},
|
|
||||||
"el_capitan": {
|
|
||||||
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine/darwin/1.0.0/intel.zip",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"sha256": "1866dfa833b123bb8fe7fa7185ebf24d28d300d0643d75798bc23730af734216"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
JSON
|
JSON
|
||||||
@ -418,22 +398,6 @@ RSpec.describe Cask::Cask, :cask do
|
|||||||
"catalina": {
|
"catalina": {
|
||||||
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel.zip",
|
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel.zip",
|
||||||
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
||||||
},
|
|
||||||
"mojave": {
|
|
||||||
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel.zip",
|
|
||||||
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
|
||||||
},
|
|
||||||
"high_sierra": {
|
|
||||||
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel.zip",
|
|
||||||
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
|
||||||
},
|
|
||||||
"sierra": {
|
|
||||||
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel.zip",
|
|
||||||
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
|
||||||
},
|
|
||||||
"el_capitan": {
|
|
||||||
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel.zip",
|
|
||||||
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
JSON
|
JSON
|
||||||
@ -469,22 +433,6 @@ RSpec.describe Cask::Cask, :cask do
|
|||||||
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel-darwin.zip",
|
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel-darwin.zip",
|
||||||
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
||||||
},
|
},
|
||||||
"mojave": {
|
|
||||||
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel-darwin.zip",
|
|
||||||
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
|
||||||
},
|
|
||||||
"high_sierra": {
|
|
||||||
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel-darwin.zip",
|
|
||||||
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
|
||||||
},
|
|
||||||
"sierra": {
|
|
||||||
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel-darwin.zip",
|
|
||||||
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
|
||||||
},
|
|
||||||
"el_capitan": {
|
|
||||||
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel-darwin.zip",
|
|
||||||
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
|
||||||
},
|
|
||||||
"x86_64_linux": {
|
"x86_64_linux": {
|
||||||
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel-linux.zip",
|
"url": "file://#{TEST_FIXTURE_DIR}/cask/caffeine-intel-linux.zip",
|
||||||
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
"sha256": "8c62a2b791cf5f0da6066a0a4b6e85f62949cd60975da062df44adf887f4370b"
|
||||||
|
|||||||
@ -175,7 +175,7 @@ RSpec.describe Homebrew::CLI::Parser do
|
|||||||
flag "--flag2=", depends_on: "--flag1="
|
flag "--flag2=", depends_on: "--flag1="
|
||||||
flag "--flag3="
|
flag "--flag3="
|
||||||
|
|
||||||
conflicts "--flag1=", "--flag3="
|
conflicts "--flag1", "--flag3"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -204,7 +204,8 @@ RSpec.describe Homebrew::CLI::Parser do
|
|||||||
described_class.new(Cmd) do
|
described_class.new(Cmd) do
|
||||||
flag "--flag1="
|
flag "--flag1="
|
||||||
flag "--flag2=", depends_on: "--flag1="
|
flag "--flag2=", depends_on: "--flag1="
|
||||||
conflicts "--flag1=", "--flag2="
|
|
||||||
|
conflicts "--flag1", "--flag2"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,61 @@ require "os/linux/ld"
|
|||||||
require "tmpdir"
|
require "tmpdir"
|
||||||
|
|
||||||
RSpec.describe OS::Linux::Ld do
|
RSpec.describe OS::Linux::Ld do
|
||||||
|
let(:diagnostics) do
|
||||||
|
<<~EOS
|
||||||
|
path.prefix="/usr"
|
||||||
|
path.sysconfdir="/usr/local/etc"
|
||||||
|
path.system_dirs[0x0]="/lib64"
|
||||||
|
path.system_dirs[0x1]="/var/lib"
|
||||||
|
EOS
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "::system_ld_so" do
|
||||||
|
let(:ld_so) { "/lib/ld-linux.so.3" }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(File).to receive(:executable?).and_return(false)
|
||||||
|
described_class.instance_variable_set(:@system_ld_so, nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns the path to a known dynamic linker" do
|
||||||
|
allow(File).to receive(:executable?).with(ld_so).and_return(true)
|
||||||
|
expect(described_class.system_ld_so).to eq(Pathname(ld_so))
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns nil when there is no known dynamic linker" do
|
||||||
|
expect(described_class.system_ld_so).to be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "::sysconfdir" do
|
||||||
|
it "returns path.sysconfdir" do
|
||||||
|
allow(described_class).to receive(:ld_so_diagnostics).and_return(diagnostics)
|
||||||
|
expect(described_class.sysconfdir).to eq("/usr/local/etc")
|
||||||
|
expect(described_class.sysconfdir(brewed: false)).to eq("/usr/local/etc")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns fallback on blank diagnostics" do
|
||||||
|
allow(described_class).to receive(:ld_so_diagnostics).and_return("")
|
||||||
|
expect(described_class.sysconfdir).to eq("/etc")
|
||||||
|
expect(described_class.sysconfdir(brewed: false)).to eq("/etc")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "::system_dirs" do
|
||||||
|
it "returns all path.system_dirs" do
|
||||||
|
allow(described_class).to receive(:ld_so_diagnostics).and_return(diagnostics)
|
||||||
|
expect(described_class.system_dirs).to eq(["/lib64", "/var/lib"])
|
||||||
|
expect(described_class.system_dirs(brewed: false)).to eq(["/lib64", "/var/lib"])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns an empty array on blank diagnostics" do
|
||||||
|
allow(described_class).to receive(:ld_so_diagnostics).and_return("")
|
||||||
|
expect(described_class.system_dirs).to eq([])
|
||||||
|
expect(described_class.system_dirs(brewed: false)).to eq([])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "::library_paths" do
|
describe "::library_paths" do
|
||||||
ld_etc = Pathname("")
|
ld_etc = Pathname("")
|
||||||
before do
|
before do
|
||||||
|
|||||||
58
Library/Homebrew/test/os/linux/libstdcxx_spec.rb
Normal file
58
Library/Homebrew/test/os/linux/libstdcxx_spec.rb
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "os/linux/libstdcxx"
|
||||||
|
|
||||||
|
RSpec.describe OS::Linux::Libstdcxx do
|
||||||
|
describe "::below_ci_version?" do
|
||||||
|
it "returns false when system version matches CI version" do
|
||||||
|
allow(described_class).to receive(:system_version).and_return(Version.new(OS::LINUX_LIBSTDCXX_CI_VERSION))
|
||||||
|
expect(described_class.below_ci_version?).to be false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns true when system version cannot be detected" do
|
||||||
|
allow(described_class).to receive(:system_version).and_return(Version::NULL)
|
||||||
|
expect(described_class.below_ci_version?).to be true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "::system_version" do
|
||||||
|
let(:tmpdir) { mktmpdir }
|
||||||
|
let(:libstdcxx) { tmpdir/described_class::SONAME }
|
||||||
|
let(:soversion) { Version.new(described_class::SOVERSION.to_s) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
tmpdir.mkpath
|
||||||
|
described_class.instance_variable_set(:@system_version, nil)
|
||||||
|
allow(described_class).to receive(:system_path).and_return(libstdcxx)
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
FileUtils.rm_rf(tmpdir)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns NULL when unable to find system path" do
|
||||||
|
allow(described_class).to receive(:system_path).and_return(nil)
|
||||||
|
expect(described_class.system_version).to be Version::NULL
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns full version from filename" do
|
||||||
|
full_version = Version.new("#{soversion}.0.999")
|
||||||
|
libstdcxx_real = libstdcxx.sub_ext(".#{full_version}")
|
||||||
|
FileUtils.touch libstdcxx_real
|
||||||
|
FileUtils.ln_s libstdcxx_real, libstdcxx
|
||||||
|
expect(described_class.system_version).to eq full_version
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns major version when non-standard libstdc++ filename without full version" do
|
||||||
|
FileUtils.touch libstdcxx
|
||||||
|
expect(described_class.system_version).to eq soversion
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns major version when non-standard libstdc++ filename with unexpected realpath" do
|
||||||
|
libstdcxx_real = tmpdir/"libstdc++.so.real"
|
||||||
|
FileUtils.touch libstdcxx_real
|
||||||
|
FileUtils.ln_s libstdcxx_real, libstdcxx
|
||||||
|
expect(described_class.system_version).to eq soversion
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -9,7 +9,7 @@ cask "with-depends-on-everything" do
|
|||||||
depends_on cask: "local-caffeine"
|
depends_on cask: "local-caffeine"
|
||||||
depends_on cask: "with-depends-on-cask"
|
depends_on cask: "with-depends-on-cask"
|
||||||
depends_on formula: "unar"
|
depends_on formula: "unar"
|
||||||
depends_on macos: ">= :el_capitan"
|
depends_on macos: ">= :catalina"
|
||||||
|
|
||||||
app "Caffeine.app"
|
app "Caffeine.app"
|
||||||
end
|
end
|
||||||
|
|||||||
@ -7,7 +7,7 @@ cask "with-depends-on-macos-comparison" do
|
|||||||
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
|
url "file://#{TEST_FIXTURE_DIR}/cask/caffeine.zip"
|
||||||
homepage "https://brew.sh/with-depends-on-macos-comparison"
|
homepage "https://brew.sh/with-depends-on-macos-comparison"
|
||||||
|
|
||||||
depends_on macos: ">= :el_capitan"
|
depends_on macos: ">= :catalina"
|
||||||
|
|
||||||
app "Caffeine.app"
|
app "Caffeine.app"
|
||||||
end
|
end
|
||||||
|
|||||||
@ -82,7 +82,7 @@
|
|||||||
],
|
],
|
||||||
"macos": {
|
"macos": {
|
||||||
">=": [
|
">=": [
|
||||||
"10.11"
|
"10.15"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
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