Improve Download Queue output

Update the naming, presence and values for various download queue
methods to improve the output for users while making the internal code
a little easier to follow.

While we're here, also ensure that a single formula download still
displays the download queue output and indirectly fix an issue with
bottle manifests being named incorrectly.
This commit is contained in:
Mike McQuaid 2025-08-04 15:51:02 +01:00
parent 9e4bedad2f
commit 774ef54981
No known key found for this signature in database
10 changed files with 48 additions and 70 deletions

View File

@ -44,10 +44,7 @@ module Homebrew
end end
sig { override.returns(String) } sig { override.returns(String) }
def name = download_name def download_queue_type = "JSON API"
sig { override.returns(String) }
def download_type = "JSON API"
end end
end end
end end

View File

@ -37,10 +37,7 @@ module Homebrew
end end
sig { override.returns(String) } sig { override.returns(String) }
def name = download_name def download_queue_type = "API Source"
sig { override.returns(String) }
def download_type = "API Source"
sig { override.returns(Pathname) } sig { override.returns(Pathname) }
def cache def cache

View File

@ -186,7 +186,10 @@ class Bottle
end end
sig { override.returns(String) } sig { override.returns(String) }
def download_type = "Bottle" def download_queue_type = "Bottle"
sig { override.returns(String) }
def download_queue_name = "#{name} (#{resource.version})"
private private

View File

@ -24,11 +24,6 @@ module Cask
@quarantine = quarantine @quarantine = quarantine
end end
sig { override.returns(String) }
def name
cask.token
end
sig { override.returns(T.nilable(::URL)) } sig { override.returns(T.nilable(::URL)) }
def url def url
return if (cask_url = cask.url).nil? return if (cask_url = cask.url).nil?
@ -95,10 +90,10 @@ module Cask
end end
sig { override.returns(String) } sig { override.returns(String) }
def download_name = cask.token def download_queue_name = "#{cask.token} (#{version})"
sig { override.returns(String) } sig { override.returns(String) }
def download_type = "Cask" def download_queue_type = "Cask"
private private

View File

@ -32,11 +32,11 @@ module Homebrew
def fetch def fetch
return if downloads.empty? return if downloads.empty?
if concurrency == 1 || downloads.one? if concurrency == 1
downloads.each do |downloadable, promise| downloads.each do |downloadable, promise|
promise.wait! promise.wait!
rescue ChecksumMismatchError => e rescue ChecksumMismatchError => e
opoo "#{downloadable.download_type} reports different checksum: #{e.expected}" opoo "#{downloadable.download_queue_type} reports different checksum: #{e.expected}"
Homebrew.failed = true if downloadable.is_a?(Resource::Patch) Homebrew.failed = true if downloadable.is_a?(Resource::Patch)
rescue => e rescue => e
raise e unless bottle_manifest_error?(downloadable, e) raise e unless bottle_manifest_error?(downloadable, e)
@ -73,7 +73,7 @@ module Homebrew
exception = future.reason if future.rejected? exception = future.reason if future.rejected?
next 1 if bottle_manifest_error?(downloadable, exception) next 1 if bottle_manifest_error?(downloadable, exception)
message = "#{downloadable.download_type} #{downloadable.name}" message = "#{downloadable.download_queue_type} #{downloadable.download_queue_name}"
if tty if tty
stdout_print_and_flush "#{status} #{message}#{"\n" unless last}" stdout_print_and_flush "#{status} #{message}#{"\n" unless last}"
elsif status elsif status
@ -82,7 +82,7 @@ module Homebrew
if future.rejected? if future.rejected?
if exception.is_a?(ChecksumMismatchError) if exception.is_a?(ChecksumMismatchError)
opoo "#{downloadable.download_type} reports different checksum: #{exception.expected}" opoo "#{downloadable.download_queue_type} reports different checksum: #{exception.expected}"
Homebrew.failed = true if downloadable.is_a?(Resource::Patch) Homebrew.failed = true if downloadable.is_a?(Resource::Patch)
next 2 next 2
else else

View File

@ -48,14 +48,11 @@ module Downloadable
super super
end end
sig { abstract.returns(String) }
def name; end
sig { returns(String) } sig { returns(String) }
def download_type def download_queue_name = download_name
class_name = T.let(self.class, T::Class[Downloadable]).name&.split("::")&.last
T.must(class_name).gsub(/([[:lower:]])([[:upper:]])/, '\1 \2').downcase sig { abstract.returns(String) }
end def download_queue_type; end
sig(:final) { returns(T::Boolean) } sig(:final) { returns(T::Boolean) }
def downloaded? def downloaded?
@ -135,13 +132,13 @@ module Downloadable
EOS EOS
end end
private
sig { overridable.returns(String) } sig { overridable.returns(String) }
def download_name def download_name
@download_name ||= File.basename(determine_url.to_s).freeze @download_name ||= File.basename(determine_url.to_s).freeze
end end
private
sig { overridable.returns(T::Boolean) } sig { overridable.returns(T::Boolean) }
def silence_checksum_missing_error? def silence_checksum_missing_error?
false false

View File

@ -632,7 +632,7 @@ class DownloadError < RuntimeError
def initialize(downloadable, cause) def initialize(downloadable, cause)
super <<~EOS super <<~EOS
Failed to download resource #{downloadable.download_name.inspect} Failed to download resource #{downloadable.download_queue_name.inspect}
#{cause.message} #{cause.message}
EOS EOS
@cause = cause @cause = cause

View File

@ -57,19 +57,8 @@ class Resource
patches.each { |p| p.owner = owner } patches.each { |p| p.owner = owner }
end end
# Removes /s from resource names; this allows Go package names sig { override.returns(String) }
# to be used as resource names without confusing software that def download_queue_type = "Resource"
# interacts with {download_name}, e.g. `github.com/foo/bar`.
def escaped_name
name.tr("/", "-")
end
def download_name
return owner.name if name.nil?
return escaped_name if owner.nil?
"#{owner.name}--#{escaped_name}"
end
# Verifies download and unpacks it. # Verifies download and unpacks it.
# The block may call `|resource, staging| staging.retain!` to retain the staging # The block may call `|resource, staging| staging.retain!` to retain the staging
@ -236,9 +225,6 @@ class Resource
@url&.specs || {}.freeze @url&.specs || {}.freeze
end end
sig { override.returns(String) }
def download_type = "Resource"
protected protected
def stage_resource(prefix, debug_symbols: false, &block) def stage_resource(prefix, debug_symbols: false, &block)
@ -247,6 +233,19 @@ class Resource
private private
sig { override.returns(String) }
def download_name
return owner.name if name.nil?
# Removes /s from resource names; this allows Go package names
# to be used as resource names without confusing software that
# interacts with {download_name}, e.g. `github.com/foo/bar`.
escaped_name = name.tr("/", "-")
return escaped_name if owner.nil?
"#{owner.name}--#{escaped_name}"
end
def determine_url_mirrors def determine_url_mirrors
extra_urls = [] extra_urls = []
url = T.must(self.url) url = T.must(self.url)
@ -288,14 +287,10 @@ class Resource
# A resource for a formula. # A resource for a formula.
class Formula < Resource class Formula < Resource
sig { override.returns(String) } sig { override.returns(String) }
def name def download_queue_type = "Formula"
T.must(owner).name
end
sig { override.returns(String) } sig { override.returns(String) }
def download_name def download_queue_name = "#{T.must(owner).name} (#{version})"
name
end
end end
# A resource containing a Go package. # A resource containing a Go package.
@ -344,10 +339,10 @@ class Resource
end end
sig { override.returns(String) } sig { override.returns(String) }
def download_type = "Bottle Manifest" def download_queue_type = "Bottle Manifest"
sig { override.returns(String) } sig { override.returns(String) }
def name = bottle.name def download_queue_name = "#{bottle.name} (#{bottle.resource.version})"
private private
@ -403,15 +398,15 @@ class Resource
end end
sig { override.returns(String) } sig { override.returns(String) }
def download_type = "Patch" def download_queue_type = "Patch"
sig { override.returns(String) } sig { override.returns(String) }
def name def download_queue_name
if (url = self.url) if (last_url_component = url.to_s.split("/").last)
url.to_s.split("/").last return last_url_component
else
super
end end
super
end end
end end
end end

View File

@ -28,10 +28,10 @@ module Homebrew
end end
sig { override.returns(String) } sig { override.returns(String) }
def name = downloadable.name def download_queue_name = downloadable.download_queue_name
sig { override.returns(String) } sig { override.returns(String) }
def download_type = downloadable.download_type def download_queue_type = downloadable.download_queue_type
sig { override.returns(Pathname) } sig { override.returns(Pathname) }
def cached_download = downloadable.cached_download def cached_download = downloadable.cached_download
@ -103,9 +103,6 @@ module Homebrew
sig { override.params(filename: Pathname).void } sig { override.params(filename: Pathname).void }
def verify_download_integrity(filename) = downloadable.verify_download_integrity(filename) def verify_download_integrity(filename) = downloadable.verify_download_integrity(filename)
sig { override.returns(String) }
def download_name = downloadable.download_name
private private
sig { returns(Downloadable) } sig { returns(Downloadable) }

View File

@ -28,9 +28,9 @@ class SoftwareSpec
attr_reader :name, :full_name, :owner, :build, :resources, :patches, :options, :deprecated_flags, attr_reader :name, :full_name, :owner, :build, :resources, :patches, :options, :deprecated_flags,
:deprecated_options, :dependency_collector, :bottle_specification, :compiler_failures :deprecated_options, :dependency_collector, :bottle_specification, :compiler_failures
def_delegators :@resource, :stage, :fetch, :verify_download_integrity, :source_modified_time, :download_name, def_delegators :@resource, :stage, :fetch, :verify_download_integrity, :source_modified_time,
:cached_download, :clear_cache, :checksum, :mirrors, :specs, :using, :version, :mirror, :cached_download, :clear_cache, :checksum, :mirrors, :specs, :using, :version, :mirror,
:downloader :downloader, :download_queue_name, :download_queue_type
def_delegators :@resource, :sha256 def_delegators :@resource, :sha256
@ -81,9 +81,6 @@ class SoftwareSpec
super super
end end
sig { override.returns(String) }
def download_type = "Formula"
def owner=(owner) def owner=(owner)
@name = owner.name @name = owner.name
@full_name = owner.full_name @full_name = owner.full_name