Move shared search logic into Homebrew::Search module.

This commit is contained in:
Markus Reiter 2018-06-02 20:49:14 +02:00
parent 49619b09ea
commit dd8370a9fa
5 changed files with 105 additions and 91 deletions

View File

@ -1,8 +1,10 @@
require "cmd/search"
require "search"
module Hbc
class CLI
class Search < AbstractCommand
extend Homebrew::Search
def run
if args.empty?
puts Formatter.columns(CLI.nice_listing(Cask.map(&:qualified_token)))
@ -34,7 +36,7 @@ module Hbc
partial_matches = simplified_tokens.grep(/#{simplified_search_term}/i) { |t| all_tokens[simplified_tokens.index(t)] }
end
_, remote_matches = Homebrew.search_taps(search_term, silent: true)
_, remote_matches = search_taps(search_term, silent: true)
[partial_matches, remote_matches, search_term]
end

View File

@ -17,10 +17,13 @@ require "formula"
require "missing_formula"
require "descriptions"
require "cli_parser"
require "search"
module Homebrew
module_function
extend Search
PACKAGE_MANAGERS = {
macports: ->(query) { "https://www.macports.org/ports.php?by=name&substr=#{query}" },
fink: ->(query) { "http://pdb.finkproject.org/pdb/browse.php?summary=#{query}" },
@ -106,74 +109,4 @@ module Homebrew
Surround your query with /slashes/ to search locally by regex.
EOS
end
def query_regexp(query)
if m = query.match(%r{^/(.*)/$})
Regexp.new(m[1])
else
/.*#{Regexp.escape(query)}.*/i
end
rescue RegexpError
raise "#{query} is not a valid regex."
end
def search_taps(query, silent: false)
return [], [] if ENV["HOMEBREW_NO_GITHUB_API"]
unless silent
# Use stderr to avoid breaking parsed output
$stderr.puts Formatter.headline("Searching taps on GitHub...", color: :blue)
end
matches = GitHub.search_code(
user: "Homebrew",
path: ["Formula", "Casks", "."],
filename: query,
extension: "rb",
)
matches.inject([[], []]) do |(formulae, casks), match|
name = File.basename(match["path"], ".rb")
tap = Tap.fetch(match["repository"]["full_name"])
full_name = "#{tap.name}/#{name}"
if tap.installed?
[formulae, casks]
elsif match["path"].start_with?("Casks/")
[formulae, [*casks, full_name].sort]
else
[[*formulae, full_name].sort, casks]
end
end
rescue GitHub::Error => error
opoo "Error searching on GitHub: #{error}\n"
[[], []]
end
def search_formulae(regex)
# Use stderr to avoid breaking parsed output
$stderr.puts Formatter.headline("Searching local taps...", color: :blue)
aliases = Formula.alias_full_names
results = (Formula.full_names + aliases).grep(regex).sort
results.map do |name|
begin
formula = Formulary.factory(name)
canonical_name = formula.name
canonical_full_name = formula.full_name
rescue
canonical_name = canonical_full_name = name
end
# Ignore aliases from results when the full name was also found
next if aliases.include?(name) && results.include?(canonical_full_name)
if (HOMEBREW_CELLAR/canonical_name).directory?
pretty_installed(name)
else
name
end
end.compact
end
end

View File

@ -0,0 +1,73 @@
module Homebrew
module Search
def query_regexp(query)
if m = query.match(%r{^/(.*)/$})
Regexp.new(m[1])
else
/.*#{Regexp.escape(query)}.*/i
end
rescue RegexpError
raise "#{query} is not a valid regex."
end
def search_taps(query, silent: false)
return [], [] if ENV["HOMEBREW_NO_GITHUB_API"]
unless silent
# Use stderr to avoid breaking parsed output
$stderr.puts Formatter.headline("Searching taps on GitHub...", color: :blue)
end
matches = GitHub.search_code(
user: "Homebrew",
path: ["Formula", "Casks", "."],
filename: query,
extension: "rb",
)
matches.inject([[], []]) do |(formulae, casks), match|
name = File.basename(match["path"], ".rb")
tap = Tap.fetch(match["repository"]["full_name"])
full_name = "#{tap.name}/#{name}"
if tap.installed?
[formulae, casks]
elsif match["path"].start_with?("Casks/")
[formulae, [*casks, full_name].sort]
else
[[*formulae, full_name].sort, casks]
end
end
rescue GitHub::Error => error
opoo "Error searching on GitHub: #{error}\n"
[[], []]
end
def search_formulae(regex)
# Use stderr to avoid breaking parsed output
$stderr.puts Formatter.headline("Searching local taps...", color: :blue)
aliases = Formula.alias_full_names
results = (Formula.full_names + aliases).grep(regex).sort
results.map do |name|
begin
formula = Formulary.factory(name)
canonical_name = formula.name
canonical_full_name = formula.full_name
rescue
canonical_name = canonical_full_name = name
end
# Ignore aliases from results when the full name was also found
next if aliases.include?(name) && results.include?(canonical_full_name)
if (HOMEBREW_CELLAR/canonical_name).directory?
pretty_installed(name)
else
name
end
end.compact
end
end
end

View File

@ -65,18 +65,4 @@ describe "brew search", :integration_test do
.and be_a_success
end
end
describe "::query_regexp" do
it "correctly parses a regex query" do
expect(Homebrew.query_regexp("/^query$/")).to eq(/^query$/)
end
it "correctly converts a query string to a regex" do
expect(Homebrew.query_regexp("query")).to eq(/.*query.*/i)
end
it "raises an error if the query is an invalid regex" do
expect { Homebrew.query_regexp("/+/") }.to raise_error(/not a valid regex/)
end
end
end

View File

@ -1,6 +1,12 @@
require "cmd/search"
require "search"
describe Homebrew::Search do
subject(:mod) { Object.new }
before do
mod.extend(described_class)
end
describe Homebrew do
describe "#search_taps" do
before do
ENV.delete("HOMEBREW_NO_GITHUB_API")
@ -8,13 +14,13 @@ describe Homebrew do
it "does not raise if `HOMEBREW_NO_GITHUB_API` is set" do
ENV["HOMEBREW_NO_GITHUB_API"] = "1"
expect(described_class.search_taps("some-formula")).to match([[], []])
expect(mod.search_taps("some-formula")).to match([[], []])
end
it "does not raise if the network fails" do
allow(GitHub).to receive(:open_api).and_raise(GitHub::Error)
expect(described_class.search_taps("some-formula"))
expect(mod.search_taps("some-formula"))
.to match([[], []])
end
@ -38,8 +44,22 @@ describe Homebrew do
allow(GitHub).to receive(:open_api).and_yield(json_response)
expect(described_class.search_taps("some-formula"))
expect(mod.search_taps("some-formula"))
.to match([["homebrew/foo/some-formula"], ["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$/)
end
it "correctly converts a query string to a regex" do
expect(mod.query_regexp("query")).to eq(/.*query.*/i)
end
it "raises an error if the query is an invalid regex" do
expect { mod.query_regexp("/+/") }.to raise_error(/not a valid regex/)
end
end
end