dev-cmd/{bottle,pr-upload}: generate, upload all: $SHA256 bottles.

Generate `all: $SHA256` bottles if:
- all generated bottles have the same cellar
- all generated bottles have the same checksum

In this case, on `brew bottle --merge --write`: delete all the non-`all`
bottles (and their JSON) and upload only the single one that's
necessary.
This commit is contained in:
Mike McQuaid 2021-04-21 17:10:05 +01:00
parent e59f93cf19
commit 521d6b51a6
No known key found for this signature in database
GPG Key ID: 48A898132FD8EE70
2 changed files with 66 additions and 13 deletions

View File

@ -607,12 +607,6 @@ module Homebrew
def merge(args:) def merge(args:)
bottles_hash = merge_json_files(parse_json_files(args.named)) bottles_hash = merge_json_files(parse_json_files(args.named))
# TODO: deduplicate --no-json bottles by:
# 1. throwing away bottles for newer versions of macOS if their SHA256 is
# identical
# 2. generating `all: $SHA256` bottles that can be used on macOS and Linux
# i.e. need to be `any_skip_relocation` and contain no ELF/MachO files.
any_cellars = ["any", "any_skip_relocation"] any_cellars = ["any", "any_skip_relocation"]
bottles_hash.each do |formula_name, bottle_hash| bottles_hash.each do |formula_name, bottle_hash|
ohai formula_name ohai formula_name
@ -620,14 +614,63 @@ module Homebrew
bottle = BottleSpecification.new bottle = BottleSpecification.new
bottle.root_url bottle_hash["bottle"]["root_url"] bottle.root_url bottle_hash["bottle"]["root_url"]
bottle.rebuild bottle_hash["bottle"]["rebuild"] bottle.rebuild bottle_hash["bottle"]["rebuild"]
# if all the cellars and checksums are the same: we can create an
# `all: $SHA256` bottle.
tag_hashes = bottle_hash["bottle"]["tags"].values
all_bottle = (tag_hashes.count > 1) && tag_hashes.uniq do |tag_hash|
"#{tag_hash["cellar"]}-#{tag_hash["sha256"]}"
end.count == 1
bottle_hash["bottle"]["tags"].each do |tag, tag_hash| bottle_hash["bottle"]["tags"].each do |tag, tag_hash|
cellar = tag_hash["cellar"] cellar = tag_hash["cellar"]
cellar = cellar.to_sym if any_cellars.include?(cellar) cellar = cellar.to_sym if any_cellars.include?(cellar)
sha256_hash = { cellar: cellar, tag.to_sym => tag_hash["sha256"] }
tag_sym = if all_bottle
:all
else
tag.to_sym
end
sha256_hash = { cellar: cellar, tag_sym => tag_hash["sha256"] }
bottle.sha256 sha256_hash bottle.sha256 sha256_hash
break if all_bottle
end end
if args.write? if args.write?
if all_bottle
all_bottle_hash = nil
bottle_hash["bottle"]["tags"].each do |tag, tag_hash|
local_filename = tag_hash["local_filename"]
local_json_filename = local_filename.sub(/\.tar\.gz$/, ".json")
if all_bottle_hash.nil?
all_filename = tag_hash["filename"].sub(tag, "all")
all_local_filename = local_filename.sub(tag, "all")
all_local_json_filename = local_json_filename.sub(tag, "all")
all_bottle_tag_hash = tag_hash.dup
all_bottle_tag_hash["filename"] = all_filename
all_bottle_tag_hash["local_filename"] = all_local_filename
cellar = all_bottle_tag_hash.delete("cellar")
all_bottle_formula_hash = bottle_hash.dup
all_bottle_formula_hash["bottle"]["cellar"] = cellar
all_bottle_formula_hash["bottle"]["tags"] = { all: all_bottle_tag_hash }
all_bottle_hash = { formula_name => all_bottle_formula_hash }
FileUtils.cp local_filename, all_local_filename
all_local_json_path = Pathname(all_local_json_filename)
all_local_json_path.unlink if all_local_json_path.exist?
all_local_json_path.write(JSON.pretty_generate(all_bottle_hash))
end
FileUtils.rm_f [local_filename, local_json_filename]
end
end
Homebrew.install_bundler_gems! Homebrew.install_bundler_gems!
require "utils/ast" require "utils/ast"

View File

@ -45,7 +45,7 @@ module Homebrew
end end
end end
def check_bottled_formulae(bottles_hash) def check_bottled_formulae!(bottles_hash)
bottles_hash.each do |name, bottle_hash| bottles_hash.each do |name, bottle_hash|
formula_path = HOMEBREW_REPOSITORY/bottle_hash["formula"]["path"] formula_path = HOMEBREW_REPOSITORY/bottle_hash["formula"]["path"]
formula_version = Formulary.factory(formula_path).pkg_version formula_version = Formulary.factory(formula_path).pkg_version
@ -84,9 +84,7 @@ module Homebrew
end end
end end
def pr_upload def bottles_hash_from_json_files(root_url)
args = pr_upload_args.parse
json_files = Dir["*.bottle.json"] json_files = Dir["*.bottle.json"]
odie "No bottle JSON files found in the current working directory" if json_files.empty? odie "No bottle JSON files found in the current working directory" if json_files.empty?
@ -94,12 +92,20 @@ module Homebrew
hash.deep_merge(JSON.parse(File.read(json_file))) hash.deep_merge(JSON.parse(File.read(json_file)))
end end
if args.root_url if root_url
bottles_hash.each_value do |bottle_hash| bottles_hash.each_value do |bottle_hash|
bottle_hash["bottle"]["root_url"] = args.root_url bottle_hash["bottle"]["root_url"] = args.root_url
end end
end end
bottles_hash
end
def pr_upload
args = pr_upload_args.parse
bottles_hash = bottles_hash_from_json_files(args.root_url)
bottle_args = ["bottle", "--merge", "--write"] bottle_args = ["bottle", "--merge", "--write"]
bottle_args << "--verbose" if args.verbose? bottle_args << "--verbose" if args.verbose?
bottle_args << "--debug" if args.debug? bottle_args << "--debug" if args.debug?
@ -133,10 +139,14 @@ module Homebrew
end end
end end
check_bottled_formulae(bottles_hash) check_bottled_formulae!(bottles_hash)
safe_system HOMEBREW_BREW_FILE, *bottle_args safe_system HOMEBREW_BREW_FILE, *bottle_args
# Reload the JSON files (in case `brew bottle --merge` generated
# `all: $SHA256` bottles)
bottles_hash = bottles_hash_from_json_files(args.root_url)
# Check the bottle commits did not break `brew audit` # Check the bottle commits did not break `brew audit`
unless args.no_commit? unless args.no_commit?
audit_args = ["audit", "--skip-style"] audit_args = ["audit", "--skip-style"]