Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cask: add mirror stanza #16828

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 11 additions & 5 deletions Library/Homebrew/cask/cask.rb
Expand Up @@ -305,11 +305,15 @@ def eql?(other)

def to_h
url_specs = url&.specs.dup
case url_specs&.dig(:user_agent)
when :default
url_specs.delete(:user_agent)
when Symbol
url_specs[:user_agent] = ":#{url_specs[:user_agent]}"
mirror_specs = Array(mirror).map { |m| m&.specs.dup }

[url_specs, *mirror_specs].each do |specs|
case specs&.dig(:user_agent)
when :default
specs.delete(:user_agent)
when Symbol
specs[:user_agent] = ":#{specs[:user_agent]}"
end
end

{
Expand All @@ -322,6 +326,8 @@ def to_h
"homepage" => homepage,
"url" => url,
"url_specs" => url_specs,
"mirror" => mirror,
"mirror_specs" => mirror_specs,
"appcast" => appcast,
"version" => version,
"installed" => installed_version,
Expand Down
2 changes: 2 additions & 0 deletions Library/Homebrew/cask/cask.rbi
Expand Up @@ -54,6 +54,8 @@ module Cask

def url; end

def mirror; end

def version; end
end
end
9 changes: 9 additions & 0 deletions Library/Homebrew/cask/cask_loader.rb
Expand Up @@ -320,6 +320,15 @@ def load(config:)
end

url json_cask[:url], **json_cask.fetch(:url_specs, {}) if json_cask[:url].present?
json_cask[:mirror]&.each_with_index do |cask_mirror, cask_mirror_index|
cask_mirror_specs = json_cask[:mirror_specs]&.fetch(cask_mirror_index, nil).to_h
user_agent = cask_mirror_specs[:user_agent]
cask_mirror_specs[:user_agent] = user_agent[1..].to_sym if user_agent && user_agent[0] == ":"
if (using = cask_mirror_specs[:using])
cask_mirror_specs[:using] = using.to_sym
end
mirror cask_mirror, **cask_mirror_specs
end
appcast json_cask[:appcast] if json_cask[:appcast].present?
json_cask[:name]&.each do |cask_name|
name cask_name
Expand Down
16 changes: 13 additions & 3 deletions Library/Homebrew/cask/download.rb
Expand Up @@ -19,14 +19,16 @@ def initialize(cask, quarantine: nil)
super()

@cask = cask
@urls = [cask.url, *cask.mirror].compact
@urls_index = 0
@quarantine = quarantine
end

sig { override.returns(T.nilable(::URL)) }
def url
return if cask.url.nil?
return if @urls.blank?

@url ||= ::URL.new(cask.url.to_s, cask.url.specs)
@url = ::URL.new(@urls[@urls_index].to_s, @urls[@urls_index].specs)
end

sig { override.returns(T.nilable(::Checksum)) }
Expand All @@ -51,9 +53,17 @@ def version
def fetch(quiet: nil, verify_download_integrity: true, timeout: nil)
downloader.quiet! if quiet

@urls_index = 0
begin
super(verify_download_integrity: false, timeout: timeout)
rescue DownloadError => e
@urls_index += 1
if @urls_index < @urls.length
@downloader = nil
puts "Trying a mirror..."
retry
end
@urls_index = 0
Comment on lines +60 to +66
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some oddness to try to allow mirrors have their own specs.

Downloadable has mirrors-support for URL strings which will use the same specs as main URL. I guess the simpler option would be to only support verified: and then set @mirrors = ...

error = CaskError.new("Download failed on Cask '#{cask}' with message: #{e.cause}")
error.set_backtrace e.backtrace
raise error
Expand Down Expand Up @@ -97,7 +107,7 @@ def quarantine(path)
return unless Quarantine.available?

if @quarantine
Quarantine.cask!(cask: @cask, download_path: path)
Quarantine.cask!(cask: @cask, download_path: path, download_url: @url.to_s)
else
Quarantine.release!(download_path: path)
end
Expand Down
14 changes: 14 additions & 0 deletions Library/Homebrew/cask/dsl.rb
Expand Up @@ -83,6 +83,7 @@ class DSL
:sha256,
:staged_path,
:url,
:mirror,
:version,
:appdir,
:deprecate!,
Expand Down Expand Up @@ -216,6 +217,19 @@ def url(*args, **options, &block)
end
end

# @api public
def mirror(*args, **options, &block)
@mirror ||= []
return @mirror if args.empty? && options.empty? && !block

caller_location = T.must(caller_locations).fetch(0)
@mirror << if block
URL.new(*args, **options, caller_location: caller_location, dsl: self, &block)
else
URL.new(*args, **options, caller_location: caller_location)
end
end

# @api public
def appcast(*args, **kwargs)
set_unique_stanza(:appcast, args.empty? && kwargs.empty?) do
Expand Down
4 changes: 2 additions & 2 deletions Library/Homebrew/cask/quarantine.rb
Expand Up @@ -122,7 +122,7 @@ def self.release!(download_path: nil)
raise CaskQuarantineReleaseError.new(download_path, quarantiner.stderr)
end

def self.cask!(cask: nil, download_path: nil, action: true)
def self.cask!(cask: nil, download_path: nil, action: true, download_url: nil)
return if cask.nil? || download_path.nil?

return if detect(download_path)
Expand All @@ -134,7 +134,7 @@ def self.cask!(cask: nil, download_path: nil, action: true)
*swift_target_args,
QUARANTINE_SCRIPT,
download_path,
cask.url.to_s,
download_url || cask.url.to_s,
cask.homepage.to_s,
],
print_stderr: false)
Expand Down