1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
require "formula"
require "formula_versions"
class Descriptions
CACHE_FILE = HOMEBREW_CACHE + "desc_cache.json"
def self.cache
@cache || self.load_cache
end
# If the cache file exists, load it into, and return, a hash; otherwise,
# return nil.
def self.load_cache
if CACHE_FILE.exist?
@cache = Utils::JSON.load(CACHE_FILE.read)
end
end
# Write the cache to disk after ensuring the existence of the containing
# directory.
def self.save_cache
HOMEBREW_CACHE.mkpath
CACHE_FILE.atomic_write Utils::JSON.dump(@cache)
end
# Create a hash mapping all formulae to their descriptions;
# save it for future use.
def self.generate_cache
@cache = {}
Formula.each do |f|
@cache[f.full_name] = f.desc
end
self.save_cache
end
# Return true if the cache exists, and none of the Taps
# repos were updated more recently than it was.
def self.cache_fresh?
return false unless CACHE_FILE.exist?
Tap.each do |tap|
next unless tap.git?
repo_mtime = File.mtime(tap.path/".git/refs/heads/master")
return false if repo_mtime > cache_mtime
end
true
end
# Create the cache if it doesn't already exist.
def self.ensure_cache
self.generate_cache unless self.cache_fresh? && self.cache
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)
if 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)
self.cache_formulae(alterations, :save => false)
self.uncache_formulae(report.select_formula(:D) +
renamings.map(&:first))
end
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.
def self.cache_formulae(formula_names, options = { :save => true })
if self.cache
formula_names.each do |name|
begin
desc = Formulary.factory(name).desc
rescue FormulaUnavailableError, *FormulaVersions::IGNORED_EXCEPTIONS
end
@cache[name] = desc
end
self.save_cache if options[:save]
end
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.
def self.uncache_formulae(formula_names, options = { :save => true })
if self.cache
formula_names.each { |name| @cache.delete(name) }
self.save_cache if options[:save]
end
end
# Given a regex, find all formulae whose specified fields contain a match.
def self.search(regex, field = :either)
self.ensure_cache
results = case field
when :name
@cache.select { |name, _| name =~ regex }
when :desc
@cache.select { |_, desc| desc =~ regex }
when :either
@cache.select { |name, desc| (name =~ regex) || (desc =~ regex) }
end
results = Hash[results] if RUBY_VERSION <= "1.8.7"
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
blank = "#{Tty.yellow}[no description]#{Tty.reset}"
@descriptions.keys.sort.each do |name|
description = @descriptions[name] || blank
puts "#{Tty.white}#{name}:#{Tty.reset} #{description}"
end
end
end
|