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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
|
require "rubygems/remote_fetcher"
require "uri"
##
# Deps plugin for hoe.
#
# === Tasks Provided:
#
# check_extra_deps:: Install missing dependencies.
# deps:email:: Print a contact list for gems dependent on this gem
# deps:fetch:: Fetch all the dependent gems of this gem into tarballs
# deps:list:: List all the dependent gems of this gem
module Hoe::Deps
##
# The main rubygems repository.
GEMURL = URI.parse "http://rubygems.org"
##
# Define tasks for plugin.
def define_deps_tasks
namespace :deps do
desc "List all the dependent gems of this gem"
task :list do
deps_list_task
end
desc "Print a contact list for gems dependent on this gem"
task :email do
deps_email_task
end
desc "Fetch all the dependent gems of this gem into tarballs"
task :fetch do
deps_fetch_task
end
end
desc "Install missing dependencies."
task :check_extra_deps do
check_extra_deps_task
end
desc "Install missing plugins."
task :install_plugins do
install_missing_plugins
end
end
def check_extra_deps_task # :nodoc:
(extra_deps + extra_dev_deps).each do |dep|
begin
gem(*dep)
rescue Gem::LoadError
name, req, = dep
install_gem name, req, false
gem(*dep)
end
end
end
def deps_list_task # :nodoc:
gems = self.get_gems_by_name
gem = gems[self.name]
abort "Couldn't find gem: #{self.name}" unless gem
deps = self.dependent_upon self.name
max = deps.map { |s| s.full_name.size }.max
puts " dependents:"
unless deps.empty? then
deps.sort_by(&:full_name).each do |spec|
vers = spec.dependencies.find { |s| s.name == name }.requirements_list
puts " %-*s - %s" % [max, spec.full_name, vers.join(", ")]
end
else
puts " none"
end
end
def deps_email_task # :nodoc:
gems = self.get_gems_by_name
gem = gems[self.name]
abort "Couldn't find gem: #{self.name}" unless gem
deps = self.dependent_upon self.name
email = deps.map(&:email).compact.flatten.sort.uniq
email = email.map { |s| s.split(/,\s*/) }.flatten.sort.uniq
email.map! { |s| # don't you people realize how easy this is?
s.gsub(/ at | _at_ |\s*(atmark|@nospam@|-at?-|@at?@|<at?>|\[at?\]|\(at?\))\s*/i, "@").gsub(/\s*(dot|\[d(ot)?\]|\.dot\.)\s*/i, ".").gsub(/\s+com$/, ".com")
}
bad, good = email.partition { |e| e !~ /^[\w.+-]+\@[\w.+-]+$/ }
warn "Rejecting #{bad.size} email. I couldn't unmunge them." unless
bad.empty?
puts good.join(", ")
warn "Warning: couldn't extract any email addresses" if good.empty?
end
def deps_fetch_task # :nodoc:
deps = self.dependent_upon self.name
mkdir "deps" unless File.directory? "deps"
Dir.chdir "deps" do
begin
deps.sort_by(&:full_name).each do |spec|
full_name = spec.full_name
tgz_name = "#{full_name}.tgz"
gem_name = "#{full_name}.gem"
next if File.exist? tgz_name
FileUtils.rm_rf [full_name, gem_name]
begin
warn "downloading #{full_name}"
Gem::RemoteFetcher.fetcher.download(spec, GEMURL, Dir.pwd)
FileUtils.mv "cache/#{gem_name}", "."
rescue Gem::RemoteFetcher::FetchError
warn " failed"
next
end
warn "converting #{gem_name} to tarball"
system "gem unpack #{gem_name} 2> /dev/null"
system "gem spec -l #{gem_name} > #{full_name}/gemspec.rb"
system "tar zmcf #{tgz_name} #{full_name}"
FileUtils.rm_rf [full_name, gem_name, "cache"]
end
ensure
FileUtils.rm_rf "cache"
end
end
end
##
# Return the rubygems source index.
def get_source_index
@@index ||= nil
return @@index if @@index
dump = unless File.exist? ".source_index" then
warn "Fetching full index and caching. This can take a while."
url = GEMURL + "Marshal.#{Gem.marshal_version}.Z"
dump = Gem::RemoteFetcher.fetcher.fetch_path url
dump = Gem.inflate dump
warn "stripping index to latest gems"
ary = Marshal.load dump
h = {}
Hash[ary].values.sort.each { |spec| h[spec.name] = spec }
ary = h.map { |_, v| [v.full_name, v] }
dump = Marshal.dump ary
open ".source_index", "wb" do |io| io.write dump end
dump
else
open ".source_index", "rb" do |io| io.read end
end
@@index = Marshal.load dump
end
##
# Return the latest rubygems.
def get_latest_gems
@@cache ||= Hash[*get_source_index.flatten].values
end
##
# Return a hash of the latest rubygems keyed by name.
def get_gems_by_name
@@by_name ||= Hash[*get_latest_gems.map { |gem|
[gem.name, gem, gem.full_name, gem]
}.flatten]
end
##
# Installs plugins that aren't currently installed
def install_missing_plugins plugins = Hoe.bad_plugins
version = ">= 0"
plugins.each do |name|
dash_name = name.to_s.gsub "_", "-"
next if have_gem?("hoe-#{name}") or
have_gem?(name) or
have_gem?(dash_name)
install_gem("hoe-#{name}", version, false) or
install_gem(name, version, false) or
install_gem(dash_name, version, false) or
warn "could not install gem for #{name} plugin"
end
end
##
# Return all the dependencies on the named rubygem.
def dependent_upon name
get_latest_gems.find_all { |gem|
gem.dependencies.any? { |dep| dep.name == name }
}
end
end
|