Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Library/Homebrew/bundle/brew_services.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ def started_services
if !Homebrew::Services::System.launchctl? && !Homebrew::Services::System.systemctl?
odie Homebrew::Services::System::MISSING_DAEMON_MANAGER_EXCEPTION_MESSAGE
end
states_to_skip = %w[stopped none]
states_to_skip = [:stopped, :none]

services_list = JSON.parse(Utils.safe_popen_read(HOMEBREW_BREW_FILE, "services", "list", "--json"))
services_list.filter_map do |hash|
hash.fetch("name") if states_to_skip.exclude?(hash.fetch("status"))
require "services/formulae"
Homebrew::Services::Formulae.services_list.filter_map do |hash|
hash.fetch(:name) if states_to_skip.exclude?(hash.fetch(:status))
Comment on lines +68 to +70
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Linux/systemd, brew services sets DBUS_SESSION_BUS_ADDRESS and XDG_RUNTIME_DIR from HOMEBREW_DBUS_SESSION_BUS_ADDRESS/HOMEBREW_XDG_RUNTIME_DIR before querying service state (see cmd/services.rb). By calling Homebrew::Services::Formulae.services_list directly here, systemctl --user calls may run without those env vars and incorrectly report services as not loaded/running. Consider mirroring the env setup (ideally scoped via with_env to avoid permanently mutating ENV) before invoking services_list, and add a spec to cover the systemd env behavior.

Suggested change
require "services/formulae"
Homebrew::Services::Formulae.services_list.filter_map do |hash|
hash.fetch(:name) if states_to_skip.exclude?(hash.fetch(:status))
old_dbus = ENV["DBUS_SESSION_BUS_ADDRESS"]
old_xdg = ENV["XDG_RUNTIME_DIR"]
new_dbus = ENV["HOMEBREW_DBUS_SESSION_BUS_ADDRESS"]
new_xdg = ENV["HOMEBREW_XDG_RUNTIME_DIR"]
ENV["DBUS_SESSION_BUS_ADDRESS"] = new_dbus if new_dbus
ENV["XDG_RUNTIME_DIR"] = new_xdg if new_xdg
begin
require "services/formulae"
Homebrew::Services::Formulae.services_list.filter_map do |hash|
hash.fetch(:name) if states_to_skip.exclude?(hash.fetch(:status))
end
ensure
if old_dbus.nil?
ENV.delete("DBUS_SESSION_BUS_ADDRESS")
else
ENV["DBUS_SESSION_BUS_ADDRESS"] = old_dbus
end
if old_xdg.nil?
ENV.delete("XDG_RUNTIME_DIR")
else
ENV["XDG_RUNTIME_DIR"] = old_xdg
end

Copilot uses AI. Check for mistakes.
end
end
end
Expand Down
23 changes: 12 additions & 11 deletions Library/Homebrew/test/bundle/brew_services_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

require "bundle"
require "bundle/brew_services"
require "services/formulae"

RSpec.describe Homebrew::Bundle::Brew::Services do
describe ".started_services" do
Expand All @@ -10,27 +11,27 @@
end

it "returns started services" do
allow(Utils).to receive(:safe_popen_read).and_return <<~EOS
allow(Homebrew::Services::Formulae).to receive(:services_list).and_return(
[
{
"name": "nginx",
"status": "started"
name: "nginx",
status: :started,
},
{
"name": "apache",
"status": "stopped"
name: "apache",
status: :stopped,
},
{
"name": "mysql",
"status": "started"
}
]
EOS
name: "mysql",
status: :started,
},
],
)
expect(described_class.started_services).to contain_exactly("nginx", "mysql")
end

it "returns empty array when no services exist" do
allow(Utils).to receive(:safe_popen_read).and_return("[]\n")
allow(Homebrew::Services::Formulae).to receive(:services_list).and_return([])
expect(described_class.started_services).to eq([])
end

Expand Down
3 changes: 2 additions & 1 deletion Library/Homebrew/test/bundle/brew_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
require "bundle/brew_services"
require "tsort"
require "formula"
require "services/formulae"
require "tab"
require "utils/bottles"

Expand Down Expand Up @@ -224,7 +225,7 @@
describe "#dump" do
it "returns a dump string with installed formulae" do
expect(Formula).to receive(:installed).and_return([foo, bar, baz])
allow(Utils).to receive(:safe_popen_read).and_return("[]")
allow(Homebrew::Services::Formulae).to receive(:services_list).and_return([])
expected = <<~EOS
# barfoo
brew "bar"
Expand Down
Loading