feat(xbar/brew-services): support error and unknown services statuses

Also work around an issue where "brew services list" does not print the
status at all for some running services, so it instead just prints the
service name and the user it's running under.
This commit is contained in:
2021-11-01 23:49:02 +00:00
parent 45032db1d1
commit 58d4660009

View File

@@ -113,7 +113,19 @@ module Brew
attr_reader :name, :status, :user
def self.from_line(line)
name, status, user, _plist = line.split
parts = line.split
name = parts[0]
if %w[started stopped error unknown].include?(parts[1])
status = parts[1]
user = parts[2]
else
# Some services (dbus and logrotate for example) don't show a status
# when running "brew services list" at the moment. Instead they only
# show the service name and the user. So we work around this issue.
status = 'unknown'
user = parts[1]
end
new(name: name, status: status, user: user)
end
@@ -128,7 +140,15 @@ module Brew
end
def stopped?
!started?
@stopped ||= @status.downcase == 'stopped'
end
def error?
@error ||= @status.downcase == 'error'
end
def unknown_status?
@unknown_status ||= @status.downcase == 'unknown'
end
end
@@ -141,72 +161,125 @@ module Brew
brew_check(printer)
printer.item(
"#{prefix}#{started_services.size}/#{stopped_services.size}",
"#{prefix}" \
"#{started_services.size}/#{services.size - started_services.size}",
dropdown: false
)
printer.sep
printer.item('Brew Services')
printer.item(
"#{started_services.size} started / " \
"#{stopped_services.size} stopped"
) do |printer|
printer.item(status_label) do |printer|
printer.sep
printer.item(':hourglass: Refresh', refresh: true)
printer.sep
printer.item(
"Start All (#{stopped_services.size} services)",
terminal: false, refresh: true, shell: brew_path,
param1: 'services', param2: 'start', param3: '--all'
)
printer.item(
"Stop All (#{started_services.size} services)",
terminal: false, refresh: true, shell: brew_path,
param1: 'services', param2: 'stop', param3: '--all'
)
printer.item(
'Restart All ' \
"(#{started_services.size + stopped_services.size} services)",
terminal: false, refresh: true, shell: brew_path,
param1: 'services', param2: 'restart', param3: '--all'
)
if stopped_services.size.positive?
printer.item(
"Start All (#{stopped_services.size} services)",
terminal: false, refresh: true, shell: brew_path,
param1: 'services', param2: 'start', param3: '--all'
)
else
printer.item("Start All (#{stopped_services.size} services)")
end
if started_services.size.positive?
printer.item(
"Stop All (#{started_services.size} services)",
terminal: false, refresh: true, shell: brew_path,
param1: 'services', param2: 'stop', param3: '--all'
)
else
printer.item("Stop All (#{started_services.size} services)")
end
if services.size.positive?
printer.item(
'Restart All ' \
"(#{started_services.size + stopped_services.size} services)",
terminal: false, refresh: true, shell: brew_path,
param1: 'services', param2: 'restart', param3: '--all'
)
else
printer.item("Restart All (#{services.size} services)")
end
end
printer.sep
use_groups? ? print_service_groups(printer) : print_services(printer)
end
private
def status_label
label = []
if started_services.size.positive?
label << "#{started_services.size} started"
end
if stopped_services.size.positive?
label << "#{stopped_services.size} stopped"
end
if errored_services.size.positive?
label << "#{errored_services.size} error"
end
if unknown_status_services.size.positive?
label << "#{unknown_status_services.size} unknown"
end
label = ['no services available'] if label.empty?
label.join(' / ')
end
def use_groups?
ENV.fetch('VAR_GROUPS', 'true') == 'true'
end
def print_service_groups(printer)
printer.item('Started:')
started_services.each do |service|
print_service(printer, service)
if started_services.size.positive?
printer.sep
printer.item("Started (#{started_services.size}):")
started_services.each do |service|
print_service(printer, service)
end
end
printer.sep
printer.item('Stopped:')
stopped_services.each do |service|
print_service(printer, service)
if stopped_services.size.positive?
printer.sep
printer.item("Stopped (#{stopped_services.size}):")
stopped_services.each do |service|
print_service(printer, service)
end
end
if errored_services.size.positive?
printer.sep
printer.item("Error (#{errored_services.size}):")
errored_services.each do |service|
print_service(printer, service)
end
end
if unknown_status_services.size.positive?
printer.sep
printer.item("Unknown Status (#{unknown_status_services.size}):")
unknown_status_services.each do |service|
print_service(printer, service)
end
end
end
def print_services(printer)
printer.sep
services.each do |service|
print_service(printer, service)
end
end
def print_service(printer, service)
label = if service.started?
":white_check_mark: #{service.name}"
else
":ballot_box_with_check: #{service.name}"
end
icon = if service.started?
':white_check_mark:'
elsif service.stopped?
':ballot_box_with_check:'
elsif service.error?
':warning:'
elsif service.unknown_status?
':question:'
end
printer.item(label) do |printer|
if service.started?
printer.item("#{icon} #{service.name}") do |printer|
if service.started? || service.error? || service.unknown_status?
printer.item(
'Stop',
terminal: false, refresh: true, shell: brew_path,
@@ -217,7 +290,8 @@ module Brew
terminal: false, refresh: true, shell: brew_path,
param1: 'services', param2: 'restart', param3: service.name
)
else
end
if service.stopped? || service.unknown_status?
printer.item(
'Start',
terminal: false, refresh: true, shell: brew_path,
@@ -250,14 +324,29 @@ module Brew
end
def stopped_services
@stopped_services ||= services.reject(&:started?)
@stopped_services ||= services.select(&:stopped?)
end
def errored_services
@errored_services ||= services.select(&:error?)
end
def unknown_status_services
@unknown_status_services ||= services.select(&:unknown_status?)
end
def services
@services ||= cmd(
return @services if @services
found = false
@services = cmd(
brew_path, 'services', 'list'
).each_line.each_with_object([]) do |line, memo|
next if line.match(/^Name\s+Status\s+User\s+Plist$/)
# Ignore header line and everything before it.
unless found
found = line.strip.match(/^Name\s+Status\s+User\s+(File|Plist)$/)
next
end
memo.push(Service.from_line(line))
end