Checksum Ruby source file downloads
This commit is contained in:
parent
b7d6d00c34
commit
e663f532a6
@ -109,8 +109,9 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(name: String, git_head: T.nilable(String)).returns(String) }
|
||||
def self.fetch_homebrew_cask_source(name, git_head: nil)
|
||||
sig { params(name: String, git_head: T.nilable(String), sha256: T.nilable(String)).returns(String) }
|
||||
def self.fetch_homebrew_cask_source(name, git_head: nil, sha256: nil)
|
||||
# TODO: unify with formula logic (https://github.com/Homebrew/brew/issues/14746)
|
||||
git_head = "master" if git_head.blank?
|
||||
raw_endpoint = "#{git_head}/Casks/#{name}.rb"
|
||||
return cache[raw_endpoint] if cache.present? && cache.key?(raw_endpoint)
|
||||
@ -118,10 +119,13 @@ module Homebrew
|
||||
# This API sometimes returns random 404s so needs a fallback at formulae.brew.sh.
|
||||
raw_source_url = "https://raw.githubusercontent.com/Homebrew/homebrew-cask/#{raw_endpoint}"
|
||||
api_source_url = "#{HOMEBREW_API_DEFAULT_DOMAIN}/cask-source/#{name}.rb"
|
||||
output = Utils::Curl.curl_output("--fail", raw_source_url)
|
||||
|
||||
url = raw_source_url
|
||||
output = Utils::Curl.curl_output("--fail", url)
|
||||
|
||||
if !output.success? || output.blank?
|
||||
output = Utils::Curl.curl_output("--fail", api_source_url)
|
||||
url = api_source_url
|
||||
output = Utils::Curl.curl_output("--fail", url)
|
||||
if !output.success? || output.blank?
|
||||
raise ArgumentError, <<~EOS
|
||||
No valid file found at either of:
|
||||
@ -131,7 +135,20 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
cache[raw_endpoint] = output.stdout
|
||||
cask_source = output.stdout
|
||||
actual_sha256 = Digest::SHA256.hexdigest(cask_source)
|
||||
if sha256 && actual_sha256 != sha256
|
||||
raise ArgumentError, <<~EOS
|
||||
SHA256 mismatch
|
||||
Expected: #{Formatter.success(sha256.to_s)}
|
||||
Actual: #{Formatter.error(actual_sha256.to_s)}
|
||||
URL: #{url}
|
||||
Check if you can access the URL in your browser.
|
||||
Regardless, try again in a few minutes.
|
||||
EOS
|
||||
end
|
||||
|
||||
cache[raw_endpoint] = cask_source
|
||||
end
|
||||
|
||||
sig { params(json: Hash).returns(Hash) }
|
||||
|
@ -20,9 +20,9 @@ module Homebrew
|
||||
Homebrew::API.fetch "cask/#{token}.json"
|
||||
end
|
||||
|
||||
sig { params(token: String, git_head: T.nilable(String)).returns(String) }
|
||||
def fetch_source(token, git_head: nil)
|
||||
Homebrew::API.fetch_homebrew_cask_source token, git_head: git_head
|
||||
sig { params(token: String, git_head: T.nilable(String), sha256: T.nilable(String)).returns(String) }
|
||||
def fetch_source(token, git_head: nil, sha256: nil)
|
||||
Homebrew::API.fetch_homebrew_cask_source token, git_head: git_head, sha256: sha256
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
|
@ -83,11 +83,12 @@ module Cask
|
||||
@tap
|
||||
end
|
||||
|
||||
def initialize(token, sourcefile_path: nil, source: nil, tap: nil, config: nil,
|
||||
allow_reassignment: false, loaded_from_api: false, loader: nil, &block)
|
||||
def initialize(token, sourcefile_path: nil, source: nil, source_checksum: nil, tap: nil,
|
||||
config: nil, allow_reassignment: false, loaded_from_api: false, loader: nil, &block)
|
||||
@token = token
|
||||
@sourcefile_path = sourcefile_path
|
||||
@source = source
|
||||
@ruby_source_checksum = source_checksum
|
||||
@tap = tap
|
||||
@allow_reassignment = allow_reassignment
|
||||
@loaded_from_api = loaded_from_api
|
||||
@ -298,6 +299,7 @@ module Cask
|
||||
"auto_updates" => auto_updates,
|
||||
"tap_git_head" => tap&.git_head,
|
||||
"languages" => languages,
|
||||
"ruby_source_checksum" => ruby_source_checksum,
|
||||
}
|
||||
end
|
||||
|
||||
@ -349,6 +351,12 @@ module Cask
|
||||
hash
|
||||
end
|
||||
|
||||
def ruby_source_checksum
|
||||
@ruby_source_checksum ||= {
|
||||
"sha256" => Digest::SHA256.file(sourcefile_path).hexdigest,
|
||||
}
|
||||
end
|
||||
|
||||
def artifacts_list
|
||||
artifacts.map do |artifact|
|
||||
case artifact
|
||||
|
@ -233,13 +233,21 @@ module Cask
|
||||
# Use the cask-source API if there are any `*flight` blocks or the cask has multiple languages
|
||||
if json_cask[:artifacts].any? { |artifact| FLIGHT_STANZAS.include?(artifact.keys.first) } ||
|
||||
json_cask[:languages].any?
|
||||
cask_source = Homebrew::API::Cask.fetch_source(token, git_head: json_cask[:tap_git_head])
|
||||
cask_source = Homebrew::API::Cask.fetch_source(token,
|
||||
git_head: json_cask[:tap_git_head],
|
||||
sha256: json_cask.dig(:ruby_source_checksum, :sha256))
|
||||
return FromContentLoader.new(cask_source).load(config: config)
|
||||
end
|
||||
|
||||
tap = Tap.fetch(json_cask[:tap]) if json_cask[:tap].to_s.include?("/")
|
||||
|
||||
Cask.new(token, tap: tap, source: cask_source, config: config, loaded_from_api: true, loader: self) do
|
||||
Cask.new(token,
|
||||
tap: tap,
|
||||
source: cask_source,
|
||||
source_checksum: json_cask[:ruby_source_checksum],
|
||||
config: config,
|
||||
loaded_from_api: true,
|
||||
loader: self) do
|
||||
version json_cask[:version]
|
||||
|
||||
if json_cask[:sha256] == "no_check"
|
||||
|
@ -2133,6 +2133,7 @@ class Formula
|
||||
"disable_date" => disable_date,
|
||||
"disable_reason" => disable_reason,
|
||||
"tap_git_head" => tap_git_head,
|
||||
"ruby_source_checksum" => {},
|
||||
}
|
||||
|
||||
if stable
|
||||
@ -2183,6 +2184,16 @@ class Formula
|
||||
}
|
||||
end
|
||||
|
||||
if self.class.loaded_from_api && active_spec.resource_defined?("ruby-source")
|
||||
hsh["ruby_source_checksum"] = {
|
||||
"sha256" => resource("ruby-source").checksum.hexdigest,
|
||||
}
|
||||
elsif !self.class.loaded_from_api && path.exist?
|
||||
hsh["ruby_source_checksum"] = {
|
||||
"sha256" => Digest::SHA256.file(path).hexdigest,
|
||||
}
|
||||
end
|
||||
|
||||
hsh
|
||||
end
|
||||
|
||||
|
@ -17,7 +17,7 @@ class Formula
|
||||
def service?; end
|
||||
def version; end
|
||||
|
||||
def resource; end
|
||||
def resource(name); end
|
||||
def deps; end
|
||||
def uses_from_macos_elements; end
|
||||
def requirements; end
|
||||
|
@ -1182,9 +1182,12 @@ class FormulaInstaller
|
||||
if pour_bottle?(output_warning: true)
|
||||
formula.fetch_bottle_tab
|
||||
else
|
||||
if formula.core_formula? && Homebrew::EnvConfig.install_from_api?
|
||||
url = "https://raw.githubusercontent.com/#{formula.tap.full_name}/#{formula.tap_git_head}/Formula/#{formula.name}.rb"
|
||||
@formula = Formulary.factory(url, formula.active_spec_sym,
|
||||
if formula.class.loaded_from_api
|
||||
# TODO: unify with cask logic (https://github.com/Homebrew/brew/issues/14746)
|
||||
resource = formula.resource("ruby-source")
|
||||
resource.fetch
|
||||
@formula = Formulary.factory(resource.cached_download,
|
||||
formula.active_spec_sym,
|
||||
alias_path: formula.alias_path,
|
||||
flags: formula.class.build_flags,
|
||||
from: :formula_installer)
|
||||
|
@ -252,6 +252,13 @@ module Formulary
|
||||
link_overwrite overwrite_path
|
||||
end
|
||||
|
||||
resource "ruby-source" do
|
||||
url "https://raw.githubusercontent.com/Homebrew/homebrew-core/#{json_formula["tap_git_head"]}/Formula/#{name}.rb"
|
||||
if (ruby_source_sha256 = json_formula.dig("ruby_source_checksum", "sha256")).present?
|
||||
sha256 ruby_source_sha256
|
||||
end
|
||||
end
|
||||
|
||||
def install
|
||||
raise "Cannot build from source from abstract formula."
|
||||
end
|
||||
@ -446,7 +453,13 @@ module Formulary
|
||||
class FromPathLoader < FormulaLoader
|
||||
def initialize(path)
|
||||
path = Pathname.new(path).expand_path
|
||||
super path.basename(".rb").to_s, path
|
||||
name = path.basename(".rb").to_s
|
||||
|
||||
# For files we've downloaded, they will be prefixed with `{URL MD5}--`.
|
||||
# Remove that prefix to get the original filename.
|
||||
name = name.split("--", 2).last if path.dirname == HOMEBREW_CACHE/"downloads"
|
||||
|
||||
super name, path
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -131,7 +131,10 @@ describe Cask::Cmd::List, :cask do
|
||||
"tap_git_head": null,
|
||||
"languages": [
|
||||
|
||||
]
|
||||
],
|
||||
"ruby_source_checksum": {
|
||||
"sha256": "#{Digest::SHA256.file(Tap.default_cask_tap.cask_dir/"local-caffeine.rb").hexdigest}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"token": "local-transmission",
|
||||
@ -166,7 +169,10 @@ describe Cask::Cmd::List, :cask do
|
||||
"tap_git_head": null,
|
||||
"languages": [
|
||||
|
||||
]
|
||||
],
|
||||
"ruby_source_checksum": {
|
||||
"sha256": "#{Digest::SHA256.file(Tap.default_cask_tap.cask_dir/"local-transmission.rb").hexdigest}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"token": "multiple-versions",
|
||||
@ -204,7 +210,10 @@ describe Cask::Cmd::List, :cask do
|
||||
"tap_git_head": null,
|
||||
"languages": [
|
||||
|
||||
]
|
||||
],
|
||||
"ruby_source_checksum": {
|
||||
"sha256": "#{Digest::SHA256.file(Tap.default_cask_tap.cask_dir/"multiple-versions.rb").hexdigest}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"token": "third-party-cask",
|
||||
@ -239,7 +248,10 @@ describe Cask::Cmd::List, :cask do
|
||||
"tap_git_head": null,
|
||||
"languages": [
|
||||
|
||||
]
|
||||
],
|
||||
"ruby_source_checksum": {
|
||||
"sha256": "#{Digest::SHA256.file(Tap.fetch("third-party", "tap").cask_dir/"third-party-cask.rb").hexdigest}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"token": "with-languages",
|
||||
@ -275,7 +287,10 @@ describe Cask::Cmd::List, :cask do
|
||||
"languages": [
|
||||
"zh",
|
||||
"en-US"
|
||||
]
|
||||
],
|
||||
"ruby_source_checksum": {
|
||||
"sha256": "#{Digest::SHA256.file(Tap.default_cask_tap.cask_dir/"with-languages.rb").hexdigest}"
|
||||
}
|
||||
}
|
||||
]
|
||||
EOS
|
||||
|
Loading…
x
Reference in New Issue
Block a user