From c82518032e08a3012897c8e0caa45a13bacdde41 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Fri, 14 Mar 2025 16:53:07 +0000 Subject: [PATCH] Fix services types Some of the typing/`T.must` usage when moving the Homebrew/homebrew-services code to Homebrew/brew was not quite correct. Rather than trying to make everything `strict` and import at the same time: let's mostly loosen the typing to fix a few bugs and allow us to add more later. --- Library/Homebrew/services/cli.rb | 52 +++--- Library/Homebrew/services/commands/info.rb | 8 +- Library/Homebrew/services/commands/kill.rb | 2 +- Library/Homebrew/services/commands/list.rb | 6 +- Library/Homebrew/services/commands/restart.rb | 3 +- Library/Homebrew/services/commands/run.rb | 2 +- Library/Homebrew/services/commands/start.rb | 2 +- Library/Homebrew/services/commands/stop.rb | 4 +- Library/Homebrew/services/formula_wrapper.rb | 151 +++++++++--------- Library/Homebrew/services/formulae.rb | 3 +- Library/Homebrew/services/system/systemctl.rb | 6 +- .../test/services/commands/restart_spec.rb | 6 +- ...rapper_spec.rb => formula_wrapper_spec.rb} | 12 +- 13 files changed, 119 insertions(+), 138 deletions(-) rename Library/Homebrew/test/services/{formulae_wrapper_spec.rb => formula_wrapper_spec.rb} (97%) diff --git a/Library/Homebrew/services/cli.rb b/Library/Homebrew/services/cli.rb index 3a9d140afe..ea1b78568f 100644 --- a/Library/Homebrew/services/cli.rb +++ b/Library/Homebrew/services/cli.rb @@ -1,4 +1,4 @@ -# typed: strict +# typed: true # rubocop:todo Sorbet/StrictSigil # frozen_string_literal: true require "services/formula_wrapper" @@ -15,7 +15,7 @@ module Homebrew sig { params(sudo_service_user: String).void } def self.sudo_service_user=(sudo_service_user) - @sudo_service_user = T.let(sudo_service_user, T.nilable(String)) + @sudo_service_user = sudo_service_user end # Binary name. @@ -41,7 +41,6 @@ module Homebrew end # Check if formula has been found. - sig { params(targets: T.untyped).returns(TrueClass) } def self.check(targets) raise UsageError, "Formula(e) missing, please provide a formula name or use --all" if targets.empty? @@ -49,7 +48,6 @@ module Homebrew end # Kill services that don't have a service file - sig { returns(T::Array[Services::FormulaWrapper]) } def self.kill_orphaned_services cleaned_labels = [] cleaned_services = [] @@ -67,7 +65,6 @@ module Homebrew cleaned_labels end - sig { returns(T::Array[T.untyped]) } def self.remove_unused_service_files cleaned = [] Dir["#{System.path}homebrew.*.{plist,service}"].each do |file| @@ -82,7 +79,7 @@ module Homebrew end # Run a service as defined in the formula. This does not clean the service file like `start` does. - sig { params(targets: T::Array[Services::FormulaWrapper], verbose: T.nilable(T::Boolean)).void } + sig { params(targets: T::Array[Services::FormulaWrapper], verbose: T::Boolean).void } def self.run(targets, verbose: false) targets.each do |service| if service.pid? @@ -102,7 +99,7 @@ module Homebrew params( targets: T::Array[Services::FormulaWrapper], service_file: T.nilable(T.any(String, Pathname)), - verbose: T.nilable(T::Boolean), + verbose: T::Boolean, ).void } def self.start(targets, service_file = nil, verbose: false) @@ -121,11 +118,12 @@ module Homebrew odie "Formula `#{service.name}` is not installed." unless service.installed? - file ||= if T.must(service.service_file).exist? || System.systemctl? + file ||= if service.service_file.exist? || System.systemctl? nil elsif service.formula.opt_prefix.exist? && - (keg = Keg.for service.formula.opt_prefix) && keg.plist_installed? - service_file = Dir["#{keg}/*#{T.must(service.service_file).extname}"].first + (keg = Keg.for service.formula.opt_prefix) && + keg.plist_installed? + service_file = Dir["#{keg}/*#{service.service_file.extname}"].first Pathname.new service_file if service_file.present? end @@ -147,8 +145,8 @@ module Homebrew sig { params( targets: T::Array[Services::FormulaWrapper], - verbose: T.nilable(T::Boolean), - no_wait: T.nilable(T::Boolean), + verbose: T::Boolean, + no_wait: T::Boolean, max_wait: T.nilable(T.any(Integer, Float)), ).void } @@ -208,7 +206,7 @@ module Homebrew end # Stop a service but keep it registered. - sig { params(targets: T::Array[Services::FormulaWrapper], verbose: T.nilable(T::Boolean)).void } + sig { params(targets: T::Array[Services::FormulaWrapper], verbose: T::Boolean).void } def self.kill(targets, verbose: false) targets.each do |service| if !service.pid? @@ -233,7 +231,6 @@ module Homebrew end # protections to avoid users editing root services - sig { params(service: T.untyped).returns(T.nilable(Integer)) } def self.take_root_ownership(service) return unless System.root? return if sudo_service_user @@ -302,7 +299,7 @@ module Homebrew params( service: Services::FormulaWrapper, file: T.nilable(T.any(String, Pathname)), - enable: T.nilable(T::Boolean), + enable: T::Boolean, ).void } def self.launchctl_load(service, file:, enable:) @@ -310,13 +307,13 @@ module Homebrew safe_system System.launchctl, "bootstrap", System.domain_target, file end - sig { params(service: Services::FormulaWrapper, enable: T.nilable(T::Boolean)).void } + sig { params(service: Services::FormulaWrapper, enable: T::Boolean).void } def self.systemd_load(service, enable:) - System::Systemctl.run("start", T.must(service.service_name)) - System::Systemctl.run("enable", T.must(service.service_name)) if enable + System::Systemctl.run("start", service.service_name) + System::Systemctl.run("enable", service.service_name) if enable end - sig { params(service: Services::FormulaWrapper, enable: T.nilable(T::Boolean)).void } + sig { params(service: Services::FormulaWrapper, enable: T::Boolean).void } def self.service_load(service, enable:) if System.root? && !service.service_startup? opoo "#{service.name} must be run as non-root to start at user login!" @@ -338,22 +335,21 @@ module Homebrew ohai("Successfully #{function} `#{service.name}` (label: #{service.service_name})") end - sig { params(service: Services::FormulaWrapper, file: T.nilable(Pathname)).void } def self.install_service_file(service, file) raise UsageError, "Formula `#{service.name}` is not installed" unless service.installed? - unless T.must(service.service_file).exist? + unless service.service_file.exist? raise UsageError, "Formula `#{service.name}` has not implemented #plist, #service or installed a locatable service file" end - temp = Tempfile.new(T.must(service.service_name)) - temp << if T.must(file).blank? - contents = T.must(service.service_file).read + temp = Tempfile.new(service.service_name) + temp << if file.blank? + contents = service.service_file.read - if sudo_service_user && Services::System.launchctl? + if sudo_service_user && System.launchctl? # set the username in the new plist file - ohai "Setting username in #{service.service_name} to #{Services::System.user}" + ohai "Setting username in #{service.service_name} to #{System.user}" plist_data = Plist.parse_xml(contents, marshal: false) plist_data["UserName"] = sudo_service_user plist_data.to_plist @@ -361,7 +357,7 @@ module Homebrew contents end else - T.must(file).read + file.read end temp.flush @@ -374,7 +370,7 @@ module Homebrew chmod 0644, service.dest - Services::System::Systemctl.run("daemon-reload") if System.systemctl? + System::Systemctl.run("daemon-reload") if System.systemctl? end end end diff --git a/Library/Homebrew/services/commands/info.rb b/Library/Homebrew/services/commands/info.rb index 4b49656fb0..c1edc2e0f1 100644 --- a/Library/Homebrew/services/commands/info.rb +++ b/Library/Homebrew/services/commands/info.rb @@ -12,8 +12,8 @@ module Homebrew sig { params( targets: T::Array[Services::FormulaWrapper], - verbose: T.nilable(T::Boolean), - json: T.nilable(T::Boolean), + verbose: T::Boolean, + json: T::Boolean, ).void } def self.run(targets, verbose:, json:) @@ -33,7 +33,7 @@ module Homebrew sig { params(bool: T.nilable(T.any(String, T::Boolean))).returns(String) } def self.pretty_bool(bool) - return T.must(bool).to_s if !$stdout.tty? || Homebrew::EnvConfig.no_emoji? + return bool.to_s if !$stdout.tty? || Homebrew::EnvConfig.no_emoji? if bool "#{Tty.bold}#{Formatter.success("✔")}#{Tty.reset}" @@ -42,7 +42,7 @@ module Homebrew end end - sig { params(hash: T.untyped, verbose: T.nilable(T::Boolean)).returns(String) } + sig { params(hash: T::Hash[Symbol, T.untyped], verbose: T::Boolean).returns(String) } def self.output(hash, verbose:) out = "#{Tty.bold}#{hash[:name]}#{Tty.reset} (#{hash[:service_name]})\n" out += "Running: #{pretty_bool(hash[:running])}\n" diff --git a/Library/Homebrew/services/commands/kill.rb b/Library/Homebrew/services/commands/kill.rb index 60d2a57c4a..c7182a33ce 100644 --- a/Library/Homebrew/services/commands/kill.rb +++ b/Library/Homebrew/services/commands/kill.rb @@ -9,7 +9,7 @@ module Homebrew module Kill TRIGGERS = %w[kill k].freeze - sig { params(targets: T::Array[Services::FormulaWrapper], verbose: T.nilable(T::Boolean)).void } + sig { params(targets: T::Array[Services::FormulaWrapper], verbose: T::Boolean).void } def self.run(targets, verbose:) Services::Cli.check(targets) Services::Cli.kill(targets, verbose:) diff --git a/Library/Homebrew/services/commands/list.rb b/Library/Homebrew/services/commands/list.rb index 8142f2c05c..b1ddc80b7d 100644 --- a/Library/Homebrew/services/commands/list.rb +++ b/Library/Homebrew/services/commands/list.rb @@ -1,4 +1,4 @@ -# typed: strict +# typed: true # rubocop:todo Sorbet/StrictSigil # frozen_string_literal: true require "services/cli" @@ -29,7 +29,6 @@ module Homebrew # Print the JSON representation in the CLI # @private - sig { params(formulae: T.untyped).returns(NilClass) } def self.print_json(formulae) services = formulae.map do |formula| formula.slice(*JSON_FIELDS) @@ -40,7 +39,6 @@ module Homebrew # Print the table in the CLI # @private - sig { params(formulae: T::Array[T::Hash[T.untyped, T.untyped]]).void } def self.print_table(formulae) services = formulae.map do |formula| status = T.must(get_status_string(formula[:status])) @@ -71,7 +69,7 @@ module Homebrew # Get formula status output # @private - sig { params(status: T.anything).returns(T.nilable(String)) } + sig { params(status: Symbol).returns(T.nilable(String)) } def self.get_status_string(status) case status when :started, :scheduled then "#{Tty.green}#{status}#{Tty.reset}" diff --git a/Library/Homebrew/services/commands/restart.rb b/Library/Homebrew/services/commands/restart.rb index dc9384dceb..94ae240c0c 100644 --- a/Library/Homebrew/services/commands/restart.rb +++ b/Library/Homebrew/services/commands/restart.rb @@ -14,7 +14,7 @@ module Homebrew TRIGGERS = %w[restart relaunch reload r].freeze - sig { params(targets: T::Array[Services::FormulaWrapper], verbose: T.nilable(T::Boolean)).returns(NilClass) } + sig { params(targets: T::Array[Services::FormulaWrapper], verbose: T::Boolean).void } def self.run(targets, verbose:) Services::Cli.check(targets) @@ -32,7 +32,6 @@ module Homebrew Services::Cli.run(targets, verbose:) if ran.present? Services::Cli.start(started, verbose:) if started.present? - nil end end end diff --git a/Library/Homebrew/services/commands/run.rb b/Library/Homebrew/services/commands/run.rb index ca0a9a36e1..467d31a7df 100644 --- a/Library/Homebrew/services/commands/run.rb +++ b/Library/Homebrew/services/commands/run.rb @@ -9,7 +9,7 @@ module Homebrew module Run TRIGGERS = ["run"].freeze - sig { params(targets: T::Array[Services::FormulaWrapper], verbose: T.nilable(T::Boolean)).void } + sig { params(targets: T::Array[Services::FormulaWrapper], verbose: T::Boolean).void } def self.run(targets, verbose:) Services::Cli.check(targets) Services::Cli.run(targets, verbose:) diff --git a/Library/Homebrew/services/commands/start.rb b/Library/Homebrew/services/commands/start.rb index 6f7f37fef0..c20ef6cba5 100644 --- a/Library/Homebrew/services/commands/start.rb +++ b/Library/Homebrew/services/commands/start.rb @@ -13,7 +13,7 @@ module Homebrew params( targets: T::Array[Services::FormulaWrapper], custom_plist: T.nilable(String), - verbose: T.nilable(T::Boolean), + verbose: T::Boolean, ).void } def self.run(targets, custom_plist, verbose:) diff --git a/Library/Homebrew/services/commands/stop.rb b/Library/Homebrew/services/commands/stop.rb index 53443d4424..2b9136da10 100644 --- a/Library/Homebrew/services/commands/stop.rb +++ b/Library/Homebrew/services/commands/stop.rb @@ -12,8 +12,8 @@ module Homebrew sig { params( targets: T::Array[Services::FormulaWrapper], - verbose: T.nilable(T::Boolean), - no_wait: T.nilable(T::Boolean), + verbose: T::Boolean, + no_wait: T::Boolean, max_wait: T.nilable(Float), ).void } diff --git a/Library/Homebrew/services/formula_wrapper.rb b/Library/Homebrew/services/formula_wrapper.rb index 0fc499dc7e..4c96f1097d 100644 --- a/Library/Homebrew/services/formula_wrapper.rb +++ b/Library/Homebrew/services/formula_wrapper.rb @@ -1,4 +1,4 @@ -# typed: strict +# typed: true # rubocop:todo Sorbet/StrictSigil # frozen_string_literal: true # Wrapper for a formula to handle service-related stuff like parsing and @@ -25,75 +25,73 @@ module Homebrew # Initialize a new `Service` instance with supplied formula. sig { params(formula: Formula).void } def initialize(formula) - @formula = T.let(formula, Formula) - @service = T.let(@formula.service? || false, T::Boolean) - @service_name = T.let(if System.launchctl? - formula.plist_name - elsif System.systemctl? - formula.service_name - end, T.nilable(String)) - @service_file = T.let(if System.launchctl? - formula.launchd_service_path - elsif System.systemctl? - formula.systemd_service_path - end, T.nilable(Pathname)) - @service_startup = T.let( - if service? - T.must(load_service).requires_root? - else - false - end, T.nilable(T::Boolean) - ) - @name = T.let(formula.name, String) + @formula = formula end # Delegate access to `formula.name`. sig { returns(String) } - attr_reader :name + def name + @name ||= formula.name + end # Delegate access to `formula.service?`. sig { returns(T::Boolean) } def service? - @service + @service ||= @formula.service? end # Delegate access to `formula.service.timed?`. + # TODO: this should either be T::Boolean or renamed to `timed` sig { returns(T.nilable(T::Boolean)) } def timed? - @timed ||= T.let(service? ? T.must(load_service).timed? : nil, T.nilable(T::Boolean)) + @timed ||= (load_service.timed? if service?) end - # Delegate access to `formula.service.keep_alive?`.` + # Delegate access to `formula.service.keep_alive?`. + # TODO: this should either be T::Boolean or renamed to `keep_alive` sig { returns(T.nilable(T::Boolean)) } def keep_alive? - @keep_alive ||= T.let(T.must(load_service).keep_alive?, T.nilable(T::Boolean)) if service? + @keep_alive ||= (load_service.keep_alive? if service?) end - # service_name delegates with formula.plist_name or formula.service_name for systemd - # (e.g., `homebrew.`). + # service_name delegates with formula.plist_name or formula.service_name + # for systemd (e.g., `homebrew.`). sig { returns(T.nilable(String)) } - attr_reader :service_name + def service_name + @service_name ||= if System.launchctl? + formula.plist_name + elsif System.systemctl? + formula.service_name + end + end # service_file delegates with formula.launchd_service_path or formula.systemd_service_path for systemd. - sig { returns(T.nilable(Pathname)) } - attr_reader :service_file + def service_file + @service_file ||= if System.launchctl? + formula.launchd_service_path + elsif System.systemctl? + formula.systemd_service_path + end + end # Whether the service should be launched at startup - sig { returns(T.nilable(T::Boolean)) } + sig { returns(T::Boolean) } def service_startup? - @service_startup ||= service? ? T.must(load_service).requires_root? : false + @service_startup ||= if service? + load_service.requires_root? + else + false + end end # Path to destination service directory. If run as root, it's `boot_path`, else `user_path`. - sig { returns(Pathname) } def dest_dir - System.root? ? T.must(System.boot_path) : T.must(System.user_path) + System.root? ? System.boot_path : System.user_path end # Path to destination service. If run as root, it's in `boot_path`, else `user_path`. - sig { returns(Pathname) } def dest - dest_dir + T.must(service_file).basename + dest_dir + service_file.basename end # Returns `true` if any version of the formula is installed. @@ -106,7 +104,7 @@ module Homebrew sig { returns(T::Boolean) } def plist? return false unless installed? - return true if T.must(service_file).file? + return true if service_file.file? return false unless formula.opt_prefix.exist? return true if Keg.for(formula.opt_prefix).plist_installed? @@ -116,6 +114,7 @@ module Homebrew end # Returns `true` if the service is loaded, else false. + # TODO: this should either be T::Boolean or renamed to `loaded` sig { params(cached: T::Boolean).returns(T.nilable(T::Boolean)) } def loaded?(cached: false) if System.launchctl? @@ -123,17 +122,18 @@ module Homebrew _, status_success, = status_output_success_type status_success elsif System.systemctl? - System::Systemctl.quiet_run("status", T.must(service_file).basename) + System::Systemctl.quiet_run("status", service_file.basename) end end # Returns `true` if service is present (e.g. .plist is present in boot or user service path), else `false` - # Accepts Hash option `:for` with values `:root` for boot path or `:user` for user path. - sig { params(opts: T.untyped).returns(T::Boolean) } - def service_file_present?(opts = { for: false }) - if opts[:for] && opts[:for] == :root + # Accepts `type` with values `:root` for boot path or `:user` for user path. + sig { params(type: T.nilable(Symbol)).returns(T::Boolean) } + def service_file_present?(type: nil) + case type + when :root boot_path_service_file_present? - elsif opts[:for] && opts[:for] == :user + when :user user_path_service_file_present? else boot_path_service_file_present? || user_path_service_file_present? @@ -161,43 +161,34 @@ module Homebrew sig { returns(T::Boolean) } def pid? - return false if pid.nil? - - !T.must(pid).zero? + pid.present? && !pid.zero? end - sig { returns(T.nilable(T.any(T::Boolean, Integer))) } + sig { returns(T::Boolean) } def error? - return false if pid? || pid.nil? - return exit_code if exit_code.nil? + return false if pid? - T.must(exit_code).nonzero? + exit_code.present? && exit_code.nonzero? end - sig { returns(T.nilable(T::Boolean)) } + sig { returns(T::Boolean) } def unknown_status? status_output.blank? && !pid? end # Get current PID of daemon process from status output. - sig { returns(T.nilable(Integer)) } def pid status_output, _, status_type = status_output_success_type - return if status_type.nil? - Regexp.last_match(1).to_i if status_output =~ pid_regex(status_type) end # Get current exit code of daemon process from status output. - sig { returns(T.nilable(Integer)) } def exit_code status_output, _, status_type = status_output_success_type - return if status_type.nil? - Regexp.last_match(1).to_i if status_output =~ exit_code_regex(status_type) end - sig { returns(T::Hash[T.untyped, T.untyped]) } + sig { returns(T::Hash[Symbol, T.anything]) } def to_hash hash = { name:, @@ -216,15 +207,15 @@ module Homebrew service = load_service - return hash if T.must(service).command.blank? + return hash if service.command.blank? - hash[:command] = T.must(service).manual_command - hash[:working_dir] = T.must(service).working_dir - hash[:root_dir] = T.must(service).root_dir - hash[:log_path] = T.must(service).log_path - hash[:error_log_path] = T.must(service).error_log_path - hash[:interval] = T.must(service).interval - hash[:cron] = T.must(service).cron + hash[:command] = service.manual_command + hash[:working_dir] = service.working_dir + hash[:root_dir] = service.root_dir + hash[:log_path] = service.log_path + hash[:error_log_path] = service.error_log_path + hash[:interval] = service.interval + hash[:cron] = service.cron hash end @@ -234,16 +225,14 @@ module Homebrew # The purpose of this function is to lazy load the Homebrew::Service class # and avoid nameclashes with the current Service module. # It should be used instead of calling formula.service directly. - sig { returns(T.nilable(Homebrew::Service)) } + sig { returns(Homebrew::Service) } def load_service require "formula" formula.service end - sig { returns(T.nilable(T::Array[T.untyped])) } def status_output_success_type - @status_output_success_type ||= T.let(nil, T.nilable(T::Array[T.untyped])) @status_output_success_type ||= if System.launchctl? cmd = [System.launchctl.to_s, "list", service_name] output = Utils.popen_read(*cmd).chomp @@ -279,7 +268,7 @@ module Homebrew :started elsif !loaded?(cached: true) :none - elsif T.must(exit_code).zero? + elsif exit_code.present? && exit_code.zero? if timed? :scheduled else @@ -294,34 +283,38 @@ module Homebrew end end - sig { params(status_type: Symbol).returns(Regexp) } def exit_code_regex(status_type) - @exit_code_regex ||= T.let({ + @exit_code_regex ||= { launchctl_list: /"LastExitStatus"\ =\ ([0-9]*);/, launchctl_print: /last exit code = ([0-9]+)/, systemctl: /\(code=exited, status=([0-9]*)\)|\(dead\)/, - }, T.nilable(T::Hash[T.untyped, Regexp])) + } @exit_code_regex.fetch(status_type) end - sig { params(status_type: Symbol).returns(Regexp) } def pid_regex(status_type) - @pid_regex ||= T.let({ + @pid_regex ||= { launchctl_list: /"PID"\ =\ ([0-9]*);/, launchctl_print: /pid = ([0-9]+)/, systemctl: /Main PID: ([0-9]*) \((?!code=)/, - }, T.nilable(T::Hash[T.untyped, Regexp])) + } @pid_regex.fetch(status_type) end sig { returns(T::Boolean) } def boot_path_service_file_present? - (T.must(System.boot_path) + T.must(service_file).basename).exist? + boot_path = System.boot_path + return false if boot_path.blank? + + (boot_path + service_file.basename).exist? end sig { returns(T::Boolean) } def user_path_service_file_present? - (T.must(System.user_path) + T.must(service_file).basename).exist? + user_path = System.user_path + return false if user_path.blank? + + (user_path + service_file.basename).exist? end sig { returns(Regexp) } diff --git a/Library/Homebrew/services/formulae.rb b/Library/Homebrew/services/formulae.rb index 711c8bb3cb..528a23a9a1 100644 --- a/Library/Homebrew/services/formulae.rb +++ b/Library/Homebrew/services/formulae.rb @@ -1,4 +1,4 @@ -# typed: strict +# typed: true # rubocop:todo Sorbet/StrictSigil # frozen_string_literal: true require "services/formula_wrapper" @@ -24,7 +24,6 @@ module Homebrew end # List all available services with status, user, and path to the file. - sig { returns(T::Array[T::Hash[T.untyped, T.untyped]]) } def self.services_list available_services.map(&:to_hash) end diff --git a/Library/Homebrew/services/system/systemctl.rb b/Library/Homebrew/services/system/systemctl.rb index 354944a2f7..9793314c75 100644 --- a/Library/Homebrew/services/system/systemctl.rb +++ b/Library/Homebrew/services/system/systemctl.rb @@ -1,4 +1,4 @@ -# typed: strict +# typed: true # rubocop:todo Sorbet/StrictSigil # frozen_string_literal: true module Homebrew @@ -20,22 +20,18 @@ module Homebrew System.root? ? "--system" : "--user" end - sig { params(args: T.nilable(T.any(String, Pathname))).void } def self.run(*args) _run(*args, mode: :default) end - sig { params(args: T.nilable(T.any(String, Pathname))).returns(T::Boolean) } def self.quiet_run(*args) _run(*args, mode: :quiet) end - sig { params(args: T.nilable(T.any(String, Pathname))).returns(String) } def self.popen_read(*args) _run(*args, mode: :read) end - sig { params(args: T.nilable(T.any(String, Pathname)), mode: T.nilable(Symbol)).returns(T.untyped) } private_class_method def self._run(*args, mode:) require "system_command" result = SystemCommand.run(executable, diff --git a/Library/Homebrew/test/services/commands/restart_spec.rb b/Library/Homebrew/test/services/commands/restart_spec.rb index d37eeab741..eb26b0c10c 100644 --- a/Library/Homebrew/test/services/commands/restart_spec.rb +++ b/Library/Homebrew/test/services/commands/restart_spec.rb @@ -21,7 +21,7 @@ RSpec.describe Homebrew::Services::Commands::Restart do expect(Homebrew::Services::Cli).not_to receive(:stop) expect(Homebrew::Services::Cli).to receive(:start).once service = instance_double(Homebrew::Services::FormulaWrapper, service_name: "name", loaded?: false) - expect(described_class.run([service], verbose: false)).to be_nil + expect { described_class.run([service], verbose: false) }.not_to raise_error end it "starts if services are loaded with file" do @@ -30,7 +30,7 @@ RSpec.describe Homebrew::Services::Commands::Restart do expect(Homebrew::Services::Cli).to receive(:stop).once service = instance_double(Homebrew::Services::FormulaWrapper, service_name: "name", loaded?: true, service_file_present?: true) - expect(described_class.run([service], verbose: false)).to be_nil + expect { described_class.run([service], verbose: false) }.not_to raise_error end it "runs if services are loaded without file" do @@ -39,7 +39,7 @@ service_file_present?: true) expect(Homebrew::Services::Cli).to receive(:stop).once service = instance_double(Homebrew::Services::FormulaWrapper, service_name: "name", loaded?: true, service_file_present?: false) - expect(described_class.run([service], verbose: false)).to be_nil + expect { described_class.run([service], verbose: false) }.not_to raise_error end end end diff --git a/Library/Homebrew/test/services/formulae_wrapper_spec.rb b/Library/Homebrew/test/services/formula_wrapper_spec.rb similarity index 97% rename from Library/Homebrew/test/services/formulae_wrapper_spec.rb rename to Library/Homebrew/test/services/formula_wrapper_spec.rb index 2e443678fa..47d46bd31a 100644 --- a/Library/Homebrew/test/services/formulae_wrapper_spec.rb +++ b/Library/Homebrew/test/services/formula_wrapper_spec.rb @@ -201,12 +201,12 @@ RSpec.describe Homebrew::Services::FormulaWrapper do it "macOS - outputs if the service file is present for root" do allow(Homebrew::Services::System).to receive_messages(launchctl?: true, systemctl?: false) - expect(service.service_file_present?(for: :root)).to be(false) + expect(service.service_file_present?(type: :root)).to be(false) end it "macOS - outputs if the service file is present for user" do allow(Homebrew::Services::System).to receive_messages(launchctl?: true, systemctl?: false) - expect(service.service_file_present?(for: :user)).to be(false) + expect(service.service_file_present?(type: :user)).to be(false) end end @@ -224,13 +224,13 @@ RSpec.describe Homebrew::Services::FormulaWrapper do end end - describe "#pid" do + describe "#pid", :needs_systemd do it "outputs nil because there is not pid" do expect(service.pid).to be_nil end end - describe "#error?" do + describe "#error?", :needs_systemd do it "outputs false because there a no PID" do allow(service).to receive(:pid).and_return(nil) expect(service.error?).to be(false) @@ -242,13 +242,13 @@ RSpec.describe Homebrew::Services::FormulaWrapper do end end - describe "#exit_code" do + describe "#exit_code", :needs_systemd do it "outputs nil because there is no exit code" do expect(service.exit_code).to be_nil end end - describe "#unknown_status?" do + describe "#unknown_status?", :needs_systemd do it "outputs true because there is no PID" do expect(service.unknown_status?).to be(true) end