cmd/update-report: display descriptions for new formulae and casks.

This parses Homebrew's API JSON data to display descriptions for new
formulae and casks if available.

While we're here also add tests for ReporterHub.
This commit is contained in:
Mike McQuaid 2025-06-24 16:59:24 +01:00
parent e42084dc6f
commit 28753ef002
No known key found for this signature in database
2 changed files with 145 additions and 3 deletions

View File

@ -869,19 +869,35 @@ class ReporterHub
sig { void }
def dump_new_formula_report
formulae = select_formula_or_cask(:A).sort.reject { |name| installed?(name) }
return if formulae.blank?
output_dump_formula_or_cask_report "New Formulae", formulae
ohai "New Formulae"
formulae.each do |formula|
if (desc = description(formula))
puts "#{formula}: #{desc}"
else
puts formula
end
end
end
sig { void }
def dump_new_cask_report
return if Homebrew::SimulateSystem.simulating_or_running_on_linux?
return unless Cask::Caskroom.any_casks_installed?
casks = select_formula_or_cask(:AC).sort.filter_map do |name|
name.split("/").last unless cask_installed?(name)
end
return if casks.blank?
output_dump_formula_or_cask_report "New Casks", casks
ohai "New Casks"
casks.each do |cask|
if (desc = cask_description(cask))
puts "#{cask}: #{desc}"
else
puts cask
end
end
end
sig { void }
@ -935,4 +951,42 @@ class ReporterHub
rescue Cask::CaskError
false
end
sig { returns(T::Array[T.untyped]) }
def all_formula_json
return @all_formula_json if @all_formula_json
@all_formula_json = T.let(nil, T.nilable(T::Array[T.untyped]))
all_formula_json, = Homebrew::API.fetch_json_api_file "formula.jws.json"
all_formula_json = T.cast(all_formula_json, T::Array[T.untyped])
@all_formula_json = all_formula_json
end
sig { returns(T::Array[T.untyped]) }
def all_cask_json
return @all_cask_json if @all_cask_json
@all_cask_json = T.let(nil, T.nilable(T::Array[T.untyped]))
all_cask_json, = Homebrew::API.fetch_json_api_file "cask.jws.json"
all_cask_json = T.cast(all_cask_json, T::Array[T.untyped])
@all_cask_json = all_cask_json
end
sig { params(formula: String).returns(T.nilable(String)) }
def description(formula)
return if Homebrew::EnvConfig.no_install_from_api?
all_formula_json.find { |f| f["name"] == formula }
&.fetch("desc", nil)
&.presence
end
sig { params(cask: String).returns(T.nilable(String)) }
def cask_description(cask)
return if Homebrew::EnvConfig.no_install_from_api?
all_cask_json.find { |f| f["token"] == cask }
&.fetch("desc", nil)
&.presence
end
end

View File

@ -131,4 +131,92 @@ RSpec.describe Homebrew::Cmd::UpdateReport do
end
end
end
describe ReporterHub do
let(:hub) { described_class.new }
before do
ENV["HOMEBREW_NO_COLOR"] = "1"
allow(hub).to receive(:select_formula_or_cask).and_return([])
end
it "dumps new formulae report" do
allow(hub).to receive(:select_formula_or_cask).with(:A).and_return(["foo", "bar", "baz"])
allow(hub).to receive_messages(installed?: false, all_formula_json: [
{ "name" => "foo", "desc" => "foobly things" },
{ "name" => "baz", "desc" => "baz desc" },
])
expect { hub.dump }.to output(<<~EOS).to_stdout
==> New Formulae
bar
baz: baz desc
foo: foobly things
EOS
end
it "dumps new casks report" do
allow(hub).to receive(:select_formula_or_cask).with(:AC).and_return(["foo/cask1", "foo/cask2", "foo/cask3"])
allow(hub).to receive_messages(cask_installed?: false, all_cask_json: [
{ "token" => "cask1", "desc" => "desc1" },
{ "token" => "cask3", "desc" => "desc3" },
])
allow(Cask::Caskroom).to receive(:any_casks_installed?).and_return(true)
expect { hub.dump }.to output(<<~EOS).to_stdout
==> New Casks
cask1: desc1
cask2
cask3: desc3
EOS
end
it "dumps deleted installed formulae and casks report" do
allow(hub).to receive(:select_formula_or_cask).with(:D).and_return(["baz", "foo", "bar"])
allow(hub).to receive(:installed?).with("baz").and_return(true)
allow(hub).to receive(:installed?).with("foo").and_return(true)
allow(hub).to receive(:installed?).with("bar").and_return(true)
allow(hub).to receive(:select_formula_or_cask).with(:A).and_return([])
allow(hub).to receive(:select_formula_or_cask).with(:DC).and_return(["cask2", "cask1"])
allow(hub).to receive(:cask_installed?).with("cask1").and_return(true)
allow(hub).to receive(:cask_installed?).with("cask2").and_return(true)
allow(Homebrew::SimulateSystem).to receive(:simulating_or_running_on_linux?).and_return(false)
expect { hub.dump }.to output(<<~EOS).to_stdout
==> Deleted Installed Formulae
bar
baz
foo
==> Deleted Installed Casks
cask1
cask2
EOS
end
it "dumps outdated formulae and casks report" do
allow(Formula).to receive(:installed).and_return([
instance_double(Formula, name: "foo", outdated?: true),
instance_double(Formula, name: "bar", outdated?: true),
])
allow(Cask::Caskroom).to receive(:casks).and_return([
instance_double(Cask::Cask, token: "baz", outdated?: true),
instance_double(Cask::Cask, token: "qux", outdated?: true),
])
expect { hub.dump }.to output(<<~EOS).to_stdout
==> Outdated Formulae
bar
foo
==> Outdated Casks
baz
qux
You have 2 outdated formulae and 2 outdated casks installed.
You can upgrade them with brew upgrade
or list them with brew outdated.
EOS
end
it "prints nothing if there are no changes" do
allow(Formula).to receive(:installed).and_return([])
allow(Cask::Caskroom).to receive(:casks).and_return([])
expect { hub.dump }.not_to output.to_stdout
end
end
end