2015-05-05 15:29:01 -07:00
|
|
|
require "formula"
|
2015-09-09 13:55:19 +08:00
|
|
|
require "formula_versions"
|
2018-06-05 10:55:00 +02:00
|
|
|
require "search"
|
2015-05-05 15:29:01 -07:00
|
|
|
|
|
|
|
class Descriptions
|
2018-06-05 10:55:00 +02:00
|
|
|
extend Homebrew::Search
|
|
|
|
|
2015-09-09 14:00:26 +08:00
|
|
|
CACHE_FILE = HOMEBREW_CACHE + "desc_cache.json"
|
2015-05-05 15:29:01 -07:00
|
|
|
|
|
|
|
def self.cache
|
2016-09-17 15:17:27 +01:00
|
|
|
@cache || load_cache
|
2015-05-05 15:29:01 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
# If the cache file exists, load it into, and return, a hash; otherwise,
|
|
|
|
# return nil.
|
|
|
|
def self.load_cache
|
2016-11-20 13:00:01 -05:00
|
|
|
@cache = JSON.parse(CACHE_FILE.read) if CACHE_FILE.exist?
|
2015-05-05 15:29:01 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
# Write the cache to disk after ensuring the existence of the containing
|
|
|
|
# directory.
|
|
|
|
def self.save_cache
|
|
|
|
HOMEBREW_CACHE.mkpath
|
2016-11-20 13:00:01 -05:00
|
|
|
CACHE_FILE.atomic_write JSON.dump(@cache)
|
2015-05-05 15:29:01 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
# Create a hash mapping all formulae to their descriptions;
|
|
|
|
# save it for future use.
|
|
|
|
def self.generate_cache
|
|
|
|
@cache = {}
|
2015-09-10 13:38:51 +08:00
|
|
|
Formula.each do |f|
|
2015-05-05 15:29:01 -07:00
|
|
|
@cache[f.full_name] = f.desc
|
|
|
|
end
|
2016-09-17 15:17:27 +01:00
|
|
|
save_cache
|
2015-05-05 15:29:01 -07:00
|
|
|
end
|
|
|
|
|
2016-02-26 19:20:18 +08:00
|
|
|
# Return true if the cache exists, and none of the Taps
|
2015-05-05 15:29:01 -07:00
|
|
|
# repos were updated more recently than it was.
|
|
|
|
def self.cache_fresh?
|
2015-09-09 13:46:08 +08:00
|
|
|
return false unless CACHE_FILE.exist?
|
2016-04-03 16:28:38 -04:00
|
|
|
cache_mtime = File.mtime(CACHE_FILE)
|
2015-05-05 15:29:01 -07:00
|
|
|
|
2015-09-09 13:46:08 +08:00
|
|
|
Tap.each do |tap|
|
|
|
|
next unless tap.git?
|
2016-02-26 19:20:18 +08:00
|
|
|
repo_mtime = File.mtime(tap.path/".git/refs/heads/master")
|
2015-09-09 13:46:08 +08:00
|
|
|
return false if repo_mtime > cache_mtime
|
2015-05-05 15:29:01 -07:00
|
|
|
end
|
2015-09-09 13:46:08 +08:00
|
|
|
|
|
|
|
true
|
2015-05-05 15:29:01 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
# Create the cache if it doesn't already exist.
|
|
|
|
def self.ensure_cache
|
2016-09-17 15:17:27 +01:00
|
|
|
generate_cache unless cache_fresh? && cache
|
2015-05-05 15:29:01 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
# Take a {Report}, as generated by cmd/update.rb.
|
|
|
|
# Unless the cache file exists, do nothing.
|
|
|
|
# If it does exist, but the Report is empty, just touch the cache file.
|
|
|
|
# Otherwise, use the report to update the cache.
|
|
|
|
def self.update_cache(report)
|
2016-10-24 17:07:57 +02:00
|
|
|
return unless CACHE_FILE.exist?
|
|
|
|
|
|
|
|
if report.empty?
|
|
|
|
FileUtils.touch CACHE_FILE
|
|
|
|
else
|
|
|
|
renamings = report.select_formula(:R)
|
|
|
|
alterations = report.select_formula(:A) + report.select_formula(:M) +
|
|
|
|
renamings.map(&:last)
|
|
|
|
cache_formulae(alterations, save: false)
|
|
|
|
uncache_formulae(report.select_formula(:D) +
|
|
|
|
renamings.map(&:first))
|
2015-05-05 15:29:01 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Given an array of formula names, add them and their descriptions to the
|
|
|
|
# cache. Save the updated cache to disk, unless explicitly told not to.
|
2016-09-17 15:32:44 +01:00
|
|
|
def self.cache_formulae(formula_names, options = { save: true })
|
2016-10-24 17:07:57 +02:00
|
|
|
return unless cache
|
|
|
|
|
|
|
|
formula_names.each do |name|
|
|
|
|
begin
|
2017-10-07 00:31:28 +02:00
|
|
|
@cache[name] = Formulary.factory(name).desc
|
2016-10-24 17:07:57 +02:00
|
|
|
rescue FormulaUnavailableError, *FormulaVersions::IGNORED_EXCEPTIONS
|
2017-10-07 00:31:28 +02:00
|
|
|
@cache.delete(name)
|
2015-09-09 13:55:19 +08:00
|
|
|
end
|
2015-05-05 15:29:01 -07:00
|
|
|
end
|
2016-10-24 17:07:57 +02:00
|
|
|
save_cache if options[:save]
|
2015-05-05 15:29:01 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
# Given an array of formula names, remove them and their descriptions from
|
|
|
|
# the cache. Save the updated cache to disk, unless explicitly told not to.
|
2016-09-17 15:32:44 +01:00
|
|
|
def self.uncache_formulae(formula_names, options = { save: true })
|
2016-10-24 17:07:57 +02:00
|
|
|
return unless cache
|
|
|
|
formula_names.each { |name| @cache.delete(name) }
|
|
|
|
save_cache if options[:save]
|
2015-05-05 15:29:01 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
# Given a regex, find all formulae whose specified fields contain a match.
|
|
|
|
def self.search(regex, field = :either)
|
2016-09-17 15:17:27 +01:00
|
|
|
ensure_cache
|
2015-05-05 15:29:01 -07:00
|
|
|
|
|
|
|
results = case field
|
|
|
|
when :name
|
2018-06-05 10:55:00 +02:00
|
|
|
@cache.select { |name, _| simplify_string(name).match?(regex) }
|
2015-05-05 15:29:01 -07:00
|
|
|
when :desc
|
2018-06-05 10:55:00 +02:00
|
|
|
@cache.select { |_, desc| simplify_string(desc).match?(regex) }
|
2015-05-05 15:29:01 -07:00
|
|
|
when :either
|
2018-06-05 10:55:00 +02:00
|
|
|
@cache.select { |name, desc| simplify_string(name).match?(regex) || simplify_string(desc).match?(regex) }
|
2015-05-05 15:29:01 -07:00
|
|
|
end
|
|
|
|
|
|
|
|
new(results)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Create an actual instance.
|
|
|
|
def initialize(descriptions)
|
|
|
|
@descriptions = descriptions
|
|
|
|
end
|
|
|
|
|
|
|
|
# Take search results -- a hash mapping formula names to descriptions -- and
|
|
|
|
# print them.
|
|
|
|
def print
|
2016-08-30 21:38:13 +02:00
|
|
|
blank = Formatter.warning("[no description]")
|
2016-04-11 17:09:40 -04:00
|
|
|
@descriptions.keys.sort.each do |full_name|
|
|
|
|
short_name = short_names[full_name]
|
2017-05-29 18:24:52 +01:00
|
|
|
printed_name = (short_name_counts[short_name] == 1) ? short_name : full_name
|
2016-04-11 17:09:40 -04:00
|
|
|
description = @descriptions[full_name] || blank
|
2016-08-26 16:04:47 +02:00
|
|
|
puts "#{Tty.bold}#{printed_name}:#{Tty.reset} #{description}"
|
2015-05-05 15:29:01 -07:00
|
|
|
end
|
|
|
|
end
|
2016-04-11 17:09:40 -04:00
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def short_names
|
|
|
|
@short_names ||= Hash[@descriptions.keys.map { |k| [k, k.split("/").last] }]
|
|
|
|
end
|
|
|
|
|
|
|
|
def short_name_counts
|
|
|
|
@short_name_counts ||=
|
2016-09-21 14:36:20 +02:00
|
|
|
short_names.values.each_with_object(Hash.new(0)) { |name, counts| counts[name] += 1 }
|
2016-04-11 17:09:40 -04:00
|
|
|
end
|
2015-05-05 15:29:01 -07:00
|
|
|
end
|