From 99486c81079ad6a1208cbdad2862b945e7b6b404 Mon Sep 17 00:00:00 2001 From: Ryan Rotter Date: Thu, 27 Jun 2024 17:28:18 -0400 Subject: [PATCH 1/3] Use API for description searches Both `brew search --desc` and `brew desc --search` use API for cask and formula searches unless `--eval-all` or `HOMEBREW_EVAL_ALL` set. Description searches do not use the description cache or eval any formulas/casks. - With `--eval-all`, description search reverts to the old behavior. - Warn if description search exludes any formulae/casks (because `--eval-all` not set). - Enforce `--eval-all` requirement if NO_INSTALL_FROM_API set. --- Library/Homebrew/cmd/desc.rb | 2 +- Library/Homebrew/cmd/search.rb | 2 +- Library/Homebrew/descriptions.rb | 6 ++++-- Library/Homebrew/search.rb | 32 ++++++++++++++++++++++++++------ 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/Library/Homebrew/cmd/desc.rb b/Library/Homebrew/cmd/desc.rb index 70088f5a99832..b43d9235f8f7b 100644 --- a/Library/Homebrew/cmd/desc.rb +++ b/Library/Homebrew/cmd/desc.rb @@ -47,7 +47,7 @@ def run end if search_type.present? - if !args.eval_all? && !Homebrew::EnvConfig.eval_all? + if !args.eval_all? && !Homebrew::EnvConfig.eval_all? && Homebrew::EnvConfig.no_install_from_api? raise UsageError, "`brew desc --search` needs `--eval-all` passed or `HOMEBREW_EVAL_ALL` set!" end diff --git a/Library/Homebrew/cmd/search.rb b/Library/Homebrew/cmd/search.rb index ccdefd308d018..8c6d89a34414f 100644 --- a/Library/Homebrew/cmd/search.rb +++ b/Library/Homebrew/cmd/search.rb @@ -70,7 +70,7 @@ def run string_or_regex = Search.query_regexp(query) if args.desc? - if !args.eval_all? && !Homebrew::EnvConfig.eval_all? + if !args.eval_all? && !Homebrew::EnvConfig.eval_all? && Homebrew::EnvConfig.no_install_from_api? raise UsageError, "`brew search --desc` needs `--eval-all` passed or `HOMEBREW_EVAL_ALL` set!" end diff --git a/Library/Homebrew/descriptions.rb b/Library/Homebrew/descriptions.rb index 309ff26cc95e1..967c0d7c22010 100644 --- a/Library/Homebrew/descriptions.rb +++ b/Library/Homebrew/descriptions.rb @@ -8,8 +8,10 @@ # Helper class for printing and searching descriptions. class Descriptions # Given a regex, find all formulae whose specified fields contain a match. - def self.search(string_or_regex, field, cache_store, eval_all = Homebrew::EnvConfig.eval_all?) - cache_store.populate_if_empty!(eval_all:) + def self.search(string_or_regex, field, cache_store, + eval_all = Homebrew::EnvConfig.eval_all?, cache_store_hash: false) + + cache_store.populate_if_empty!(eval_all:) unless cache_store_hash results = case field when :name diff --git a/Library/Homebrew/search.rb b/Library/Homebrew/search.rb index 8c04f4356156d..3e78204d09962 100644 --- a/Library/Homebrew/search.rb +++ b/Library/Homebrew/search.rb @@ -22,9 +22,19 @@ def self.search_descriptions(string_or_regex, args, search_type: :desc) if args.formula? || both ohai "Formulae" - CacheStoreDatabase.use(:descriptions) do |db| - cache_store = DescriptionCacheStore.new(db) - Descriptions.search(string_or_regex, search_type, cache_store, eval_all).print + if eval_all + CacheStoreDatabase.use(:descriptions) do |db| + cache_store = DescriptionCacheStore.new(db) + Descriptions.search(string_or_regex, search_type, cache_store, eval_all).print + end + else + unofficial = Tap.all.sum { |tap| tap.official? ? 0 : tap.formula_files.size } + if unofficial.positive? + opoo "Use `--eval-all` to search #{unofficial} additional " \ + "#{Utils.pluralize("formula", unofficial, plural: "e")} in third party taps." + end + descriptions = Homebrew::API::Formula.all_formulae.transform_values { |data| data["desc"] } + Descriptions.search(string_or_regex, search_type, descriptions, eval_all, cache_store_hash: true).print end end return if !args.cask? && !both @@ -32,9 +42,19 @@ def self.search_descriptions(string_or_regex, args, search_type: :desc) puts if both ohai "Casks" - CacheStoreDatabase.use(:cask_descriptions) do |db| - cache_store = CaskDescriptionCacheStore.new(db) - Descriptions.search(string_or_regex, search_type, cache_store, eval_all).print + if eval_all + CacheStoreDatabase.use(:cask_descriptions) do |db| + cache_store = CaskDescriptionCacheStore.new(db) + Descriptions.search(string_or_regex, search_type, cache_store, eval_all).print + end + else + unofficial = Tap.all.sum { |tap| tap.official? ? 0 : tap.cask_files.size } + if unofficial.positive? + opoo "Use `--eval-all` to search #{unofficial} additional " \ + "#{Utils.pluralize("cask", unofficial)} in third party taps." + end + descriptions = Homebrew::API::Cask.all_casks.transform_values { |c| [c["name"].join(", "), c["desc"]] } + Descriptions.search(string_or_regex, search_type, descriptions, eval_all, cache_store_hash: true).print end end From 4f6771ccabc5ebcb6c62b998d4c56167306f36e7 Mon Sep 17 00:00:00 2001 From: Ryan Rotter Date: Sun, 30 Jun 2024 18:53:57 -0400 Subject: [PATCH 2/3] test `brew desc -s` works w/ API w/o `--eval-all` --- Library/Homebrew/test/cmd/desc_spec.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Library/Homebrew/test/cmd/desc_spec.rb b/Library/Homebrew/test/cmd/desc_spec.rb index 1ceb790260964..512f35fbb12ce 100644 --- a/Library/Homebrew/test/cmd/desc_spec.rb +++ b/Library/Homebrew/test/cmd/desc_spec.rb @@ -30,4 +30,11 @@ .to output(/testball: Some test/).to_stdout .and not_to_output.to_stderr end + + it "successfully searches without --eval-all, with API", :integration_test do + setup_test_formula "testball" + + expect { brew "desc", "--search", "testball", "HOMEBREW_NO_INSTALL_FROM_API" => nil } + .to be_a_success + end end From 816fe36a41a3c9bb7cb1018535b00662b8f2efc6 Mon Sep 17 00:00:00 2001 From: Ryan Rotter Date: Sun, 30 Jun 2024 21:09:30 -0400 Subject: [PATCH 3/3] test Search.search_descriptions --- Library/Homebrew/test/search_spec.rb | 32 ++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/Library/Homebrew/test/search_spec.rb b/Library/Homebrew/test/search_spec.rb index dc67320fdebac..39b10cb7dc9ad 100644 --- a/Library/Homebrew/test/search_spec.rb +++ b/Library/Homebrew/test/search_spec.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true require "search" +require "descriptions" +require "cmd/desc" RSpec.describe Homebrew::Search do describe "#query_regexp" do @@ -57,4 +59,34 @@ end end end + + describe "#search_descriptions" do + let(:args) { Homebrew::Cmd::Desc.new(["min_arg_placeholder"]).args } + + context "with api" do + let(:api_formulae) do + { "testball" => { "desc" => "Some test" } } + end + + let(:api_casks) do + { "testball" => { "desc" => "Some test", "name" => ["Test Ball"] } } + end + + before do + allow(Homebrew::API::Formula).to receive(:all_formulae).and_return(api_formulae) + allow(Homebrew::API::Cask).to receive(:all_casks).and_return(api_casks) + end + + it "searches formula descriptions" do + expect { described_class.search_descriptions(described_class.query_regexp("some"), args) } + .to output(/testball: Some test/).to_stdout + end + + it "searches cask descriptions", :needs_macos do + expect { described_class.search_descriptions(described_class.query_regexp("ball"), args) } + .to output(/testball: \(Test Ball\) Some test/).to_stdout + .and not_to_output(/testball: Some test/).to_stdout + end + end + end end