From ba664fa1b4c8f13284c8e5517ec278d456c58bf3 Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Sat, 17 Dec 2022 09:27:33 -0800 Subject: [PATCH 1/4] Move Search#search_casks out of extend/os This doesn't need to be isolated anymore because there is a check for the formula and cask args and formula is passed by default on Linux now. --- Library/Homebrew/search.rb | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/Library/Homebrew/search.rb b/Library/Homebrew/search.rb index 674e956b40..fb0bd0b2eb 100644 --- a/Library/Homebrew/search.rb +++ b/Library/Homebrew/search.rb @@ -111,8 +111,33 @@ module Homebrew end.compact end - def search_casks(_string_or_regex) - [] + def search_casks(string_or_regex) + if string_or_regex.is_a?(String) && string_or_regex.match?(HOMEBREW_TAP_CASK_REGEX) + return begin + [Cask::CaskLoader.load(string_or_regex).token] + rescue Cask::CaskUnavailableError + [] + end + end + + cask_tokens = Tap.flat_map(&:cask_tokens).map do |c| + c.sub(%r{^homebrew/cask.*/}, "") + end + + results = cask_tokens.extend(Searchable) + .search(string_or_regex) + + results += DidYouMean::SpellChecker.new(dictionary: cask_tokens) + .correct(string_or_regex) + + results.sort.map do |name| + cask = Cask::CaskLoader.load(name) + if cask.installed? + pretty_installed(cask.full_name) + else + cask.full_name + end + end.uniq end def search_names(query, string_or_regex, args) From 0ae416d0ee83d966f1530951c71e4b79c15f45b8 Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Sat, 17 Dec 2022 10:03:41 -0800 Subject: [PATCH 2/4] Refactor Search#search_descriptions - Move cask logic back into method from extend/os and check whether to display it based on args since formula? is passed by default on Linux now - Use #search_descriptions in `brew desc` instead of duplicating logic - Remove need for extend/os/search --- Library/Homebrew/cmd/desc.rb | 17 +------ Library/Homebrew/extend/os/mac/search.rb | 56 ------------------------ Library/Homebrew/extend/os/search.rb | 4 -- Library/Homebrew/search.rb | 27 ++++++++---- 4 files changed, 19 insertions(+), 85 deletions(-) delete mode 100644 Library/Homebrew/extend/os/mac/search.rb delete mode 100644 Library/Homebrew/extend/os/search.rb diff --git a/Library/Homebrew/cmd/desc.rb b/Library/Homebrew/cmd/desc.rb index 46fff56915..a303a8d09b 100644 --- a/Library/Homebrew/cmd/desc.rb +++ b/Library/Homebrew/cmd/desc.rb @@ -72,22 +72,7 @@ module Homebrew else query = args.named.join(" ") string_or_regex = query_regexp(query) - eval_all = args.eval_all? || Homebrew::EnvConfig.eval_all? - unless args.cask? - ohai "Formulae" - CacheStoreDatabase.use(:descriptions) do |db| - cache_store = DescriptionCacheStore.new(db) - Descriptions.search(string_or_regex, search_type, cache_store, eval_all).print - end - end - unless args.formula? - puts unless args.cask? - 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 - end - end + search_descriptions(string_or_regex, args, search_type: search_type) end end end diff --git a/Library/Homebrew/extend/os/mac/search.rb b/Library/Homebrew/extend/os/mac/search.rb deleted file mode 100644 index 5901ac74ba..0000000000 --- a/Library/Homebrew/extend/os/mac/search.rb +++ /dev/null @@ -1,56 +0,0 @@ -# typed: false -# frozen_string_literal: true - -require "cask/cask" -require "cask/cask_loader" - -module Homebrew - module Search - module Extension - def search_descriptions(string_or_regex, args) - super - - return if args.formula? - - puts unless args.cask? - ohai "Casks" - CacheStoreDatabase.use(:cask_descriptions) do |db| - cache_store = CaskDescriptionCacheStore.new(db) - eval_all = args.eval_all? || Homebrew::EnvConfig.eval_all? - Descriptions.search(string_or_regex, :desc, cache_store, eval_all).print - end - end - - def search_casks(string_or_regex) - if string_or_regex.is_a?(String) && string_or_regex.match?(HOMEBREW_TAP_CASK_REGEX) - return begin - [Cask::CaskLoader.load(string_or_regex).token] - rescue Cask::CaskUnavailableError - [] - end - end - - cask_tokens = Tap.flat_map(&:cask_tokens).map do |c| - c.sub(%r{^homebrew/cask.*/}, "") - end - - results = cask_tokens.extend(Searchable) - .search(string_or_regex) - - results += DidYouMean::SpellChecker.new(dictionary: cask_tokens) - .correct(string_or_regex) - - results.sort.map do |name| - cask = Cask::CaskLoader.load(name) - if cask.installed? - pretty_installed(cask.full_name) - else - cask.full_name - end - end.uniq - end - end - - prepend Extension - end -end diff --git a/Library/Homebrew/extend/os/search.rb b/Library/Homebrew/extend/os/search.rb deleted file mode 100644 index 96e7ff28ec..0000000000 --- a/Library/Homebrew/extend/os/search.rb +++ /dev/null @@ -1,4 +0,0 @@ -# typed: strict -# frozen_string_literal: true - -require "extend/os/mac/search" if OS.mac? diff --git a/Library/Homebrew/search.rb b/Library/Homebrew/search.rb index fb0bd0b2eb..c2ec5419f5 100644 --- a/Library/Homebrew/search.rb +++ b/Library/Homebrew/search.rb @@ -19,14 +19,25 @@ module Homebrew raise "#{query} is not a valid regex." end - def search_descriptions(string_or_regex, args) - return if args.cask? + def search_descriptions(string_or_regex, args, search_type: :desc) + both = !args.formula? && !args.cask? + eval_all = args.eval_all? || Homebrew::EnvConfig.eval_all? - ohai "Formulae" - CacheStoreDatabase.use(:descriptions) do |db| - cache_store = DescriptionCacheStore.new(db) - eval_all = args.eval_all? || Homebrew::EnvConfig.eval_all? - Descriptions.search(string_or_regex, :desc, cache_store, eval_all).print + 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 + end + end + return if !args.cask? && !both + + 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 end end @@ -161,5 +172,3 @@ module Homebrew end end end - -require "extend/os/search" From 47b3f6fe6e93904bb81f7ab66f3759bc7eabd696 Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Sat, 17 Dec 2022 11:03:18 -0800 Subject: [PATCH 3/4] Stop including/extending search.rb - Instead use class methods. - This is better than use it as a mixin when only a small number of methods are used in each class or module. - It also allows us to conditionally require it in `brew install`. - Removed unused search require in descriptions.rb. --- Library/Homebrew/cask/cmd/abstract_command.rb | 4 +--- Library/Homebrew/cmd/desc.rb | 6 ++---- Library/Homebrew/cmd/install.rb | 6 ++---- Library/Homebrew/cmd/search.rb | 8 +++----- Library/Homebrew/descriptions.rb | 3 --- Library/Homebrew/search.rb | 12 ++++++------ Library/Homebrew/test/search_spec.rb | 18 ++++++------------ 7 files changed, 20 insertions(+), 37 deletions(-) diff --git a/Library/Homebrew/cask/cmd/abstract_command.rb b/Library/Homebrew/cask/cmd/abstract_command.rb index 6690ae55a3..23e972087c 100644 --- a/Library/Homebrew/cask/cmd/abstract_command.rb +++ b/Library/Homebrew/cask/cmd/abstract_command.rb @@ -12,8 +12,6 @@ module Cask extend T::Sig extend T::Helpers - include Homebrew::Search - OPTIONS = [ [:switch, "--[no-]binaries", { description: "Disable/enable linking of helper executables (default: enabled).", @@ -87,7 +85,7 @@ module Cask end def suggestion_message(cask_token) - matches = search_casks(cask_token) + matches = Homebrew::Search.search_casks(cask_token) if matches.one? "Did you mean '#{matches.first}'?" diff --git a/Library/Homebrew/cmd/desc.rb b/Library/Homebrew/cmd/desc.rb index a303a8d09b..b38a8ae11f 100644 --- a/Library/Homebrew/cmd/desc.rb +++ b/Library/Homebrew/cmd/desc.rb @@ -11,8 +11,6 @@ module Homebrew module_function - extend Search - sig { returns(CLI::Parser) } def desc_args Homebrew::CLI::Parser.new do @@ -71,8 +69,8 @@ module Homebrew Descriptions.new(desc).print else query = args.named.join(" ") - string_or_regex = query_regexp(query) - search_descriptions(string_or_regex, args, search_type: search_type) + string_or_regex = Search.query_regexp(query) + Search.search_descriptions(string_or_regex, args, search_type: search_type) end end end diff --git a/Library/Homebrew/cmd/install.rb b/Library/Homebrew/cmd/install.rb index 8dc6251c46..8a67db1249 100644 --- a/Library/Homebrew/cmd/install.rb +++ b/Library/Homebrew/cmd/install.rb @@ -8,7 +8,6 @@ require "missing_formula" require "formula_installer" require "development_tools" require "install" -require "search" require "cleanup" require "cli/parser" require "upgrade" @@ -16,8 +15,6 @@ require "upgrade" module Homebrew extend T::Sig - extend Search - module_function sig { returns(CLI::Parser) } @@ -299,11 +296,12 @@ module Homebrew # so we might as well return early. return if name.include?("/") + require "search" ohai "Searching for similarly named formulae and casks..." # Don't treat formula/cask name as a regex query = string_or_regex = name - all_formulae, all_casks = search_names(query, string_or_regex, args) + all_formulae, all_casks = Search.search_names(query, string_or_regex, args) if all_formulae.any? ohai "Formulae", Formatter.columns(all_formulae) diff --git a/Library/Homebrew/cmd/search.rb b/Library/Homebrew/cmd/search.rb index bc0e6d01b1..ba56e35d74 100644 --- a/Library/Homebrew/cmd/search.rb +++ b/Library/Homebrew/cmd/search.rb @@ -12,8 +12,6 @@ module Homebrew module_function - extend Search - PACKAGE_MANAGERS = { repology: ->(query) { "https://repology.org/projects/?search=#{query}" }, macports: ->(query) { "https://ports.macports.org/search/?q=#{query}" }, @@ -76,17 +74,17 @@ module Homebrew return if search_package_manager(args) query = args.named.join(" ") - string_or_regex = query_regexp(query) + string_or_regex = Search.query_regexp(query) if args.desc? if !args.eval_all? && !Homebrew::EnvConfig.eval_all? odeprecated "brew search --desc", "brew search --desc --eval-all or HOMEBREW_EVAL_ALL" end - search_descriptions(string_or_regex, args) + Search.search_descriptions(string_or_regex, args) elsif args.pull_request? search_pull_requests(query, args) else - formulae, casks = search_names(query, string_or_regex, args) + formulae, casks = Search.search_names(query, string_or_regex, args) print_results(formulae, casks, query) end diff --git a/Library/Homebrew/descriptions.rb b/Library/Homebrew/descriptions.rb index 9382bc2107..ff252b5798 100644 --- a/Library/Homebrew/descriptions.rb +++ b/Library/Homebrew/descriptions.rb @@ -3,15 +3,12 @@ require "formula" require "formula_versions" -require "search" require "searchable" # Helper class for printing and searching descriptions. # # @api private class Descriptions - extend Homebrew::Search - # 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: eval_all) diff --git a/Library/Homebrew/search.rb b/Library/Homebrew/search.rb index c2ec5419f5..4b265f88d7 100644 --- a/Library/Homebrew/search.rb +++ b/Library/Homebrew/search.rb @@ -9,7 +9,7 @@ module Homebrew # # @api private module Search - def query_regexp(query) + def self.query_regexp(query) if (m = query.match(%r{^/(.*)/$})) Regexp.new(m[1]) else @@ -19,7 +19,7 @@ module Homebrew raise "#{query} is not a valid regex." end - def search_descriptions(string_or_regex, args, search_type: :desc) + def self.search_descriptions(string_or_regex, args, search_type: :desc) both = !args.formula? && !args.cask? eval_all = args.eval_all? || Homebrew::EnvConfig.eval_all? @@ -41,7 +41,7 @@ module Homebrew end end - def search_taps(query, silent: false) + def self.search_taps(query, silent: false) if query.match?(Regexp.union(HOMEBREW_TAP_FORMULA_REGEX, HOMEBREW_TAP_CASK_REGEX)) _, _, query = query.split("/", 3) end @@ -86,7 +86,7 @@ module Homebrew results end - def search_formulae(string_or_regex) + def self.search_formulae(string_or_regex) if string_or_regex.is_a?(String) && string_or_regex.match?(HOMEBREW_TAP_FORMULA_REGEX) return begin [Formulary.factory(string_or_regex).name] @@ -122,7 +122,7 @@ module Homebrew end.compact end - def search_casks(string_or_regex) + def self.search_casks(string_or_regex) if string_or_regex.is_a?(String) && string_or_regex.match?(HOMEBREW_TAP_CASK_REGEX) return begin [Cask::CaskLoader.load(string_or_regex).token] @@ -151,7 +151,7 @@ module Homebrew end.uniq end - def search_names(query, string_or_regex, args) + def self.search_names(query, string_or_regex, args) both = !args.formula? && !args.cask? remote_results = search_taps(query, silent: true) diff --git a/Library/Homebrew/test/search_spec.rb b/Library/Homebrew/test/search_spec.rb index 56949f2340..ef3f383919 100644 --- a/Library/Homebrew/test/search_spec.rb +++ b/Library/Homebrew/test/search_spec.rb @@ -4,12 +4,6 @@ require "search" describe Homebrew::Search do - subject(:mod) { Object.new } - - before do - mod.extend(described_class) - end - describe "#search_taps" do before do ENV.delete("HOMEBREW_NO_GITHUB_API") @@ -17,13 +11,13 @@ describe Homebrew::Search do it "does not raise if `HOMEBREW_NO_GITHUB_API` is set" do ENV["HOMEBREW_NO_GITHUB_API"] = "1" - expect(mod.search_taps("some-formula")).to match(formulae: [], casks: []) + expect(described_class.search_taps("some-formula")).to match(formulae: [], casks: []) end it "does not raise if the network fails" do allow(GitHub::API).to receive(:open_rest).and_raise(GitHub::API::Error) - expect(mod.search_taps("some-formula")) + expect(described_class.search_taps("some-formula")) .to match(formulae: [], casks: []) end @@ -47,22 +41,22 @@ describe Homebrew::Search do allow(GitHub::API).to receive(:open_rest).and_yield(json_response) - expect(mod.search_taps("some-formula")) + expect(described_class.search_taps("some-formula")) .to match(formulae: ["homebrew/foo/some-formula"], casks: ["homebrew/bar/some-cask"]) end end describe "#query_regexp" do it "correctly parses a regex query" do - expect(mod.query_regexp("/^query$/")).to eq(/^query$/) + expect(described_class.query_regexp("/^query$/")).to eq(/^query$/) end it "returns the original string if it is not a regex query" do - expect(mod.query_regexp("query")).to eq("query") + expect(described_class.query_regexp("query")).to eq("query") end it "raises an error if the query is an invalid regex" do - expect { mod.query_regexp("/+/") }.to raise_error(/not a valid regex/) + expect { described_class.query_regexp("/+/") }.to raise_error(/not a valid regex/) end end end From f41089fff497a30e15998e8a3e0269511441f763 Mon Sep 17 00:00:00 2001 From: apainintheneck Date: Mon, 19 Dec 2022 19:27:48 -0800 Subject: [PATCH 4/4] Use module_function in search.rb --- Library/Homebrew/search.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Library/Homebrew/search.rb b/Library/Homebrew/search.rb index 4b265f88d7..632ab6e3c2 100644 --- a/Library/Homebrew/search.rb +++ b/Library/Homebrew/search.rb @@ -9,7 +9,9 @@ module Homebrew # # @api private module Search - def self.query_regexp(query) + module_function + + def query_regexp(query) if (m = query.match(%r{^/(.*)/$})) Regexp.new(m[1]) else @@ -19,7 +21,7 @@ module Homebrew raise "#{query} is not a valid regex." end - def self.search_descriptions(string_or_regex, args, search_type: :desc) + def search_descriptions(string_or_regex, args, search_type: :desc) both = !args.formula? && !args.cask? eval_all = args.eval_all? || Homebrew::EnvConfig.eval_all? @@ -41,7 +43,7 @@ module Homebrew end end - def self.search_taps(query, silent: false) + def search_taps(query, silent: false) if query.match?(Regexp.union(HOMEBREW_TAP_FORMULA_REGEX, HOMEBREW_TAP_CASK_REGEX)) _, _, query = query.split("/", 3) end @@ -86,7 +88,7 @@ module Homebrew results end - def self.search_formulae(string_or_regex) + def search_formulae(string_or_regex) if string_or_regex.is_a?(String) && string_or_regex.match?(HOMEBREW_TAP_FORMULA_REGEX) return begin [Formulary.factory(string_or_regex).name] @@ -122,7 +124,7 @@ module Homebrew end.compact end - def self.search_casks(string_or_regex) + def search_casks(string_or_regex) if string_or_regex.is_a?(String) && string_or_regex.match?(HOMEBREW_TAP_CASK_REGEX) return begin [Cask::CaskLoader.load(string_or_regex).token] @@ -151,7 +153,7 @@ module Homebrew end.uniq end - def self.search_names(query, string_or_regex, args) + def search_names(query, string_or_regex, args) both = !args.formula? && !args.cask? remote_results = search_taps(query, silent: true)