mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
Introduce CoreCaskTap class
This commit is contained in:
parent
1b7f3a7f1d
commit
ba02c669e1
@ -438,7 +438,7 @@ module Cask
|
||||
end
|
||||
|
||||
def self.default_path(token)
|
||||
Tap.default_cask_tap.cask_dir/"#{token.to_s.downcase}.rb"
|
||||
CoreCaskTap.instance.cask_dir/"#{token.to_s.downcase}.rb"
|
||||
end
|
||||
|
||||
def self.tap_paths(token, warn: true)
|
||||
|
@ -197,7 +197,11 @@ module Homebrew
|
||||
formulae, casks = args.named.to_formulae_and_casks
|
||||
.partition { |formula_or_cask| formula_or_cask.is_a?(Formula) }
|
||||
rescue FormulaOrCaskUnavailableError, Cask::CaskUnavailableError
|
||||
retry if Tap.install_default_cask_tap_if_necessary(force: args.cask?)
|
||||
cask_tap = CoreCaskTap.instance
|
||||
if !cask_tap.installed? && (args.cask? || Tap.untapped_official_taps.exclude?(cask_tap.name))
|
||||
cask_tap.ensure_installed!
|
||||
retry if cask_tap.installed?
|
||||
end
|
||||
|
||||
raise
|
||||
end
|
||||
|
@ -149,7 +149,7 @@ module Homebrew
|
||||
updated_taps = []
|
||||
Tap.each do |tap|
|
||||
next if !tap.git? || tap.git_repo.origin_url.nil?
|
||||
next if (tap.core_tap? || tap == "homebrew/cask") && !Homebrew::EnvConfig.no_install_from_api?
|
||||
next if (tap.core_tap? || tap.core_cask_tap?) && !Homebrew::EnvConfig.no_install_from_api?
|
||||
|
||||
if ENV["HOMEBREW_MIGRATE_LINUXBREW_FORMULAE"].present? && tap.core_tap? &&
|
||||
Settings.read("linuxbrewmigrated") != "true"
|
||||
@ -193,7 +193,7 @@ module Homebrew
|
||||
unless Homebrew::EnvConfig.no_install_from_api?
|
||||
api_cache = Homebrew::API::HOMEBREW_CACHE_API
|
||||
core_tap = CoreTap.instance
|
||||
cask_tap = Tap.fetch("homebrew/cask")
|
||||
cask_tap = CoreCaskTap.instance
|
||||
[
|
||||
[:formula, core_tap, core_tap.formula_dir],
|
||||
[:cask, cask_tap, cask_tap.cask_dir],
|
||||
@ -402,7 +402,7 @@ module Homebrew
|
||||
return if (HOMEBREW_PREFIX/".homebrewdocker").exist?
|
||||
|
||||
core_tap = CoreTap.instance
|
||||
cask_tap = Tap.default_cask_tap
|
||||
cask_tap = CoreCaskTap.instance
|
||||
return if !core_tap.installed? && !cask_tap.installed?
|
||||
|
||||
puts "Installing from the API is now the default behaviour!"
|
||||
@ -504,7 +504,7 @@ class Reporter
|
||||
new_name = tap.cask_renames[old_name]
|
||||
next unless new_name
|
||||
|
||||
new_full_name = if tap.name == "homebrew/cask"
|
||||
new_full_name = if tap.core_cask_tap?
|
||||
new_name
|
||||
else
|
||||
"#{tap}/#{new_name}"
|
||||
@ -518,7 +518,7 @@ class Reporter
|
||||
old_name = tap.cask_renames.key(new_name)
|
||||
next unless old_name
|
||||
|
||||
old_full_name = if tap.name == "homebrew/cask"
|
||||
old_full_name = if tap.core_cask_tap?
|
||||
old_name
|
||||
else
|
||||
"#{tap}/#{old_name}"
|
||||
|
@ -42,7 +42,7 @@ module Homebrew
|
||||
def generate_cask_api
|
||||
args = generate_cask_api_args.parse
|
||||
|
||||
tap = Tap.default_cask_tap
|
||||
tap = CoreCaskTap.instance
|
||||
raise TapUnavailableError, tap.name unless tap.installed?
|
||||
|
||||
unless args.dry_run?
|
||||
|
@ -531,7 +531,7 @@ module Homebrew
|
||||
end
|
||||
|
||||
def check_casktap_integrity
|
||||
default_cask_tap = Tap.default_cask_tap
|
||||
default_cask_tap = CoreCaskTap.instance
|
||||
return unless default_cask_tap.installed?
|
||||
|
||||
broken_tap(default_cask_tap) || examine_git_origin(default_cask_tap.git_repo, default_cask_tap.remote)
|
||||
@ -861,7 +861,7 @@ module Homebrew
|
||||
return if Homebrew::EnvConfig.no_install_from_api?
|
||||
return if Homebrew::Settings.read("devcmdrun") == "true"
|
||||
|
||||
cask_tap = Tap.fetch("homebrew", "cask")
|
||||
cask_tap = CoreCaskTap.instance
|
||||
return unless cask_tap.installed?
|
||||
|
||||
<<~EOS
|
||||
@ -921,7 +921,7 @@ module Homebrew
|
||||
end
|
||||
|
||||
def check_cask_taps
|
||||
default_cask_tap = Tap.default_cask_tap
|
||||
default_cask_tap = CoreCaskTap.instance
|
||||
alt_taps = Tap.select { |t| t.cask_dir.exist? && t != default_cask_tap }
|
||||
|
||||
error_tap_paths = []
|
||||
|
@ -3,12 +3,15 @@
|
||||
|
||||
class Tap
|
||||
def self.install_default_cask_tap_if_necessary(force: false)
|
||||
return false if default_cask_tap.installed?
|
||||
odeprecated "Tap.install_default_cask_tap_if_necessary", "CoreCaskTap.ensure_installed!"
|
||||
|
||||
cask_tap = CoreCaskTap.instance
|
||||
return false if cask_tap.installed?
|
||||
return false unless Homebrew::EnvConfig.no_install_from_api?
|
||||
return false if Homebrew::EnvConfig.automatically_set_no_install_from_api?
|
||||
return false if !force && Tap.untapped_official_taps.include?(default_cask_tap.name)
|
||||
return false if !force && Tap.untapped_official_taps.include?(cask_tap.name)
|
||||
|
||||
default_cask_tap.install
|
||||
cask_tap.install
|
||||
true
|
||||
end
|
||||
end
|
||||
|
@ -52,6 +52,7 @@ class Tap
|
||||
repo = repo.sub(HOMEBREW_OFFICIAL_REPO_PREFIXES_REGEX, "")
|
||||
|
||||
return CoreTap.instance if ["Homebrew", "Linuxbrew"].include?(user) && ["core", "homebrew"].include?(repo)
|
||||
return CoreCaskTap.instance if user == "Homebrew" && repo == "cask"
|
||||
|
||||
cache_key = "#{user}/#{repo}".downcase
|
||||
cache.fetch(cache_key) { |key| cache[key] = Tap.new(user, repo) }
|
||||
@ -64,13 +65,17 @@ class Tap
|
||||
fetch(match[:user], match[:repo])
|
||||
end
|
||||
|
||||
sig { returns(T.attached_class) }
|
||||
sig { returns(CoreCaskTap) }
|
||||
def self.default_cask_tap
|
||||
@default_cask_tap ||= fetch("Homebrew", "cask")
|
||||
odeprecated "Tap.default_cask_tap", "CoreCaskTap.instance"
|
||||
|
||||
CoreCaskTap.instance
|
||||
end
|
||||
|
||||
sig { params(force: T::Boolean).returns(T::Boolean) }
|
||||
def self.install_default_cask_tap_if_necessary(force: false)
|
||||
odeprecated "Tap.install_default_cask_tap_if_necessary", "CoreCaskTap.ensure_installed!"
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
@ -122,6 +127,7 @@ class Tap
|
||||
@cask_dir = nil
|
||||
@command_dir = nil
|
||||
@formula_files = nil
|
||||
@cask_files = nil
|
||||
@alias_dir = nil
|
||||
@alias_files = nil
|
||||
@aliases = nil
|
||||
@ -138,6 +144,13 @@ class Tap
|
||||
remove_instance_variable(:@private) if instance_variable_defined?(:@private)
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def ensure_installed!
|
||||
return if installed?
|
||||
|
||||
install
|
||||
end
|
||||
|
||||
# The remote path to this {Tap}.
|
||||
# e.g. `https://github.com/user/homebrew-repo`
|
||||
def remote
|
||||
@ -245,6 +258,12 @@ class Tap
|
||||
false
|
||||
end
|
||||
|
||||
# @private
|
||||
sig { returns(T::Boolean) }
|
||||
def core_cask_tap?
|
||||
false
|
||||
end
|
||||
|
||||
# Install this {Tap}.
|
||||
#
|
||||
# @param clone_target [String] If passed, it will be used as the clone remote.
|
||||
@ -299,7 +318,7 @@ class Tap
|
||||
args << "-q" if quiet
|
||||
path.cd { safe_system "git", *args }
|
||||
return
|
||||
elsif (core_tap? || name == "homebrew/cask") && !Homebrew::EnvConfig.no_install_from_api? && !force
|
||||
elsif (core_tap? || core_cask_tap?) && !Homebrew::EnvConfig.no_install_from_api? && !force
|
||||
# odeprecated: move to odie in the next minor release. This may break some CI so we should give notice.
|
||||
opoo "Tapping #{name} is no longer typically necessary.\n" \
|
||||
"Add #{Formatter.option("--force")} if you are sure you need one."
|
||||
@ -553,15 +572,20 @@ class Tap
|
||||
sig { params(tap: Tap).returns(T::Hash[String, Pathname]) }
|
||||
def self.cask_files_by_name(tap)
|
||||
cache_key = "cask_files_by_name_#{tap}"
|
||||
|
||||
cache.fetch(cache_key) do |key|
|
||||
cache[key] = tap.cask_files.each_with_object({}) do |file, hash|
|
||||
cache[key] = tap.cask_files_by_name
|
||||
end
|
||||
end
|
||||
|
||||
# @private
|
||||
sig { returns(T::Hash[String, Pathname]) }
|
||||
def cask_files_by_name
|
||||
cask_files.each_with_object({}) do |file, hash|
|
||||
# If there's more than one file with the same basename: intentionally
|
||||
# ignore the later ones here.
|
||||
hash[file.basename.to_s] ||= file
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# returns true if the file has a Ruby extension
|
||||
# @private
|
||||
@ -696,9 +720,7 @@ class Tap
|
||||
# Hash with tap cask renames.
|
||||
sig { returns(T::Hash[String, String]) }
|
||||
def cask_renames
|
||||
@cask_renames ||= if name == "homebrew/cask" && !Homebrew::EnvConfig.no_install_from_api?
|
||||
Homebrew::API::Cask.all_renames
|
||||
elsif (rename_file = path/HOMEBREW_TAP_CASK_RENAMES_FILE).file?
|
||||
@cask_renames ||= if (rename_file = path/HOMEBREW_TAP_CASK_RENAMES_FILE).file?
|
||||
JSON.parse(rename_file.read)
|
||||
else
|
||||
{}
|
||||
@ -718,11 +740,7 @@ class Tap
|
||||
# Hash with tap migrations.
|
||||
sig { returns(Hash) }
|
||||
def tap_migrations
|
||||
@tap_migrations ||= if name == "homebrew/cask" && !Homebrew::EnvConfig.no_install_from_api?
|
||||
migrations, = Homebrew::API.fetch_json_api_file "cask_tap_migrations.jws.json",
|
||||
stale_seconds: TAP_MIGRATIONS_STALE_SECONDS
|
||||
migrations
|
||||
elsif (migration_file = path/HOMEBREW_TAP_MIGRATIONS_FILE).file?
|
||||
@tap_migrations ||= if (migration_file = path/HOMEBREW_TAP_MIGRATIONS_FILE).file?
|
||||
JSON.parse(migration_file.read)
|
||||
else
|
||||
{}
|
||||
@ -749,9 +767,7 @@ class Tap
|
||||
# @private
|
||||
sig { returns(T::Boolean) }
|
||||
def should_report_analytics?
|
||||
return !Homebrew::EnvConfig.no_install_from_api? && official? unless installed?
|
||||
|
||||
!private?
|
||||
installed? && !private?
|
||||
end
|
||||
|
||||
sig { params(other: T.nilable(T.any(String, Tap))).returns(T::Boolean) }
|
||||
@ -867,29 +883,51 @@ class Tap
|
||||
end
|
||||
end
|
||||
|
||||
class AbstractCoreTap < Tap
|
||||
extend T::Helpers
|
||||
|
||||
abstract!
|
||||
|
||||
sig { returns(T.attached_class) }
|
||||
def self.instance
|
||||
@instance ||= T.unsafe(self).new
|
||||
end
|
||||
|
||||
sig { override.void }
|
||||
def ensure_installed!
|
||||
return unless Homebrew::EnvConfig.no_install_from_api?
|
||||
return if Homebrew::EnvConfig.automatically_set_no_install_from_api?
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def self.ensure_installed!
|
||||
instance.ensure_installed!
|
||||
end
|
||||
|
||||
# @private
|
||||
sig { override.returns(T::Boolean) }
|
||||
def should_report_analytics?
|
||||
return super if Homebrew::EnvConfig.no_install_from_api?
|
||||
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
# A specialized {Tap} class for the core formulae.
|
||||
class CoreTap < Tap
|
||||
class CoreTap < AbstractCoreTap
|
||||
# @private
|
||||
sig { void }
|
||||
def initialize
|
||||
super "Homebrew", "core"
|
||||
end
|
||||
|
||||
sig { returns(CoreTap) }
|
||||
def self.instance
|
||||
@instance ||= new
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def self.ensure_installed!
|
||||
return if instance.installed?
|
||||
return unless Homebrew::EnvConfig.no_install_from_api?
|
||||
return if Homebrew::EnvConfig.automatically_set_no_install_from_api?
|
||||
|
||||
# Tests override homebrew-core locations and we don't want to auto-tap in them.
|
||||
sig { override.void }
|
||||
def ensure_installed!
|
||||
return if ENV["HOMEBREW_TESTS"]
|
||||
|
||||
instance.install
|
||||
super
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
@ -1046,20 +1084,74 @@ class CoreTap < Tap
|
||||
def formula_files_by_name
|
||||
return super if Homebrew::EnvConfig.no_install_from_api?
|
||||
|
||||
formula_names.each_with_object({}) do |name, hash|
|
||||
Homebrew::API::Formula.all_formulae.each_with_object({}) do |item, hash|
|
||||
name, formula_hash = item
|
||||
# If there's more than one file with the same basename: intentionally
|
||||
# ignore the later ones here.
|
||||
hash[name] ||= sharded_formula_path(name)
|
||||
hash[name] ||= path/formula_hash["ruby_source_path"]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
# A specialized {Tap} class for homebrew-cask.
|
||||
class CoreCaskTap < AbstractCoreTap
|
||||
# @private
|
||||
sig { void }
|
||||
def initialize
|
||||
super "Homebrew", "cask"
|
||||
end
|
||||
|
||||
# @private
|
||||
sig { params(name: String).returns(Pathname) }
|
||||
def sharded_formula_path(name)
|
||||
# TODO: add sharding logic.
|
||||
formula_dir/"#{name}.rb"
|
||||
sig { override.returns(T::Boolean) }
|
||||
def core_cask_tap?
|
||||
true
|
||||
end
|
||||
|
||||
sig { override.returns(T::Array[Pathname]) }
|
||||
def cask_files
|
||||
return super if Homebrew::EnvConfig.no_install_from_api? || installed?
|
||||
|
||||
raise TapUnavailableError, name
|
||||
end
|
||||
|
||||
sig { override.returns(T::Array[String]) }
|
||||
def cask_tokens
|
||||
return super if Homebrew::EnvConfig.no_install_from_api?
|
||||
|
||||
Homebrew::API::Cask.all_casks.keys
|
||||
end
|
||||
|
||||
# @private
|
||||
sig { override.returns(T::Hash[String, Pathname]) }
|
||||
def cask_files_by_name
|
||||
return super if Homebrew::EnvConfig.no_install_from_api?
|
||||
|
||||
Homebrew::API::Cask.all_casks.each_with_object({}) do |item, hash|
|
||||
name, cask_hash = item
|
||||
# If there's more than one file with the same basename: intentionally
|
||||
# ignore the later ones here.
|
||||
hash[name] ||= path/cask_hash["ruby_source_path"]
|
||||
end
|
||||
end
|
||||
|
||||
sig { override.returns(T::Hash[String, String]) }
|
||||
def cask_renames
|
||||
@cask_renames ||= if Homebrew::EnvConfig.no_install_from_api?
|
||||
super
|
||||
else
|
||||
Homebrew::API::Cask.all_renames
|
||||
end
|
||||
end
|
||||
|
||||
sig { override.returns(Hash) }
|
||||
def tap_migrations
|
||||
@tap_migrations ||= if Homebrew::EnvConfig.no_install_from_api?
|
||||
super
|
||||
else
|
||||
migrations, = Homebrew::API.fetch_json_api_file "cask_tap_migrations.jws.json",
|
||||
stale_seconds: TAP_MIGRATIONS_STALE_SECONDS
|
||||
migrations
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -3,10 +3,11 @@
|
||||
describe Cask::CaskLoader::FromTapLoader do
|
||||
let(:cask_name) { "testball" }
|
||||
let(:cask_full_name) { "homebrew/cask/#{cask_name}" }
|
||||
let(:cask_path) { Tap.default_cask_tap.cask_dir/"#{cask_name}.rb" }
|
||||
let(:cask_path) { CoreCaskTap.instance.cask_dir/"#{cask_name}.rb" }
|
||||
|
||||
describe "#load" do
|
||||
before do
|
||||
CoreCaskTap.instance.clear_cache
|
||||
cask_path.parent.mkpath
|
||||
cask_path.write <<~RUBY
|
||||
cask '#{cask_name}' do
|
||||
@ -24,7 +25,7 @@ describe Cask::CaskLoader::FromTapLoader do
|
||||
end
|
||||
|
||||
context "with sharded Cask directory" do
|
||||
let(:cask_path) { Tap.default_cask_tap.cask_dir/cask_name[0]/"#{cask_name}.rb" }
|
||||
let(:cask_path) { CoreCaskTap.instance.cask_dir/cask_name[0]/"#{cask_name}.rb" }
|
||||
|
||||
it "returns a Cask" do
|
||||
expect(described_class.new(cask_full_name).load(config: nil)).to be_a(Cask::Cask)
|
||||
|
@ -24,7 +24,7 @@ describe Cask::Cask, :cask do
|
||||
end
|
||||
|
||||
describe "load" do
|
||||
let(:tap_path) { Tap.default_cask_tap.path }
|
||||
let(:tap_path) { CoreCaskTap.instance.path }
|
||||
let(:file_dirname) { Pathname.new(__FILE__).dirname }
|
||||
let(:relative_tap_path) { tap_path.relative_path_from(file_dirname) }
|
||||
|
||||
|
@ -119,7 +119,7 @@ describe Homebrew::Diagnostic::Checks do
|
||||
ENV.delete("HOMEBREW_DEVELOPER")
|
||||
ENV.delete("HOMEBREW_NO_INSTALL_FROM_API")
|
||||
|
||||
allow(CoreTap).to receive(:installed?).and_return(true)
|
||||
expect_any_instance_of(CoreTap).to receive(:installed?).and_return(true)
|
||||
|
||||
expect(checks.check_for_unnecessary_core_tap).to match("You have an unnecessary local Core tap")
|
||||
end
|
||||
@ -128,9 +128,7 @@ describe Homebrew::Diagnostic::Checks do
|
||||
ENV.delete("HOMEBREW_DEVELOPER")
|
||||
ENV.delete("HOMEBREW_NO_INSTALL_FROM_API")
|
||||
|
||||
cask_tap = Tap.new("homebrew", "cask")
|
||||
allow(Tap).to receive(:fetch).with("homebrew", "cask").and_return(cask_tap)
|
||||
allow(cask_tap).to receive(:installed?).and_return(true)
|
||||
expect_any_instance_of(CoreCaskTap).to receive(:installed?).and_return(true)
|
||||
|
||||
expect(checks.check_for_unnecessary_cask_tap).to match("unnecessary local Cask tap")
|
||||
end
|
||||
|
@ -38,7 +38,7 @@ RSpec.shared_context "Homebrew Cask", :needs_macos do # rubocop:disable RSpec/Co
|
||||
begin
|
||||
Cask::Config::DEFAULT_DIRS_PATHNAMES.each_value(&:mkpath)
|
||||
|
||||
Tap.default_cask_tap.tap do |tap|
|
||||
CoreCaskTap.instance.tap do |tap|
|
||||
FileUtils.mkdir_p tap.path.dirname
|
||||
FileUtils.ln_sf TEST_FIXTURE_DIR.join("cask"), tap.path
|
||||
end
|
||||
@ -52,7 +52,7 @@ RSpec.shared_context "Homebrew Cask", :needs_macos do # rubocop:disable RSpec/Co
|
||||
ensure
|
||||
FileUtils.rm_rf Cask::Config::DEFAULT_DIRS_PATHNAMES.values
|
||||
FileUtils.rm_rf [Cask::Config.new.binarydir, Cask::Caskroom.path, Cask::Cache.path]
|
||||
Tap.default_cask_tap.path.unlink
|
||||
CoreCaskTap.instance.path.unlink
|
||||
third_party_tap.path.unlink
|
||||
FileUtils.rm_rf third_party_tap.path.parent
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user