rubygems-update 1.5.3 → 1.6.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.

Potentially problematic release.


This version of rubygems-update might be problematic. Click here for more details.

Files changed (79) hide show
  1. data.tar.gz.sig +2 -1
  2. data/History.txt +60 -9
  3. data/Manifest.txt +1 -1
  4. data/Rakefile +0 -2
  5. data/lib/rubygems.rb +142 -65
  6. data/lib/rubygems/commands/owner_command.rb +3 -2
  7. data/lib/rubygems/commands/pristine_command.rb +5 -3
  8. data/lib/rubygems/commands/push_command.rb +8 -4
  9. data/lib/rubygems/commands/setup_command.rb +1 -2
  10. data/lib/rubygems/commands/uninstall_command.rb +5 -0
  11. data/lib/rubygems/commands/unpack_command.rb +10 -16
  12. data/lib/rubygems/config_file.rb +12 -5
  13. data/lib/rubygems/custom_require.rb +27 -7
  14. data/lib/rubygems/dependency.rb +33 -8
  15. data/lib/rubygems/dependency_installer.rb +21 -6
  16. data/lib/rubygems/dependency_list.rb +35 -3
  17. data/lib/rubygems/doc_manager.rb +6 -4
  18. data/lib/rubygems/gem_path_searcher.rb +45 -1
  19. data/lib/rubygems/gemcutter_utilities.rb +33 -0
  20. data/lib/rubygems/indexer.rb +1 -0
  21. data/lib/rubygems/installer.rb +11 -7
  22. data/lib/rubygems/installer_test_case.rb +23 -15
  23. data/lib/rubygems/mock_gem_ui.rb +1 -1
  24. data/lib/rubygems/remote_fetcher.rb +29 -10
  25. data/lib/rubygems/requirement.rb +1 -1
  26. data/lib/rubygems/security.rb +1 -0
  27. data/lib/rubygems/source_index.rb +3 -2
  28. data/lib/rubygems/spec_fetcher.rb +3 -1
  29. data/lib/rubygems/specification.rb +54 -12
  30. data/lib/rubygems/test_case.rb +99 -28
  31. data/lib/rubygems/test_utilities.rb +11 -1
  32. data/lib/rubygems/uninstaller.rb +22 -11
  33. data/lib/rubygems/user_interaction.rb +50 -29
  34. data/lib/rubygems/validator.rb +1 -1
  35. data/test/rubygems/fix_openssl_warnings.rb +12 -0
  36. data/test/rubygems/plugin/load/rubygems_plugin.rb +3 -1
  37. data/test/rubygems/test_gem.rb +384 -38
  38. data/test/rubygems/test_gem_builder.rb +1 -1
  39. data/test/rubygems/test_gem_command_manager.rb +2 -2
  40. data/test/rubygems/test_gem_commands_build_command.rb +1 -1
  41. data/test/rubygems/test_gem_commands_cert_command.rb +2 -1
  42. data/test/rubygems/test_gem_commands_dependency_command.rb +6 -5
  43. data/test/rubygems/test_gem_commands_fetch_command.rb +4 -4
  44. data/test/rubygems/test_gem_commands_install_command.rb +21 -18
  45. data/test/rubygems/test_gem_commands_lock_command.rb +1 -1
  46. data/test/rubygems/test_gem_commands_outdated_command.rb +2 -5
  47. data/test/rubygems/test_gem_commands_owner_command.rb +42 -0
  48. data/test/rubygems/test_gem_commands_pristine_command.rb +28 -8
  49. data/test/rubygems/test_gem_commands_push_command.rb +31 -5
  50. data/test/rubygems/test_gem_commands_specification_command.rb +8 -8
  51. data/test/rubygems/test_gem_commands_stale_command.rb +4 -2
  52. data/test/rubygems/test_gem_commands_uninstall_command.rb +23 -4
  53. data/test/rubygems/test_gem_commands_unpack_command.rb +10 -8
  54. data/test/rubygems/test_gem_commands_update_command.rb +16 -13
  55. data/test/rubygems/test_gem_commands_which_command.rb +1 -1
  56. data/test/rubygems/test_gem_config_file.rb +14 -0
  57. data/test/rubygems/test_gem_dependency.rb +39 -0
  58. data/test/rubygems/test_gem_dependency_installer.rb +213 -92
  59. data/test/rubygems/test_gem_dependency_list.rb +37 -17
  60. data/test/rubygems/test_gem_doc_manager.rb +5 -4
  61. data/test/rubygems/test_gem_format.rb +2 -2
  62. data/test/rubygems/test_gem_gemcutter_utilities.rb +48 -0
  63. data/test/rubygems/test_gem_indexer.rb +11 -10
  64. data/test/rubygems/test_gem_install_update_options.rb +0 -2
  65. data/test/rubygems/test_gem_installer.rb +151 -78
  66. data/test/rubygems/test_gem_package_tar_output.rb +3 -0
  67. data/test/rubygems/test_gem_remote_fetcher.rb +23 -14
  68. data/test/rubygems/test_gem_requirement.rb +4 -0
  69. data/test/rubygems/test_gem_security.rb +1 -0
  70. data/test/rubygems/test_gem_source_index.rb +17 -16
  71. data/test/rubygems/test_gem_spec_fetcher.rb +6 -1
  72. data/test/rubygems/test_gem_specification.rb +81 -31
  73. data/test/rubygems/test_gem_stream_ui.rb +11 -1
  74. data/test/rubygems/test_gem_uninstaller.rb +70 -10
  75. data/test/rubygems/test_gem_validator.rb +1 -1
  76. data/test/rubygems/test_kernel.rb +1 -1
  77. metadata +7 -7
  78. metadata.gz.sig +0 -0
  79. data/ChangeLog +0 -5811
@@ -162,10 +162,10 @@ class Gem::DocManager
162
162
  def run_rdoc(*args)
163
163
  args << @spec.rdoc_options
164
164
  args << self.class.configured_args
165
- args << '--quiet'
166
165
  args << @spec.require_paths.clone
167
166
  args << @spec.extra_rdoc_files
168
167
  args << '--title' << "#{@spec.full_name} Documentation"
168
+ args << '--quiet'
169
169
  args = args.flatten.map do |arg| arg.to_s end
170
170
 
171
171
  if self.class.rdoc_version >= Gem::Version.new('2.4.0') then
@@ -176,6 +176,8 @@ class Gem::DocManager
176
176
  # HACK more
177
177
  end
178
178
 
179
+ debug_args = args.dup
180
+
179
181
  r = RDoc::RDoc.new
180
182
 
181
183
  old_pwd = Dir.pwd
@@ -193,10 +195,10 @@ class Gem::DocManager
193
195
  rescue Exception => ex
194
196
  alert_error "While generating documentation for #{@spec.full_name}"
195
197
  ui.errs.puts "... MESSAGE: #{ex}"
196
- ui.errs.puts "... RDOC args: #{args.join(' ')}"
198
+ ui.errs.puts "... RDOC args: #{debug_args.join(' ')}"
197
199
  ui.errs.puts "\t#{ex.backtrace.join "\n\t"}" if
198
- Gem.configuration.backtrace
199
- ui.errs.puts "(continuing with the rest of the installation)"
200
+ Gem.configuration.backtrace
201
+ terminate_interaction 1
200
202
  ensure
201
203
  Dir.chdir old_pwd
202
204
  end
@@ -10,6 +10,7 @@ class Gem::GemPathSearcher
10
10
  def initialize
11
11
  # We want a record of all the installed gemspecs, in the order we wish to
12
12
  # examine them.
13
+ # TODO: remove this stupid method
13
14
  @gemspecs = init_gemspecs
14
15
 
15
16
  # Map gem spec to glob of full require_path directories. Preparing this
@@ -42,7 +43,9 @@ class Gem::GemPathSearcher
42
43
  # only that there is a match.
43
44
 
44
45
  def find(glob)
46
+ # HACK violation of encapsulation
45
47
  @gemspecs.find do |spec|
48
+ # TODO: inverted responsibility
46
49
  matching_file? spec, glob
47
50
  end
48
51
  end
@@ -51,9 +54,39 @@ class Gem::GemPathSearcher
51
54
  # Works like #find, but finds all gemspecs matching +glob+.
52
55
 
53
56
  def find_all(glob)
57
+ # HACK violation of encapsulation
54
58
  @gemspecs.select do |spec|
59
+ # TODO: inverted responsibility
55
60
  matching_file? spec, glob
61
+ end || []
62
+ end
63
+
64
+ def find_in_unresolved(glob)
65
+ # HACK violation
66
+ specs = Gem.unresolved_deps.values.map { |dep|
67
+ Gem.source_index.search dep, true
68
+ }.flatten
69
+
70
+ specs.select do |spec|
71
+ # TODO: inverted responsibility
72
+ matching_file? spec, glob
73
+ end || []
74
+ end
75
+
76
+ def find_in_unresolved_tree glob
77
+ # HACK violation
78
+ # TODO: inverted responsibility
79
+ specs = Gem.unresolved_deps.values.map { |dep|
80
+ Gem.source_index.search dep, true
81
+ }.flatten
82
+
83
+ specs.reverse_each do |spec|
84
+ trails = matching_paths(spec, glob)
85
+ next if trails.empty?
86
+ return trails.map(&:reverse).sort.first.reverse
56
87
  end
88
+
89
+ []
57
90
  end
58
91
 
59
92
  ##
@@ -61,7 +94,18 @@ class Gem::GemPathSearcher
61
94
  # +spec+.
62
95
 
63
96
  def matching_file?(spec, path)
64
- !matching_files(spec, path).empty?
97
+ not matching_files(spec, path).empty?
98
+ end
99
+
100
+ def matching_paths(spec, path)
101
+ trails = []
102
+
103
+ spec.traverse do |from_spec, dep, to_spec, trail|
104
+ next unless to_spec.conflicts.empty?
105
+ trails << trail unless matching_files(to_spec, path).empty?
106
+ end
107
+
108
+ trails
65
109
  end
66
110
 
67
111
  ##
@@ -1,6 +1,28 @@
1
1
  require 'rubygems/remote_fetcher'
2
2
 
3
3
  module Gem::GemcutterUtilities
4
+ OptionParser.accept Symbol do |value|
5
+ value.to_sym
6
+ end
7
+
8
+ ##
9
+ # Add the --key option
10
+
11
+ def add_key_option
12
+ add_option('-k', '--key KEYNAME', Symbol,
13
+ 'Use the given API key',
14
+ 'from ~/.gem/credentials') do |value,options|
15
+ options[:key] = value
16
+ end
17
+ end
18
+
19
+ def api_key
20
+ if options[:key] then
21
+ verify_api_key options[:key]
22
+ else
23
+ Gem.configuration.rubygems_api_key
24
+ end
25
+ end
4
26
 
5
27
  def sign_in
6
28
  return if Gem.configuration.rubygems_api_key
@@ -27,6 +49,8 @@ module Gem::GemcutterUtilities
27
49
  host = ENV['RUBYGEMS_HOST'] if ENV['RUBYGEMS_HOST']
28
50
  uri = URI.parse "#{host}/#{path}"
29
51
 
52
+ say "Pushing gem to #{host}..."
53
+
30
54
  request_method = Net::HTTP.const_get method.to_s.capitalize
31
55
 
32
56
  Gem::RemoteFetcher.fetcher.request(uri, request_method, &block)
@@ -46,4 +70,13 @@ module Gem::GemcutterUtilities
46
70
  end
47
71
  end
48
72
 
73
+ def verify_api_key(key)
74
+ if Gem.configuration.api_keys.key? key then
75
+ Gem.configuration.api_keys[key]
76
+ else
77
+ alert_error "No such API key. You can add it with gem keys --add #{key}"
78
+ terminate_interaction 1
79
+ end
80
+ end
81
+
49
82
  end
@@ -1,5 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'rubygems/format'
3
+ require 'time'
3
4
 
4
5
  begin
5
6
  gem 'builder'
@@ -150,6 +150,9 @@ class Gem::Installer
150
150
 
151
151
  Gem.ensure_gem_subdirectories @gem_home
152
152
 
153
+ # Completely remove any previous gem files
154
+ FileUtils.rm_rf(@gem_dir) if File.exist?(@gem_dir)
155
+
153
156
  FileUtils.mkdir_p @gem_dir
154
157
 
155
158
  extract_files
@@ -173,10 +176,9 @@ class Gem::Installer
173
176
 
174
177
  write_require_paths_file_if_needed if Gem::QUICKLOADER_SUCKAGE
175
178
 
176
- # HACK remove? Isn't this done in multiple places?
177
- cached_gem = File.join @gem_home, "cache", @gem.split(/\//).pop
179
+ cached_gem = Gem.cache_gem(File.basename(@gem), @gem_home)
178
180
  unless File.exist? cached_gem then
179
- FileUtils.cp @gem, File.join(@gem_home, "cache")
181
+ FileUtils.cp @gem, Gem.cache_dir(@gem_home)
180
182
  end
181
183
 
182
184
  say @spec.post_install_message unless @spec.post_install_message.nil?
@@ -229,7 +231,7 @@ class Gem::Installer
229
231
  # specifications directory.
230
232
 
231
233
  def write_spec
232
- rubycode = @spec.to_ruby
234
+ rubycode = @spec.to_ruby_for_cache
233
235
 
234
236
  file_name = File.join @gem_home, 'specifications', @spec.spec_name
235
237
 
@@ -269,8 +271,10 @@ class Gem::Installer
269
271
  @spec.executables.each do |filename|
270
272
  filename.untaint
271
273
  bin_path = File.expand_path "#{@spec.bindir}/#{filename}", @gem_dir
272
- mode = File.stat(bin_path).mode | 0111
273
- File.chmod mode, bin_path
274
+ if File.exist?(bin_path)
275
+ mode = File.stat(bin_path).mode | 0111
276
+ File.chmod mode, bin_path
277
+ end
274
278
 
275
279
  if @wrappers then
276
280
  generate_bin_script filename, bindir
@@ -292,7 +296,7 @@ class Gem::Installer
292
296
 
293
297
  FileUtils.rm_f bin_script_path # prior install may have been --no-wrappers
294
298
 
295
- File.open bin_script_path, 'w', 0755 do |file|
299
+ File.open bin_script_path, 'wb', 0755 do |file|
296
300
  file.print app_script_text(filename)
297
301
  end
298
302
 
@@ -58,12 +58,15 @@ class Gem::InstallerTestCase < Gem::TestCase
58
58
  super
59
59
 
60
60
  @spec = quick_gem 'a'
61
+ util_make_exec @spec
61
62
 
62
63
  @gem = File.join @tempdir, @spec.file_name
63
64
 
64
65
  @installer = util_installer @spec, @gem, @gemhome
65
66
 
66
67
  @user_spec = quick_gem 'b'
68
+ util_make_exec @user_spec
69
+
67
70
  @user_gem = File.join @tempdir, @user_spec.file_name
68
71
 
69
72
  @user_installer = util_installer @user_spec, @user_gem, Gem.user_dir
@@ -71,31 +74,38 @@ class Gem::InstallerTestCase < Gem::TestCase
71
74
  @user_spec.full_name)
72
75
  end
73
76
 
74
- def util_gem_bindir(version = '2')
75
- File.join util_gem_dir(version), "bin"
77
+ def util_gem_bindir spec = @spec
78
+ File.join util_gem_dir(spec), "bin"
76
79
  end
77
80
 
78
- def util_gem_dir(version = '2')
79
- File.join @gemhome, "gems", "a-#{version}" # HACK
81
+ def util_gem_dir spec = @spec
82
+ File.join @gemhome, "gems", spec.full_name
80
83
  end
81
84
 
82
85
  def util_inst_bindir
83
86
  File.join @gemhome, "bin"
84
87
  end
85
88
 
86
- def util_make_exec(version = '2', shebang = "#!/usr/bin/ruby")
87
- @spec.executables = ["my_exec"]
89
+ def util_make_exec(spec = @spec, shebang = "#!/usr/bin/ruby")
90
+ spec.executables = %w[executable]
91
+ spec.files << 'bin/executable'
92
+
93
+ bindir = util_gem_bindir spec
94
+ FileUtils.mkdir_p bindir
95
+ exec_path = File.join bindir, 'executable'
96
+ open exec_path, 'w' do |io|
97
+ io.puts shebang
98
+ end
88
99
 
89
- FileUtils.mkdir_p util_gem_bindir(version)
90
- exec_path = File.join util_gem_bindir(version), "my_exec"
91
- File.open exec_path, 'w' do |f|
92
- f.puts shebang
100
+ temp_bin = File.join(@tempdir, 'bin')
101
+ FileUtils.mkdir_p temp_bin
102
+ open File.join(temp_bin, 'executable'), 'w' do |io|
103
+ io.puts shebang
93
104
  end
94
105
  end
95
106
 
96
107
  def util_setup_gem(ui = @ui) # HACK fix use_ui to make this automatic
97
- @spec.files = File.join('lib', 'code.rb')
98
- @spec.executables << 'executable'
108
+ @spec.files << File.join('lib', 'code.rb')
99
109
  @spec.extensions << File.join('ext', 'a', 'mkrf_conf.rb')
100
110
 
101
111
  Dir.chdir @tempdir do
@@ -121,9 +131,7 @@ class Gem::InstallerTestCase < Gem::TestCase
121
131
 
122
132
  def util_installer(spec, gem_path, gem_home)
123
133
  util_build_gem spec
124
- FileUtils.mv File.join(@gemhome, 'cache', spec.file_name),
125
- @tempdir
126
-
134
+ FileUtils.mv Gem.cache_gem(spec.file_name), @tempdir
127
135
  installer = Gem::Installer.new gem_path
128
136
  installer.gem_dir = util_gem_dir
129
137
  installer.gem_home = gem_home
@@ -31,7 +31,7 @@ class Gem::MockGemUi < Gem::StreamUI
31
31
  outs.extend TTY
32
32
  errs.extend TTY
33
33
 
34
- super ins, outs, errs
34
+ super ins, outs, errs, true
35
35
 
36
36
  @terminated = false
37
37
  end
@@ -71,6 +71,23 @@ class Gem::RemoteFetcher
71
71
  end
72
72
  end
73
73
 
74
+ ##
75
+ # Given a name and requirement, downloads this gem into cache and returns the
76
+ # filename. Returns nil if the gem cannot be located.
77
+ #--
78
+ # Should probably be integrated with #download below, but that will be a
79
+ # larger, more emcompassing effort. -erikh
80
+
81
+ def download_to_cache dependency
82
+ found = Gem::SpecFetcher.fetcher.fetch dependency
83
+
84
+ return if found.empty?
85
+
86
+ spec, source_uri = found.first
87
+
88
+ download spec, source_uri
89
+ end
90
+
74
91
  ##
75
92
  # Moves the gem +spec+ from +source_uri+ to the cache dir unless it is
76
93
  # already there. If the source_uri is local the gem cache dir copy is
@@ -80,9 +97,9 @@ class Gem::RemoteFetcher
80
97
  Gem.ensure_gem_subdirectories(install_dir) rescue nil
81
98
 
82
99
  if File.writable?(install_dir)
83
- cache_dir = File.join install_dir, 'cache'
100
+ cache_dir = Gem.cache_dir(install_dir)
84
101
  else
85
- cache_dir = File.join(Gem.user_dir, 'cache')
102
+ cache_dir = Gem.cache_dir(Gem.user_dir)
86
103
  end
87
104
 
88
105
  gem_file_name = spec.file_name
@@ -134,7 +151,7 @@ class Gem::RemoteFetcher
134
151
  path = source_uri.path
135
152
  path = File.dirname(path) if File.extname(path) == '.gem'
136
153
 
137
- remote_gem_path = File.join(path, 'gems', gem_file_name)
154
+ remote_gem_path = correct_for_windows_path(File.join(path, 'gems', gem_file_name))
138
155
 
139
156
  FileUtils.cp(remote_gem_path, local_gem_path)
140
157
  rescue Errno::EACCES
@@ -270,6 +287,14 @@ class Gem::RemoteFetcher
270
287
  raise FetchError.new(e.message, uri)
271
288
  end
272
289
 
290
+ def correct_for_windows_path(path)
291
+ if path[0].chr == '/' && path[1].chr =~ /[a-z]/i && path[2].chr == ':'
292
+ path = path[1..-1]
293
+ else
294
+ path
295
+ end
296
+ end
297
+
273
298
  ##
274
299
  # Read the data from the (source based) URI, but if it is a file:// URI,
275
300
  # read from the filesystem instead.
@@ -287,13 +312,7 @@ class Gem::RemoteFetcher
287
312
  end
288
313
 
289
314
  if uri.scheme == 'file'
290
- path = uri.path
291
-
292
- # Deal with leading slash on Windows paths
293
- if path[0].chr == '/' && path[1].chr =~ /[a-zA-Z]/ && path[2].chr == ':'
294
- path = path[1..-1]
295
- end
296
-
315
+ path = correct_for_windows_path(uri.path)
297
316
  return Gem.read_binary(path)
298
317
  end
299
318
 
@@ -102,7 +102,7 @@ class Gem::Requirement
102
102
  end
103
103
 
104
104
  def as_list # :nodoc:
105
- requirements.map { |op, version| "#{op} #{version}" }
105
+ requirements.map { |op, version| "#{op} #{version}" }.sort
106
106
  end
107
107
 
108
108
  def hash # :nodoc:
@@ -6,6 +6,7 @@
6
6
 
7
7
  require 'rubygems/exceptions'
8
8
  require 'rubygems/gem_openssl'
9
+ require 'fileutils'
9
10
 
10
11
  #
11
12
  # = Signed Gems README
@@ -125,7 +125,7 @@ class Gem::SourceIndex
125
125
  # Returns an Array specifications for the latest released versions
126
126
  # of each gem in this index.
127
127
 
128
- def latest_specs
128
+ def latest_specs(include_prerelease=false)
129
129
  result = Hash.new { |h,k| h[k] = [] }
130
130
  latest = {}
131
131
 
@@ -134,7 +134,7 @@ class Gem::SourceIndex
134
134
  curr_ver = spec.version
135
135
  prev_ver = latest.key?(name) ? latest[name].version : nil
136
136
 
137
- next if curr_ver.prerelease?
137
+ next if !include_prerelease && curr_ver.prerelease?
138
138
  next unless prev_ver.nil? or curr_ver >= prev_ver or
139
139
  latest[name].platform != Gem::Platform::RUBY
140
140
 
@@ -267,6 +267,7 @@ class Gem::SourceIndex
267
267
  when Gem::Dependency then
268
268
  only_platform = platform_only
269
269
  requirement = gem_pattern.requirement
270
+
270
271
  gem_pattern = if Regexp === gem_pattern.name then
271
272
  gem_pattern.name
272
273
  elsif gem_pattern.name.empty? then
@@ -70,7 +70,8 @@ class Gem::SpecFetcher
70
70
  # Returns the local directory to write +uri+ to.
71
71
 
72
72
  def cache_dir(uri)
73
- File.join @dir, "#{uri.host}%#{uri.port}", File.dirname(uri.path)
73
+ escaped_path = uri.path.sub(%r[^/([a-z]):/]i, '/\\1-/') # Correct for windows paths
74
+ File.join @dir, "#{uri.host}%#{uri.port}", File.dirname(escaped_path)
74
75
  end
75
76
 
76
77
  ##
@@ -94,6 +95,7 @@ class Gem::SpecFetcher
94
95
  end
95
96
 
96
97
  def fetch_spec(spec, source_uri)
98
+ source_uri = URI.parse source_uri if String === source_uri
97
99
  spec = spec - [nil, 'ruby', '']
98
100
  spec_file_name = "#{spec.join '-'}.gemspec"
99
101
 
@@ -333,7 +333,8 @@ class Gem::Specification
333
333
  # List of dependencies that will automatically be activated at runtime.
334
334
 
335
335
  def runtime_dependencies
336
- dependencies.select { |d| d.type == :runtime || d.type == nil }
336
+ # TODO: fix #type to return :runtime if nil
337
+ dependencies.select { |d| d.type == :runtime }
337
338
  end
338
339
 
339
340
  ##
@@ -678,6 +679,14 @@ class Gem::Specification
678
679
 
679
680
  alias eql? == # :nodoc:
680
681
 
682
+ ##
683
+ # A macro to yield cached gem path
684
+ #
685
+ def cache_gem
686
+ cache_name = File.join(Gem.dir, 'cache', file_name)
687
+ return File.exist?(cache_name) ? cache_name : nil
688
+ end
689
+
681
690
  ##
682
691
  # True if this gem has the same attributes as +other+.
683
692
 
@@ -791,21 +800,17 @@ class Gem::Specification
791
800
 
792
801
  result << " if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then"
793
802
 
794
- unless dependencies.empty? then
795
- dependencies.each do |dep|
796
- version_reqs_param = dep.requirements_list.inspect
797
- dep.instance_variable_set :@type, :runtime if dep.type.nil? # HACK
798
- result << " s.add_#{dep.type}_dependency(%q<#{dep.name}>, #{version_reqs_param})"
799
- end
803
+ dependencies.each do |dep|
804
+ req = dep.requirements_list.inspect
805
+ dep.instance_variable_set :@type, :runtime if dep.type.nil? # HACK
806
+ result << " s.add_#{dep.type}_dependency(%q<#{dep.name}>, #{req})"
800
807
  end
801
808
 
802
809
  result << " else"
803
810
 
804
- unless dependencies.empty? then
805
- dependencies.each do |dep|
806
- version_reqs_param = dep.requirements_list.inspect
807
- result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})"
808
- end
811
+ dependencies.each do |dep|
812
+ version_reqs_param = dep.requirements_list.inspect
813
+ result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})"
809
814
  end
810
815
 
811
816
  result << ' end'
@@ -823,6 +828,15 @@ class Gem::Specification
823
828
  result.join "\n"
824
829
  end
825
830
 
831
+ def to_ruby_for_cache
832
+ s = dup
833
+ # remove large blobs that aren't used at runtime:
834
+ s.files = nil
835
+ s.extra_rdoc_files = nil
836
+ s.rdoc_options = nil
837
+ s.to_ruby
838
+ end
839
+
826
840
  ##
827
841
  # Checks that the specification contains all required fields, and does a
828
842
  # very basic sanity check.
@@ -1520,4 +1534,32 @@ class Gem::Specification
1520
1534
  @extensions,
1521
1535
  ].flatten.uniq.compact
1522
1536
  end
1537
+
1538
+ def conflicts
1539
+ conflicts = {}
1540
+ Gem.loaded_specs.values.each do |spec|
1541
+ bad = self.runtime_dependencies.find_all { |dep|
1542
+ spec.name == dep.name and not spec.satisfies_requirement? dep
1543
+ }
1544
+
1545
+ conflicts[spec] = bad unless bad.empty?
1546
+ end
1547
+ conflicts
1548
+ end
1549
+
1550
+ def traverse trail = [], &b
1551
+ trail = trail + [self]
1552
+ runtime_dependencies.each do |dep|
1553
+ dep_specs = Gem.source_index.search dep, true
1554
+ dep_specs.each do |dep_spec|
1555
+ b[self, dep, dep_spec, trail + [dep_spec]]
1556
+ dep_spec.traverse(trail, &b) unless
1557
+ trail.map(&:name).include? dep_spec.name
1558
+ end
1559
+ end
1560
+ end
1561
+
1562
+ def dependent_specs
1563
+ runtime_dependencies.map { |dep| Gem.source_index.search dep, true }.flatten
1564
+ end
1523
1565
  end