gauntlet 1.1.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data.tar.gz.sig CHANGED
Binary file
File without changes
@@ -1,3 +1,24 @@
1
+ === 2.0.0 / 2011-02-18
2
+
3
+ * 1 major enhancement:
4
+
5
+ * Dropped dependencies_of, dependent_upon, gems_by_name, find_stupid_gems.
6
+
7
+ * 4 minor enhancements:
8
+
9
+ * Added support for new rubygem server changes
10
+ * Separate downloads from conversion to .tar.gz
11
+ * Stripped down gauntlet_grep to pass all args through to grep
12
+ * Switched to net-http-persistent to clean up and speed up downloads.
13
+
14
+ * 5 bug fixes:
15
+
16
+ * 1.9 fix for shadowed variables
17
+ * Add TERM and KILL handlers that shutdown nicely
18
+ * Fixes for stupidly named gems (--1)
19
+ * Handle SocketError and 404s more elegantly
20
+ * Switch to SpecFetcher for latest RubyGems
21
+
1
22
  === 1.1.0 / 2009-06-23
2
23
 
3
24
  * 6 minor enhancements:
data/Rakefile CHANGED
@@ -4,11 +4,19 @@ require 'rubygems'
4
4
  require 'hoe'
5
5
 
6
6
  Hoe.plugin :seattlerb
7
+ Hoe.plugin :isolate
7
8
 
8
9
  Hoe.spec 'gauntlet' do
9
10
  developer 'Ryan Davis', 'ryand-ruby@zenspider.com'
10
11
 
11
12
  self.rubyforge_name = 'seattlerb'
13
+
14
+ extra_deps << ["net-http-persistent", "~> 1.4.1"]
15
+ end
16
+
17
+ desc "update your gauntlet gems"
18
+ task :update do
19
+ sh "ruby -I lib ./bin/gauntlet update"
12
20
  end
13
21
 
14
22
  # vim: syntax=ruby
@@ -18,6 +18,7 @@ when "help" then
18
18
  puts " cmds:"
19
19
  puts " help - show help"
20
20
  puts " list - list known gauntlet data for reports"
21
+ puts " update - update the gems, but don't run anything"
21
22
  puts " report <name> - show a report on <name>, requires specific data format"
22
23
  puts " <name> - run the gauntlet for named plugin"
23
24
  Gem.find_files('gauntlet_*.rb').each do |path|
@@ -51,7 +52,7 @@ when "report" then
51
52
  good += 1
52
53
  next
53
54
  end
54
- files.each do |path, result|
55
+ files.each do |dir, result|
55
56
  case result
56
57
  when true then
57
58
  good += 1
@@ -62,12 +63,12 @@ when "report" then
62
63
  when String then
63
64
  bad += 1
64
65
 
65
- names[File.basename(path)] += 1
66
+ names[File.basename(dir)] += 1
66
67
 
67
68
  loop do
68
- path = File.dirname path
69
- break if path.empty? or path == "."
70
- paths[path] += 1
69
+ dir = File.dirname dir
70
+ break if dir.empty? or dir == "."
71
+ dirs[dir] += 1
71
72
  end
72
73
  end
73
74
  end
@@ -1,6 +1,7 @@
1
- require 'rubygems/remote_fetcher'
1
+ require 'rubygems'
2
2
  require 'thread'
3
3
  require 'yaml'
4
+ require 'net/http/persistent'
4
5
 
5
6
  $u ||= false
6
7
  $f ||= false
@@ -9,36 +10,18 @@ $F ||= false
9
10
  Thread.abort_on_exception = true
10
11
 
11
12
  class Gauntlet
12
- VERSION = '1.1.0'
13
-
14
- GEMURL = URI.parse 'http://gems.rubyforge.org'
15
- GEMDIR = File.expand_path "~/.gauntlet"
13
+ VERSION = '2.0.0'
14
+ GEMURL = URI.parse 'http://gems.rubyforge.org'
15
+ GEMDIR = File.expand_path "~/.gauntlet"
16
16
  DATADIR = File.expand_path "~/.gauntlet/data"
17
17
 
18
- # stupid dups usually because of "dash" renames
19
- STUPID_GEMS = %w(ajax-scaffold-generator
20
- extract_curves
21
- flickr-fu
22
- hpricot-scrub
23
- html_me
24
- merb-builder
25
- merb-jquery
26
- merb-parts
27
- merb_exceptions
28
- merb_helpers
29
- merb_param_protection
30
- model_graph
31
- not_naughty
32
- rfeedparser-ictv
33
- spec-converter
34
- spec_unit)
35
-
36
18
  attr_accessor :dirty, :data_file, :data
37
19
 
38
20
  def initialize
39
21
  name = self.class.name.downcase.sub(/gauntlet/, '')
40
22
  self.data_file = "#{DATADIR}/#{name}-data.yml"
41
23
  self.dirty = false
24
+ @cache = nil
42
25
  end
43
26
 
44
27
  def initialize_dir
@@ -69,48 +52,19 @@ class Gauntlet
69
52
  end
70
53
 
71
54
  def latest_gems
72
- @cache ||= source_index.latest_specs
73
- end
74
-
75
- def gems_by_name
76
- @by_name ||= Hash[*latest_gems.map { |gem|
77
- [gem.name, gem, gem.full_name, gem]
78
- }.flatten]
79
- end
80
-
81
- def dependencies_of name
82
- index = source_index
83
- gems_by_name[name].dependencies.map { |dep| index.search(dep).last }
84
- end
85
-
86
- def dependent_upon name
87
- latest_gems.find_all { |gem|
88
- gem.dependencies.any? { |dep| dep.name == name }
89
- }
90
- end
91
-
92
- def find_stupid_gems
93
- gems = Hash.new { |h,k| h[k] = [] }
94
- stupid = []
95
- latest = {}
96
-
97
- latest_gems.each do |spec|
98
- name = spec.name.gsub(/-/, '_')
99
- next unless name =~ /_/
100
- gems[name] << spec
101
- end
102
-
103
- gems.reject! { |k,v| v.size == 1 || v.map { |s| s.name }.uniq.size == 1 }
104
-
105
- gems.each do |k,v|
106
- sorted = v.sort_by { |spec| spec.version }
107
- latest[sorted.last.name] = true
108
- sorted.each do |spec|
109
- stupid << spec.name unless latest[spec.name]
110
- end
111
- end
112
-
113
- stupid.uniq
55
+ Gem::SpecFetcher.new.list.map { |source_uri, gems|
56
+ base_url = source_uri.to_s
57
+ gems.map { |(name, version, platform)|
58
+ gem_name = case platform
59
+ when Gem::Platform::RUBY then
60
+ [name, version].join '-'
61
+ else
62
+ [name, version, platform].join '-'
63
+ end
64
+
65
+ [gem_name, File.join(base_url, "/gems/#{gem_name}.gem")]
66
+ }
67
+ }.flatten(1)
114
68
  end
115
69
 
116
70
  def update_gem_tarballs
@@ -124,7 +78,7 @@ class Gauntlet
124
78
  gems = Dir["*.gem"]
125
79
  tgzs = Dir["*.tgz"]
126
80
 
127
- old = tgzs - latest.map { |spec| "#{spec.full_name}.tgz" }
81
+ old = tgzs - latest.map { |(full_name, url)| "#{full_name}.tgz" }
128
82
  unless old.empty? then
129
83
  warn "deleting #{old.size} tgzs"
130
84
  old.each do |tgz|
@@ -132,54 +86,106 @@ class Gauntlet
132
86
  end
133
87
  end
134
88
 
135
- tasks = Queue.new
136
- latest.sort!
137
- latest.reject! { |spec| tgzs.include? "#{spec.full_name}.tgz" }
138
- tasks.push(latest.shift) until latest.empty? # LAME
139
-
140
- warn "fetching #{tasks.size} gems"
141
-
142
- threads = []
143
- 10.times do
144
- threads << Thread.new do
145
- fetcher = Gem::RemoteFetcher.new nil # fuck proxies
146
- until tasks.empty? do
147
- spec = tasks.shift
148
- full_name = spec.full_name
149
- tgz_name = "#{full_name}.tgz"
150
- gem_name = "#{full_name}.gem"
151
-
152
- unless gems.include? gem_name then
153
- begin
154
- warn "downloading #{full_name}"
155
- fetcher.download(spec, GEMURL, Dir.pwd)
156
- rescue Gem::RemoteFetcher::FetchError => e
157
- warn " failed #{full_name}: #{e.message}"
158
- next
159
- end
160
- end
89
+ conversions = Queue.new
90
+ gem_names = gems.map { |gem| File.basename gem, '.gem' }
91
+ tgz_names = tgzs.map { |tgz| File.basename tgz, '.tgz' }
92
+ to_convert = gem_names - tgz_names
161
93
 
162
- warn " converting #{gem_name} to tarball"
94
+ seen_tgzs = Hash[*tgzs.map { |name| [name, true] }.flatten]
163
95
 
164
- unless File.directory? full_name then
165
- system "gem unpack cache/#{gem_name} &> /dev/null"
166
- system "gem spec -l cache/#{gem_name} > #{full_name}/gemspec"
167
- end
96
+ warn "adding #{to_convert.size} unconverted gems" unless to_convert.empty?
97
+
98
+ conversions.push to_convert.shift until to_convert.empty? # LAME
99
+
100
+ downloads = Queue.new
101
+ latest = latest.sort_by { |(full_name, url)| full_name.downcase }
102
+ latest.reject! { |(full_name, url)| seen_tgzs["#{full_name}.tgz"] }
103
+
104
+ downloads.push(latest.shift) until latest.empty? # LAME
105
+
106
+ converter = Thread.start do
107
+ while payload = conversions.shift do
108
+ full_name, _ = payload
109
+ tgz_name = "#{full_name}.tgz"
110
+ gem_name = "#{full_name}.gem"
111
+
112
+ warn " converting #{gem_name} to tarball"
168
113
 
169
- system "chmod -R u+rwX #{full_name} && tar zmcf #{tgz_name} #{full_name} && rm -rf #{full_name} #{gem_name}"
114
+ unless File.directory? full_name then
115
+ system "gem unpack cache/#{gem_name} &> /dev/null"
116
+ system "gem spec -l cache/#{gem_name} > #{full_name}/gemspec"
170
117
  end
118
+
119
+ system ["chmod -R u+rwX #{full_name}",
120
+ "tar zmcf #{tgz_name} -- #{full_name}",
121
+ "rm -rf -- #{full_name} #{gem_name}"].join(" && ")
171
122
  end
172
123
  end
173
124
 
174
- threads.each do |thread|
175
- thread.join
125
+ warn "fetching #{downloads.size} gems"
126
+
127
+ http = Net::HTTP::Persistent.new
128
+
129
+ workers downloads do |full_name, url|
130
+ gem_name = "#{full_name}.gem"
131
+
132
+ unless gems.include? gem_name then
133
+ limit = 3
134
+ begin
135
+ warn "downloading #{full_name}"
136
+ while limit > 0 do
137
+ http.request URI.parse(url) do |response|
138
+ case response
139
+ when Net::HTTPSuccess
140
+ File.open gem_name, "wb" do |f|
141
+ response.read_body do |chunk|
142
+ f.write chunk
143
+ end
144
+ end
145
+ limit = 0 # kinda lame.
146
+ when Net::HTTPRedirection
147
+ url = response['location']
148
+ limit -= 1
149
+ else
150
+ warn " #{full_name} got #{response.code}. skipping."
151
+ limit = 0
152
+ end
153
+ end
154
+ end
155
+ rescue SocketError, Net::HTTP::Persistent::Error => e
156
+ warn " #{full_name} raised #{e.message}. skipping."
157
+ end
158
+ end
159
+
160
+ conversions.push full_name
176
161
  end
162
+
163
+ conversions.push nil
164
+
165
+ converter.join
177
166
  end
167
+
178
168
  rescue Interrupt
179
169
  warn "user cancelled... quitting"
180
170
  exit 1
181
171
  end
182
172
 
173
+ def workers tasks, count = 10
174
+ threads = []
175
+ count.times do
176
+ threads << Thread.new do
177
+ until tasks.empty? do
178
+ task = tasks.shift
179
+ yield task
180
+ end
181
+ end
182
+ end
183
+
184
+ threads.each do |thread|
185
+ thread.join
186
+ end
187
+ end
188
+
183
189
  def each_gem filter = nil
184
190
  filter ||= /^[\w-]+-\d+(\.\d+)*\.tgz$/
185
191
  in_gem_dir do
@@ -203,7 +209,7 @@ class Gauntlet
203
209
  end
204
210
  end
205
211
  ensure
206
- system "rm -rf #{process_dir}"
212
+ system "rm -rf -- #{process_dir}"
207
213
  end
208
214
  end
209
215
  end
@@ -262,6 +268,13 @@ class Gauntlet
262
268
  self.data.delete outdated
263
269
  end
264
270
 
271
+ %w[TERM KILL].each do |signal|
272
+ trap signal do
273
+ shutdown
274
+ exit
275
+ end
276
+ end
277
+
265
278
  each_gem filter do |name|
266
279
  next if should_skip? name
267
280
  with_gem name do
@@ -275,6 +288,10 @@ class Gauntlet
275
288
  rescue Interrupt
276
289
  warn "user cancelled. quitting"
277
290
  ensure
291
+ shutdown
292
+ end
293
+
294
+ def shutdown
278
295
  save_yaml data_file, data if dirty
279
296
  end
280
297
  end
@@ -282,68 +299,15 @@ end
282
299
  ############################################################
283
300
  # Extensions and Overrides
284
301
 
285
- # bug in RemoteFetcher#download prevents multithreading. Remove after 1.3.2
286
- class Gem::RemoteFetcher
287
- alias :old_download :download
288
- def download(spec, source_uri, install_dir = Gem.dir)
289
- if File.writable?(install_dir)
290
- cache_dir = File.join install_dir, 'cache'
291
- else
292
- cache_dir = File.join(Gem.user_dir, 'cache')
293
- end
294
-
295
- gem_file_name = "#{spec.full_name}.gem"
296
- local_gem_path = File.join cache_dir, gem_file_name
297
-
298
- FileUtils.mkdir_p cache_dir rescue nil unless File.exist? cache_dir
302
+ class Gem::SpecFetcher
303
+ attr_writer :fetcher
299
304
 
300
- source_uri = URI.parse source_uri unless URI::Generic === source_uri
301
- scheme = source_uri.scheme
305
+ alias :old_initialize :initialize
302
306
 
303
- # URI.parse gets confused by MS Windows paths with forward slashes.
304
- scheme = nil if scheme =~ /^[a-z]$/i
307
+ def initialize fetcher = Gem::RemoteFetcher.fetcher
308
+ old_initialize
305
309
 
306
- case scheme
307
- when 'http', 'https' then
308
- unless File.exist? local_gem_path then
309
- begin
310
- say "Downloading gem #{gem_file_name}" if
311
- Gem.configuration.really_verbose
312
-
313
- remote_gem_path = source_uri + "gems/#{gem_file_name}"
314
-
315
- gem = self.fetch_path remote_gem_path
316
- rescue Gem::RemoteFetcher::FetchError
317
- raise if spec.original_platform == spec.platform
318
-
319
- alternate_name = "#{spec.original_name}.gem"
320
-
321
- say "Failed, downloading gem #{alternate_name}" if
322
- Gem.configuration.really_verbose
323
-
324
- remote_gem_path = source_uri + "gems/#{alternate_name}"
325
-
326
- gem = self.fetch_path remote_gem_path
327
- end
328
-
329
- File.open local_gem_path, 'wb' do |fp|
330
- fp.write gem
331
- end
332
- end
333
- when nil, 'file' then # TODO test for local overriding cache
334
- begin
335
- FileUtils.cp source_uri.to_s, local_gem_path
336
- rescue Errno::EACCES
337
- local_gem_path = source_uri.to_s
338
- end
339
-
340
- say "Using local gem #{local_gem_path}" if
341
- Gem.configuration.really_verbose
342
- else
343
- raise Gem::InstallError, "unsupported URI scheme #{source_uri.scheme}"
344
- end
345
-
346
- local_gem_path
310
+ self.fetcher = fetcher
347
311
  end
348
312
  end
349
313
 
@@ -369,3 +333,4 @@ class Array
369
333
  return Math.sqrt(self.sample_variance)
370
334
  end
371
335
  end
336
+
@@ -6,18 +6,17 @@ require 'rubygems'
6
6
  require 'gauntlet'
7
7
 
8
8
  class GrepGauntlet < Gauntlet
9
- attr_accessor :pattern
9
+ attr_accessor :args
10
10
 
11
- def initialize pattern
12
- self.pattern = pattern
11
+ def initialize args
12
+ self.args = args
13
13
  end
14
14
 
15
15
  def run name
16
- system "find . -type f -print0 | xargs -0 grep #{pattern}"
16
+ system "grep", *args
17
17
  end
18
18
  end
19
19
 
20
- pattern = ARGV.shift
21
- flogger = GrepGauntlet.new pattern
20
+ flogger = GrepGauntlet.new ARGV
22
21
  flogger.run_the_gauntlet
23
22
 
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gauntlet
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ hash: 15
5
+ prerelease:
6
+ segments:
7
+ - 2
8
+ - 0
9
+ - 0
10
+ version: 2.0.0
5
11
  platform: ruby
6
12
  authors:
7
13
  - Ryan Davis
@@ -30,19 +36,57 @@ cert_chain:
30
36
  FBHgymkyj/AOSqKRIpXPhjC6
31
37
  -----END CERTIFICATE-----
32
38
 
33
- date: 2009-06-23 00:00:00 -07:00
39
+ date: 2011-02-18 00:00:00 -08:00
34
40
  default_executable:
35
41
  dependencies:
36
42
  - !ruby/object:Gem::Dependency
37
- name: hoe
43
+ name: net-http-persistent
44
+ prerelease: false
45
+ requirement: &id001 !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ~>
49
+ - !ruby/object:Gem::Version
50
+ hash: 5
51
+ segments:
52
+ - 1
53
+ - 4
54
+ - 1
55
+ version: 1.4.1
56
+ type: :runtime
57
+ version_requirements: *id001
58
+ - !ruby/object:Gem::Dependency
59
+ name: minitest
60
+ prerelease: false
61
+ requirement: &id002 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ hash: 11
67
+ segments:
68
+ - 2
69
+ - 0
70
+ - 2
71
+ version: 2.0.2
38
72
  type: :development
39
- version_requirement:
40
- version_requirements: !ruby/object:Gem::Requirement
73
+ version_requirements: *id002
74
+ - !ruby/object:Gem::Dependency
75
+ name: hoe
76
+ prerelease: false
77
+ requirement: &id003 !ruby/object:Gem::Requirement
78
+ none: false
41
79
  requirements:
42
80
  - - ">="
43
81
  - !ruby/object:Gem::Version
44
- version: 2.3.0
45
- version:
82
+ hash: 41
83
+ segments:
84
+ - 2
85
+ - 9
86
+ - 1
87
+ version: 2.9.1
88
+ type: :development
89
+ version_requirements: *id003
46
90
  description: |-
47
91
  Gauntlet is a pluggable means of running code against all the latest
48
92
  gems and storing off the data.
@@ -65,6 +109,7 @@ files:
65
109
  - lib/gauntlet.rb
66
110
  - lib/gauntlet_grep.rb
67
111
  - test/test_gauntlet.rb
112
+ - .gemtest
68
113
  has_rdoc: true
69
114
  homepage: http://rubyforge.org/projects/seattlerb
70
115
  licenses: []
@@ -76,21 +121,27 @@ rdoc_options:
76
121
  require_paths:
77
122
  - lib
78
123
  required_ruby_version: !ruby/object:Gem::Requirement
124
+ none: false
79
125
  requirements:
80
126
  - - ">="
81
127
  - !ruby/object:Gem::Version
128
+ hash: 3
129
+ segments:
130
+ - 0
82
131
  version: "0"
83
- version:
84
132
  required_rubygems_version: !ruby/object:Gem::Requirement
133
+ none: false
85
134
  requirements:
86
135
  - - ">="
87
136
  - !ruby/object:Gem::Version
137
+ hash: 3
138
+ segments:
139
+ - 0
88
140
  version: "0"
89
- version:
90
141
  requirements: []
91
142
 
92
143
  rubyforge_project: seattlerb
93
- rubygems_version: 1.3.4
144
+ rubygems_version: 1.4.2
94
145
  signing_key:
95
146
  specification_version: 3
96
147
  summary: Gauntlet is a pluggable means of running code against all the latest gems and storing off the data.
metadata.gz.sig CHANGED
Binary file