Skip to content

Commit

Permalink
dev-cmd/generate-cask-api: start generating cask internal JSON v3
Browse files Browse the repository at this point in the history
This adds a new file to the output of `brew generate-cask-api` which
represents the new internal JSON v3 file. It involves removing
a bunch of unneeded hash keys while removing blank ones as well.

I've made some slight changes to the cask loader as well but more
might be necessary before this starts loading things correctly.
The full loader code will be added in a separate PR.
  • Loading branch information
apainintheneck committed Mar 3, 2024
1 parent 53c1107 commit df2397c
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 23 deletions.
100 changes: 78 additions & 22 deletions Library/Homebrew/cask/cask.rb
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ def ruby_source_path

def ruby_source_checksum
@ruby_source_checksum ||= {
"sha256" => Digest::SHA256.file(sourcefile_path).hexdigest,
sha256: Digest::SHA256.file(sourcefile_path).hexdigest,
}.freeze
end

Expand All @@ -283,7 +283,10 @@ def populate_from_api!(json_cask)
@tap_git_head = json_cask.fetch(:tap_git_head, "HEAD")

@ruby_source_path = json_cask[:ruby_source_path]
@ruby_source_checksum = json_cask[:ruby_source_checksum].freeze

ruby_source_sha256 = json_cask.dig(:ruby_source_checksum, :sha256)
ruby_source_sha256 ||= json_cask[:ruby_source_sha256]
@ruby_source_checksum = { "sha256" => ruby_source_sha256 }
end

def to_s
Expand All @@ -304,14 +307,6 @@ def eql?(other)
alias == eql?

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]}"
end

{
"token" => token,
"full_token" => full_name,
Expand Down Expand Up @@ -347,15 +342,64 @@ def to_h
}
end

def to_hash_with_variations
if loaded_from_api? && !Homebrew::EnvConfig.no_install_from_api?
return api_to_local_hash(Homebrew::API::Cask.all_casks[token].dup)
# @private
def to_api_hash
api_hash = {
"token" => token,

Check warning on line 348 in Library/Homebrew/cask/cask.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/cask.rb#L348

Added line #L348 was not covered by tests
"name" => name,
"desc" => desc,
"homepage" => homepage,
"url" => url,
"version" => version,
"sha256" => sha256,
"artifacts" => artifacts_list(compact: true),
"ruby_source_path" => ruby_source_path,
"ruby_source_sha256" => ruby_source_checksum.fetch(:sha256),
}

if deprecation_date
api_hash["deprecation_date"] = deprecation_date
api_hash["deprecation_reason"] = deprecation_reason

Check warning on line 362 in Library/Homebrew/cask/cask.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/cask.rb#L362

Added line #L362 was not covered by tests
end

hash = to_h
variations = {}
if disable_date
api_hash["disable_date"] = disable_date
api_hash["disable_reason"] = disable_reason

Check warning on line 367 in Library/Homebrew/cask/cask.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/cask.rb#L367

Added line #L367 was not covered by tests
end

if (url_specs_hash = url_specs).present?
api_hash["url_specs"] = url_specs_hash
end

api_hash["caskfile_only"] = true if caskfile_only?
api_hash["conflicts_with"] = conflicts_with if conflicts_with.present?
api_hash["depends_on"] = depends_on if depends_on.present?
api_hash["container"] = container.pairs if container
api_hash["caveats"] = caveats if caveats.present?
api_hash["auto_updates"] = auto_updates if auto_updates
api_hash["languages"] = languages if languages.present?

api_hash

Check warning on line 382 in Library/Homebrew/cask/cask.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/cask/cask.rb#L382

Added line #L382 was not covered by tests
end

HASH_KEYS_TO_SKIP = %w[outdated installed versions].freeze
private_constant :HASH_KEYS_TO_SKIP

hash_keys_to_skip = %w[outdated installed versions]
# @private
def to_hash_with_variations(hash_method: :to_h)
case hash_method
when :to_h
if loaded_from_api? && !Homebrew::EnvConfig.no_install_from_api?
return api_to_local_hash(Homebrew::API::Cask.all_casks[token].dup)
end
when :to_api_hash
raise ArgumentError, "API Hash must be generated from Ruby source files" if loaded_from_api?
else
raise ArgumentError, "Unknown hash method #{hash_method.inspect}"
end

hash = public_send(hash_method)
variations = {}

if @dsl.on_system_blocks_exist?
begin
Expand All @@ -366,8 +410,8 @@ def to_hash_with_variations
Homebrew::SimulateSystem.with os: os, arch: arch do
refresh

to_h.each do |key, value|
next if hash_keys_to_skip.include? key
public_send(hash_method).each do |key, value|
next if HASH_KEYS_TO_SKIP.include? key
next if value.to_s == hash[key].to_s

variations[bottle_tag.to_sym] ||= {}
Expand All @@ -380,7 +424,7 @@ def to_hash_with_variations
end
end

hash["variations"] = variations
hash["variations"] = variations if hash_method != :to_api_hash || variations.present?
hash
end

Expand All @@ -393,16 +437,28 @@ def api_to_local_hash(hash)
hash
end

def artifacts_list
artifacts.map do |artifact|
def artifacts_list(compact: false)
artifacts.filter_map do |artifact|
case artifact
when Artifact::AbstractFlightBlock
# Only indicate whether this block is used as we don't load it from the API
{ artifact.summarize => nil }
# We can skip this entirely once we move to internal JSON v3.
{ artifact.summarize => nil } unless compact
else
{ artifact.class.dsl_key => artifact.to_args }
end
end
end

def url_specs
url&.specs.dup.tap do |url_specs|
case url_specs&.dig(:user_agent)
when :default
url_specs.delete(:user_agent)
when Symbol
url_specs[:user_agent] = ":#{url_specs[:user_agent]}"
end
end
end
end
end
5 changes: 4 additions & 1 deletion Library/Homebrew/dev-cmd/generate-cask-api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def generate_cask_api
raise TapUnavailableError, tap.name unless tap.installed?

unless args.dry_run?
directories = ["_data/cask", "api/cask", "api/cask-source", "cask"].freeze
directories = ["_data/cask", "api/cask", "api/cask-source", "cask", "api/internal/v3"].freeze
FileUtils.rm_rf directories
FileUtils.mkdir_p directories
end
Expand Down Expand Up @@ -74,6 +74,9 @@ def generate_cask_api
onoe "Error while generating data for cask '#{path.stem}'."
raise
end

homebrew_cask_tap_json = JSON.generate(tap.to_api_hash)

Check warning on line 78 in Library/Homebrew/dev-cmd/generate-cask-api.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/generate-cask-api.rb#L78

Added line #L78 was not covered by tests
File.write("api/internal/v3/homebrew-cask.json", homebrew_cask_tap_json) unless args.dry_run?
end
end
end
16 changes: 16 additions & 0 deletions Library/Homebrew/tap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,22 @@ def tap_migrations
migrations
end
end

sig { returns(T::Hash[String, T.untyped]) }
def to_api_hash
casks_api_hash = cask_tokens.to_h do |token|
cask = Cask::CaskLoader.load(token)
cask_hash = cask.to_hash_with_variations(hash_method: :to_api_hash)
[token, cask_hash]

Check warning on line 1318 in Library/Homebrew/tap.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/tap.rb#L1315-L1318

Added lines #L1315 - L1318 were not covered by tests
end

{
"tap_git_head" => git_head,

Check warning on line 1322 in Library/Homebrew/tap.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/tap.rb#L1322

Added line #L1322 was not covered by tests
"renames" => cask_renames,
"tap_migrations" => tap_migrations,
"casks" => casks_api_hash,
}
end
end

# Permanent configuration per {Tap} using `git-config(1)`.
Expand Down

0 comments on commit df2397c

Please sign in to comment.