mirror of
https://github.com/Homebrew/brew.git
synced 2025-07-14 16:09:03 +08:00
tab, cask/tab: add more Sorbet types and signatures.
I bailed before going all the way to `typed: strict` but this should at least improve things and fix: `Library/Homebrew/tab.rb:111: warning: The class Tab reached 8 shape variations, instance variables accesses will be slower and memory usage increased.`
This commit is contained in:
parent
27b9bf2377
commit
05c7b65f54
@ -5,10 +5,24 @@ require "tab"
|
|||||||
|
|
||||||
module Cask
|
module Cask
|
||||||
class Tab < ::AbstractTab
|
class Tab < ::AbstractTab
|
||||||
attr_accessor :uninstall_flight_blocks, :uninstall_artifacts
|
sig { returns(T.nilable(T::Boolean)) }
|
||||||
|
attr_accessor :uninstall_flight_blocks
|
||||||
|
|
||||||
|
sig { returns(T.nilable(T::Array[T.untyped])) }
|
||||||
|
attr_accessor :uninstall_artifacts
|
||||||
|
|
||||||
|
sig { params(attributes: T::Hash[String, T.untyped]).void }
|
||||||
|
def initialize(attributes = {})
|
||||||
|
@uninstall_flight_blocks = T.let(nil, T.nilable(T::Boolean))
|
||||||
|
@uninstall_artifacts = T.let(nil, T.nilable(T::Array[T.untyped]))
|
||||||
|
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
# Instantiates a {Tab} for a new installation of a cask.
|
# Instantiates a {Tab} for a new installation of a cask.
|
||||||
def self.create(cask)
|
sig { override.params(formula_or_cask: T.any(Formula, Cask)).returns(T.attached_class) }
|
||||||
|
def self.create(formula_or_cask)
|
||||||
|
cask = T.cast(formula_or_cask, Cask)
|
||||||
tab = super
|
tab = super
|
||||||
|
|
||||||
tab.tabfile = cask.metadata_main_container_path/FILENAME
|
tab.tabfile = cask.metadata_main_container_path/FILENAME
|
||||||
@ -23,6 +37,7 @@ module Cask
|
|||||||
|
|
||||||
# Returns a {Tab} for an already installed cask,
|
# Returns a {Tab} for an already installed cask,
|
||||||
# or a fake one if the cask is not installed.
|
# or a fake one if the cask is not installed.
|
||||||
|
sig { params(cask: Cask).returns(T.attached_class) }
|
||||||
def self.for_cask(cask)
|
def self.for_cask(cask)
|
||||||
path = cask.metadata_main_container_path/FILENAME
|
path = cask.metadata_main_container_path/FILENAME
|
||||||
|
|
||||||
@ -40,6 +55,7 @@ module Cask
|
|||||||
tab
|
tab
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T.attached_class) }
|
||||||
def self.empty
|
def self.empty
|
||||||
tab = super
|
tab = super
|
||||||
tab.uninstall_flight_blocks = false
|
tab.uninstall_flight_blocks = false
|
||||||
@ -76,10 +92,12 @@ module Cask
|
|||||||
runtime_deps
|
runtime_deps
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T.nilable(String)) }
|
||||||
def version
|
def version
|
||||||
source["version"]
|
source["version"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(_args: T.untyped).returns(String) }
|
||||||
def to_json(*_args)
|
def to_json(*_args)
|
||||||
attributes = {
|
attributes = {
|
||||||
"homebrew_version" => homebrew_version,
|
"homebrew_version" => homebrew_version,
|
||||||
@ -98,6 +116,7 @@ module Cask
|
|||||||
JSON.pretty_generate(attributes)
|
JSON.pretty_generate(attributes)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(String) }
|
||||||
def to_s
|
def to_s
|
||||||
s = ["Installed"]
|
s = ["Installed"]
|
||||||
s << "using the formulae.brew.sh API" if loaded_from_api
|
s << "using the formulae.brew.sh API" if loaded_from_api
|
||||||
|
@ -675,7 +675,7 @@ module Homebrew
|
|||||||
"filename" => filename.url_encode,
|
"filename" => filename.url_encode,
|
||||||
"local_filename" => filename.to_s,
|
"local_filename" => filename.to_s,
|
||||||
"sha256" => sha256,
|
"sha256" => sha256,
|
||||||
"tab" => tab.to_bottle_hash,
|
"tab" => T.must(tab).to_bottle_hash,
|
||||||
"path_exec_files" => path_exec_files,
|
"path_exec_files" => path_exec_files,
|
||||||
"all_files" => all_files,
|
"all_files" => all_files,
|
||||||
"installed_size" => installed_size,
|
"installed_size" => installed_size,
|
||||||
|
@ -730,7 +730,9 @@ class Formula
|
|||||||
tab = Tab.for_keg(prefix(version))
|
tab = Tab.for_keg(prefix(version))
|
||||||
|
|
||||||
return true if tab.version_scheme < version_scheme
|
return true if tab.version_scheme < version_scheme
|
||||||
return true if stable && tab.stable_version && tab.stable_version < T.must(stable).version
|
|
||||||
|
tab_stable_version = tab.stable_version
|
||||||
|
return true if stable && tab_stable_version && tab_stable_version < T.must(stable).version
|
||||||
return false unless fetch_head
|
return false unless fetch_head
|
||||||
return false unless head&.downloader.is_a?(VCSDownloadStrategy)
|
return false unless head&.downloader.is_a?(VCSDownloadStrategy)
|
||||||
|
|
||||||
|
@ -420,7 +420,8 @@ class FormulaInstaller
|
|||||||
invalid_arch_dependencies = []
|
invalid_arch_dependencies = []
|
||||||
pinned_unsatisfied_deps = []
|
pinned_unsatisfied_deps = []
|
||||||
recursive_deps.each do |dep|
|
recursive_deps.each do |dep|
|
||||||
if (tab = Tab.for_formula(dep.to_formula)) && tab.arch.present? && tab.arch.to_s != Hardware::CPU.arch.to_s
|
tab = Tab.for_formula(dep.to_formula)
|
||||||
|
if tab.arch.present? && tab.arch.to_s != Hardware::CPU.arch.to_s
|
||||||
invalid_arch_dependencies << "#{dep} was built for #{tab.arch}"
|
invalid_arch_dependencies << "#{dep} was built for #{tab.arch}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -10,6 +10,9 @@ require "cachable"
|
|||||||
# Rather than calling `new` directly, use one of the class methods like {Tab.create}.
|
# Rather than calling `new` directly, use one of the class methods like {Tab.create}.
|
||||||
class AbstractTab
|
class AbstractTab
|
||||||
extend Cachable
|
extend Cachable
|
||||||
|
extend T::Helpers
|
||||||
|
|
||||||
|
abstract!
|
||||||
|
|
||||||
FILENAME = "INSTALL_RECEIPT.json"
|
FILENAME = "INSTALL_RECEIPT.json"
|
||||||
|
|
||||||
@ -25,14 +28,34 @@ class AbstractTab
|
|||||||
sig { returns(T.nilable(T::Boolean)) } # TODO: change this to always return a boolean
|
sig { returns(T.nilable(T::Boolean)) } # TODO: change this to always return a boolean
|
||||||
attr_accessor :installed_on_request
|
attr_accessor :installed_on_request
|
||||||
|
|
||||||
attr_accessor :homebrew_version, :tabfile, :loaded_from_api, :time, :arch, :source, :built_on
|
sig { returns(T.nilable(String)) }
|
||||||
|
attr_accessor :homebrew_version
|
||||||
|
|
||||||
|
attr_accessor :tabfile, :loaded_from_api, :time, :arch, :source, :built_on
|
||||||
|
|
||||||
# Returns the formula or cask runtime dependencies.
|
# Returns the formula or cask runtime dependencies.
|
||||||
#
|
#
|
||||||
# @api internal
|
# @api internal
|
||||||
attr_accessor :runtime_dependencies
|
attr_accessor :runtime_dependencies
|
||||||
|
|
||||||
|
sig { params(attributes: T::Hash[String, T.untyped]).void }
|
||||||
|
def initialize(attributes = {})
|
||||||
|
@installed_as_dependency = T.let(nil, T.nilable(T::Boolean))
|
||||||
|
@installed_on_request = T.let(nil, T.nilable(T::Boolean))
|
||||||
|
@homebrew_version = T.let(nil, T.nilable(String))
|
||||||
|
@tabfile = T.let(nil, T.nilable(Pathname))
|
||||||
|
@loaded_from_api = T.let(nil, T.nilable(T::Boolean))
|
||||||
|
@time = T.let(nil, T.nilable(Integer))
|
||||||
|
@arch = T.let(nil, T.nilable(String))
|
||||||
|
@source = T.let(nil, T.nilable(T::Hash[String, T.untyped]))
|
||||||
|
@built_on = T.let(nil, T.nilable(T::Hash[String, T.untyped]))
|
||||||
|
@runtime_dependencies = T.let(nil, T.nilable(T::Array[T.untyped]))
|
||||||
|
|
||||||
|
attributes.each { |key, value| instance_variable_set(:"@#{key}", value) }
|
||||||
|
end
|
||||||
|
|
||||||
# Instantiates a {Tab} for a new installation of a formula or cask.
|
# Instantiates a {Tab} for a new installation of a formula or cask.
|
||||||
|
sig { params(formula_or_cask: T.any(Formula, Cask::Cask)).returns(T.attached_class) }
|
||||||
def self.create(formula_or_cask)
|
def self.create(formula_or_cask)
|
||||||
attributes = {
|
attributes = {
|
||||||
"homebrew_version" => HOMEBREW_VERSION,
|
"homebrew_version" => HOMEBREW_VERSION,
|
||||||
@ -54,6 +77,7 @@ class AbstractTab
|
|||||||
# Returns the {Tab} for a formula or cask install receipt at `path`.
|
# Returns the {Tab} for a formula or cask install receipt at `path`.
|
||||||
#
|
#
|
||||||
# NOTE: Results are cached.
|
# NOTE: Results are cached.
|
||||||
|
sig { params(path: T.any(Pathname, String)).returns(T.attached_class) }
|
||||||
def self.from_file(path)
|
def self.from_file(path)
|
||||||
cache.fetch(path) do |p|
|
cache.fetch(path) do |p|
|
||||||
content = File.read(p)
|
content = File.read(p)
|
||||||
@ -64,6 +88,7 @@ class AbstractTab
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Like {from_file}, but bypass the cache.
|
# Like {from_file}, but bypass the cache.
|
||||||
|
sig { params(content: String, path: T.any(Pathname, String)).returns(T.attached_class) }
|
||||||
def self.from_file_content(content, path)
|
def self.from_file_content(content, path)
|
||||||
attributes = begin
|
attributes = begin
|
||||||
JSON.parse(content)
|
JSON.parse(content)
|
||||||
@ -75,6 +100,7 @@ class AbstractTab
|
|||||||
new(attributes)
|
new(attributes)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T.attached_class) }
|
||||||
def self.empty
|
def self.empty
|
||||||
attributes = {
|
attributes = {
|
||||||
"homebrew_version" => HOMEBREW_VERSION,
|
"homebrew_version" => HOMEBREW_VERSION,
|
||||||
@ -107,11 +133,9 @@ class AbstractTab
|
|||||||
end
|
end
|
||||||
private_class_method :formula_to_dep_hash
|
private_class_method :formula_to_dep_hash
|
||||||
|
|
||||||
def initialize(attributes = {})
|
sig { returns(Version) }
|
||||||
attributes.each { |key, value| instance_variable_set(:"@#{key}", value) }
|
|
||||||
end
|
|
||||||
|
|
||||||
def parsed_homebrew_version
|
def parsed_homebrew_version
|
||||||
|
homebrew_version = self.homebrew_version
|
||||||
return Version::NULL if homebrew_version.nil?
|
return Version::NULL if homebrew_version.nil?
|
||||||
|
|
||||||
Version.new(homebrew_version)
|
Version.new(homebrew_version)
|
||||||
@ -123,11 +147,13 @@ class AbstractTab
|
|||||||
Tap.fetch(tap_name) if tap_name
|
Tap.fetch(tap_name) if tap_name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(tap: T.nilable(T.any(Tap, String))).void }
|
||||||
def tap=(tap)
|
def tap=(tap)
|
||||||
tap_name = tap.respond_to?(:name) ? tap.name : tap
|
tap_name = tap.is_a?(Tap) ? tap.name : tap
|
||||||
source["tap"] = tap_name
|
source["tap"] = tap_name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { void }
|
||||||
def write
|
def write
|
||||||
self.class.cache[tabfile] = self
|
self.class.cache[tabfile] = self
|
||||||
tabfile.atomic_write(to_json)
|
tabfile.atomic_write(to_json)
|
||||||
@ -144,8 +170,30 @@ class Tab < AbstractTab
|
|||||||
attr_writer :used_options, :unused_options, :compiler, :source_modified_time
|
attr_writer :used_options, :unused_options, :compiler, :source_modified_time
|
||||||
attr_reader :tapped_from
|
attr_reader :tapped_from
|
||||||
|
|
||||||
|
sig { params(attributes: T::Hash[String, T.untyped]).void }
|
||||||
|
def initialize(attributes = {})
|
||||||
|
@poured_from_bottle = T.let(nil, T.nilable(T::Boolean))
|
||||||
|
@built_as_bottle = T.let(nil, T.nilable(T::Boolean))
|
||||||
|
@changed_files = T.let(nil, T.nilable(T::Array[Pathname]))
|
||||||
|
@stdlib = T.let(nil, T.nilable(String))
|
||||||
|
@aliases = T.let(nil, T.nilable(T::Array[String]))
|
||||||
|
@used_options = T.let(nil, T.nilable(T::Array[String]))
|
||||||
|
@unused_options = T.let(nil, T.nilable(T::Array[String]))
|
||||||
|
@compiler = T.let(nil, T.nilable(String))
|
||||||
|
@source_modified_time = T.let(nil, T.nilable(Integer))
|
||||||
|
@tapped_from = T.let(nil, T.nilable(String))
|
||||||
|
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
# Instantiates a {Tab} for a new installation of a formula.
|
# Instantiates a {Tab} for a new installation of a formula.
|
||||||
def self.create(formula, compiler, stdlib)
|
sig {
|
||||||
|
override.params(formula_or_cask: T.any(Formula, Cask::Cask), compiler: T.any(Symbol, String),
|
||||||
|
stdlib: T.nilable(T.any(String, Symbol))).returns(T.attached_class)
|
||||||
|
}
|
||||||
|
def self.create(formula_or_cask, compiler = DevelopmentTools.default_compiler, stdlib = nil)
|
||||||
|
formula = T.cast(formula_or_cask, Formula)
|
||||||
|
|
||||||
tab = super(formula)
|
tab = super(formula)
|
||||||
build = formula.build
|
build = formula.build
|
||||||
runtime_deps = formula.runtime_dependencies(undeclared: false)
|
runtime_deps = formula.runtime_dependencies(undeclared: false)
|
||||||
@ -172,10 +220,10 @@ class Tab < AbstractTab
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Like {from_file}, but bypass the cache.
|
# Like {from_file}, but bypass the cache.
|
||||||
|
sig { params(content: String, path: T.any(Pathname, String)).returns(T.attached_class) }
|
||||||
def self.from_file_content(content, path)
|
def self.from_file_content(content, path)
|
||||||
tab = super
|
tab = super
|
||||||
|
|
||||||
tab.source_modified_time ||= 0
|
|
||||||
tab.source ||= {}
|
tab.source ||= {}
|
||||||
|
|
||||||
tab.tap = tab.tapped_from if !tab.tapped_from.nil? && tab.tapped_from != "path or URL"
|
tab.tap = tab.tapped_from if !tab.tapped_from.nil? && tab.tapped_from != "path or URL"
|
||||||
@ -220,6 +268,7 @@ class Tab < AbstractTab
|
|||||||
|
|
||||||
# Returns a {Tab} for the named formula's installation,
|
# Returns a {Tab} for the named formula's installation,
|
||||||
# or a fake one if the formula is not installed.
|
# or a fake one if the formula is not installed.
|
||||||
|
sig { params(name: String).returns(T.attached_class) }
|
||||||
def self.for_name(name)
|
def self.for_name(name)
|
||||||
for_formula(Formulary.factory(name))
|
for_formula(Formulary.factory(name))
|
||||||
end
|
end
|
||||||
@ -237,6 +286,7 @@ class Tab < AbstractTab
|
|||||||
|
|
||||||
# Returns a {Tab} for an already installed formula,
|
# Returns a {Tab} for an already installed formula,
|
||||||
# or a fake one if the formula is not installed.
|
# or a fake one if the formula is not installed.
|
||||||
|
sig { params(formula: Formula).returns(T.attached_class) }
|
||||||
def self.for_formula(formula)
|
def self.for_formula(formula)
|
||||||
paths = []
|
paths = []
|
||||||
|
|
||||||
@ -276,6 +326,7 @@ class Tab < AbstractTab
|
|||||||
tab
|
tab
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T.attached_class) }
|
||||||
def self.empty
|
def self.empty
|
||||||
tab = super
|
tab = super
|
||||||
|
|
||||||
@ -293,6 +344,7 @@ class Tab < AbstractTab
|
|||||||
tab
|
tab
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Hash[String, T.untyped]) }
|
||||||
def self.empty_source_versions
|
def self.empty_source_versions
|
||||||
{
|
{
|
||||||
"stable" => nil,
|
"stable" => nil,
|
||||||
@ -308,6 +360,7 @@ class Tab < AbstractTab
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def any_args_or_options?
|
def any_args_or_options?
|
||||||
!used_options.empty? || !unused_options.empty?
|
!used_options.empty? || !unused_options.empty?
|
||||||
end
|
end
|
||||||
@ -324,14 +377,17 @@ class Tab < AbstractTab
|
|||||||
!with?(val)
|
!with?(val)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(opt: String).returns(T::Boolean) }
|
||||||
def include?(opt)
|
def include?(opt)
|
||||||
used_options.include? opt
|
used_options.include? opt
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def head?
|
def head?
|
||||||
spec == :head
|
spec == :head
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def stable?
|
def stable?
|
||||||
spec == :stable
|
spec == :stable
|
||||||
end
|
end
|
||||||
@ -344,10 +400,12 @@ class Tab < AbstractTab
|
|||||||
Options.create(@used_options)
|
Options.create(@used_options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(Options) }
|
||||||
def unused_options
|
def unused_options
|
||||||
Options.create(@unused_options)
|
Options.create(@unused_options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T.any(String, Symbol)) }
|
||||||
def compiler
|
def compiler
|
||||||
@compiler || DevelopmentTools.default_compiler
|
@compiler || DevelopmentTools.default_compiler
|
||||||
end
|
end
|
||||||
@ -358,36 +416,44 @@ class Tab < AbstractTab
|
|||||||
@runtime_dependencies if parsed_homebrew_version >= "1.1.6"
|
@runtime_dependencies if parsed_homebrew_version >= "1.1.6"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(CxxStdlib) }
|
||||||
def cxxstdlib
|
def cxxstdlib
|
||||||
# Older tabs won't have these values, so provide sensible defaults
|
# Older tabs won't have these values, so provide sensible defaults
|
||||||
lib = stdlib.to_sym if stdlib
|
lib = stdlib.to_sym if stdlib
|
||||||
CxxStdlib.create(lib, compiler.to_sym)
|
CxxStdlib.create(lib, compiler.to_sym)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def built_bottle?
|
def built_bottle?
|
||||||
built_as_bottle && !poured_from_bottle
|
built_as_bottle && !poured_from_bottle
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Boolean) }
|
||||||
def bottle?
|
def bottle?
|
||||||
built_as_bottle
|
built_as_bottle
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(Symbol) }
|
||||||
def spec
|
def spec
|
||||||
source["spec"].to_sym
|
source["spec"].to_sym
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T::Hash[String, T.untyped]) }
|
||||||
def versions
|
def versions
|
||||||
source["versions"]
|
source["versions"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T.nilable(Version)) }
|
||||||
def stable_version
|
def stable_version
|
||||||
versions["stable"]&.then { Version.new(_1) }
|
versions["stable"]&.then { Version.new(_1) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(T.nilable(Version)) }
|
||||||
def head_version
|
def head_version
|
||||||
versions["head"]&.then { Version.new(_1) }
|
versions["head"]&.then { Version.new(_1) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { returns(Integer) }
|
||||||
def version_scheme
|
def version_scheme
|
||||||
versions["version_scheme"] || 0
|
versions["version_scheme"] || 0
|
||||||
end
|
end
|
||||||
@ -397,6 +463,7 @@ class Tab < AbstractTab
|
|||||||
Time.at(@source_modified_time || 0)
|
Time.at(@source_modified_time || 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { params(options: T.nilable(T::Hash[String, T.untyped])).returns(String) }
|
||||||
def to_json(options = nil)
|
def to_json(options = nil)
|
||||||
attributes = {
|
attributes = {
|
||||||
"homebrew_version" => homebrew_version,
|
"homebrew_version" => homebrew_version,
|
||||||
@ -411,7 +478,7 @@ class Tab < AbstractTab
|
|||||||
"time" => time,
|
"time" => time,
|
||||||
"source_modified_time" => source_modified_time.to_i,
|
"source_modified_time" => source_modified_time.to_i,
|
||||||
"stdlib" => stdlib&.to_s,
|
"stdlib" => stdlib&.to_s,
|
||||||
"compiler" => compiler&.to_s,
|
"compiler" => compiler.to_s,
|
||||||
"aliases" => aliases,
|
"aliases" => aliases,
|
||||||
"runtime_dependencies" => runtime_dependencies,
|
"runtime_dependencies" => runtime_dependencies,
|
||||||
"source" => source,
|
"source" => source,
|
||||||
@ -424,13 +491,14 @@ class Tab < AbstractTab
|
|||||||
end
|
end
|
||||||
|
|
||||||
# A subset of to_json that we care about for bottles.
|
# A subset of to_json that we care about for bottles.
|
||||||
|
sig { returns(T::Hash[String, T.untyped]) }
|
||||||
def to_bottle_hash
|
def to_bottle_hash
|
||||||
attributes = {
|
attributes = {
|
||||||
"homebrew_version" => homebrew_version,
|
"homebrew_version" => homebrew_version,
|
||||||
"changed_files" => changed_files&.map(&:to_s),
|
"changed_files" => changed_files&.map(&:to_s),
|
||||||
"source_modified_time" => source_modified_time.to_i,
|
"source_modified_time" => source_modified_time.to_i,
|
||||||
"stdlib" => stdlib&.to_s,
|
"stdlib" => stdlib&.to_s,
|
||||||
"compiler" => compiler&.to_s,
|
"compiler" => compiler.to_s,
|
||||||
"runtime_dependencies" => runtime_dependencies,
|
"runtime_dependencies" => runtime_dependencies,
|
||||||
"arch" => arch,
|
"arch" => arch,
|
||||||
"built_on" => built_on,
|
"built_on" => built_on,
|
||||||
@ -439,6 +507,7 @@ class Tab < AbstractTab
|
|||||||
attributes
|
attributes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sig { void }
|
||||||
def write
|
def write
|
||||||
# If this is a new installation, the cache of installed formulae
|
# If this is a new installation, the cache of installed formulae
|
||||||
# will no longer be valid.
|
# will no longer be valid.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user