From 58d4660009885f2231327dc13ca8e53460693b4d Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Mon, 1 Nov 2021 23:49:02 +0000 Subject: [PATCH] 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. --- xbar/brew-services.10m.rb | 173 +++++++++++++++++++++++++++++--------- 1 file changed, 131 insertions(+), 42 deletions(-) diff --git a/xbar/brew-services.10m.rb b/xbar/brew-services.10m.rb index 3b9eb00..1e15c8e 100755 --- a/xbar/brew-services.10m.rb +++ b/xbar/brew-services.10m.rb @@ -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