gauntlet 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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