Move Services module to Homebrew namespace

This commit is contained in:
Bo Anderson 2025-03-14 04:35:30 +00:00 committed by Mike McQuaid
parent 25b9000c77
commit 02cd7a63c8
No known key found for this signature in database
23 changed files with 1162 additions and 1088 deletions

View File

@ -3,7 +3,6 @@
require "abstract_command"
require "services/system"
require "services/cli"
require "services/commands/list"
require "services/commands/cleanup"
require "services/commands/info"
@ -73,36 +72,40 @@ module Homebrew
# Keep this after the .parse to keep --help fast.
require "utils"
if !::Services::System.launchctl? && !::Services::System.systemctl?
if !Homebrew::Services::System.launchctl? && !Homebrew::Services::System.systemctl?
raise UsageError,
"`brew services` is supported only on macOS or Linux (with systemd)!"
end
if (sudo_service_user = args.sudo_service_user)
unless ::Services::System.root?
unless Homebrew::Services::System.root?
raise UsageError,
"`brew services` is supported only when running as root!"
end
unless ::Services::System.launchctl?
unless Homebrew::Services::System.launchctl?
raise UsageError,
"`brew services --sudo-service-user` is currently supported only on macOS " \
"(but we'd love a PR to add Linux support)!"
end
::Services::Cli.sudo_service_user = sudo_service_user
Homebrew::Services::Cli.sudo_service_user = sudo_service_user
end
# Parse arguments.
subcommand, formula, = args.named
if [*::Services::Commands::List::TRIGGERS, *::Services::Commands::Cleanup::TRIGGERS].include?(subcommand)
no_named_formula_commands = [
*Homebrew::Services::Commands::List::TRIGGERS,
*Homebrew::Services::Commands::Cleanup::TRIGGERS,
]
if no_named_formula_commands.include?(subcommand)
raise UsageError, "The `#{subcommand}` subcommand does not accept a formula argument!" if formula
raise UsageError, "The `#{subcommand}` subcommand does not accept the --all argument!" if args.all?
end
if args.file
if ::Services::Commands::Start::TRIGGERS.exclude?(subcommand)
if Homebrew::Services::Commands::Start::TRIGGERS.exclude?(subcommand)
raise UsageError, "The `#{subcommand}` subcommand does not accept the --file= argument!"
elsif args.all?
raise UsageError, "The start subcommand does not accept the --all and --file= arguments at the same time!"
@ -113,14 +116,20 @@ module Homebrew
targets = if args.all?
if subcommand == "start"
::Services::Formulae.available_services(loaded: false, skip_root: !::Services::System.root?)
Homebrew::Services::Formulae.available_services(
loaded: false,
skip_root: !Homebrew::Services::System.root?,
)
elsif subcommand == "stop"
::Services::Formulae.available_services(loaded: true, skip_root: !::Services::System.root?)
Homebrew::Services::Formulae.available_services(
loaded: true,
skip_root: !Homebrew::Services::System.root?,
)
else
::Services::Formulae.available_services
Homebrew::Services::Formulae.available_services
end
elsif formula
[::Services::FormulaWrapper.new(Formulary.factory(formula))]
[Homebrew::Services::FormulaWrapper.new(Formulary.factory(formula))]
else
[]
end
@ -128,30 +137,30 @@ module Homebrew
# Exit successfully if --all was used but there is nothing to do
return if args.all? && targets.empty?
if ::Services::System.systemctl?
if Homebrew::Services::System.systemctl?
ENV["DBUS_SESSION_BUS_ADDRESS"] = ENV.fetch("HOMEBREW_DBUS_SESSION_BUS_ADDRESS", nil)
ENV["XDG_RUNTIME_DIR"] = ENV.fetch("HOMEBREW_XDG_RUNTIME_DIR", nil)
end
# Dispatch commands and aliases.
case subcommand.presence
when *::Services::Commands::List::TRIGGERS
::Services::Commands::List.run(json: args.json?)
when *::Services::Commands::Cleanup::TRIGGERS
::Services::Commands::Cleanup.run
when *::Services::Commands::Info::TRIGGERS
::Services::Commands::Info.run(targets, verbose: args.verbose?, json: args.json?)
when *::Services::Commands::Restart::TRIGGERS
::Services::Commands::Restart.run(targets, verbose: args.verbose?)
when *::Services::Commands::Run::TRIGGERS
::Services::Commands::Run.run(targets, verbose: args.verbose?)
when *::Services::Commands::Start::TRIGGERS
::Services::Commands::Start.run(targets, args.file, verbose: args.verbose?)
when *::Services::Commands::Stop::TRIGGERS
when *Homebrew::Services::Commands::List::TRIGGERS
Homebrew::Services::Commands::List.run(json: args.json?)
when *Homebrew::Services::Commands::Cleanup::TRIGGERS
Homebrew::Services::Commands::Cleanup.run
when *Homebrew::Services::Commands::Info::TRIGGERS
Homebrew::Services::Commands::Info.run(targets, verbose: args.verbose?, json: args.json?)
when *Homebrew::Services::Commands::Restart::TRIGGERS
Homebrew::Services::Commands::Restart.run(targets, verbose: args.verbose?)
when *Homebrew::Services::Commands::Run::TRIGGERS
Homebrew::Services::Commands::Run.run(targets, verbose: args.verbose?)
when *Homebrew::Services::Commands::Start::TRIGGERS
Homebrew::Services::Commands::Start.run(targets, args.file, verbose: args.verbose?)
when *Homebrew::Services::Commands::Stop::TRIGGERS
max_wait = args.max_wait.to_f
::Services::Commands::Stop.run(targets, verbose: args.verbose?, no_wait: args.no_wait?, max_wait:)
when *::Services::Commands::Kill::TRIGGERS
::Services::Commands::Kill.run(targets, verbose: args.verbose?)
Homebrew::Services::Commands::Stop.run(targets, verbose: args.verbose?, no_wait: args.no_wait?, max_wait:)
when *Homebrew::Services::Commands::Kill::TRIGGERS
Homebrew::Services::Commands::Kill.run(targets, verbose: args.verbose?)
else
raise UsageError, "unknown subcommand: `#{subcommand}`"
end

View File

@ -1,6 +1,9 @@
# typed: strict
# frozen_string_literal: true
require "services/formula_wrapper"
module Homebrew
module Services
module Cli
extend FileUtils
@ -96,8 +99,11 @@ module Services
# Start a service.
sig {
params(targets: T::Array[Services::FormulaWrapper], service_file: T.nilable(T.any(String, Pathname)),
verbose: T.nilable(T::Boolean)).void
params(
targets: T::Array[Services::FormulaWrapper],
service_file: T.nilable(T.any(String, Pathname)),
verbose: T.nilable(T::Boolean),
).void
}
def self.start(targets, service_file = nil, verbose: false)
file = T.let(nil, T.nilable(Pathname))
@ -117,7 +123,8 @@ module Services
file ||= if T.must(service.service_file).exist? || System.systemctl?
nil
elsif service.formula.opt_prefix.exist? && (keg = Keg.for service.formula.opt_prefix) && keg.plist_installed?
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
Pathname.new service_file if service_file.present?
end
@ -138,10 +145,12 @@ module Services
# Stop a service and unload it.
sig {
params(targets: T::Array[Services::FormulaWrapper],
params(
targets: T::Array[Services::FormulaWrapper],
verbose: T.nilable(T::Boolean),
no_wait: T.nilable(T::Boolean),
max_wait: T.nilable(T.any(Integer, Float))).void
max_wait: T.nilable(T.any(Integer, Float)),
).void
}
def self.stop(targets, verbose: false, no_wait: false, max_wait: 0)
targets.each do |service|
@ -290,8 +299,11 @@ module Services
end
sig {
params(service: Services::FormulaWrapper, file: T.nilable(T.any(String, Pathname)),
enable: T.nilable(T::Boolean)).void
params(
service: Services::FormulaWrapper,
file: T.nilable(T.any(String, Pathname)),
enable: T.nilable(T::Boolean),
).void
}
def self.launchctl_load(service, file:, enable:)
safe_system System.launchctl, "enable", "#{System.domain_target}/#{service.service_name}" if enable
@ -366,3 +378,4 @@ module Services
end
end
end
end

View File

@ -1,6 +1,9 @@
# typed: strict
# frozen_string_literal: true
require "services/cli"
module Homebrew
module Services
module Commands
module Cleanup
@ -18,3 +21,4 @@ module Services
end
end
end
end

View File

@ -1,17 +1,20 @@
# typed: strict
# frozen_string_literal: true
require "services/formula_wrapper"
require "services/cli"
module Homebrew
module Services
module Commands
module Info
TRIGGERS = %w[info i].freeze
sig {
params(targets: T::Array[Services::FormulaWrapper], verbose: T.nilable(T::Boolean),
json: T.nilable(T::Boolean)).void
params(
targets: T::Array[Services::FormulaWrapper],
verbose: T.nilable(T::Boolean),
json: T.nilable(T::Boolean),
).void
}
def self.run(targets, verbose:, json:)
Services::Cli.check(targets)
@ -63,3 +66,4 @@ module Services
end
end
end
end

View File

@ -1,6 +1,9 @@
# typed: strict
# frozen_string_literal: true
require "services/cli"
module Homebrew
module Services
module Commands
module Kill
@ -14,3 +17,4 @@ module Services
end
end
end
end

View File

@ -1,9 +1,10 @@
# typed: strict
# frozen_string_literal: true
require "services/formulae"
require "services/cli"
require "services/formulae"
module Homebrew
module Services
module Commands
module List
@ -83,3 +84,4 @@ module Services
end
end
end
end

View File

@ -1,6 +1,9 @@
# typed: strict
# frozen_string_literal: true
require "services/cli"
module Homebrew
module Services
module Commands
module Restart
@ -34,3 +37,4 @@ module Services
end
end
end
end

View File

@ -1,6 +1,9 @@
# typed: strict
# frozen_string_literal: true
require "services/cli"
module Homebrew
module Services
module Commands
module Run
@ -14,3 +17,4 @@ module Services
end
end
end
end

View File

@ -1,14 +1,20 @@
# typed: strict
# frozen_string_literal: true
require "services/cli"
module Homebrew
module Services
module Commands
module Start
TRIGGERS = %w[start launch load s l].freeze
sig {
params(targets: T::Array[Services::FormulaWrapper], custom_plist: T.nilable(String),
verbose: T.nilable(T::Boolean)).void
params(
targets: T::Array[Services::FormulaWrapper],
custom_plist: T.nilable(String),
verbose: T.nilable(T::Boolean),
).void
}
def self.run(targets, custom_plist, verbose:)
Services::Cli.check(targets)
@ -17,3 +23,4 @@ module Services
end
end
end
end

View File

@ -1,16 +1,21 @@
# typed: strict
# frozen_string_literal: true
require "services/cli"
module Homebrew
module Services
module Commands
module Stop
TRIGGERS = %w[stop unload terminate term t u].freeze
sig {
params(targets: T::Array[Services::FormulaWrapper],
params(
targets: T::Array[Services::FormulaWrapper],
verbose: T.nilable(T::Boolean),
no_wait: T.nilable(T::Boolean),
max_wait: T.nilable(Float)).void
max_wait: T.nilable(Float),
).void
}
def self.run(targets, verbose:, no_wait:, max_wait:)
Services::Cli.check(targets)
@ -19,3 +24,4 @@ module Services
end
end
end
end

View File

@ -3,6 +3,7 @@
# Wrapper for a formula to handle service-related stuff like parsing and
# generating the service/plist files.
module Homebrew
module Services
class FormulaWrapper
# Access the `Formula` instance.
@ -68,7 +69,8 @@ module Services
@keep_alive ||= T.let(T.must(load_service).keep_alive?, T.nilable(T::Boolean)) if service?
end
# service_name delegates with formula.plist_name or formula.service_name for systemd (e.g., `homebrew.<formula>`).
# service_name delegates with formula.plist_name or formula.service_name for systemd
# (e.g., `homebrew.<formula>`).
sig { returns(T.nilable(String)) }
attr_reader :service_name
@ -250,8 +252,7 @@ module Services
odebug cmd.join(" "), output
[output, success, :launchctl_list]
else
cmd = [System.launchctl.to_s, "print",
"#{System.domain_target}/#{service_name}"]
cmd = [System.launchctl.to_s, "print", "#{System.domain_target}/#{service_name}"]
output = Utils.popen_read(*cmd).chomp
success = $CHILD_STATUS.present? && $CHILD_STATUS.success? && output.present?
odebug cmd.join(" "), output
@ -261,8 +262,7 @@ module Services
cmd = ["status", service_name]
output = System::Systemctl.popen_read(*cmd).chomp
success = $CHILD_STATUS.present? && $CHILD_STATUS.success? && output.present?
odebug [System::Systemctl.executable, System::Systemctl.scope, *cmd].join(" "),
output
odebug [System::Systemctl.executable, System::Systemctl.scope, *cmd].join(" "), output
[output, success, :systemctl]
end
end
@ -330,3 +330,4 @@ module Services
end
end
end
end

View File

@ -3,6 +3,7 @@
require "services/formula_wrapper"
module Homebrew
module Services
module Formulae
# All available services, with optional filters applied
@ -29,3 +30,4 @@ module Services
end
end
end
end

View File

@ -3,6 +3,7 @@
require_relative "system/systemctl"
module Homebrew
module Services
module System
extend FileUtils
@ -76,7 +77,8 @@ module Services
def self.domain_target
if root?
"system"
elsif (ssh_tty = ENV.fetch("HOMEBREW_SSH_TTY", nil).present? && File.stat("/dev/console").uid != Process.uid) ||
elsif (ssh_tty = ENV.fetch("HOMEBREW_SSH_TTY", nil).present? &&
File.stat("/dev/console").uid != Process.uid) ||
(sudo_user = ENV.fetch("HOMEBREW_SUDO_USER", nil).present?) ||
(Process.uid != Process.euid)
if @output_warning.blank? && ENV.fetch("HOMEBREW_SERVICES_NO_DOMAIN_WARNING", nil).blank?
@ -100,3 +102,4 @@ module Services
end
end
end
end

View File

@ -1,6 +1,7 @@
# typed: strict
# frozen_string_literal: true
module Homebrew
module Services
module System
module Systemctl
@ -52,3 +53,4 @@ module Services
end
end
end
end

View File

@ -4,7 +4,7 @@ require "services/cli"
require "services/system"
require "services/formula_wrapper"
RSpec.describe Services::Cli do
RSpec.describe Homebrew::Services::Cli do
subject(:services_cli) { described_class }
let(:service_string) { "service" }
@ -17,7 +17,7 @@ RSpec.describe Services::Cli do
describe "#running" do
it "macOS - returns the currently running services" do
allow(Services::System).to receive_messages(launchctl?: true, systemctl?: false)
allow(Homebrew::Services::System).to receive_messages(launchctl?: true, systemctl?: false)
allow(Utils).to receive(:popen_read).and_return <<~EOS
77513 50 homebrew.mxcl.php
495 0 homebrew.mxcl.node_exporter
@ -31,8 +31,8 @@ RSpec.describe Services::Cli do
end
it "systemD - returns the currently running services" do
allow(Services::System).to receive(:launchctl?).and_return(false)
allow(Services::System::Systemctl).to receive(:popen_read).and_return <<~EOS
allow(Homebrew::Services::System).to receive(:launchctl?).and_return(false)
allow(Homebrew::Services::System::Systemctl).to receive(:popen_read).and_return <<~EOS
homebrew.php.service loaded active running Homebrew PHP service
systemd-udevd.service loaded active running Rule-based Manager for Device Events and Files
udisks2.service loaded active running Disk Manager
@ -74,7 +74,7 @@ RSpec.describe Services::Cli do
keep_alive?: false,
)
allow(service).to receive(:service_name)
allow(Services::FormulaWrapper).to receive(:from).and_return(service)
allow(Homebrew::Services::FormulaWrapper).to receive(:from).and_return(service)
allow(services_cli).to receive(:running).and_return(["example_service"])
expect do
services_cli.kill_orphaned_services
@ -84,7 +84,7 @@ RSpec.describe Services::Cli do
describe "#run" do
it "checks empty targets cause no error" do
expect(Services::System).not_to receive(:root?)
expect(Homebrew::Services::System).not_to receive(:root?)
services_cli.run([])
end
@ -100,14 +100,14 @@ RSpec.describe Services::Cli do
describe "#start" do
it "checks missing file causes error" do
expect(Services::System).not_to receive(:root?)
expect(Homebrew::Services::System).not_to receive(:root?)
expect do
services_cli.start(["service_name"], "/hfdkjshksdjhfkjsdhf/fdsjghsdkjhb")
end.to raise_error(UsageError, "Invalid usage: Provided service file does not exist")
end
it "checks empty targets cause no error" do
expect(Services::System).not_to receive(:root?)
expect(Homebrew::Services::System).not_to receive(:root?)
services_cli.start([])
end
@ -123,14 +123,14 @@ RSpec.describe Services::Cli do
describe "#stop" do
it "checks empty targets cause no error" do
expect(Services::System).not_to receive(:root?)
expect(Homebrew::Services::System).not_to receive(:root?)
services_cli.stop([])
end
end
describe "#kill" do
it "checks empty targets cause no error" do
expect(Services::System).not_to receive(:root?)
expect(Homebrew::Services::System).not_to receive(:root?)
services_cli.kill([])
end
@ -153,7 +153,7 @@ RSpec.describe Services::Cli do
describe "#install_service_file" do
it "checks service is installed" do
service = instance_double(Services::FormulaWrapper, name: "name", installed?: false)
service = instance_double(Homebrew::Services::FormulaWrapper, name: "name", installed?: false)
expect do
services_cli.install_service_file(service, nil)
end.to raise_error(UsageError, "Invalid usage: Formula `name` is not installed")
@ -161,7 +161,7 @@ RSpec.describe Services::Cli do
it "checks service file exists" do
service = instance_double(
Services::FormulaWrapper,
Homebrew::Services::FormulaWrapper,
name: "name",
installed?: true,
service_file: instance_double(Pathname, exist?: false),
@ -177,17 +177,17 @@ RSpec.describe Services::Cli do
describe "#systemd_load", :needs_linux do
it "checks non-enabling run" do
expect(Services::System::Systemctl).to receive(:run).once.and_return(true)
expect(Homebrew::Services::System::Systemctl).to receive(:run).once.and_return(true)
services_cli.systemd_load(
instance_double(Services::FormulaWrapper, service_name: "name"),
instance_double(Homebrew::Services::FormulaWrapper, service_name: "name"),
enable: false,
)
end
it "checks enabling run" do
expect(Services::System::Systemctl).to receive(:run).twice.and_return(true)
expect(Homebrew::Services::System::Systemctl).to receive(:run).twice.and_return(true)
services_cli.systemd_load(
instance_double(Services::FormulaWrapper, service_name: "name"),
instance_double(Homebrew::Services::FormulaWrapper, service_name: "name"),
enable: true,
)
end
@ -195,57 +195,67 @@ RSpec.describe Services::Cli do
describe "#launchctl_load", :needs_macos do
it "checks non-enabling run" do
allow(Services::System).to receive(:launchctl).and_return(Pathname.new("/bin/launchctl"))
expect(Services::System).to receive(:domain_target).once.and_return("target")
allow(Homebrew::Services::System).to receive(:launchctl).and_return(Pathname.new("/bin/launchctl"))
expect(Homebrew::Services::System).to receive(:domain_target).once.and_return("target")
expect(described_class).to receive(:safe_system).once.and_return(true)
services_cli.launchctl_load(instance_double(Services::FormulaWrapper), file: "a", enable: false)
services_cli.launchctl_load(instance_double(Homebrew::Services::FormulaWrapper), file: "a", enable: false)
end
it "checks enabling run" do
allow(Services::System).to receive(:launchctl).and_return(Pathname.new("/bin/launchctl"))
expect(Services::System).to receive(:domain_target).twice.and_return("target")
allow(Homebrew::Services::System).to receive(:launchctl).and_return(Pathname.new("/bin/launchctl"))
expect(Homebrew::Services::System).to receive(:domain_target).twice.and_return("target")
expect(described_class).to receive(:safe_system).twice.and_return(true)
services_cli.launchctl_load(instance_double(Services::FormulaWrapper, service_name: "name"), file: "a",
services_cli.launchctl_load(instance_double(Homebrew::Services::FormulaWrapper, service_name: "name"),
file: "a",
enable: true)
end
end
describe "#service_load" do
it "checks non-root for login" do
expect(Services::System).to receive(:launchctl?).once.and_return(false)
expect(Services::System).to receive(:systemctl?).once.and_return(false)
expect(Services::System).to receive(:root?).once.and_return(true)
expect(Homebrew::Services::System).to receive(:launchctl?).once.and_return(false)
expect(Homebrew::Services::System).to receive(:systemctl?).once.and_return(false)
expect(Homebrew::Services::System).to receive(:root?).once.and_return(true)
expect do
services_cli.service_load(
instance_double(Services::FormulaWrapper, name: "name", service_name: "service.name",
service_startup?: false), enable: false
instance_double(
Homebrew::Services::FormulaWrapper,
name: "name",
service_name: "service.name",
service_startup?: false,
),
enable: false,
)
end.to output("==> Successfully ran `name` (label: service.name)\n").to_stdout
end
it "checks root for startup" do
expect(Services::System).to receive(:launchctl?).once.and_return(false)
expect(Services::System).to receive(:systemctl?).once.and_return(false)
expect(Services::System).to receive(:root?).twice.and_return(false)
expect(Homebrew::Services::System).to receive(:launchctl?).once.and_return(false)
expect(Homebrew::Services::System).to receive(:systemctl?).once.and_return(false)
expect(Homebrew::Services::System).to receive(:root?).twice.and_return(false)
expect do
services_cli.service_load(
instance_double(Services::FormulaWrapper, name: "name", service_name: "service.name",
service_startup?: true),
instance_double(
Homebrew::Services::FormulaWrapper,
name: "name",
service_name: "service.name",
service_startup?: true,
),
enable: false,
)
end.to output("==> Successfully ran `name` (label: service.name)\n").to_stdout
end
it "triggers launchctl" do
expect(Services::System).to receive(:launchctl?).once.and_return(true)
expect(Services::System).not_to receive(:systemctl?)
expect(Services::System).to receive(:root?).twice.and_return(false)
expect(Homebrew::Services::System).to receive(:launchctl?).once.and_return(true)
expect(Homebrew::Services::System).not_to receive(:systemctl?)
expect(Homebrew::Services::System).to receive(:root?).twice.and_return(false)
expect(described_class).to receive(:launchctl_load).once.and_return(true)
expect do
services_cli.service_load(
instance_double(
Services::FormulaWrapper,
Homebrew::Services::FormulaWrapper,
name: "name",
service_name: "service.name",
service_startup?: false,
@ -257,14 +267,14 @@ service_startup?: true),
end
it "triggers systemctl" do
expect(Services::System).to receive(:launchctl?).once.and_return(false)
expect(Services::System).to receive(:systemctl?).once.and_return(true)
expect(Services::System).to receive(:root?).twice.and_return(false)
expect(Services::System::Systemctl).to receive(:run).once.and_return(true)
expect(Homebrew::Services::System).to receive(:launchctl?).once.and_return(false)
expect(Homebrew::Services::System).to receive(:systemctl?).once.and_return(true)
expect(Homebrew::Services::System).to receive(:root?).twice.and_return(false)
expect(Homebrew::Services::System::Systemctl).to receive(:run).once.and_return(true)
expect do
services_cli.service_load(
instance_double(
Services::FormulaWrapper,
Homebrew::Services::FormulaWrapper,
name: "name",
service_name: "service.name",
service_startup?: false,
@ -276,14 +286,14 @@ service_startup?: true),
end
it "represents correct action" do
expect(Services::System).to receive(:launchctl?).once.and_return(false)
expect(Services::System).to receive(:systemctl?).once.and_return(true)
expect(Services::System).to receive(:root?).twice.and_return(false)
expect(Services::System::Systemctl).to receive(:run).twice.and_return(true)
expect(Homebrew::Services::System).to receive(:launchctl?).once.and_return(false)
expect(Homebrew::Services::System).to receive(:systemctl?).once.and_return(true)
expect(Homebrew::Services::System).to receive(:root?).twice.and_return(false)
expect(Homebrew::Services::System::Systemctl).to receive(:run).twice.and_return(true)
expect do
services_cli.service_load(
instance_double(
Services::FormulaWrapper,
Homebrew::Services::FormulaWrapper,
name: "name",
service_name: "service.name",
service_startup?: false,

View File

@ -4,7 +4,7 @@ require "services/commands/cleanup"
require "services/system"
require "services/cli"
RSpec.describe Services::Commands::Cleanup do
RSpec.describe Homebrew::Services::Commands::Cleanup do
describe "#TRIGGERS" do
it "contains all restart triggers" do
expect(described_class::TRIGGERS).to eq(%w[cleanup clean cl rm])
@ -13,9 +13,9 @@ RSpec.describe Services::Commands::Cleanup do
describe "#run" do
it "root - prints on empty cleanup" do
expect(Services::System).to receive(:root?).once.and_return(true)
expect(Services::Cli).to receive(:kill_orphaned_services).once.and_return([])
expect(Services::Cli).to receive(:remove_unused_service_files).once.and_return([])
expect(Homebrew::Services::System).to receive(:root?).once.and_return(true)
expect(Homebrew::Services::Cli).to receive(:kill_orphaned_services).once.and_return([])
expect(Homebrew::Services::Cli).to receive(:remove_unused_service_files).once.and_return([])
expect do
described_class.run
@ -23,9 +23,9 @@ RSpec.describe Services::Commands::Cleanup do
end
it "user - prints on empty cleanup" do
expect(Services::System).to receive(:root?).once.and_return(false)
expect(Services::Cli).to receive(:kill_orphaned_services).once.and_return([])
expect(Services::Cli).to receive(:remove_unused_service_files).once.and_return([])
expect(Homebrew::Services::System).to receive(:root?).once.and_return(false)
expect(Homebrew::Services::Cli).to receive(:kill_orphaned_services).once.and_return([])
expect(Homebrew::Services::Cli).to receive(:remove_unused_service_files).once.and_return([])
expect do
described_class.run
@ -33,9 +33,9 @@ RSpec.describe Services::Commands::Cleanup do
end
it "prints nothing on cleanup" do
expect(Services::System).not_to receive(:root?)
expect(Services::Cli).to receive(:kill_orphaned_services).once.and_return(["a"])
expect(Services::Cli).to receive(:remove_unused_service_files).once.and_return(["b"])
expect(Homebrew::Services::System).not_to receive(:root?)
expect(Homebrew::Services::Cli).to receive(:kill_orphaned_services).once.and_return(["a"])
expect(Homebrew::Services::Cli).to receive(:remove_unused_service_files).once.and_return(["b"])
expect do
described_class.run

View File

@ -2,7 +2,7 @@
require "services/commands/info"
RSpec.describe Services::Commands::Info do
RSpec.describe Homebrew::Services::Commands::Info do
before do
allow_any_instance_of(IO).to receive(:tty?).and_return(false)
end

View File

@ -2,7 +2,7 @@
require "services/commands/list"
RSpec.describe Services::Commands::List do
RSpec.describe Homebrew::Services::Commands::List do
describe "#TRIGGERS" do
it "contains all restart triggers" do
expect(described_class::TRIGGERS).to eq([nil, "list", "ls"])
@ -11,7 +11,7 @@ RSpec.describe Services::Commands::List do
describe "#run" do
it "fails with empty list" do
expect(Services::Formulae).to receive(:services_list).and_return([])
expect(Homebrew::Services::Formulae).to receive(:services_list).and_return([])
expect do
allow($stderr).to receive(:tty?).and_return(true)
described_class.run
@ -27,7 +27,7 @@ RSpec.describe Services::Commands::List do
file: "/dev/null",
loaded: true,
}
expect(Services::Formulae).to receive(:services_list).and_return([formula])
expect(Homebrew::Services::Formulae).to receive(:services_list).and_return([formula])
expect do
described_class.run
end.to output(out).to_stdout
@ -47,7 +47,7 @@ RSpec.describe Services::Commands::List do
filtered_formula = formula.slice(*described_class::JSON_FIELDS)
expected_output = "#{JSON.pretty_generate([filtered_formula])}\n"
expect(Services::Formulae).to receive(:services_list).and_return([formula])
expect(Homebrew::Services::Formulae).to receive(:services_list).and_return([formula])
expect do
described_class.run(json: true)
end.to output(expected_output).to_stdout

View File

@ -1,9 +1,8 @@
# frozen_string_literal: true
require "services/commands/restart"
require "services/cli"
require "services/formula_wrapper"
RSpec.describe Services::Commands::Restart do
RSpec.describe Homebrew::Services::Commands::Restart do
describe "#TRIGGERS" do
it "contains all restart triggers" do
expect(described_class::TRIGGERS).to eq(%w[restart relaunch reload r])
@ -18,27 +17,27 @@ RSpec.describe Services::Commands::Restart do
end
it "starts if services are not loaded" do
expect(Services::Cli).not_to receive(:run)
expect(Services::Cli).not_to receive(:stop)
expect(Services::Cli).to receive(:start).once
service = instance_double(Services::FormulaWrapper, service_name: "name", loaded?: false)
expect(Homebrew::Services::Cli).not_to receive(:run)
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
end
it "starts if services are loaded with file" do
expect(Services::Cli).not_to receive(:run)
expect(Services::Cli).to receive(:start).once
expect(Services::Cli).to receive(:stop).once
service = instance_double(Services::FormulaWrapper, service_name: "name", loaded?: true,
expect(Homebrew::Services::Cli).not_to receive(:run)
expect(Homebrew::Services::Cli).to receive(:start).once
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
end
it "runs if services are loaded without file" do
expect(Services::Cli).not_to receive(:start)
expect(Services::Cli).to receive(:run).once
expect(Services::Cli).to receive(:stop).once
service = instance_double(Services::FormulaWrapper, service_name: "name", loaded?: true,
expect(Homebrew::Services::Cli).not_to receive(:start)
expect(Homebrew::Services::Cli).to receive(:run).once
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
end

View File

@ -2,7 +2,7 @@
require "services/formulae"
RSpec.describe Services::Formulae do
RSpec.describe Homebrew::Services::Formulae do
describe "#services_list" do
it "empty list without available formulae" do
allow(described_class).to receive(:available_services).and_return({})
@ -10,7 +10,7 @@ RSpec.describe Services::Formulae do
end
it "list with available formulae" do
formula = instance_double(Services::FormulaWrapper)
formula = instance_double(Homebrew::Services::FormulaWrapper)
expected = [
{
file: Pathname.new("/Library/LaunchDaemons/file.plist"),

View File

@ -4,7 +4,7 @@ require "services/system"
require "services/formula_wrapper"
require "tempfile"
RSpec.describe Services::FormulaWrapper do
RSpec.describe Homebrew::Services::FormulaWrapper do
subject(:service) { described_class.new(formula) }
let(:formula) do
@ -41,17 +41,17 @@ RSpec.describe Services::FormulaWrapper do
describe "#service_file" do
it "macOS - outputs the full service file path" do
allow(Services::System).to receive(:launchctl?).and_return(true)
allow(Homebrew::Services::System).to receive(:launchctl?).and_return(true)
expect(service.service_file.to_s).to eq("/usr/local/opt/mysql/homebrew.mysql.plist")
end
it "systemD - outputs the full service file path" do
allow(Services::System).to receive_messages(launchctl?: false, systemctl?: true)
allow(Homebrew::Services::System).to receive_messages(launchctl?: false, systemctl?: true)
expect(service.service_file.to_s).to eq("/usr/local/opt/mysql/homebrew.mysql.service")
end
it "Other - outputs no service file" do
allow(Services::System).to receive_messages(launchctl?: false, systemctl?: false)
allow(Homebrew::Services::System).to receive_messages(launchctl?: false, systemctl?: false)
expect(service.service_file).to be_nil
end
end
@ -64,45 +64,45 @@ RSpec.describe Services::FormulaWrapper do
describe "#service_name" do
it "macOS - outputs the service name" do
allow(Services::System).to receive(:launchctl?).and_return(true)
allow(Homebrew::Services::System).to receive(:launchctl?).and_return(true)
expect(service.service_name).to eq("plist-mysql-test")
end
it "systemD - outputs the service name" do
allow(Services::System).to receive_messages(launchctl?: false, systemctl?: true)
allow(Homebrew::Services::System).to receive_messages(launchctl?: false, systemctl?: true)
expect(service.service_name).to eq("plist-mysql-test")
end
it "Other - outputs no service name" do
allow(Services::System).to receive_messages(launchctl?: false, systemctl?: false)
allow(Homebrew::Services::System).to receive_messages(launchctl?: false, systemctl?: false)
expect(service.service_name).to be_nil
end
end
describe "#dest_dir" do
before do
allow(Services::System).to receive_messages(launchctl?: false, systemctl?: false)
allow(Homebrew::Services::System).to receive_messages(launchctl?: false, systemctl?: false)
end
it "macOS - user - outputs the destination directory for the service file" do
ENV["HOME"] = "/tmp_home"
allow(Services::System).to receive_messages(root?: false, launchctl?: true)
allow(Homebrew::Services::System).to receive_messages(root?: false, launchctl?: true)
expect(service.dest_dir.to_s).to eq("/tmp_home/Library/LaunchAgents")
end
it "macOS - root - outputs the destination directory for the service file" do
allow(Services::System).to receive_messages(launchctl?: true, root?: true)
allow(Homebrew::Services::System).to receive_messages(launchctl?: true, root?: true)
expect(service.dest_dir.to_s).to eq("/Library/LaunchDaemons")
end
it "systemD - user - outputs the destination directory for the service file" do
ENV["HOME"] = "/tmp_home"
allow(Services::System).to receive_messages(root?: false, launchctl?: false, systemctl?: true)
allow(Homebrew::Services::System).to receive_messages(root?: false, launchctl?: false, systemctl?: true)
expect(service.dest_dir.to_s).to eq("/tmp_home/.config/systemd/user")
end
it "systemD - root - outputs the destination directory for the service file" do
allow(Services::System).to receive_messages(root?: true, launchctl?: false, systemctl?: true)
allow(Homebrew::Services::System).to receive_messages(root?: true, launchctl?: false, systemctl?: true)
expect(service.dest_dir.to_s).to eq("/usr/lib/systemd/system")
end
end
@ -110,16 +110,16 @@ RSpec.describe Services::FormulaWrapper do
describe "#dest" do
before do
ENV["HOME"] = "/tmp_home"
allow(Services::System).to receive_messages(launchctl?: false, systemctl?: false)
allow(Homebrew::Services::System).to receive_messages(launchctl?: false, systemctl?: false)
end
it "macOS - outputs the destination for the service file" do
allow(Services::System).to receive(:launchctl?).and_return(true)
allow(Homebrew::Services::System).to receive(:launchctl?).and_return(true)
expect(service.dest.to_s).to eq("/tmp_home/Library/LaunchAgents/homebrew.mysql.plist")
end
it "systemD - outputs the destination for the service file" do
allow(Services::System).to receive(:systemctl?).and_return(true)
allow(Homebrew::Services::System).to receive(:systemctl?).and_return(true)
expect(service.dest.to_s).to eq("/tmp_home/.config/systemd/user/homebrew.mysql.service")
end
end
@ -132,20 +132,20 @@ RSpec.describe Services::FormulaWrapper do
describe "#loaded?" do
it "macOS - outputs if the service is loaded" do
allow(Services::System).to receive_messages(launchctl?: true, systemctl?: false)
allow(Homebrew::Services::System).to receive_messages(launchctl?: true, systemctl?: false)
allow(Utils).to receive(:safe_popen_read)
expect(service.loaded?).to be(false)
end
it "systemD - outputs if the service is loaded" do
allow(Services::System).to receive_messages(launchctl?: false, systemctl?: true)
allow(Services::System::Systemctl).to receive(:quiet_run).and_return(false)
allow(Homebrew::Services::System).to receive_messages(launchctl?: false, systemctl?: true)
allow(Homebrew::Services::System::Systemctl).to receive(:quiet_run).and_return(false)
allow(Utils).to receive(:safe_popen_read)
expect(service.loaded?).to be(false)
end
it "Other - outputs no status" do
allow(Services::System).to receive_messages(launchctl?: false, systemctl?: false)
allow(Homebrew::Services::System).to receive_messages(launchctl?: false, systemctl?: false)
expect(service.loaded?).to be_nil
end
end
@ -182,7 +182,7 @@ RSpec.describe Services::FormulaWrapper do
it "user if file present" do
allow(service).to receive_messages(boot_path_service_file_present?: false,
user_path_service_file_present?: true)
allow(Services::System).to receive(:user).and_return("user")
allow(Homebrew::Services::System).to receive(:user).and_return("user")
expect(service.owner).to eq("user")
end
@ -195,24 +195,24 @@ RSpec.describe Services::FormulaWrapper do
describe "#service_file_present?" do
it "macOS - outputs if the service file is present" do
allow(Services::System).to receive_messages(launchctl?: true, systemctl?: false)
allow(Homebrew::Services::System).to receive_messages(launchctl?: true, systemctl?: false)
expect(service.service_file_present?).to be(false)
end
it "macOS - outputs if the service file is present for root" do
allow(Services::System).to receive_messages(launchctl?: true, systemctl?: false)
allow(Homebrew::Services::System).to receive_messages(launchctl?: true, systemctl?: false)
expect(service.service_file_present?(for: :root)).to be(false)
end
it "macOS - outputs if the service file is present for user" do
allow(Services::System).to receive_messages(launchctl?: true, systemctl?: false)
allow(Homebrew::Services::System).to receive_messages(launchctl?: true, systemctl?: false)
expect(service.service_file_present?(for: :user)).to be(false)
end
end
describe "#owner?" do
it "macOS - outputs the service file owner" do
allow(Services::System).to receive_messages(launchctl?: true, systemctl?: false)
allow(Homebrew::Services::System).to receive_messages(launchctl?: true, systemctl?: false)
expect(service.owner).to be_nil
end
end
@ -321,7 +321,7 @@ RSpec.describe Services::FormulaWrapper do
describe "#to_hash" do
it "represents non-service values" do
allow(Services::System).to receive_messages(launchctl?: true, systemctl?: false)
allow(Homebrew::Services::System).to receive_messages(launchctl?: true, systemctl?: false)
allow_any_instance_of(described_class).to receive_messages(service?: false, service_file_present?: false)
expected = {
exit_code: nil,
@ -340,7 +340,7 @@ RSpec.describe Services::FormulaWrapper do
it "represents running non-service values" do
ENV["HOME"] = "/tmp_home"
allow(Services::System).to receive_messages(launchctl?: true, systemctl?: false)
allow(Homebrew::Services::System).to receive_messages(launchctl?: true, systemctl?: false)
expect(service).to receive(:service?).twice.and_return(false)
expect(service).to receive(:service_file_present?).and_return(true)
expected = {
@ -360,7 +360,7 @@ RSpec.describe Services::FormulaWrapper do
it "represents service values" do
ENV["HOME"] = "/tmp_home"
allow(Services::System).to receive_messages(launchctl?: true, systemctl?: false)
allow(Homebrew::Services::System).to receive_messages(launchctl?: true, systemctl?: false)
expect(service).to receive(:service?).twice.and_return(true)
expect(service).to receive(:service_file_present?).and_return(true)
expect(service).to receive(:load_service).twice.and_return(service_object)

View File

@ -3,15 +3,15 @@
require "services/system"
require "services/system/systemctl"
RSpec.describe Services::System::Systemctl do
RSpec.describe Homebrew::Services::System::Systemctl do
describe ".scope" do
it "outputs systemctl scope for user" do
allow(Services::System).to receive(:root?).and_return(false)
allow(Homebrew::Services::System).to receive(:root?).and_return(false)
expect(described_class.scope).to eq("--user")
end
it "outputs systemctl scope for root" do
allow(Services::System).to receive(:root?).and_return(true)
allow(Homebrew::Services::System).to receive(:root?).and_return(true)
expect(described_class.scope).to eq("--system")
end
end

View File

@ -2,7 +2,7 @@
require "services/system"
RSpec.describe Services::System do
RSpec.describe Homebrew::Services::System do
describe "#launchctl" do
it "macOS - outputs launchctl command location", :needs_macos do
expect(described_class.launchctl).to eq(Pathname.new("/bin/launchctl"))