Reduce shape variations in Homebrew::Service
This commit is contained in:
parent
00c528bc54
commit
c4b02465f5
@ -306,7 +306,7 @@ module FormulaCellarChecks
|
||||
return unless formula.service?
|
||||
return unless formula.service.command?
|
||||
|
||||
"Service command does not exist" unless File.exist?(T.must(formula.service.command).first)
|
||||
"Service command does not exist" unless File.exist?(formula.service.command.first)
|
||||
end
|
||||
|
||||
sig { params(formula: Formula).returns(T.nilable(String)) }
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# typed: true # rubocop:todo Sorbet/StrictSigil
|
||||
# typed: strict
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "ipaddr"
|
||||
@ -23,13 +23,38 @@ module Homebrew
|
||||
PROCESS_TYPE_ADAPTIVE = :adaptive
|
||||
|
||||
KEEP_ALIVE_KEYS = [:always, :successful_exit, :crashed, :path].freeze
|
||||
SOCKET_STRING_REGEX = %r{^([a-z]+)://(.+):([0-9]+)$}i
|
||||
|
||||
# sig { params(formula: Formula).void }
|
||||
RunParam = T.type_alias { T.nilable(T.any(T::Array[T.any(String, Pathname)], String, Pathname)) }
|
||||
Sockets = T.type_alias { T::Hash[Symbol, { host: String, port: String, type: String }] }
|
||||
|
||||
sig { returns(String) }
|
||||
attr_reader :plist_name, :service_name
|
||||
|
||||
sig { params(formula: Formula, block: T.nilable(T.proc.void)).void }
|
||||
def initialize(formula, &block)
|
||||
@cron = T.let({}, T::Hash[Symbol, T.any(Integer, String)])
|
||||
@environment_variables = T.let({}, T::Hash[Symbol, String])
|
||||
@error_log_path = T.let(nil, T.nilable(String))
|
||||
@formula = formula
|
||||
@run_type = RUN_TYPE_IMMEDIATE
|
||||
@run_at_load = true
|
||||
@environment_variables = {}
|
||||
@input_path = T.let(nil, T.nilable(String))
|
||||
@interval = T.let(nil, T.nilable(Integer))
|
||||
@keep_alive = T.let({}, T::Hash[Symbol, T.untyped])
|
||||
@launch_only_once = T.let(false, T::Boolean)
|
||||
@log_path = T.let(nil, T.nilable(String))
|
||||
@macos_legacy_timers = T.let(false, T::Boolean)
|
||||
@plist_name = T.let(default_plist_name, String)
|
||||
@process_type = T.let(nil, T.nilable(Symbol))
|
||||
@require_root = T.let(false, T::Boolean)
|
||||
@restart_delay = T.let(nil, T.nilable(Integer))
|
||||
@root_dir = T.let(nil, T.nilable(String))
|
||||
@run = T.let([], T::Array[String])
|
||||
@run_at_load = T.let(true, T::Boolean)
|
||||
@run_params = T.let(nil, T.any(RunParam, T::Hash[Symbol, RunParam]))
|
||||
@run_type = T.let(RUN_TYPE_IMMEDIATE, Symbol)
|
||||
@service_name = T.let(default_service_name, String)
|
||||
@sockets = T.let({}, Sockets)
|
||||
@working_dir = T.let(nil, T.nilable(String))
|
||||
instance_eval(&block) if block
|
||||
end
|
||||
|
||||
@ -43,21 +68,11 @@ module Homebrew
|
||||
"homebrew.mxcl.#{@formula.name}"
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def plist_name
|
||||
@plist_name ||= default_plist_name
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def default_service_name
|
||||
"homebrew.#{@formula.name}"
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def service_name
|
||||
@service_name ||= default_service_name
|
||||
end
|
||||
|
||||
sig { params(macos: T.nilable(String), linux: T.nilable(String)).void }
|
||||
def name(macos: nil, linux: nil)
|
||||
raise TypeError, "Service#name expects at least one String" if [macos, linux].none?(String)
|
||||
@ -68,9 +83,9 @@ module Homebrew
|
||||
|
||||
sig {
|
||||
params(
|
||||
command: T.nilable(T.any(T::Array[T.any(String, Pathname)], String, Pathname)),
|
||||
macos: T.nilable(T.any(T::Array[T.any(String, Pathname)], String, Pathname)),
|
||||
linux: T.nilable(T.any(T::Array[T.any(String, Pathname)], String, Pathname)),
|
||||
command: T.nilable(RunParam),
|
||||
macos: T.nilable(RunParam),
|
||||
linux: T.nilable(RunParam),
|
||||
).returns(T.nilable(T::Array[T.any(String, Pathname)]))
|
||||
}
|
||||
def run(command = nil, macos: nil, linux: nil)
|
||||
@ -78,7 +93,7 @@ module Homebrew
|
||||
if command
|
||||
@run_params = command
|
||||
elsif macos || linux
|
||||
@run_params = { macos:, linux: }.compact
|
||||
@run_params = { macos:, linux: }.compact, T.any(RunParam, T::Hash[Symbol, RunParam])
|
||||
end
|
||||
|
||||
command ||= on_system_conditional(macos:, linux:)
|
||||
@ -86,9 +101,9 @@ module Homebrew
|
||||
when nil
|
||||
@run
|
||||
when String, Pathname
|
||||
@run = [command]
|
||||
@run = [command.to_s]
|
||||
when Array
|
||||
@run = command
|
||||
@run = command.map(&:to_s)
|
||||
end
|
||||
end
|
||||
|
||||
@ -161,12 +176,12 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(value: T.nilable(T::Boolean)).returns(T.nilable(T::Boolean)) }
|
||||
sig { params(value: T.nilable(T::Boolean)).returns(T::Boolean) }
|
||||
def require_root(value = nil)
|
||||
case value
|
||||
when nil
|
||||
@require_root
|
||||
when true, false
|
||||
when TrueClass, FalseClass
|
||||
@require_root = value
|
||||
end
|
||||
end
|
||||
@ -183,16 +198,14 @@ module Homebrew
|
||||
case value
|
||||
when nil
|
||||
@run_at_load
|
||||
when true, false
|
||||
when TrueClass, FalseClass
|
||||
@run_at_load = value
|
||||
end
|
||||
end
|
||||
|
||||
SOCKET_STRING_REGEX = %r{^([a-z]+)://(.+):([0-9]+)$}i
|
||||
|
||||
sig {
|
||||
params(value: T.nilable(T.any(String, T::Hash[Symbol, String])))
|
||||
.returns(T.nilable(T::Hash[Symbol, T::Hash[Symbol, String]]))
|
||||
.returns(T::Hash[Symbol, T::Hash[Symbol, String]])
|
||||
}
|
||||
def sockets(value = nil)
|
||||
return @sockets if value.nil?
|
||||
@ -204,9 +217,11 @@ module Homebrew
|
||||
value
|
||||
end.transform_values do |socket_string|
|
||||
match = socket_string.match(SOCKET_STRING_REGEX)
|
||||
raise TypeError, "Service#sockets a formatted socket definition as <type>://<host>:<port>" if match.blank?
|
||||
raise TypeError, "Service#sockets a formatted socket definition as <type>://<host>:<port>" unless match
|
||||
|
||||
type, host, port = match.captures
|
||||
type = T.must(match[1])
|
||||
host = T.must(match[2])
|
||||
port = T.must(match[3])
|
||||
|
||||
begin
|
||||
IPAddr.new(host)
|
||||
@ -222,15 +237,15 @@ module Homebrew
|
||||
# @return [Boolean]
|
||||
sig { returns(T::Boolean) }
|
||||
def keep_alive?
|
||||
@keep_alive.present? && @keep_alive[:always] != false
|
||||
!@keep_alive.empty? && @keep_alive[:always] != false
|
||||
end
|
||||
|
||||
sig { params(value: T.nilable(T::Boolean)).returns(T.nilable(T::Boolean)) }
|
||||
sig { params(value: T.nilable(T::Boolean)).returns(T::Boolean) }
|
||||
def launch_only_once(value = nil)
|
||||
case value
|
||||
when nil
|
||||
@launch_only_once
|
||||
when true, false
|
||||
when TrueClass, FalseClass
|
||||
@launch_only_once = value
|
||||
end
|
||||
end
|
||||
@ -281,13 +296,13 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(value: T.nilable(String)).returns(T.nilable(Hash)) }
|
||||
sig { params(value: T.nilable(String)).returns(T::Hash[Symbol, T.any(Integer, String)]) }
|
||||
def cron(value = nil)
|
||||
case value
|
||||
when nil
|
||||
@cron
|
||||
when String
|
||||
@cron = parse_cron(T.must(value))
|
||||
@cron = parse_cron(value)
|
||||
end
|
||||
end
|
||||
|
||||
@ -345,12 +360,12 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(value: T.nilable(T::Boolean)).returns(T.nilable(T::Boolean)) }
|
||||
sig { params(value: T.nilable(T::Boolean)).returns(T::Boolean) }
|
||||
def macos_legacy_timers(value = nil)
|
||||
case value
|
||||
when nil
|
||||
@macos_legacy_timers
|
||||
when true, false
|
||||
when TrueClass, FalseClass
|
||||
@macos_legacy_timers = value
|
||||
end
|
||||
end
|
||||
@ -362,14 +377,14 @@ module Homebrew
|
||||
"#{HOMEBREW_PREFIX}/bin:#{HOMEBREW_PREFIX}/sbin:/usr/bin:/bin:/usr/sbin:/sbin"
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(T::Array[String])) }
|
||||
sig { returns(T::Array[String]) }
|
||||
def command
|
||||
@run&.map(&:to_s)&.map { |arg| arg.start_with?("~") ? File.expand_path(arg) : arg }
|
||||
@run.map(&:to_s).map { |arg| arg.start_with?("~") ? File.expand_path(arg) : arg }
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def command?
|
||||
@run.present?
|
||||
!@run.empty?
|
||||
end
|
||||
|
||||
# Returns the `String` command to run manually instead of the service.
|
||||
@ -379,8 +394,8 @@ module Homebrew
|
||||
vars = @environment_variables.except(:PATH)
|
||||
.map { |k, v| "#{k}=\"#{v}\"" }
|
||||
|
||||
out = vars + T.must(command).map { |arg| Utils::Shell.sh_quote(arg) } if command?
|
||||
out.join(" ")
|
||||
vars.concat(command.map { |arg| Utils::Shell.sh_quote(arg) })
|
||||
vars.join(" ")
|
||||
end
|
||||
|
||||
# Returns a `Boolean` describing if a service is timed.
|
||||
@ -425,7 +440,7 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
if @sockets.present?
|
||||
unless @sockets.empty?
|
||||
base[:Sockets] = {}
|
||||
@sockets.each do |name, info|
|
||||
base[:Sockets][name] = {
|
||||
@ -436,7 +451,7 @@ module Homebrew
|
||||
end
|
||||
end
|
||||
|
||||
if @cron.present? && @run_type == RUN_TYPE_CRON
|
||||
if !@cron.empty? && @run_type == RUN_TYPE_CRON
|
||||
base[:StartCalendarInterval] = @cron.reject { |_, value| value == "*" }
|
||||
end
|
||||
|
||||
@ -456,8 +471,8 @@ module Homebrew
|
||||
sig { returns(String) }
|
||||
def to_systemd_unit
|
||||
# command needs to be first because it initializes all other values
|
||||
cmd = command&.map { |arg| Utils::Service.systemd_quote(arg) }
|
||||
&.join(" ")
|
||||
cmd = command.map { |arg| Utils::Service.systemd_quote(arg) }
|
||||
.join(" ")
|
||||
|
||||
options = []
|
||||
options << "Type=#{(@launch_only_once == true) ? "oneshot" : "simple"}"
|
||||
@ -512,7 +527,7 @@ module Homebrew
|
||||
end
|
||||
|
||||
# Prepare the service hash for inclusion in the formula API JSON.
|
||||
sig { returns(Hash) }
|
||||
sig { returns(T::Hash[Symbol, T.untyped]) }
|
||||
def to_hash
|
||||
name_params = {
|
||||
macos: (plist_name if plist_name != default_plist_name),
|
||||
@ -521,13 +536,13 @@ module Homebrew
|
||||
|
||||
return { name: name_params }.compact_blank if @run_params.blank?
|
||||
|
||||
cron_string = if @cron.present?
|
||||
cron_string = unless @cron.empty?
|
||||
[:Minute, :Hour, :Day, :Month, :Weekday]
|
||||
.map { |key| @cron[key].to_s }
|
||||
.join(" ")
|
||||
end
|
||||
|
||||
sockets_var = if @sockets.present?
|
||||
sockets_var = unless @sockets.empty?
|
||||
@sockets.transform_values { |info| "#{info[:type]}://#{info[:host]}:#{info[:port]}" }
|
||||
.then do |sockets_hash|
|
||||
# TODO: Remove this code when all users are running on versions of Homebrew
|
||||
@ -565,7 +580,7 @@ module Homebrew
|
||||
end
|
||||
|
||||
# Turn the service API hash values back into what is expected by the formula DSL.
|
||||
sig { params(api_hash: Hash).returns(Hash) }
|
||||
sig { params(api_hash: T::Hash[String, T.untyped]).returns(T::Hash[Symbol, T.untyped]) }
|
||||
def self.from_hash(api_hash)
|
||||
hash = {}
|
||||
hash[:name] = api_hash["name"].transform_keys(&:to_sym) if api_hash.key?("name")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user