Skip to content
Snippets Groups Projects
Commit 1690f064 authored by Markus Reiter's avatar Markus Reiter
Browse files

Add types for `Formula`.

parent c5a9de8f
No related branches found
No related tags found
No related merge requests found
......@@ -10,7 +10,7 @@ class PATH
include Enumerable
extend Forwardable
def_delegator :@paths, :each
delegate each: :@paths
# FIXME: Enable cop again when https://github.com/sorbet/sorbet/issues/3532 is fixed.
# rubocop:disable Style/MutableConstant
......
# typed: false
# typed: true
# frozen_string_literal: true
require "cache_store"
......@@ -124,6 +124,7 @@ class Formula
# The currently active {SoftwareSpec}.
# @see #determine_active_spec
sig { returns(SoftwareSpec) }
attr_reader :active_spec
protected :active_spec
......@@ -939,6 +940,7 @@ class Formula
end
# The generated launchd {.plist} file path.
sig { returns(Pathname) }
def plist_path
prefix/"#{plist_name}.plist"
end
......@@ -961,38 +963,47 @@ class Formula
HOMEBREW_PREFIX/"opt"/name
end
sig { returns(Pathname) }
def opt_bin
opt_prefix/"bin"
end
sig { returns(Pathname) }
def opt_include
opt_prefix/"include"
end
sig { returns(Pathname) }
def opt_lib
opt_prefix/"lib"
end
sig { returns(Pathname) }
def opt_libexec
opt_prefix/"libexec"
end
sig { returns(Pathname) }
def opt_sbin
opt_prefix/"sbin"
end
sig { returns(Pathname) }
def opt_share
opt_prefix/"share"
end
sig { returns(Pathname) }
def opt_pkgshare
opt_prefix/"share"/name
end
sig { returns(Pathname) }
def opt_elisp
opt_prefix/"share/emacs/site-lisp"/name
end
sig { returns(Pathname) }
def opt_frameworks
opt_prefix/"Frameworks"
end
......@@ -1012,40 +1023,45 @@ class Formula
delegate pour_bottle_check_unsatisfied_reason: :"self.class"
# Can be overridden to run commands on both source and bottle installation.
sig { overridable.void }
def post_install; end
# @private
sig { void }
def run_post_install
@prefix_returns_versioned_prefix = true
build = self.build
self.build = Tab.for_formula(self)
new_env = {
TMPDIR: HOMEBREW_TEMP,
TEMP: HOMEBREW_TEMP,
TMP: HOMEBREW_TEMP,
_JAVA_OPTIONS: "-Djava.io.tmpdir=#{HOMEBREW_TEMP}",
HOMEBREW_PATH: nil,
PATH: ENV["HOMEBREW_PATH"],
}
begin
self.build = Tab.for_formula(self)
with_env(new_env) do
ENV.clear_sensitive_environment!
new_env = {
TMPDIR: HOMEBREW_TEMP,
TEMP: HOMEBREW_TEMP,
TMP: HOMEBREW_TEMP,
_JAVA_OPTIONS: "-Djava.io.tmpdir=#{HOMEBREW_TEMP}",
HOMEBREW_PATH: nil,
PATH: ENV["HOMEBREW_PATH"],
}
etc_var_dirs = [bottle_prefix/"etc", bottle_prefix/"var"]
Find.find(*etc_var_dirs.select(&:directory?)) do |path|
path = Pathname.new(path)
path.extend(InstallRenamed)
path.cp_path_sub(bottle_prefix, HOMEBREW_PREFIX)
end
with_env(new_env) do
ENV.clear_sensitive_environment!
with_logging("post_install") do
post_install
etc_var_dirs = [bottle_prefix/"etc", bottle_prefix/"var"]
T.unsafe(Find).find(*etc_var_dirs.select(&:directory?)) do |path|
path = Pathname.new(path)
path.extend(InstallRenamed)
path.cp_path_sub(bottle_prefix, HOMEBREW_PREFIX)
end
with_logging("post_install") do
post_install
end
end
ensure
self.build = build
@prefix_returns_versioned_prefix = false
end
ensure
self.build = build
@prefix_returns_versioned_prefix = false
end
# Warn the user about any Homebrew-specific issues or quirks for this package.
......@@ -1067,6 +1083,7 @@ class Formula
# s += "Some issue only on older systems" if MacOS.version < :el_capitan
# s
# end</pre>
sig { overridable.returns(T.nilable(String)) }
def caveats
nil
end
......@@ -1089,6 +1106,8 @@ class Formula
# keep .la files with:
# skip_clean :la
# @private
sig { params(path: Pathname).returns(T::Boolean) }
def skip_clean?(path)
return true if path.extname == ".la" && self.class.skip_clean_paths.include?(:la)
......@@ -1241,7 +1260,7 @@ class Formula
Formula.cache[:outdated_kegs] ||= {}
Formula.cache[:outdated_kegs][cache_key] ||= begin
all_kegs = []
current_version = false
current_version = T.let(false, T::Boolean)
installed_kegs.each do |keg|
all_kegs << keg
......@@ -1427,13 +1446,15 @@ class Formula
# Standard parameters for cabal-v2 builds.
sig { returns(T::Array[String]) }
def std_cabal_v2_args
env = T.cast(ENV, T.any(Stdenv, Superenv))
# cabal-install's dependency-resolution backtracking strategy can
# easily need more than the default 2,000 maximum number of
# "backjumps," since Hackage is a fast-moving, rolling-release
# target. The highest known needed value by a formula was 43,478
# for git-annex, so 100,000 should be enough to avoid most
# gratuitous backjumps build failures.
["--jobs=#{ENV.make_jobs}", "--max-backjumps=100000", "--install-method=copy", "--installdir=#{bin}"]
["--jobs=#{env.make_jobs}", "--max-backjumps=100000", "--install-method=copy", "--installdir=#{bin}"]
end
# Standard parameters for meson builds.
......@@ -1960,6 +1981,7 @@ class Formula
#
# # If there is a "make install" available, please use it!
# system "make", "install"</pre>
sig { params(cmd: T.any(String, Pathname), args: T.any(String, Pathname)).void }
def system(cmd, *args)
verbose_using_dots = Homebrew::EnvConfig.verbose_using_dots?
......@@ -2026,10 +2048,12 @@ class Formula
rd.close
end
else
pid = fork { exec_cmd(cmd, args, log, logfn) }
pid = fork do
exec_cmd(cmd, args, log, logfn)
end
end
Process.wait(pid)
Process.wait(T.must(pid))
$stdout.flush
......@@ -2114,11 +2138,15 @@ class Formula
end
# Runs `xcodebuild` without Homebrew's compiler environment variables set.
sig { params(args: T.any(String, Pathname)).void }
def xcodebuild(*args)
removed = ENV.remove_cc_etc
system "xcodebuild", *args
ensure
ENV.update(removed)
begin
T.unsafe(self).system("xcodebuild", *args)
ensure
ENV.update(removed)
end
end
def fetch_patches
......@@ -2148,7 +2176,8 @@ class Formula
if cmd == "python"
setup_py_in_args = %w[setup.py build.py].include?(args.first)
setuptools_shim_in_args = args.any? { |a| a.to_s.start_with? "import setuptools" }
ENV.refurbish_args if setup_py_in_args || setuptools_shim_in_args
env = T.cast(ENV, T.any(Stdenv, Superenv))
env.refurbish_args if setup_py_in_args || setuptools_shim_in_args
end
$stdout.reopen(out)
......@@ -2156,7 +2185,7 @@ class Formula
out.close
args.map!(&:to_s)
begin
exec(cmd, *args)
T.unsafe(Kernel).exec(cmd, *args)
rescue
nil
end
......@@ -2420,7 +2449,7 @@ class Formula
# Get the `BUILD_FLAGS` from the formula's namespace set in `Formulary::load_formula`.
# @private
def build_flags
namespace = to_s.split("::")[0..-2].join("::")
namespace = T.must(to_s.split("::")[0..-2]).join("::")
return [] if namespace.empty?
mod = const_get(namespace)
......
......@@ -12,6 +12,8 @@ require "mktemp"
#
# @api private
class Resource
extend T::Sig
include Context
include FileUtils
......@@ -221,8 +223,8 @@ class Resource
# A resource containing a Go package.
class Go < Resource
def stage(target)
super(target/name)
def stage(target, &block)
super(target/name, &block)
end
end
......
......@@ -29,7 +29,9 @@ class SoftwareSpec
def_delegators :@resource, :stage, :fetch, :verify_download_integrity, :source_modified_time, :download_name,
:cached_download, :clear_cache, :checksum, :mirrors, :specs, :using, :version, :mirror,
:downloader, *Checksum::TYPES
:downloader
def_delegators :@resource, *Checksum::TYPES
def initialize(flags: [])
@resource = Resource.new
......
# typed: strict
# frozen_string_literal: true
source = ARGV[5]
source.scan(/:([^\s,]+)/).flatten.each do |method|
puts <<~RUBY
# typed: strict
sig { params(arg: T.untyped).returns(T.untyped) }
def #{method}(arg = T.unsafe(nil)); end
RUBY
end
# typed: strict
# frozen_string_literal: true
source = ARGV[5]
match = source.match(/\s*def_delegator\s+.*:(?<method>[^:]+)\s*\Z/m)
raise if match.nil?
method = match[:method]
puts <<~RUBY
# typed: strict
sig {params(arg0: T.untyped, blk: T.untyped).returns(T.untyped)}
def #{method}(*arg0, &blk); end
RUBY
# typed: strict
# frozen_string_literal: true
source = ARGV[5]
symbols = source.scan(/:[^\s,]+/)
_, *methods = symbols.map { |s| s.delete_prefix(":") }
methods.each do |method|
puts <<~RUBY
# typed: strict
sig {params(arg0: T.untyped, blk: T.untyped).returns(T.untyped)}
def #{method}(*arg0, &blk); end
RUBY
end
......@@ -15,7 +15,7 @@ methods.each do |method|
puts <<~RUBY
# typed: strict
sig {params(arg0: T.untyped).returns(T.untyped)}
def #{method}(*arg0); end
sig {params(arg0: T.untyped, blk: T.untyped).returns(T.untyped)}
def #{method}(*arg0, &blk); end
RUBY
end
......@@ -9,3 +9,48 @@ class Pathname
sig { params(with_directory: T::Boolean).returns(T::Array[Pathname]) }
def children(with_directory = true); end
end
module FileUtils
# https://github.com/sorbet/sorbet/pull/3730
module_function
sig do
params(
src: T.untyped,
dest: T.untyped,
preserve: T.nilable(T::Boolean),
noop: T.nilable(T::Boolean),
verbose: T.nilable(T::Boolean)
).returns(T.untyped)
end
def cp(src, dest, preserve: nil, noop: nil, verbose: nil); end
sig do
params(
list: T.any(String, Pathname),
mode: T.nilable(Integer),
noop: T.nilable(T::Boolean),
verbose: T.nilable(T::Boolean)
).returns(T::Array[String])
end
def mkdir_p(list, mode: nil, noop: nil, verbose: nil); end
end
class Module
# https://github.com/sorbet/sorbet/pull/3732
sig do
params(
arg0: T.any(Symbol, String),
arg1: T.any(Proc, Method, UnboundMethod)
)
.returns(Symbol)
end
sig do
params(
arg0: T.any(Symbol, String),
blk: T.proc.bind(T.untyped).returns(T.untyped),
)
.returns(Symbol)
end
def define_method(arg0, arg1=T.unsafe(nil), &blk); end
end
......@@ -4,4 +4,7 @@ ruby_extra_args:
triggers:
using: sorbet/plugins/using.rb
attr_predicate: sorbet/plugins/attr_predicate.rb
attr_rw: sorbet/plugins/attr_rw.rb
def_delegator: sorbet/plugins/def_delegator.rb
def_delegators: sorbet/plugins/def_delegators.rb
delegate: sorbet/plugins/delegate.rb
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment