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

formula: add size information to JSON API #18403

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Library/Homebrew/cmd/fetch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class FetchCmd < AbstractCommand
switch "--force-bottle",
description: "Download a bottle if it exists for the current or newest version of macOS, " \
"even if it would not be used during installation."
switch "--only-manifests",
description: "Only download GitHub Packages manifests."
switch "--[no-]quarantine",
description: "Disable/enable quarantining of downloads (default: enabled).",
env: :cask_opts_quarantine
Expand All @@ -62,6 +64,7 @@ class FetchCmd < AbstractCommand
conflicts "--cask", "--build-bottle"
conflicts "--cask", "--force-bottle"
conflicts "--cask", "--bottle-tag"
conflicts "--cask", "--only-manifests"
conflicts "--formula", "--cask"
conflicts "--os", "--bottle-tag"
conflicts "--arch", "--bottle-tag"
Expand Down Expand Up @@ -173,7 +176,7 @@ def run
if (manifest_resource = bottle.github_packages_manifest_resource)
fetch_downloadable(manifest_resource)
end
fetch_downloadable(bottle)
fetch_downloadable(bottle) unless args.only_manifests?
rescue Interrupt
raise
rescue => e
Expand All @@ -187,7 +190,7 @@ def run
end
end

next if fetched_bottle
next if fetched_bottle || args.only_manifests?

fetch_downloadable(formula.resource)

Expand Down
7 changes: 7 additions & 0 deletions Library/Homebrew/formula.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2623,6 +2623,13 @@ def bottle_hash(compact_for_api: false)
end
file_hash["sha256"] = checksum

if (bottle = bottle_for_tag(tag))
bottle_size = bottle.bottle_size
installed_size = bottle.installed_size
file_hash["bottle_size"] = bottle_size if bottle_size
file_hash["installed_size"] = installed_size if installed_size
end

hash["files"][tag.to_sym] = file_hash
end
hash
Expand Down
3 changes: 2 additions & 1 deletion Library/Homebrew/formulary.rb
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,8 @@ def self.load_formula_from_api(name, flags:)
rebuild bottles_stable["rebuild"]
bottles_stable["files"].each do |tag, bottle_spec|
cellar = Formulary.convert_to_string_or_symbol bottle_spec["cellar"]
sha256 cellar:, tag.to_sym => bottle_spec["sha256"]
sizes = bottle_spec.slice("bottle_size", "installed_size").transform_keys!(&:to_sym)
sha256 cellar:, tag.to_sym => bottle_spec["sha256"], **sizes
end
end
end
Expand Down
33 changes: 25 additions & 8 deletions Library/Homebrew/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ class Error < RuntimeError; end
def initialize(bottle)
super("#{bottle.name}_bottle_manifest")
@bottle = bottle
@manifest_annotations = nil
end

def verify_download_integrity(_filename)
Expand All @@ -314,6 +315,29 @@ def verify_download_integrity(_filename)
end

def tab
tab = manifest_annotations["sh.brew.tab"]
raise Error, "Couldn't find tab from manifest." if tab.blank?

begin
JSON.parse(tab)
rescue JSON::ParserError
raise Error, "Couldn't parse tab JSON."
end
end

def bottle_size
manifest_annotations["sh.brew.bottle.size"]&.to_i
end

def installed_size
manifest_annotations["sh.brew.bottle.installed_size"]&.to_i
end

private

def manifest_annotations
return @manifest_annotations if @manifest_annotations.present?

json = begin
JSON.parse(cached_download.read)
rescue JSON::ParserError
Expand All @@ -336,14 +360,7 @@ def tab
end
raise Error, "Couldn't find manifest matching bottle checksum." if manifest_annotations.blank?

tab = manifest_annotations["sh.brew.tab"]
raise Error, "Couldn't find tab from manifest." if tab.blank?

begin
JSON.parse(tab)
rescue JSON::ParserError
raise Error, "Couldn't parse tab JSON."
end
@manifest_annotations = manifest_annotations
end
end

Expand Down
20 changes: 19 additions & 1 deletion Library/Homebrew/software_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,8 @@ def initialize(formula, spec, tag = nil)
@tag = tag_spec.tag
@cellar = tag_spec.cellar
@rebuild = spec.rebuild
@bottle_size = tag_spec.bottle_size
@installed_size = tag_spec.installed_size

@resource.version(formula.pkg_version.to_s)
@resource.checksum = tag_spec.checksum
Expand Down Expand Up @@ -436,6 +438,22 @@ def tab_attributes
{}
end

sig { returns(T.nilable(Integer)) }
def bottle_size
return @bottle_size unless @bottle_size.nil?
return unless (resource = github_packages_manifest_resource)&.downloaded?

resource.bottle_size
end

sig { returns(T.nilable(Integer)) }
def installed_size
return @installed_size unless @installed_size.nil?
return unless (resource = github_packages_manifest_resource)&.downloaded?

resource.installed_size
end

sig { returns(Filename) }
def filename
Filename.create(resource.owner, @tag, @spec.rebuild)
Expand Down Expand Up @@ -596,7 +614,7 @@ def sha256(hash)

cellar ||= tag.default_cellar

collector.add(tag, checksum: Checksum.new(digest), cellar:)
collector.add(tag, checksum: Checksum.new(digest), cellar:, **hash.slice(:bottle_size, :installed_size))
end

sig {
Expand Down
24 changes: 20 additions & 4 deletions Library/Homebrew/utils/bottles.rb
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,18 @@ class TagSpecification
sig { returns(T.any(Symbol, String)) }
attr_reader :cellar

def initialize(tag:, checksum:, cellar:)
sig { returns(T.nilable(Integer)) }
attr_reader :bottle_size

sig { returns(T.nilable(Integer)) }
attr_reader :installed_size

def initialize(tag:, checksum:, cellar:, bottle_size: nil, installed_size: nil)
@tag = tag
@checksum = checksum
@cellar = cellar
@bottle_size = bottle_size
@installed_size = installed_size
end

def ==(other)
Expand All @@ -294,9 +302,17 @@ def ==(other)
end
alias eql? ==

sig { params(tag: Utils::Bottles::Tag, checksum: Checksum, cellar: T.any(Symbol, String)).void }
def add(tag, checksum:, cellar:)
spec = Utils::Bottles::TagSpecification.new(tag:, checksum:, cellar:)
sig {
params(
tag: Utils::Bottles::Tag,
checksum: Checksum,
cellar: T.any(Symbol, String),
bottle_size: T.nilable(Integer),
installed_size: T.nilable(Integer),
).void
}
def add(tag, checksum:, cellar:, bottle_size: nil, installed_size: nil)
spec = Utils::Bottles::TagSpecification.new(tag:, checksum:, cellar:, bottle_size:, installed_size:)
@tag_specs[tag] = spec
end

Expand Down
Loading