Skip to content

Commit 0bfdc8c

Browse files
committed
fetch: add --all-platforms to fetch every cask variant
- Iterate the full OS/arch matrix plus each `language` for `--all-platforms`, downloading each distinct URL once. This covers per-macOS-version URL variants, not just a fixed set of corners. - Collapse to a single combination for casks without `on_system` blocks, since they resolve identically on every platform. - Tolerate `CaskInvalidError`/`CaskUnreadableError` for casks that omit some platforms (mirrors the `bump-cask-pr.rb` rescue pattern). - Warn when a cask is loaded from the API, since OS/arch cannot be simulated without the source. Signed-off-by: Patrick Linnane <patrick@linnane.io>
1 parent edf610a commit 0bfdc8c

8 files changed

Lines changed: 80 additions & 20 deletions

File tree

Library/Homebrew/cli/args.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,10 @@ def only_formula_or_cask
128128
def os_arch_combinations
129129
skip_invalid_combinations = false
130130

131-
oses = case (os_sym = @table[:os]&.to_sym)
131+
# `--all-platforms` is equivalent to `--os=all --arch=all`.
132+
all_platforms = @table[:all_platforms?]
133+
134+
oses = case (os_sym = all_platforms ? :all : @table[:os]&.to_sym)
132135
when nil
133136
[SimulateSystem.current_os]
134137
when :all
@@ -139,7 +142,7 @@ def os_arch_combinations
139142
[os_sym]
140143
end
141144

142-
arches = case (arch_sym = @table[:arch]&.to_sym)
145+
arches = case (arch_sym = all_platforms ? :all : @table[:arch]&.to_sym)
143146
when nil
144147
[SimulateSystem.current_arch]
145148
when :all

Library/Homebrew/cmd/fetch.rb

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
require "abstract_command"
55
require "formula"
66
require "fetch"
7+
require "cask/config"
78
require "cask/download"
89
require "download_queue"
910

@@ -25,6 +26,9 @@ class FetchCmd < AbstractCommand
2526
flag "--arch=",
2627
description: "Download for the given CPU architecture. " \
2728
"(Pass `all` to download for all architectures.)"
29+
switch "--all-platforms",
30+
description: "Download each <cask> for every supported operating system, architecture and " \
31+
"language, fetching each distinct URL once."
2832
flag "--bottle-tag=",
2933
description: "Download a bottle for given tag."
3034
switch "--HEAD",
@@ -65,6 +69,10 @@ class FetchCmd < AbstractCommand
6569
conflicts "--formula", "--cask"
6670
conflicts "--os", "--bottle-tag"
6771
conflicts "--arch", "--bottle-tag"
72+
conflicts "--all-platforms", "--os"
73+
conflicts "--all-platforms", "--arch"
74+
conflicts "--all-platforms", "--bottle-tag"
75+
conflicts "--all-platforms", "--formula"
6876

6977
named_args [:formula, :cask], min: 1
7078
end
@@ -158,24 +166,59 @@ def run
158166
ref = cask.loaded_from_api? ? cask.full_name : cask.sourcefile_path
159167
odie "unexpected nil cask sourcefile_path" unless ref
160168

161-
os_arch_combinations.each do |os, arch|
162-
SimulateSystem.with(os:, arch:) do
163-
cask = Cask::CaskLoader.load(ref)
169+
quarantine = args.quarantine?
170+
quarantine = true if quarantine.nil?
171+
172+
if args.all_platforms? && cask.loaded_from_api?
173+
opoo "Cask #{cask} was loaded from the API; cannot fetch all operating system and " \
174+
"architecture variants. Set `HOMEBREW_NO_INSTALL_FROM_API=1` to fetch them all."
175+
end
176+
177+
# A cask without `on_system` blocks resolves identically on every
178+
# OS/arch, so a single combination covers the whole matrix.
179+
cask_combinations = if cask.on_system_blocks_exist?
180+
os_arch_combinations
181+
else
182+
os_arch_combinations.first(1)
183+
end
164184

165-
if cask.url.nil? || cask.sha256.nil?
166-
opoo "Cask #{cask} is not supported on os #{os} and arch #{arch}"
167-
next
185+
enqueued_urls = Set.new
186+
187+
cask_combinations.each do |os, arch|
188+
SimulateSystem.with(os:, arch:) do
189+
loaded_cask = begin
190+
Cask::CaskLoader.load(ref)
191+
rescue Cask::CaskInvalidError, Cask::CaskUnreadableError
192+
raise unless cask.on_system_blocks_exist?
168193
end
194+
next if loaded_cask.nil?
195+
196+
languages = (loaded_cask.languages if args.all_platforms?)
197+
languages = [nil] if languages.blank?
198+
199+
languages.each do |language|
200+
localized_cask = loaded_cask
201+
if language
202+
localized_cask = Cask::CaskLoader.load(ref)
203+
localized_cask.config = localized_cask.config.merge(
204+
Cask::Config.new(explicit: { languages: [language] }),
205+
)
206+
end
169207

170-
quarantine = args.quarantine?
171-
quarantine = true if quarantine.nil?
208+
if localized_cask.url.nil? || localized_cask.sha256.nil?
209+
opoo "Cask #{cask} is not supported on os #{os} and arch #{arch}"
210+
next
211+
end
172212

173-
download = Cask::Download.new(
174-
cask,
175-
quarantine:,
176-
require_sha: Homebrew::EnvConfig.cask_opts_require_sha?,
177-
)
178-
download_queue.enqueue(download)
213+
next unless enqueued_urls.add?(localized_cask.url.to_s)
214+
215+
download = Cask::Download.new(
216+
localized_cask,
217+
quarantine:,
218+
require_sha: Homebrew::EnvConfig.cask_opts_require_sha?,
219+
)
220+
download_queue.enqueue(download)
221+
end
179222
end
180223
end
181224
else

Library/Homebrew/sorbet/rbi/dsl/homebrew/cmd/fetch_cmd.rbi

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

completions/bash/brew

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,6 +1453,7 @@ _brew_fetch() {
14531453
-*)
14541454
__brewcomp "
14551455
--HEAD
1456+
--all-platforms
14561457
--arch
14571458
--bottle-tag
14581459
--build-bottle

completions/fish/brew.fish

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,7 @@ __fish_brew_complete_arg 'extract' -a '(__fish_brew_suggest_taps_installed)'
974974

975975
__fish_brew_complete_cmd 'fetch' 'Download a bottle (if available) or source packages for formulae and binaries for casks'
976976
__fish_brew_complete_arg 'fetch' -l HEAD -d 'Fetch HEAD version instead of stable version'
977+
__fish_brew_complete_arg 'fetch' -l all-platforms -d 'Download each cask for every supported operating system, architecture and language, fetching each distinct URL once'
977978
__fish_brew_complete_arg 'fetch' -l arch -d 'Download for the given CPU architecture. (Pass `all` to download for all architectures.)'
978979
__fish_brew_complete_arg 'fetch' -l bottle-tag -d 'Download a bottle for given tag'
979980
__fish_brew_complete_arg 'fetch' -l build-bottle -d 'Download source packages (for eventual bottling) rather than a bottle'

completions/zsh/_brew

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,21 +1274,22 @@ _brew_extract() {
12741274
_brew_fetch() {
12751275
_arguments \
12761276
'(--cask)--HEAD[Fetch HEAD version instead of stable version]' \
1277-
'(--bottle-tag)--arch[Download for the given CPU architecture. (Pass `all` to download for all architectures.)]' \
1278-
'(--build-from-source --build-bottle --force-bottle --cask --os --arch)--bottle-tag[Download a bottle for given tag]' \
1277+
'(--os --arch --bottle-tag --formula)--all-platforms[Download each cask for every supported operating system, architecture and language, fetching each distinct URL once]' \
1278+
'(--bottle-tag --all-platforms)--arch[Download for the given CPU architecture. (Pass `all` to download for all architectures.)]' \
1279+
'(--build-from-source --build-bottle --force-bottle --cask --os --arch --all-platforms)--bottle-tag[Download a bottle for given tag]' \
12791280
'(--build-from-source --force-bottle --bottle-tag --cask)--build-bottle[Download source packages (for eventual bottling) rather than a bottle]' \
12801281
'(--build-bottle --force-bottle --bottle-tag)--build-from-source[Download source packages rather than a bottle]' \
12811282
'--debug[Display any debugging information]' \
12821283
'(--cask)--deps[Also download dependencies for any listed formula]' \
12831284
'--force[Remove a previously cached version and re-fetch]' \
12841285
'(--build-from-source --build-bottle --bottle-tag --cask)--force-bottle[Download a bottle if it exists for the current or newest version of macOS, even if it would not be used during installation]' \
12851286
'--help[Show this message]' \
1286-
'(--bottle-tag)--os[Download for the given operating system. (Pass `all` to download for all operating systems.)]' \
1287+
'(--bottle-tag --all-platforms)--os[Download for the given operating system. (Pass `all` to download for all operating systems.)]' \
12871288
'--quiet[Make some output more quiet]' \
12881289
'--retry[Retry if downloading fails or re-download if the checksum of a previously cached version no longer matches. Tries at most 5 times with exponential backoff]' \
12891290
'--verbose[Do a verbose VCS checkout, if the URL represents a VCS. This is useful for seeing if an existing VCS cache has been updated]' \
12901291
- formula \
1291-
'(--cask)--formula[Treat all named arguments as formulae]' \
1292+
'(--cask --all-platforms)--formula[Treat all named arguments as formulae]' \
12921293
'*:formula:__brew_formulae' \
12931294
- cask \
12941295
'(--HEAD --deps -s --build-bottle --force-bottle --bottle-tag --formula)--cask[Treat all named arguments as casks]' \

docs/Manpage.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,11 @@ binaries for *`cask`*s. For files, also print SHA-256 checksums.
993993
: Download for the given CPU architecture. (Pass `all` to download for all
994994
architectures.)
995995

996+
`--all-platforms`
997+
998+
: Download each *`cask`* for every supported operating system, architecture and
999+
language, fetching each distinct URL once.
1000+
9961001
`--bottle-tag`
9971002

9981003
: Download a bottle for given tag.

manpages/brew.1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,9 @@ Download for the given operating system\. (Pass \fBall\fP to download for all op
650650
\fB\-\-arch\fP
651651
Download for the given CPU architecture\. (Pass \fBall\fP to download for all architectures\.)
652652
.TP
653+
\fB\-\-all\-platforms\fP
654+
Download each \fIcask\fP for every supported operating system, architecture and language, fetching each distinct URL once\.
655+
.TP
653656
\fB\-\-bottle\-tag\fP
654657
Download a bottle for given tag\.
655658
.TP

0 commit comments

Comments
 (0)