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
@@ -17,6 +17,7 @@ class Gem::Commands::OwnerCommand < Gem::Command
17
17
  def initialize
18
18
  super 'owner', description
19
19
  add_proxy_option
20
+ add_key_option
20
21
  defaults.merge! :add => [], :remove => []
21
22
 
22
23
  add_option '-a', '--add EMAIL', 'Add an owner' do |value, options|
@@ -39,7 +40,7 @@ class Gem::Commands::OwnerCommand < Gem::Command
39
40
 
40
41
  def show_owners name
41
42
  response = rubygems_api_request :get, "api/v1/gems/#{name}/owners.yaml" do |request|
42
- request.add_field "Authorization", Gem.configuration.rubygems_api_key
43
+ request.add_field "Authorization", api_key
43
44
  end
44
45
 
45
46
  with_response response do |resp|
@@ -64,7 +65,7 @@ class Gem::Commands::OwnerCommand < Gem::Command
64
65
  owners.each do |owner|
65
66
  response = rubygems_api_request method, "api/v1/gems/#{name}/owners" do |request|
66
67
  request.set_form_data 'email' => owner
67
- request.add_field "Authorization", Gem.configuration.rubygems_api_key
68
+ request.add_field "Authorization", api_key
68
69
  end
69
70
 
70
71
  with_response response
@@ -73,11 +73,13 @@ revert the gem.
73
73
  say "Restoring gem(s) to pristine condition..."
74
74
 
75
75
  specs.each do |spec|
76
- gem = Dir[File.join(Gem.dir, 'cache', spec.file_name)].first
76
+ gem = spec.cache_gem
77
77
 
78
78
  if gem.nil? then
79
- alert_error "Cached gem for #{spec.full_name} not found, use `gem install` to restore"
80
- next
79
+ say "Cached gem for #{spec.full_name} not found, attempting to fetch..."
80
+ dep = Gem::Dependency.new spec.name, spec.version
81
+ Gem::RemoteFetcher.fetcher.download_to_cache dep
82
+ gem = spec.cache_gem
81
83
  end
82
84
 
83
85
  # TODO use installer options
@@ -21,7 +21,8 @@ class Gem::Commands::PushCommand < Gem::Command
21
21
  def initialize
22
22
  super 'push', description
23
23
  add_proxy_option
24
-
24
+ add_key_option
25
+
25
26
  add_option(
26
27
  '--host HOST',
27
28
  'Push to another gemcutter-compatible host'
@@ -36,17 +37,20 @@ class Gem::Commands::PushCommand < Gem::Command
36
37
  end
37
38
 
38
39
  def send_gem name
39
- say "Pushing gem to #{options[:host] || Gem.host}..."
40
-
41
40
  args = [:post, "api/v1/gems"]
42
41
 
43
42
  args << options[:host] if options[:host]
44
43
 
44
+ if Gem.latest_rubygems_version < Gem::Version.new(Gem::VERSION) then
45
+ alert_error "Using beta/unreleased version of rubygems. Not pushing."
46
+ terminate_interaction 1
47
+ end
48
+
45
49
  response = rubygems_api_request(*args) do |request|
46
50
  request.body = Gem.read_binary name
47
51
  request.add_field "Content-Length", request.body.size
48
52
  request.add_field "Content-Type", "application/octet-stream"
49
- request.add_field "Authorization", Gem.configuration.rubygems_api_key
53
+ request.add_field "Authorization", api_key
50
54
  end
51
55
 
52
56
  with_response response
@@ -329,8 +329,7 @@ abort "#{deprecation_message}"
329
329
 
330
330
  require 'rdoc/rdoc'
331
331
 
332
- args << '--quiet'
333
- args << '--main' << 'README.rdoc'
332
+ args << '--main' << 'README.rdoc' << '--quiet'
334
333
  args << '.'
335
334
  args << 'README.rdoc' << 'UPGRADING.rdoc'
336
335
  args << 'LICENSE.txt' << 'GPL.txt' << 'History.txt'
@@ -49,6 +49,11 @@ class Gem::Commands::UninstallCommand < Gem::Command
49
49
  options[:user_install] = value
50
50
  end
51
51
 
52
+ add_option('--[no-]format-executable',
53
+ 'Assume executable names match Ruby\'s prefix and suffix.') do |value, options|
54
+ options[:format_executable] = value
55
+ end
56
+
52
57
  add_version_option
53
58
  add_platform_option
54
59
  end
@@ -1,6 +1,7 @@
1
1
  require 'rubygems/command'
2
2
  require 'rubygems/installer'
3
3
  require 'rubygems/version_option'
4
+ require 'rubygems/remote_fetcher'
4
5
 
5
6
  class Gem::Commands::UnpackCommand < Gem::Command
6
7
 
@@ -33,16 +34,6 @@ class Gem::Commands::UnpackCommand < Gem::Command
33
34
  "#{program_name} GEMNAME"
34
35
  end
35
36
 
36
- def download dependency
37
- found = Gem::SpecFetcher.fetcher.fetch dependency
38
-
39
- return if found.empty?
40
-
41
- spec, source_uri = found.first
42
-
43
- Gem::RemoteFetcher.fetcher.download spec, source_uri
44
- end
45
-
46
37
  #--
47
38
  # TODO: allow, e.g., 'gem unpack rake-0.3.1'. Find a general solution for
48
39
  # this, so that it works for uninstall as well. (And check other commands
@@ -73,8 +64,9 @@ class Gem::Commands::UnpackCommand < Gem::Command
73
64
  # TODO: see comments in get_path() about general service.
74
65
 
75
66
  def find_in_cache(filename)
76
- Gem.path.each do |gem_dir|
77
- this_path = File.join gem_dir, 'cache', filename
67
+
68
+ Gem.path.each do |path|
69
+ this_path = Gem.cache_gem(filename, path)
78
70
  return this_path if File.exist? this_path
79
71
  end
80
72
 
@@ -105,15 +97,17 @@ class Gem::Commands::UnpackCommand < Gem::Command
105
97
 
106
98
  selected = specs.sort_by { |s| s.version }.last
107
99
 
108
- return download(dependency) if selected.nil?
100
+ return Gem::RemoteFetcher.fetcher.download_to_cache(dependency) unless
101
+ selected
109
102
 
110
103
  return unless dependency.name =~ /^#{selected.name}$/i
111
104
 
112
105
  # We expect to find (basename).gem in the 'cache' directory. Furthermore,
113
106
  # the name match must be exact (ignoring case).
114
-
115
- path = find_in_cache(selected.file_name)
116
- return download(dependency) unless path
107
+
108
+ path = find_in_cache selected.file_name
109
+
110
+ return Gem::RemoteFetcher.fetcher.download_to_cache(dependency) unless path
117
111
 
118
112
  path
119
113
  end
@@ -123,6 +123,11 @@ class Gem::ConfigFile
123
123
 
124
124
  attr_reader :rubygems_api_key
125
125
 
126
+ ##
127
+ # Hash of RubyGems.org and alternate API keys
128
+
129
+ attr_reader :api_keys
130
+
126
131
  ##
127
132
  # Create the config file object. +args+ is the list of arguments
128
133
  # from the command line.
@@ -186,7 +191,7 @@ class Gem::ConfigFile
186
191
  @update_sources = @hash[:update_sources] if @hash.key? :update_sources
187
192
  @verbose = @hash[:verbose] if @hash.key? :verbose
188
193
 
189
- load_rubygems_api_key
194
+ load_api_keys
190
195
 
191
196
  Gem.sources = @hash[:sources] if @hash.key? :sources
192
197
  handle_arguments arg_list
@@ -199,10 +204,12 @@ class Gem::ConfigFile
199
204
  File.join(Gem.user_home, '.gem', 'credentials')
200
205
  end
201
206
 
202
- def load_rubygems_api_key
203
- api_key_hash = File.exists?(credentials_path) ? load_file(credentials_path) : @hash
204
-
205
- @rubygems_api_key = api_key_hash[:rubygems_api_key] if api_key_hash.key? :rubygems_api_key
207
+ def load_api_keys
208
+ @api_keys = File.exists?(credentials_path) ? load_file(credentials_path) : @hash
209
+ if @api_keys.key? :rubygems_api_key then
210
+ @rubygems_api_key = @api_keys[:rubygems_api_key]
211
+ @api_keys[:rubygems] = @api_keys.delete :rubygems_api_key unless @api_keys.key? :rubygems
212
+ end
206
213
  end
207
214
 
208
215
  def rubygems_api_key=(api_key)
@@ -6,10 +6,16 @@
6
6
 
7
7
  module Kernel
8
8
 
9
- ##
10
- # The Kernel#require from before RubyGems was loaded.
11
-
12
- alias gem_original_require require
9
+ if defined?(gem_original_require) then
10
+ # Ruby ships with a custom_require, override its require
11
+ remove_method :require
12
+ else
13
+ ##
14
+ # The Kernel#require from before RubyGems was loaded.
15
+
16
+ alias gem_original_require require
17
+ private :gem_original_require
18
+ end
13
19
 
14
20
  ##
15
21
  # When RubyGems is required, Kernel#require is replaced with our own which
@@ -25,8 +31,23 @@ module Kernel
25
31
  # The normal <tt>require</tt> functionality of returning false if
26
32
  # that file has already been loaded is preserved.
27
33
 
28
- def require(path) # :doc:
29
- gem_original_require path
34
+ def require path
35
+ if Gem.unresolved_deps.empty? or Gem.loaded_path? path then
36
+ gem_original_require path
37
+ else
38
+ specs = Gem.searcher.find_in_unresolved path
39
+ unless specs.empty? then
40
+ specs = [specs.last]
41
+ else
42
+ specs = Gem.searcher.find_in_unresolved_tree path
43
+ end
44
+
45
+ specs.each do |spec|
46
+ Gem.activate spec.name, spec.version # FIX: this is dumb
47
+ end
48
+
49
+ return gem_original_require path
50
+ end
30
51
  rescue LoadError => load_error
31
52
  if load_error.message.end_with?(path) and Gem.try_activate(path) then
32
53
  return gem_original_require(path)
@@ -36,7 +57,6 @@ module Kernel
36
57
  end
37
58
 
38
59
  private :require
39
- private :gem_original_require
40
60
 
41
61
  end
42
62
 
@@ -26,11 +26,6 @@ class Gem::Dependency
26
26
 
27
27
  attr_writer :prerelease
28
28
 
29
- ##
30
- # Dependency type.
31
-
32
- attr_reader :type
33
-
34
29
  ##
35
30
  # Constructs a dependency with +name+ and +requirements+. The last
36
31
  # argument can optionally be the dependency type, which defaults to
@@ -66,7 +61,7 @@ class Gem::Dependency
66
61
 
67
62
  def inspect # :nodoc:
68
63
  "<%s type=%p name=%p requirements=%p>" %
69
- [self.class, @type, @name, requirement.to_s]
64
+ [self.class, self.type, self.name, requirement.to_s]
70
65
  end
71
66
 
72
67
  ##
@@ -126,7 +121,18 @@ class Gem::Dependency
126
121
  end
127
122
 
128
123
  def to_s # :nodoc:
129
- "#{name} (#{requirement}, #{type})"
124
+ if type != :runtime then
125
+ "#{name} (#{requirement}, #{type})"
126
+ else
127
+ "#{name} (#{requirement})"
128
+ end
129
+ end
130
+
131
+ ##
132
+ # Dependency type.
133
+
134
+ def type
135
+ @type ||= :runtime
130
136
  end
131
137
 
132
138
  def == other # :nodoc:
@@ -140,7 +146,7 @@ class Gem::Dependency
140
146
  # Dependencies are ordered by name.
141
147
 
142
148
  def <=> other
143
- @name <=> other.name
149
+ self.name <=> other.name
144
150
  end
145
151
 
146
152
  ##
@@ -181,5 +187,24 @@ class Gem::Dependency
181
187
  requirement.satisfied_by?(spec.version)
182
188
  end
183
189
 
190
+ ##
191
+ # Merges the requirements of +other+ into this dependency
192
+
193
+ def merge other
194
+ unless name == other.name then
195
+ raise ArgumentError,
196
+ "#{self} and #{other} have different names"
197
+ end
198
+
199
+ default = Gem::Requirement.default
200
+ self_req = self.requirement
201
+ other_req = other.requirement
202
+
203
+ return self.class.new name, self_req if other_req == default
204
+ return self.class.new name, other_req if self_req == default
205
+
206
+ self.class.new name, self_req.as_list.concat(other_req.as_list)
207
+ end
208
+
184
209
  end
185
210
 
@@ -68,7 +68,7 @@ class Gem::DependencyInstaller
68
68
  @installed_gems = []
69
69
 
70
70
  @install_dir = options[:install_dir] || Gem.dir
71
- @cache_dir = options[:cache_dir] || @install_dir
71
+ @cache_dir = options[:cache_dir] || Gem.cache_dir(@install_dir)
72
72
 
73
73
  # Set with any errors that SpecFetcher finds while search through
74
74
  # gemspecs for a dep
@@ -130,17 +130,33 @@ class Gem::DependencyInstaller
130
130
  def gather_dependencies
131
131
  specs = @specs_and_sources.map { |spec,_| spec }
132
132
 
133
+ # these gems were listed by the user, always install them
134
+ keep_names = specs.map { |spec| spec.full_name }
135
+
133
136
  dependency_list = Gem::DependencyList.new @development
134
137
  dependency_list.add(*specs)
135
138
  to_do = specs.dup
136
139
 
137
140
  add_found_dependencies to_do, dependency_list unless @ignore_dependencies
138
141
 
142
+ dependency_list.specs.reject! { |spec|
143
+ ! keep_names.include? spec.full_name and
144
+ @source_index.any? { |n,_| n == spec.full_name }
145
+ }
146
+
147
+ unless dependency_list.ok? or @ignore_dependencies or @force then
148
+ reason = dependency_list.why_not_ok?.map { |k,v|
149
+ "#{k} requires #{v.join(", ")}"
150
+ }.join("; ")
151
+ raise Gem::DependencyError, "Unable to resolve dependencies: #{reason}"
152
+ end
153
+
139
154
  @gems_to_install = dependency_list.dependency_order.reverse
140
155
  end
141
156
 
142
157
  def add_found_dependencies to_do, dependency_list
143
158
  seen = {}
159
+ dependencies = Hash.new { |h, name| h[name] = Gem::Dependency.new name }
144
160
 
145
161
  until to_do.empty? do
146
162
  spec = to_do.shift
@@ -151,10 +167,10 @@ class Gem::DependencyInstaller
151
167
  deps |= spec.development_dependencies if @development
152
168
 
153
169
  deps.each do |dep|
170
+ dependencies[dep.name] = dependencies[dep.name].merge dep
171
+
154
172
  results = find_gems_with_sources(dep).reverse
155
173
 
156
- # FIX: throw in everything that satisfies, and let
157
- # FIX: dependencylist reduce to the chosen few
158
174
  results.reject! do |dep_spec,|
159
175
  to_do.push dep_spec
160
176
 
@@ -166,14 +182,14 @@ class Gem::DependencyInstaller
166
182
  end
167
183
 
168
184
  results.each do |dep_spec, source_uri|
169
- next if seen[dep_spec.name]
170
185
  @specs_and_sources << [dep_spec, source_uri]
171
186
 
172
- # FIX: this is the bug
173
187
  dependency_list.add dep_spec
174
188
  end
175
189
  end
176
190
  end
191
+
192
+ dependency_list.remove_specs_unsatisfied_by dependencies
177
193
  end
178
194
 
179
195
  ##
@@ -253,7 +269,6 @@ class Gem::DependencyInstaller
253
269
 
254
270
  @gems_to_install.each do |spec|
255
271
  last = spec == @gems_to_install.last
256
- # HACK is this test for full_name acceptable?
257
272
  next if @source_index.any? { |n,_| n == spec.full_name } and not last
258
273
 
259
274
  # TODO: make this sorta_verbose so other users can benefit from it
@@ -11,6 +11,7 @@ require 'tsort'
11
11
  # correct order to avoid conflicts.
12
12
 
13
13
  class Gem::DependencyList
14
+ attr_reader :specs
14
15
 
15
16
  include Enumerable
16
17
  include TSort
@@ -50,6 +51,10 @@ class Gem::DependencyList
50
51
  @specs.push(*gemspecs)
51
52
  end
52
53
 
54
+ def clear
55
+ @specs.clear
56
+ end
57
+
53
58
  ##
54
59
  # Return a list of the gem specifications in the dependency list, sorted in
55
60
  # order so that no gemspec in the list depends on a gemspec earlier in the
@@ -104,11 +109,26 @@ class Gem::DependencyList
104
109
  # Are all the dependencies in the list satisfied?
105
110
 
106
111
  def ok?
107
- @specs.all? do |spec|
108
- spec.runtime_dependencies.all? do |dep|
109
- @specs.find { |s| s.satisfies_requirement? dep }
112
+ why_not_ok?(:quick).empty?
113
+ end
114
+
115
+ def why_not_ok? quick = false
116
+ unsatisfied = Hash.new { |h,k| h[k] = [] }
117
+ source_index = Gem.source_index
118
+ @specs.each do |spec|
119
+ spec.runtime_dependencies.each do |dep|
120
+ inst = source_index.any? { |_, installed_spec|
121
+ dep.name == installed_spec.name and
122
+ dep.requirement.satisfied_by? installed_spec.version
123
+ }
124
+
125
+ unless inst or @specs.find { |s| s.satisfies_requirement? dep } then
126
+ unsatisfied[spec.name] << dep
127
+ return unsatisfied if quick
128
+ end
110
129
  end
111
130
  end
131
+ unsatisfied
112
132
  end
113
133
 
114
134
  ##
@@ -140,6 +160,18 @@ class Gem::DependencyList
140
160
  }
141
161
  end
142
162
 
163
+ ##
164
+ # Remove everything in the DependencyList that matches but doesn't
165
+ # satisfy items in +dependencies+ (a hash of gem names to arrays of
166
+ # dependencies).
167
+
168
+ def remove_specs_unsatisfied_by dependencies
169
+ specs.reject! { |spec|
170
+ dep = dependencies[spec.name]
171
+ dep and not dep.requirement.satisfied_by? spec.version
172
+ }
173
+ end
174
+
143
175
  ##
144
176
  # Removes the gemspec matching +full_name+ from the dependency list
145
177