rubygems-update 0.9.4 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

Files changed (225) hide show
  1. data/ChangeLog +587 -0
  2. data/README +0 -1
  3. data/Rakefile +39 -12
  4. data/TODO +0 -5
  5. data/bin/gem +7 -7
  6. data/bin/update_rubygems +1 -1
  7. data/examples/application/an-app.gemspec +1 -1
  8. data/gemspecs/cgikit-1.1.0.gemspec +1 -2
  9. data/gemspecs/jabber4r.gemspec +1 -1
  10. data/gemspecs/linguistics.gemspec +1 -1
  11. data/gemspecs/ook.gemspec +1 -1
  12. data/gemspecs/progressbar.gemspec +1 -1
  13. data/gemspecs/redcloth.gemspec +1 -1
  14. data/gemspecs/rublog.gemspec +1 -1
  15. data/gemspecs/ruby-doom.gemspec +1 -1
  16. data/gemspecs/rubyjdwp.gemspec +1 -1
  17. data/gemspecs/statistics.gemspec +1 -1
  18. data/lib/rubygems.rb +167 -105
  19. data/lib/rubygems/builder.rb +12 -10
  20. data/lib/rubygems/command.rb +177 -60
  21. data/lib/rubygems/command_manager.rb +30 -38
  22. data/lib/rubygems/commands/build_command.rb +42 -46
  23. data/lib/rubygems/commands/cert_command.rb +72 -69
  24. data/lib/rubygems/commands/check_command.rb +63 -63
  25. data/lib/rubygems/commands/cleanup_command.rb +25 -7
  26. data/lib/rubygems/commands/contents_command.rb +70 -62
  27. data/lib/rubygems/commands/dependency_command.rb +131 -86
  28. data/lib/rubygems/commands/environment_command.rb +67 -46
  29. data/lib/rubygems/commands/fetch_command.rb +62 -0
  30. data/lib/rubygems/commands/generate_index_command.rb +57 -0
  31. data/lib/rubygems/commands/help_command.rb +163 -73
  32. data/lib/rubygems/commands/install_command.rb +114 -128
  33. data/lib/rubygems/commands/list_command.rb +10 -8
  34. data/lib/rubygems/commands/lock_command.rb +101 -0
  35. data/lib/rubygems/commands/mirror_command.rb +105 -0
  36. data/lib/rubygems/commands/outdated_command.rb +24 -15
  37. data/lib/rubygems/commands/pristine_command.rb +118 -88
  38. data/lib/rubygems/commands/query_command.rb +109 -77
  39. data/lib/rubygems/commands/rdoc_command.rb +13 -10
  40. data/lib/rubygems/commands/search_command.rb +10 -8
  41. data/lib/rubygems/commands/server_command.rb +48 -0
  42. data/lib/rubygems/commands/sources_command.rb +104 -83
  43. data/lib/rubygems/commands/specification_command.rb +65 -51
  44. data/lib/rubygems/commands/uninstall_command.rb +17 -12
  45. data/lib/rubygems/commands/unpack_command.rb +68 -68
  46. data/lib/rubygems/commands/update_command.rb +72 -25
  47. data/lib/rubygems/commands/which_command.rb +86 -0
  48. data/lib/rubygems/config_file.rb +202 -78
  49. data/lib/rubygems/custom_require.rb +7 -88
  50. data/lib/rubygems/dependency.rb +65 -0
  51. data/lib/rubygems/dependency_installer.rb +232 -0
  52. data/lib/rubygems/dependency_list.rb +133 -105
  53. data/lib/rubygems/digest/md5.rb +4 -1
  54. data/lib/rubygems/digest/sha2.rb +1 -1
  55. data/lib/rubygems/doc_manager.rb +41 -19
  56. data/lib/rubygems/exceptions.rb +63 -0
  57. data/lib/rubygems/ext.rb +18 -0
  58. data/lib/rubygems/ext/builder.rb +56 -0
  59. data/lib/rubygems/ext/configure_builder.rb +24 -0
  60. data/lib/rubygems/ext/ext_conf_builder.rb +23 -0
  61. data/lib/rubygems/ext/rake_builder.rb +27 -0
  62. data/lib/rubygems/format.rb +16 -6
  63. data/lib/rubygems/gem_openssl.rb +43 -6
  64. data/lib/rubygems/gem_path_searcher.rb +84 -0
  65. data/lib/rubygems/gem_runner.rb +20 -5
  66. data/lib/rubygems/indexer.rb +163 -0
  67. data/lib/rubygems/indexer/abstract_index_builder.rb +80 -0
  68. data/lib/rubygems/indexer/marshal_index_builder.rb +17 -0
  69. data/lib/rubygems/indexer/master_index_builder.rb +53 -0
  70. data/lib/rubygems/indexer/quick_index_builder.rb +48 -0
  71. data/lib/rubygems/install_update_options.rb +87 -0
  72. data/lib/rubygems/installer.rb +316 -562
  73. data/lib/rubygems/local_remote_options.rb +106 -0
  74. data/lib/rubygems/old_format.rb +5 -13
  75. data/lib/rubygems/open-uri.rb +2 -0
  76. data/lib/rubygems/package.rb +28 -32
  77. data/lib/rubygems/platform.rb +187 -0
  78. data/lib/rubygems/remote_fetcher.rb +46 -29
  79. data/lib/rubygems/remote_installer.rb +11 -18
  80. data/lib/rubygems/requirement.rb +157 -0
  81. data/lib/rubygems/rubygems_version.rb +1 -1
  82. data/lib/rubygems/security.rb +715 -457
  83. data/lib/rubygems/server.rb +77 -59
  84. data/lib/rubygems/source_index.rb +154 -83
  85. data/lib/rubygems/source_info_cache.rb +73 -30
  86. data/lib/rubygems/source_info_cache_entry.rb +12 -3
  87. data/lib/rubygems/specification.rb +378 -145
  88. data/lib/rubygems/uninstaller.rb +183 -0
  89. data/lib/rubygems/user_interaction.rb +38 -9
  90. data/lib/rubygems/validator.rb +53 -24
  91. data/lib/rubygems/version.rb +126 -289
  92. data/lib/rubygems/version_option.rb +49 -0
  93. data/pkgs/sources/lib/sources.rb +1 -4
  94. data/pkgs/sources/sources.gemspec +3 -3
  95. data/scripts/gemdoc.rb +0 -1
  96. data/setup.rb +166 -1505
  97. data/test/bogussources.rb +0 -1
  98. data/test/data/gem-private_key.pem +27 -0
  99. data/test/data/gem-public_cert.pem +20 -0
  100. data/test/functional.rb +3 -105
  101. data/test/gemutilities.rb +145 -24
  102. data/test/insure_session.rb +0 -1
  103. data/test/{test_datadir.rb → test_config.rb} +7 -13
  104. data/test/test_gem.rb +360 -9
  105. data/test/test_gem_builder.rb +34 -0
  106. data/test/{test_command.rb → test_gem_command.rb} +119 -62
  107. data/test/{test_parse_commands.rb → test_gem_command_manager.rb} +64 -40
  108. data/test/test_gem_commands_build_command.rb +75 -0
  109. data/test/test_gem_commands_cert_command.rb +122 -0
  110. data/test/test_gem_commands_check_command.rb +25 -0
  111. data/test/test_gem_commands_contents_command.rb +92 -0
  112. data/test/test_gem_commands_dependency_command.rb +108 -0
  113. data/test/test_gem_commands_environment_command.rb +117 -0
  114. data/test/test_gem_commands_fetch_command.rb +34 -0
  115. data/test/test_gem_commands_generate_index_command.rb +32 -0
  116. data/test/test_gem_commands_install_command.rb +160 -0
  117. data/test/test_gem_commands_mirror_command.rb +56 -0
  118. data/test/test_gem_commands_pristine_command.rb +100 -0
  119. data/test/test_gem_commands_query_command.rb +82 -0
  120. data/test/test_gem_commands_sources_command.rb +147 -0
  121. data/test/test_gem_commands_specification_command.rb +93 -0
  122. data/test/test_gem_commands_unpack_command.rb +55 -0
  123. data/test/test_gem_config_file.rb +210 -0
  124. data/test/test_gem_dependency.rb +89 -0
  125. data/test/test_gem_dependency_installer.rb +542 -0
  126. data/test/test_gem_dependency_list.rb +212 -0
  127. data/test/test_gem_doc_manager.rb +32 -0
  128. data/test/test_gem_ext_configure_builder.rb +13 -17
  129. data/test/test_gem_ext_ext_conf_builder.rb +9 -9
  130. data/test/test_gem_ext_rake_builder.rb +23 -11
  131. data/test/test_gem_format.rb +69 -0
  132. data/test/test_gem_gem_path_searcher.rb +57 -0
  133. data/test/test_gem_gem_runner.rb +35 -0
  134. data/test/test_gem_indexer.rb +119 -0
  135. data/test/test_gem_install_update_options.rb +40 -0
  136. data/test/test_gem_installer.rb +796 -0
  137. data/test/test_gem_local_remote_options.rb +84 -0
  138. data/test/test_gem_outdated_command.rb +11 -9
  139. data/test/test_gem_platform.rb +240 -0
  140. data/test/{test_remote_fetcher.rb → test_gem_remote_fetcher.rb} +124 -55
  141. data/test/{test_remote_installer.rb → test_gem_remote_installer.rb} +3 -4
  142. data/test/test_gem_requirement.rb +223 -0
  143. data/test/test_gem_server.rb +71 -0
  144. data/test/test_gem_source_index.rb +429 -0
  145. data/test/test_gem_source_info_cache.rb +79 -17
  146. data/test/test_gem_source_info_cache_entry.rb +11 -9
  147. data/test/test_gem_specification.rb +738 -0
  148. data/test/test_gem_stream_ui.rb +117 -0
  149. data/test/test_gem_validator.rb +70 -0
  150. data/test/test_gem_version.rb +191 -0
  151. data/test/test_gem_version_option.rb +77 -0
  152. data/test/{test_require_gem.rb → test_kernel.rb} +19 -12
  153. data/test/test_open_uri.rb +1 -2
  154. data/test/test_package.rb +45 -34
  155. metadata +116 -141
  156. data/Releases +0 -127
  157. data/bin/gem_mirror +0 -73
  158. data/bin/gem_server +0 -6
  159. data/bin/gemlock +0 -127
  160. data/bin/gemri +0 -24
  161. data/bin/gemwhich +0 -89
  162. data/bin/index_gem_repository.rb +0 -302
  163. data/lib/gemconfigure.rb +0 -24
  164. data/lib/rubygems/gem_commands.rb +0 -273
  165. data/pkgs/sources/sources-0.0.1.gem +0 -0
  166. data/post-install.rb +0 -121
  167. data/test/brokenbuildgem.rb +0 -35
  168. data/test/data/PostMessage-0.0.1.gem +0 -0
  169. data/test/data/a-0.0.1.gem +0 -0
  170. data/test/data/a-0.0.2.gem +0 -0
  171. data/test/data/b-0.0.2.gem +0 -0
  172. data/test/data/broken-1.0.0.gem +0 -0
  173. data/test/data/broken_build/broken-build.gemspec +0 -20
  174. data/test/data/broken_build/ext/extconf.rb +0 -3
  175. data/test/data/broken_build/ext/foo.c +0 -1
  176. data/test/data/c-1.2.gem +0 -0
  177. data/test/data/gemhome/cache/a-0.0.1.gem +0 -0
  178. data/test/data/gemhome/cache/a-0.0.2.gem +0 -0
  179. data/test/data/gemhome/cache/b-0.0.2.gem +0 -0
  180. data/test/data/gemhome/cache/c-1.2.gem +0 -0
  181. data/test/data/gemhome/gems/a-0.0.1/lib/code.rb +0 -1
  182. data/test/data/gemhome/gems/a-0.0.2/lib/code.rb +0 -1
  183. data/test/data/gemhome/gems/b-0.0.2/lib/code.rb +0 -1
  184. data/test/data/gemhome/gems/c-1.2/lib/code.rb +0 -1
  185. data/test/data/gemhome/specifications/a-0.0.1.gemspec +0 -8
  186. data/test/data/gemhome/specifications/a-0.0.2.gemspec +0 -8
  187. data/test/data/gemhome/specifications/b-0.0.2.gemspec +0 -8
  188. data/test/data/gemhome/specifications/c-1.2.gemspec +0 -8
  189. data/test/data/legacy/keyedlist-0.4.0.ruby +0 -11
  190. data/test/data/legacy/keyedlist-0.4.0.yaml +0 -16
  191. data/test/data/lib/code.rb +0 -1
  192. data/test/data/one/README.one +0 -1
  193. data/test/data/one/lib/one.rb +0 -9
  194. data/test/data/one/one-0.0.1.gem +0 -0
  195. data/test/data/one/one.gemspec +0 -17
  196. data/test/data/one/one.yaml +0 -40
  197. data/test/data/post_install.gemspec +0 -19
  198. data/test/functional_extension_gems.rb +0 -48
  199. data/test/functional_generate_yaml_index.rb +0 -104
  200. data/test/gemenvironment.rb +0 -59
  201. data/test/io_capture.rb +0 -33
  202. data/test/mock/gems/gems/sources-0.0.1/lib/sources.rb +0 -11
  203. data/test/mock/gems/specifications/sources-0.0.1.gemspec +0 -8
  204. data/test/onegem.rb +0 -35
  205. data/test/test_builder.rb +0 -34
  206. data/test/test_check_command.rb +0 -34
  207. data/test/test_configfile.rb +0 -42
  208. data/test/test_dependency_list.rb +0 -169
  209. data/test/test_file_list.rb +0 -101
  210. data/test/test_format.rb +0 -49
  211. data/test/test_gem_sources_command.rb +0 -135
  212. data/test/test_gemloadpaths.rb +0 -51
  213. data/test/test_gempaths.rb +0 -170
  214. data/test/test_installer.rb +0 -369
  215. data/test/test_loadmanager.rb +0 -48
  216. data/test/test_process_commands.rb +0 -52
  217. data/test/test_source_index.rb +0 -231
  218. data/test/test_specific_extras.rb +0 -46
  219. data/test/test_specification.rb +0 -565
  220. data/test/test_user_interaction.rb +0 -48
  221. data/test/test_validator.rb +0 -59
  222. data/test/test_version_comparison.rb +0 -321
  223. data/test/testgem.rc +0 -7
  224. data/test/user_capture.rb +0 -7
  225. data/test/yaml_data.rb +0 -63
@@ -0,0 +1,183 @@
1
+ #--
2
+ # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+ require 'fileutils'
8
+ require 'rubygems'
9
+ require 'rubygems/dependency_list'
10
+ require 'rubygems/doc_manager'
11
+ require 'rubygems/user_interaction'
12
+
13
+ ##
14
+ # An Uninstaller.
15
+ #
16
+ class Gem::Uninstaller
17
+
18
+ include Gem::UserInteraction
19
+
20
+ ##
21
+ # Constructs an Uninstaller instance
22
+ #
23
+ # gem:: [String] The Gem name to uninstall
24
+ #
25
+ def initialize(gem, options)
26
+ @gem = gem
27
+ @version = options[:version] || Gem::Requirement.default
28
+ @force_executables = options[:executables]
29
+ @force_all = options[:all]
30
+ @force_ignore = options[:ignore]
31
+ end
32
+
33
+ ##
34
+ # Performs the uninstall of the Gem. This removes the spec, the
35
+ # Gem directory, and the cached .gem file,
36
+ #
37
+ def uninstall
38
+ list = Gem.source_index.search(/^#{@gem}$/, @version)
39
+
40
+ if list.empty? then
41
+ raise Gem::InstallError, "Unknown gem #{@gem}-#{@version}"
42
+ elsif list.size > 1 && @force_all
43
+ remove_all(list.dup)
44
+ remove_executables(list.last)
45
+ elsif list.size > 1
46
+ say
47
+ gem_names = list.collect {|gem| gem.full_name} + ["All versions"]
48
+ gem_name, index =
49
+ choose_from_list("Select gem to uninstall:", gem_names)
50
+ if index == list.size
51
+ remove_all(list.dup)
52
+ remove_executables(list.last)
53
+ elsif index >= 0 && index < list.size
54
+ to_remove = list[index]
55
+ remove(to_remove, list)
56
+ remove_executables(to_remove)
57
+ else
58
+ say "Error: must enter a number [1-#{list.size+1}]"
59
+ end
60
+ else
61
+ remove(list[0], list.dup)
62
+ remove_executables(list.last)
63
+ end
64
+ end
65
+
66
+ ##
67
+ # Remove executables and batch files (windows only) for the gem as
68
+ # it is being installed
69
+ #
70
+ # gemspec::[Specification] the gem whose executables need to be removed.
71
+ #
72
+ def remove_executables(gemspec)
73
+ return if gemspec.nil?
74
+ if(gemspec.executables.size > 0)
75
+ raise Gem::FilePermissionError.new(Gem.bindir) unless
76
+ File.writable?(Gem.bindir)
77
+ list = Gem.source_index.search(gemspec.name).delete_if { |spec|
78
+ spec.version == gemspec.version
79
+ }
80
+ executables = gemspec.executables.clone
81
+ list.each do |spec|
82
+ spec.executables.each do |exe_name|
83
+ executables.delete(exe_name)
84
+ end
85
+ end
86
+ return if executables.size == 0
87
+ answer = @force_executables || ask_yes_no(
88
+ "Remove executables and scripts for\n" +
89
+ "'#{gemspec.executables.join(", ")}' in addition to the gem?",
90
+ true) # " # appease ruby-mode - don't ask
91
+ unless answer
92
+ say "Executables and scripts will remain installed."
93
+ return
94
+ else
95
+ gemspec.executables.each do |exe_name|
96
+ say "Removing #{exe_name}"
97
+ File.unlink File.join(Gem.bindir, exe_name) rescue nil
98
+ File.unlink File.join(Gem.bindir, exe_name + ".bat") rescue nil
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ #
105
+ # list:: the list of all gems to remove
106
+ #
107
+ # Warning: this method modifies the +list+ parameter. Once it has
108
+ # uninstalled a gem, it is removed from that list.
109
+ #
110
+ def remove_all(list)
111
+ list.dup.each { |gem| remove(gem, list) }
112
+ end
113
+
114
+ #
115
+ # spec:: the spec of the gem to be uninstalled
116
+ # list:: the list of all such gems
117
+ #
118
+ # Warning: this method modifies the +list+ parameter. Once it has
119
+ # uninstalled a gem, it is removed from that list.
120
+ #
121
+ def remove(spec, list)
122
+ unless ok_to_remove? spec then
123
+ raise Gem::DependencyRemovalException,
124
+ "Uninstallation aborted due to dependent gem(s)"
125
+ end
126
+
127
+ raise Gem::FilePermissionError, spec.installation_path unless
128
+ File.writable?(spec.installation_path)
129
+
130
+ FileUtils.rm_rf spec.full_gem_path
131
+
132
+ original_platform_name = [
133
+ spec.name, spec.version, spec.original_platform].join '-'
134
+
135
+ spec_dir = File.join spec.installation_path, 'specifications'
136
+ gemspec = File.join spec_dir, "#{spec.full_name}.gemspec"
137
+
138
+ unless File.exist? gemspec then
139
+ gemspec = File.join spec_dir, "#{original_platform_name}.gemspec"
140
+ end
141
+
142
+ FileUtils.rm_rf gemspec
143
+
144
+ cache_dir = File.join spec.installation_path, 'cache'
145
+ gem = File.join cache_dir, "#{spec.full_name}.gem"
146
+
147
+ unless File.exist? gemspec then
148
+ gem = File.join cache_dir, "#{original_platform_name}.gem"
149
+ end
150
+
151
+ FileUtils.rm_rf gem
152
+
153
+ Gem::DocManager.new(spec).uninstall_doc
154
+
155
+ say "Successfully uninstalled #{spec.full_name}"
156
+
157
+ list.delete spec
158
+ end
159
+
160
+ def ok_to_remove?(spec)
161
+ return true if @force_ignore
162
+
163
+ srcindex = Gem::SourceIndex.from_installed_gems
164
+ deplist = Gem::DependencyList.from_source_index srcindex
165
+ deplist.ok_to_remove?(spec.full_name) || ask_if_ok(spec)
166
+ end
167
+
168
+ def ask_if_ok(spec)
169
+ msg = ['']
170
+ msg << 'You have requested to uninstall the gem:'
171
+ msg << "\t#{spec.full_name}"
172
+ spec.dependent_gems.each do |gem,dep,satlist|
173
+ msg <<
174
+ ("#{gem.name}-#{gem.version} depends on " +
175
+ "[#{dep.name} (#{dep.version_requirements})]")
176
+ end
177
+ msg << 'If you remove this gems, one or more dependencies will not be met.'
178
+ msg << 'Continue with Uninstall?'
179
+ return ask_yes_no(msg.join("\n"), true)
180
+ end
181
+
182
+ end
183
+
@@ -81,6 +81,9 @@ module Gem
81
81
  ####################################################################
82
82
  # StreamUI implements a simple stream based user interface.
83
83
  class StreamUI
84
+
85
+ attr_reader :ins, :outs, :errs
86
+
84
87
  def initialize(in_stream, out_stream, err_stream=STDERR)
85
88
  @ins = in_stream
86
89
  @outs = out_stream
@@ -97,12 +100,28 @@ module Gem
97
100
  end
98
101
  @outs.print "> "
99
102
  @outs.flush
100
- result = @ins.gets.strip.to_i - 1
103
+
104
+ result = @ins.gets
105
+
106
+ return nil, nil unless result
107
+
108
+ result = result.strip.to_i - 1
101
109
  return list[result], result
102
110
  end
103
111
 
104
- # Ask a question. Returns a true for yes, false for no.
112
+ # Ask a question. Returns a true for yes, false for no. If not
113
+ # connected to a tty, raises an exception if default is nil,
114
+ # otherwise returns default.
105
115
  def ask_yes_no(question, default=nil)
116
+ if not @ins.tty? then
117
+ if default.nil? then
118
+ raise(
119
+ Gem::OperationNotSupportedError,
120
+ "Not connected to a tty and no default specified")
121
+ else
122
+ return default
123
+ end
124
+ end
106
125
  qstr = case default
107
126
  when nil
108
127
  'yn'
@@ -119,15 +138,19 @@ module Gem
119
138
  true
120
139
  when /^[Nn].*/
121
140
  false
122
- else
141
+ when /^$/
123
142
  default
143
+ else
144
+ nil
124
145
  end
125
146
  end
126
147
  return result
127
148
  end
128
149
 
129
- # Ask a question. Returns an answer.
150
+ # Ask a question. Returns an answer if connected to a tty, nil
151
+ # otherwise.
130
152
  def ask(question)
153
+ return nil if not @ins.tty?
131
154
  @outs.print(question + " ")
132
155
  @outs.flush
133
156
  result = @ins.gets
@@ -186,7 +209,7 @@ module Gem
186
209
  class SilentProgressReporter
187
210
  attr_reader :count
188
211
 
189
- def initialize(out_stream, size, initial_message)
212
+ def initialize(out_stream, size, initial_message, terminal_message = nil)
190
213
  end
191
214
 
192
215
  def updated(message)
@@ -201,10 +224,13 @@ module Gem
201
224
 
202
225
  attr_reader :count
203
226
 
204
- def initialize(out_stream, size, initial_message)
227
+ def initialize(out_stream, size, initial_message,
228
+ terminal_message = "complete")
205
229
  @out = out_stream
206
230
  @total = size
207
231
  @count = 0
232
+ @terminal_message = terminal_message
233
+
208
234
  @out.puts initial_message
209
235
  end
210
236
 
@@ -215,7 +241,7 @@ module Gem
215
241
  end
216
242
 
217
243
  def done
218
- @out.puts "\ncomplete"
244
+ @out.puts "\n#{@terminal_message}"
219
245
  end
220
246
  end
221
247
 
@@ -224,10 +250,13 @@ module Gem
224
250
 
225
251
  attr_reader :count
226
252
 
227
- def initialize(out_stream, size, initial_message)
253
+ def initialize(out_stream, size, initial_message,
254
+ terminal_message = 'complete')
228
255
  @out = out_stream
229
256
  @total = size
230
257
  @count = 0
258
+ @terminal_message = terminal_message
259
+
231
260
  @out.puts initial_message
232
261
  end
233
262
 
@@ -237,7 +266,7 @@ module Gem
237
266
  end
238
267
 
239
268
  def done
240
- @out.puts "complete"
269
+ @out.puts @terminal_message
241
270
  end
242
271
  end
243
272
  end
@@ -4,9 +4,13 @@
4
4
  # See LICENSE.txt for permissions.
5
5
  #++
6
6
 
7
- module Gem
7
+ require 'find'
8
+
9
+ require 'rubygems/digest/md5'
10
+ require 'rubygems/format'
11
+ require 'rubygems/installer'
8
12
 
9
- class VerificationError < Gem::Exception; end
13
+ module Gem
10
14
 
11
15
  ##
12
16
  # Validator performs various gem file and gem database validation
@@ -17,17 +21,19 @@ module Gem
17
21
  # Given a gem file's contents, validates against its own MD5 checksum
18
22
  # gem_data:: [String] Contents of the gem file
19
23
  def verify_gem(gem_data)
20
- if(gem_data.size == 0) then
21
- raise VerificationError.new("Empty Gem file")
22
- end
23
- require 'rubygems/digest/md5'
24
- unless(gem_data =~ /MD5SUM/m)
24
+ raise VerificationError, 'empty gem file' if gem_data.size == 0
25
+
26
+ unless gem_data =~ /MD5SUM/ then
25
27
  return # Don't worry about it...this sucks. Need to fix MD5 stuff for
26
28
  # new format
27
29
  # FIXME
28
30
  end
29
- unless (Gem::MD5.hexdigest(gem_data.gsub(/MD5SUM = "([a-z0-9]+)"/, "MD5SUM = \"" + ("F" * 32) + "\"")) == $1.to_s)
30
- raise VerificationError.new("Invalid checksum for Gem file")
31
+
32
+ sum_data = gem_data.gsub(/MD5SUM = "([a-z0-9]+)"/,
33
+ "MD5SUM = \"#{"F" * 32}\"")
34
+
35
+ unless Gem::MD5.hexdigest(sum_data) == $1.to_s then
36
+ raise VerificationError, 'invalid checksum for gem file'
31
37
  end
32
38
  end
33
39
 
@@ -36,14 +42,12 @@ module Gem
36
42
  #
37
43
  # gem_path:: [String] Path to gem file
38
44
  def verify_gem_file(gem_path)
39
- begin
40
- File.open(gem_path, 'rb') do |file|
41
- gem_data = file.read
42
- verify_gem(gem_data)
43
- end
44
- rescue Errno::ENOENT
45
- raise Gem::VerificationError.new("Missing gem file #{gem_path}")
45
+ File.open gem_path, 'rb' do |file|
46
+ gem_data = file.read
47
+ verify_gem gem_data
46
48
  end
49
+ rescue Errno::ENOENT
50
+ raise Gem::VerificationError.new("missing gem file #{gem_path}")
47
51
  end
48
52
 
49
53
  private
@@ -73,9 +77,6 @@ module Gem
73
77
  #
74
78
  # returns a hash of ErrorData objects, keyed on the problem gem's name.
75
79
  def alien
76
- require 'rubygems/installer'
77
- require 'find'
78
- require 'rubygems/digest/md5'
79
80
  errors = {}
80
81
  Gem::SourceIndex.from_installed_gems.each do |gem_name, gem_spec|
81
82
  errors[gem_name] ||= []
@@ -89,15 +90,18 @@ module Gem
89
90
  end
90
91
 
91
92
  begin
92
- require 'rubygems/format.rb'
93
93
  verify_gem_file(gem_path)
94
- File.open(gem_path) do |file|
94
+ File.open(gem_path, 'rb') do |file|
95
95
  format = Gem::Format.from_file_by_path(gem_path)
96
96
  format.file_entries.each do |entry, data|
97
97
  # Found this file. Delete it from list
98
98
  installed_files.delete remove_leading_dot_dir(entry['path'])
99
+
100
+ next unless data # HACK `gem check -a mkrf`
101
+
99
102
  File.open(File.join(gem_directory, entry['path']), 'rb') do |f|
100
- unless Gem::MD5.hexdigest(f.read).to_s == Gem::MD5.hexdigest(data).to_s
103
+ unless Gem::MD5.hexdigest(f.read).to_s ==
104
+ Gem::MD5.hexdigest(data).to_s then
101
105
  errors[gem_name] << ErrorData.new(entry['path'], "installed file doesn't match original from gem")
102
106
  end
103
107
  end
@@ -117,6 +121,32 @@ module Gem
117
121
  end
118
122
  errors
119
123
  end
124
+
125
+ class TestRunner
126
+ def initialize(suite, ui)
127
+ @suite = suite
128
+ @ui = ui
129
+ end
130
+
131
+ def self.run(suite, ui)
132
+ require 'test/unit/ui/testrunnermediator'
133
+ return new(suite, ui).start
134
+ end
135
+
136
+ def start
137
+ @mediator = Test::Unit::UI::TestRunnerMediator.new(@suite)
138
+ @mediator.add_listener(Test::Unit::TestResult::FAULT, &method(:add_fault))
139
+ return @mediator.run_suite
140
+ end
141
+
142
+ def add_fault(fault)
143
+ if Gem.configuration.verbose then
144
+ @ui.say fault.long_display
145
+ end
146
+ end
147
+ end
148
+
149
+ autoload :TestRunner, 'test/unit/ui/testrunnerutilities'
120
150
 
121
151
  ##
122
152
  # Runs unit tests for a given gem specification
@@ -132,12 +162,11 @@ module Gem
132
162
  end
133
163
  gem gem_spec.name, "= #{gem_spec.version.version}"
134
164
  test_files.each do |f| require f end
135
- require 'test/unit/ui/console/testrunner'
136
165
  suite = Test::Unit::TestSuite.new("#{gem_spec.name}-#{gem_spec.version}")
137
166
  ObjectSpace.each_object(Class) do |klass|
138
167
  suite << klass.suite if (klass < Test::Unit::TestCase)
139
168
  end
140
- result = Test::Unit::UI::Console::TestRunner.run(suite, Test::Unit::UI::SILENT)
169
+ result = TestRunner.run(suite, ui())
141
170
  unless result.passed?
142
171
  alert_error(result.to_s)
143
172
  #unless ask_yes_no(result.to_s + "...keep Gem?", true) then
@@ -4,318 +4,155 @@
4
4
  # See LICENSE.txt for permissions.
5
5
  #++
6
6
 
7
- module Gem
8
-
9
- ####################################################################
10
- # The Dependency class holds a Gem name and Version::Requirement
11
- #
12
- class Dependency
13
- attr_accessor :name
7
+ require 'rubygems'
14
8
 
15
- attr_writer :version_requirements
9
+ ##
10
+ # The Version class processes string versions into comparable values
11
+ class Gem::Version
16
12
 
17
- def <=>(other)
18
- [@name] <=> [other.name]
19
- end
20
-
21
- ##
22
- # Constructs the dependency
23
- #
24
- # name:: [String] name of the Gem
25
- # version_requirements:: [String Array] version requirement (e.g. ["> 1.2"])
26
- #
27
- def initialize(name, version_requirements)
28
- @name = name
29
- @version_requirements = Version::Requirement.new(version_requirements)
30
- @version_requirement = nil # Avoid warnings.
31
- end
13
+ include Comparable
14
+
15
+ attr_reader :ints
32
16
 
33
- def version_requirements
34
- normalize if defined? @version_requirement and @version_requirement
35
- @version_requirements
17
+ attr_reader :version
18
+
19
+ ##
20
+ # Checks if version string is valid format
21
+ #
22
+ # str:: [String] the version string
23
+ # return:: [Boolean] true if the string format is correct, otherwise false
24
+ #
25
+ def self.correct?(version)
26
+ case version
27
+ when Integer, /\A\s*(\d+(\.\d+)*)*\s*\z/ then true
28
+ else false
36
29
  end
30
+ end
37
31
 
38
- def requirement_list
39
- version_requirements.as_list
32
+ ##
33
+ # Factory method to create a Version object. Input may be a Version or a
34
+ # String. Intended to simplify client code.
35
+ #
36
+ # ver1 = Version.create('1.3.17') # -> (Version object)
37
+ # ver2 = Version.create(ver1) # -> (ver1)
38
+ # ver3 = Version.create(nil) # -> nil
39
+ #
40
+ def self.create(input)
41
+ if input.respond_to? :version then
42
+ input
43
+ elsif input.nil? then
44
+ nil
45
+ else
46
+ new input
40
47
  end
48
+ end
41
49
 
42
- alias requirements_list requirement_list
50
+ ##
51
+ # Constructs a version from the supplied string
52
+ #
53
+ # version:: [String] The version string. Format is digit.digit...
54
+ #
55
+ def initialize(version)
56
+ raise ArgumentError, "Malformed version number string #{version}" unless
57
+ self.class.correct?(version)
43
58
 
44
- def normalize
45
- ver = @version_requirement.instance_eval { @version }
46
- @version_requirements = Version::Requirement.new([ver])
47
- @version_requirement = nil
48
- end
59
+ self.version = version
60
+ end
49
61
 
50
- def to_s
51
- "#{name} (#{version_requirements})"
52
- end
62
+ def inspect # :nodoc:
63
+ "#<#{self.class} #{@version.inspect}>"
64
+ end
53
65
 
54
- def ==(other)
55
- other.kind_of?(self.class) &&
56
- self.name == other.name &&
57
- self.version_requirements == other.version_requirements
58
- end
66
+ # Dump only the raw version string, not the complete object
67
+ def marshal_dump
68
+ [@version]
69
+ end
59
70
 
60
- def hash
61
- name.hash + version_requirements.hash
62
- end
63
-
71
+ # Load custom marshal format
72
+ def marshal_load(array)
73
+ self.version = array[0]
64
74
  end
65
-
66
- ####################################################################
67
- # The Version class processes string versions into comparable values
68
- #
69
- class Version
70
- include Comparable
71
75
 
72
- # The originating definition of Requirement is left nested in
73
- # Version for compatibility. The full definition is given in
74
- # Gem::Requirement.
75
- class Requirement
76
- end
77
-
78
- attr_accessor :version
79
-
80
- NUM_RE = /\s*(\d+(\.\d+)*)*\s*/
81
-
82
- ##
83
- # Checks if version string is valid format
84
- #
85
- # str:: [String] the version string
86
- # return:: [Boolean] true if the string format is correct, otherwise false
87
- #
88
- def self.correct?(str)
89
- /^#{NUM_RE}$/.match(str)
90
- end
76
+ # Strip ignored trailing zeros.
77
+ def normalize
78
+ @ints = @version.to_s.scan(/\d+/).map { |s| s.to_i }
91
79
 
92
- ##
93
- # Factory method to create a Version object. Input may be a Version or a
94
- # String. Intended to simplify client code.
95
- #
96
- # ver1 = Version.create('1.3.17') # -> (Version object)
97
- # ver2 = Version.create(ver1) # -> (ver1)
98
- # ver3 = Version.create(nil) # -> nil
99
- #
100
- def self.create(input)
101
- if input.respond_to? :version
102
- return input
103
- elsif input.nil?
104
- return nil
105
- else
106
- return Version.new(input)
107
- end
108
- end
80
+ return if @ints.length == 1
109
81
 
110
- ##
111
- # Constructs a version from the supplied string
112
- #
113
- # version:: [String] The version string. Format is digit.digit...
114
- #
115
- def initialize(version)
116
- raise ArgumentError,
117
- "Malformed version number string #{version}" unless Version.correct?(version)
118
- @version = version
119
- end
120
-
121
- ##
122
- # Returns the text representation of the version
123
- #
124
- # return:: [String] version as string
125
- #
126
- def to_s
127
- @version
128
- end
129
-
130
- ##
131
- # Convert version to integer array
132
- #
133
- # return:: [Array] list of integers
134
- #
135
- def to_ints
136
- @version.scan(/\d+/).map {|s| s.to_i}
137
- end
138
-
139
- ##
140
- # Compares two versions
141
- #
142
- # other:: [Version or .to_ints] other version to compare to
143
- # return:: [Fixnum] -1, 0, 1
144
- #
145
- def <=>(other)
146
- return 1 unless other
147
- rnums, vnums = to_ints, other.to_ints
148
- [rnums.size, vnums.size].max.times {|i|
149
- rnums[i] ||= 0
150
- vnums[i] ||= 0
151
- }
152
-
153
- begin
154
- r,v = rnums.shift, vnums.shift
155
- end until (r != v || rnums.empty?)
82
+ @ints.pop while @ints.last == 0
156
83
 
157
- return r <=> v
158
- end
84
+ @ints = [0] if @ints.empty?
85
+ end
159
86
 
160
- def hash
161
- to_ints.inject { |hash_code, n| hash_code + n }
162
- end
87
+ ##
88
+ # Returns the text representation of the version
89
+ #
90
+ # return:: [String] version as string
91
+ #
92
+ def to_s
93
+ @version
94
+ end
163
95
 
164
- # Return a new version object where the next to the last revision
165
- # number is one greater. (e.g. 5.3.1 => 5.4)
166
- def bump
167
- ints = to_ints
168
- ints.pop if ints.size > 1
169
- ints[-1] += 1
170
- self.class.new(ints.join("."))
171
- end
172
-
96
+ ##
97
+ # Convert version to integer array
98
+ #
99
+ # return:: [Array] list of integers
100
+ #
101
+ def to_ints
102
+ normalize unless @ints
103
+ @ints
104
+ end
105
+
106
+ def to_yaml_properties
107
+ ['@version']
108
+ end
109
+
110
+ def version=(version)
111
+ @version = version.to_s.strip
112
+ normalize
173
113
  end
174
114
 
175
- # Class Requirement's original definition is nested in Version.
176
- # Although an probably inappropriate place, current gems specs
177
- # reference the nested class name explicitly. To remain compatible
178
- # with old software loading gemspecs, we leave the original
179
- # definition in Version, but define an alias Gem::Requirement for
180
- # use everywhere else.
181
- Requirement = ::Gem::Version::Requirement
115
+ def yaml_initialize(tag, values)
116
+ self.version = values['version']
117
+ end
182
118
 
183
- ##################################################################
184
- # Requirement version includes a prefaced comparator in addition
185
- # to a version number.
119
+ ##
120
+ # Compares two versions
186
121
  #
187
- # A Requirement object can actually contain multiple, er,
188
- # requirements, as in (> 1.2, < 2.0).
122
+ # other:: [Version or .ints] other version to compare to
123
+ # return:: [Fixnum] -1, 0, 1
189
124
  #
190
- class Requirement
191
- include Comparable
192
-
193
- OPS = {
194
- "=" => lambda { |v, r| v == r },
195
- "!=" => lambda { |v, r| v != r },
196
- ">" => lambda { |v, r| v > r },
197
- "<" => lambda { |v, r| v < r },
198
- ">=" => lambda { |v, r| v >= r },
199
- "<=" => lambda { |v, r| v <= r },
200
- "~>" => lambda { |v, r| v >= r && v < r.bump }
201
- }
202
-
203
- OP_RE = Regexp.new(OPS.keys.collect{|k| Regexp.quote(k)}.join("|"))
204
- REQ_RE = /\s*(#{OP_RE})\s*/
205
-
206
- ##
207
- # Factory method to create a Version::Requirement object. Input may be a
208
- # Version, a String, or nil. Intended to simplify client code.
209
- #
210
- # If the input is "weird", the default version requirement is returned.
211
- #
212
- def self.create(input)
213
- if input.kind_of?(Requirement)
214
- return input
215
- elsif input.kind_of?(Array)
216
- return self.new(input)
217
- elsif input.respond_to? :to_str
218
- return self.new([input.to_str])
219
- else
220
- return self.default
221
- end
222
- end
223
-
224
- ##
225
- # A default "version requirement" can surely _only_ be '> 0'.
226
- #
227
- def self.default
228
- self.new(['> 0.0.0'])
229
- end
230
-
231
- ##
232
- # Constructs a version requirement instance
233
- #
234
- # str:: [String Array] the version requirement string (e.g. ["> 1.23"])
235
- #
236
- def initialize(reqs)
237
- @requirements = reqs.collect do |rq|
238
- op, version_string = parse(rq)
239
- [op, Version.new(version_string)]
240
- end
241
- @version = nil # Avoid warnings.
242
- end
243
-
244
- ##
245
- # Overrides to check for comparator
246
- #
247
- # str:: [String] the version requirement string
248
- # return:: [Boolean] true if the string format is correct, otherwise false
249
- #
250
- # NOTE: Commented out because I don't think it is used.
251
- # def correct?(str)
252
- # /^#{REQ_RE}#{NUM_RE}$/.match(str)
253
- # end
254
-
255
- def to_s
256
- as_list.join(", ")
257
- end
258
-
259
- def as_list
260
- normalize
261
- @requirements.collect { |req|
262
- "#{req[0]} #{req[1]}"
263
- }
264
- end
265
-
266
- def normalize
267
- return if not defined? @version or @version.nil?
268
- @requirements = [parse(@version)]
269
- @nums = nil
270
- @version = nil
271
- @op = nil
272
- end
273
-
274
- ##
275
- # Is the requirement satifised by +version+.
276
- #
277
- # version:: [Gem::Version] the version to compare against
278
- # return:: [Boolean] true if this requirement is satisfied by
279
- # the version, otherwise false
280
- #
281
- def satisfied_by?(version)
282
- normalize
283
- @requirements.all? { |op, rv| satisfy?(op, version, rv) }
284
- end
285
-
286
- private
287
-
288
- ##
289
- # Is "version op required_version" satisfied?
290
- #
291
- def satisfy?(op, version, required_version)
292
- OPS[op].call(version, required_version)
293
- end
294
-
295
- ##
296
- # Parse the version requirement string. Return the operator and
297
- # version strings.
298
- #
299
- def parse(str)
300
- if md = /^\s*(#{OP_RE})\s*([0-9.]+)\s*$/.match(str)
301
- [md[1], md[2]]
302
- elsif md = /^\s*([0-9.]+)\s*$/.match(str)
303
- ["=", md[1]]
304
- elsif md = /^\s*(#{OP_RE})\s*$/.match(str)
305
- [md[1], "0"]
306
- else
307
- fail ArgumentError, "Illformed requirement [#{str}]"
308
- end
309
- end
310
-
311
- def <=>(other)
312
- to_s <=> other.to_s
313
- end
125
+ def <=>(other)
126
+ return 1 unless other
127
+ @ints <=> other.ints
128
+ end
314
129
 
315
- def hash
316
- to_s.hash
317
- end
318
- public :hash
130
+ def hash
131
+ to_ints.inject { |hash_code, n| hash_code + n }
132
+ end
133
+
134
+ # Return a new version object where the next to the last revision
135
+ # number is one greater. (e.g. 5.3.1 => 5.4)
136
+ def bump
137
+ ints = @ints.dup
138
+ ints.pop if ints.size > 1
139
+ ints[-1] += 1
140
+ self.class.new(ints.join("."))
319
141
  end
320
-
142
+
143
+ #:stopdoc:
144
+
145
+ require 'rubygems/requirement'
146
+
147
+ # Gem::Requirement's original definition is nested in Version.
148
+ # Although an inappropriate place, current gems specs reference the nested
149
+ # class name explicitly. To remain compatible with old software loading
150
+ # gemspecs, we leave a copy of original definition in Version, but define an
151
+ # alias Gem::Requirement for use everywhere else.
152
+
153
+ Requirement = ::Gem::Requirement
154
+
155
+ # :startdoc:
156
+
321
157
  end
158
+