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,48 @@
1
+ require 'rubygems/indexer'
2
+
3
+ # Construct a quick index file and all of the individual specs to support
4
+ # incremental loading.
5
+ class Gem::Indexer::QuickIndexBuilder < Gem::Indexer::AbstractIndexBuilder
6
+
7
+ def initialize(filename, directory)
8
+ directory = File.join directory, 'quick'
9
+
10
+ super filename, directory
11
+ end
12
+
13
+ def cleanup
14
+ super
15
+
16
+ quick_index_file = File.join(@directory, @filename)
17
+ compress quick_index_file
18
+
19
+ # the complete quick index is in a directory, so move it as a whole
20
+ @files.delete quick_index_file
21
+ @files << @directory
22
+ end
23
+
24
+ def add(spec)
25
+ @file.puts spec.original_name
26
+ add_yaml(spec)
27
+ add_marshal(spec)
28
+ end
29
+
30
+ def add_yaml(spec)
31
+ fn = File.join @directory, "#{spec.original_name}.gemspec.rz"
32
+ zipped = zip spec.to_yaml
33
+ File.open fn, "wb" do |gsfile| gsfile.write zipped end
34
+ end
35
+
36
+ def add_marshal(spec)
37
+ # HACK why does this not work in #initialize?
38
+ FileUtils.mkdir_p File.join(@directory, "Marshal.#{Gem.marshal_version}")
39
+
40
+ fn = File.join @directory, "Marshal.#{Gem.marshal_version}",
41
+ "#{spec.original_name}.gemspec.rz"
42
+
43
+ zipped = zip Marshal.dump(spec)
44
+ File.open fn, "wb" do |gsfile| gsfile.write zipped end
45
+ end
46
+
47
+ end
48
+
@@ -0,0 +1,87 @@
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 'rubygems'
8
+ require 'rubygems/security'
9
+
10
+ ##
11
+ # Mixin methods for install and update options for Gem::Commands
12
+ module Gem::InstallUpdateOptions
13
+
14
+ # Add the install/update options to the option parser.
15
+ def add_install_update_options
16
+ OptionParser.accept Gem::Security::Policy do |value|
17
+ value = Gem::Security::Policies[value]
18
+ raise OptionParser::InvalidArgument, value if value.nil?
19
+ value
20
+ end
21
+
22
+ add_option(:"Install/Update", '-i', '--install-dir DIR',
23
+ 'Gem repository directory to get installed',
24
+ 'gems') do |value, options|
25
+ options[:install_dir] = File.expand_path(value)
26
+ end
27
+
28
+ add_option(:"Install/Update", '-d', '--[no-]rdoc',
29
+ 'Generate RDoc documentation for the gem on',
30
+ 'install') do |value, options|
31
+ options[:generate_rdoc] = value
32
+ end
33
+
34
+ add_option(:"Install/Update", '--[no-]ri',
35
+ 'Generate RI documentation for the gem on',
36
+ 'install') do |value, options|
37
+ options[:generate_ri] = value
38
+ end
39
+
40
+ add_option(:"Install/Update", '-E', '--env-shebang',
41
+ "Rewrite the shebang line on installed",
42
+ "scripts to use /usr/bin/env") do |value, options|
43
+ options[:env_shebang] = value
44
+ end
45
+
46
+ add_option(:"Install/Update", '-f', '--[no-]force',
47
+ 'Force gem to install, bypassing dependency',
48
+ 'checks') do |value, options|
49
+ options[:force] = value
50
+ end
51
+
52
+ add_option(:"Install/Update", '-t', '--[no-]test',
53
+ 'Run unit tests prior to installation') do |value, options|
54
+ options[:test] = value
55
+ end
56
+
57
+ add_option(:"Install/Update", '-w', '--[no-]wrappers',
58
+ 'Use bin wrappers for executables',
59
+ 'Not available on dosish platforms') do |value, options|
60
+ options[:wrappers] = value
61
+ end
62
+
63
+ add_option(:"Install/Update", '-P', '--trust-policy POLICY',
64
+ Gem::Security::Policy,
65
+ 'Specify gem trust policy') do |value, options|
66
+ options[:security_policy] = value
67
+ end
68
+
69
+ add_option(:"Install/Update", '--ignore-dependencies',
70
+ 'Do not install any required dependent gems') do |value, options|
71
+ options[:ignore_dependencies] = value
72
+ end
73
+
74
+ add_option(:"Install/Update", '-y', '--include-dependencies',
75
+ 'Unconditionally install the required',
76
+ 'dependent gems') do |value, options|
77
+ options[:include_dependencies] = value
78
+ end
79
+ end
80
+
81
+ # Default options for the gem install command.
82
+ def install_update_defaults_str
83
+ '--rdoc --no-force --no-test --wrappers'
84
+ end
85
+
86
+ end
87
+
@@ -7,661 +7,415 @@
7
7
  require 'fileutils'
8
8
  require 'pathname'
9
9
  require 'rbconfig'
10
+
10
11
  require 'rubygems/format'
11
- require 'rubygems/dependency_list'
12
+ require 'rubygems/ext'
12
13
 
13
- class Gem::InstallError < Gem::Exception; end
14
+ ##
15
+ # The installer class processes RubyGem .gem files and installs the
16
+ # files contained in the .gem into the Gem.path.
17
+ #
18
+ # Gem::Installer does the work of putting files in all the right places on the
19
+ # filesystem including unpacking the gem into its gem dir, installing the
20
+ # gemspec in the specifications dir, storing the cached gem in the cache dir,
21
+ # and installing either wrappers or symlinks for executables.
22
+ class Gem::Installer
14
23
 
15
- module Gem
24
+ ##
25
+ # Raised when there is an error while building extensions.
26
+ #
27
+ class ExtensionBuildError < Gem::InstallError; end
16
28
 
17
- class DependencyRemovalException < Gem::Exception; end
29
+ include Gem::UserInteraction
18
30
 
19
31
  ##
20
- # The installer class processes RubyGem .gem files and installs the
21
- # files contained in the .gem into the Gem.path.
32
+ # Constructs an Installer instance that will install the gem located at
33
+ # +gem+. +options+ is a Hash with the following keys:
22
34
  #
23
- class Installer
24
-
25
- ##
26
- # Raised when there is an error while building extensions.
27
- #
28
- class ExtensionBuildError < Gem::InstallError; end
29
-
30
- include UserInteraction
31
-
32
- ##
33
- # Constructs an Installer instance
34
- #
35
- # gem:: [String] The file name of the gem
36
- #
37
- def initialize(gem, options={})
38
- @gem = gem
39
- @options = options
40
- end
41
-
42
- ##
43
- # Installs the gem in the Gem.path. This will fail (unless
44
- # force=true) if a Gem has a requirement on another Gem that is
45
- # not installed. The installation will install in the following
46
- # structure:
47
- #
48
- # Gem.path/
49
- # specifications/<gem-version>.gemspec #=> the extracted YAML gemspec
50
- # gems/<gem-version>/... #=> the extracted Gem files
51
- # cache/<gem-version>.gem #=> a cached copy of the installed Gem
52
- #
53
- # force:: [default = false] if false will fail if a required Gem is not
54
- # installed, or if the Ruby version is too low for the gem
55
- # install_dir:: [default = Gem.dir] directory that Gem is to be installed in
56
- #
57
- # return:: [Gem::Specification] The specification for the newly installed
58
- # Gem.
59
- #
60
- def install(force=false, install_dir=Gem.dir, ignore_this_parameter=false)
61
- # if we're forcing the install, then disable security, _unless_
62
- # the security policy says that we only install singed gems
63
- # (this includes Gem::Security::HighSecurity)
64
- security_policy = @options[:security_policy]
65
- security_policy = nil if force && security_policy && security_policy.only_signed != true
35
+ # :env_shebang:: Use /usr/bin/env in bin wrappers.
36
+ # :force:: Overrides all version checks and security policy checks, except
37
+ # for a signed-gems-only policy.
38
+ # :ignore_dependencies:: Don't raise if a dependency is missing.
39
+ # :install_dir:: The directory to install the gem into.
40
+ # :security_policy:: Use the specified security policy. See Gem::Security
41
+ # :wrappers:: Install wrappers if true, symlinks if false.
42
+ def initialize(gem, options={})
43
+ @gem = gem
44
+
45
+ options = { :force => false, :install_dir => Gem.dir }.merge options
46
+
47
+ @env_shebang = options[:env_shebang]
48
+ @force = options[:force]
49
+ gem_home = options[:install_dir]
50
+ @gem_home = Pathname.new(gem_home).expand_path
51
+ @ignore_dependencies = options[:ignore_dependencies]
52
+ @security_policy = options[:security_policy]
53
+ @wrappers = options[:wrappers]
54
+
55
+ begin
56
+ @format = Gem::Format.from_file_by_path @gem, @security_policy
57
+ rescue Gem::Package::FormatError
58
+ raise Gem::InstallError, "invalid gem format for #{@gem}"
59
+ end
60
+
61
+ @spec = @format.spec
62
+
63
+ @gem_dir = File.join(@gem_home, "gems", @spec.full_name).untaint
64
+ end
66
65
 
67
- begin
68
- format = Gem::Format.from_file_by_path @gem, security_policy
69
- rescue Gem::Package::FormatError
70
- raise Gem::InstallError, "invalid gem format for #{@gem}"
66
+ ##
67
+ # Installs the gem and returns a loaded Gem::Specification for the installed
68
+ # gem.
69
+ #
70
+ # The gem will be installed with the following structure:
71
+ #
72
+ # @gem_home/
73
+ # cache/<gem-version>.gem #=> a cached copy of the installed gem
74
+ # gems/<gem-version>/... #=> extracted files
75
+ # specifications/<gem-version>.gemspec #=> the Gem::Specification
76
+ def install
77
+ # If we're forcing the install then disable security unless the security
78
+ # policy says that we only install singed gems.
79
+ @security_policy = nil if @force and @security_policy and
80
+ not @security_policy.only_signed
81
+
82
+ unless @force then
83
+ if rrv = @spec.required_ruby_version then
84
+ unless rrv.satisfied_by? Gem::Version.new(RUBY_VERSION) then
85
+ raise Gem::InstallError, "#{@spec.name} requires Ruby version #{rrv}"
86
+ end
71
87
  end
72
- unless force
73
- spec = format.spec
74
- # Check the Ruby version.
75
- if (rrv = spec.required_ruby_version)
76
- unless rrv.satisfied_by?(Gem::Version.new(RUBY_VERSION))
77
- raise Gem::InstallError, "#{spec.name} requires Ruby version #{rrv}"
78
- end
88
+
89
+ if rrgv = @spec.required_rubygems_version then
90
+ unless rrgv.satisfied_by? Gem::Version.new(Gem::RubyGemsVersion) then
91
+ raise Gem::InstallError,
92
+ "#{@spec.name} requires RubyGems version #{rrgv}"
79
93
  end
80
- unless @options[:ignore_dependencies]
81
- spec.dependencies.each do |dep_gem|
82
- ensure_dependency!(spec, dep_gem)
83
- end
94
+ end
95
+
96
+ unless @ignore_dependencies then
97
+ @spec.dependencies.each do |dep_gem|
98
+ ensure_dependency @spec, dep_gem
84
99
  end
85
100
  end
101
+ end
86
102
 
87
- raise Gem::FilePermissionError.new(Pathname.new(install_dir).expand_path) unless File.writable?(install_dir)
103
+ FileUtils.mkdir_p @gem_home unless File.directory? @gem_home
104
+ raise Gem::FilePermissionError, @gem_home unless File.writable? @gem_home
88
105
 
89
- # Build spec dir.
90
- @directory = File.join(install_dir, "gems", format.spec.full_name).untaint
91
- FileUtils.mkdir_p @directory
106
+ Gem.ensure_gem_subdirectories @gem_home
92
107
 
93
- extract_files(@directory, format)
94
- generate_bin(format.spec, install_dir)
95
- build_extensions(@directory, format.spec)
108
+ FileUtils.mkdir_p @gem_dir
96
109
 
97
- # Build spec/cache/doc dir.
98
- build_support_directories(install_dir)
110
+ extract_files
111
+ generate_bin
112
+ build_extensions
113
+ write_spec
99
114
 
100
- # Write the spec and cache files.
101
- write_spec(format.spec, File.join(install_dir, "specifications"))
102
- unless File.exist? File.join(install_dir, "cache", @gem.split(/\//).pop)
103
- FileUtils.cp @gem, File.join(install_dir, "cache")
104
- end
115
+ # HACK remove? Isn't this done in multiple places?
116
+ cached_gem = File.join @gem_home, "cache", @gem.split(/\//).pop
117
+ unless File.exist? cached_gem then
118
+ FileUtils.cp @gem, File.join(@gem_home, "cache")
119
+ end
105
120
 
106
- puts format.spec.post_install_message unless format.spec.post_install_message.nil?
121
+ say @spec.post_install_message unless @spec.post_install_message.nil?
107
122
 
108
- format.spec.loaded_from = File.join(install_dir, 'specifications', format.spec.full_name+".gemspec")
109
- return format.spec
110
- rescue Zlib::GzipFile::Error
111
- raise InstallError, "gzip error installing #{@gem}"
112
- end
123
+ @spec.loaded_from = File.join(@gem_home, 'specifications',
124
+ "#{@spec.full_name}.gemspec")
113
125
 
114
- ##
115
- # Ensure that the dependency is satisfied by the current
116
- # installation of gem. If it is not, then fail (i.e. throw and
117
- # exception).
118
- #
119
- # spec :: Gem::Specification
120
- # dependency :: Gem::Dependency
121
- def ensure_dependency!(spec, dependency)
122
- raise Gem::InstallError, "#{spec.name} requires #{dependency.name} #{dependency.version_requirements} " unless
123
- installation_satisfies_dependency?(dependency)
124
- end
126
+ return @spec
127
+ rescue Zlib::GzipFile::Error
128
+ raise Gem::InstallError, "gzip error installing #{@gem}"
129
+ end
125
130
 
126
- ##
127
- # True if the current installed gems satisfy the given dependency.
128
- #
129
- # dependency :: Gem::Dependency
130
- def installation_satisfies_dependency?(dependency)
131
- current_index = SourceIndex.from_installed_gems
132
- current_index.find_name(dependency.name, dependency.version_requirements).size > 0
131
+ ##
132
+ # Ensure that the dependency is satisfied by the current installation of
133
+ # gem. If it is not an exception is raised.
134
+ #
135
+ # spec :: Gem::Specification
136
+ # dependency :: Gem::Dependency
137
+ def ensure_dependency(spec, dependency)
138
+ unless installation_satisfies_dependency? dependency then
139
+ raise Gem::InstallError, "#{spec.name} requires #{dependency}"
133
140
  end
134
141
 
135
- ##
136
- # Unpacks the gem into the given directory.
137
- #
138
- def unpack(directory)
139
- format = Gem::Format.from_file_by_path(@gem, @options[:security_policy])
140
- extract_files(directory, format)
141
- end
142
+ true
143
+ end
142
144
 
143
- ##
144
- # Given a root gem directory, build supporting directories for gem
145
- # if they do not already exist
146
- def build_support_directories(install_dir)
147
- unless File.exist? File.join(install_dir, "specifications")
148
- FileUtils.mkdir_p File.join(install_dir, "specifications")
149
- end
150
- unless File.exist? File.join(install_dir, "cache")
151
- FileUtils.mkdir_p File.join(install_dir, "cache")
152
- end
153
- unless File.exist? File.join(install_dir, "doc")
154
- FileUtils.mkdir_p File.join(install_dir, "doc")
155
- end
156
- end
145
+ ##
146
+ # True if the current installed gems satisfy the given dependency.
147
+ #
148
+ # dependency :: Gem::Dependency
149
+ def installation_satisfies_dependency?(dependency)
150
+ current_index = Gem::SourceIndex.from_installed_gems
151
+ current_index.find_name(dependency.name, dependency.version_requirements).size > 0
152
+ end
157
153
 
158
- ##
159
- # Writes the .gemspec specification (in Ruby) to the supplied
160
- # spec_path.
161
- #
162
- # spec:: [Gem::Specification] The Gem specification to output
163
- # spec_path:: [String] The location (path) to write the gemspec to
164
- #
165
- def write_spec(spec, spec_path)
166
- rubycode = spec.to_ruby
167
- file_name = File.join(spec_path, spec.full_name+".gemspec").untaint
168
- File.open(file_name, "w") do |file|
169
- file.puts rubycode
170
- end
171
- end
154
+ ##
155
+ # Unpacks the gem into the given directory.
156
+ #
157
+ def unpack(directory)
158
+ @gem_dir = directory
159
+ @format = Gem::Format.from_file_by_path @gem, @security_policy
160
+ extract_files
161
+ end
172
162
 
173
- ##
174
- # Creates windows .cmd files for easy running of commands
175
- #
176
- def generate_windows_script(bindir, filename)
177
- if Config::CONFIG["arch"] =~ /dos|win32/i
178
- script_name = filename + ".cmd"
179
- File.open(File.join(bindir, File.basename(script_name)), "w") do |file|
180
- file.puts "@#{Gem.ruby} \"#{File.join(bindir,filename)}\" %*"
181
- end
182
- end
183
- end
163
+ ##
164
+ # Writes the .gemspec specification (in Ruby) to the supplied
165
+ # spec_path.
166
+ #
167
+ # spec:: [Gem::Specification] The Gem specification to output
168
+ # spec_path:: [String] The location (path) to write the gemspec to
169
+ #
170
+ def write_spec
171
+ rubycode = @spec.to_ruby
184
172
 
185
- def generate_bin(spec, install_dir=Gem.dir)
186
- return unless spec.executables && ! spec.executables.empty?
187
-
188
- # If the user has asked for the gem to be installed in
189
- # a directory that is the system gem directory, then
190
- # use the system bin directory, else create (or use) a
191
- # new bin dir under the install_dir.
192
- bindir = Gem.bindir(install_dir)
193
-
194
- Dir.mkdir bindir unless File.exist? bindir
195
- raise Gem::FilePermissionError.new(bindir) unless File.writable?(bindir)
196
-
197
- spec.executables.each do |filename|
198
- if @options[:wrappers] then
199
- generate_bin_script spec, filename, bindir, install_dir
200
- else
201
- generate_bin_symlink spec, filename, bindir, install_dir
202
- end
203
- end
173
+ file_name = File.join @gem_home, 'specifications',
174
+ "#{@spec.full_name}.gemspec"
175
+ file_name.untaint
176
+
177
+ File.open(file_name, "w") do |file|
178
+ file.puts rubycode
204
179
  end
180
+ end
205
181
 
206
- ##
207
- # Creates the scripts to run the applications in the gem.
208
- #
209
- def generate_bin_script(spec, filename, bindir, install_dir)
210
- File.open(File.join(bindir, File.basename(filename)), "w", 0755) do |file|
211
- file.print app_script_text(spec, install_dir, filename)
182
+ ##
183
+ # Creates windows .bat files for easy running of commands
184
+ #
185
+ def generate_windows_script(bindir, filename)
186
+ if Gem.win_platform? then
187
+ script_name = filename + ".bat"
188
+ File.open(File.join(bindir, File.basename(script_name)), "w") do |file|
189
+ file.puts windows_stub_script(bindir, filename)
212
190
  end
213
- generate_windows_script bindir, filename
214
191
  end
192
+ end
215
193
 
216
- ##
217
- # Creates the symlinks to run the applications in the gem. Moves
218
- # the symlink if the gem being installed has a newer version.
219
- #
220
- def generate_bin_symlink(spec, filename, bindir, install_dir)
221
- if Config::CONFIG["arch"] =~ /dos|win32/i then
222
- warn "Unable to use symlinks on win32, installing wrapper"
223
- generate_bin_script spec, filename, bindir, install_dir
224
- return
225
- end
194
+ def generate_bin
195
+ return if @spec.executables.nil? or @spec.executables.empty?
226
196
 
227
- src = File.join @directory, 'bin', filename
228
- dst = File.join bindir, File.basename(filename)
197
+ # If the user has asked for the gem to be installed in a directory that is
198
+ # the system gem directory, then use the system bin directory, else create
199
+ # (or use) a new bin dir under the gem_home.
200
+ bindir = Gem.bindir @gem_home
229
201
 
230
- if File.exist? dst then
231
- if File.symlink? dst then
232
- link = File.readlink(dst).split File::SEPARATOR
233
- cur_version = Gem::Version.create(link[-3].sub(/^.*-/, ''))
234
- return if spec.version < cur_version
235
- end
236
- File.unlink dst
202
+ Dir.mkdir bindir unless File.exist? bindir
203
+ raise Gem::FilePermissionError.new(bindir) unless File.writable? bindir
204
+
205
+ @spec.executables.each do |filename|
206
+ filename.untaint
207
+ bin_path = File.join @gem_dir, 'bin', filename
208
+ mode = File.stat(bin_path).mode | 0111
209
+ File.chmod mode, bin_path
210
+
211
+ if @wrappers then
212
+ generate_bin_script filename, bindir
213
+ else
214
+ generate_bin_symlink filename, bindir
237
215
  end
216
+ end
217
+ end
238
218
 
239
- File.symlink src, dst
219
+ ##
220
+ # Creates the scripts to run the applications in the gem.
221
+ #--
222
+ # The Windows script is generated in addition to the regular one due to a
223
+ # bug or misfeature in the Windows shell's pipe. See
224
+ # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/193379
225
+ #
226
+ def generate_bin_script(filename, bindir)
227
+ File.open(File.join(bindir, File.basename(filename)), "w", 0755) do |file|
228
+ file.print app_script_text(filename)
240
229
  end
230
+ generate_windows_script bindir, filename
231
+ end
241
232
 
242
- def shebang(spec, install_dir, bin_file_name)
243
- if @options[:env_shebang]
244
- shebang_env
245
- else
246
- shebang_default(spec, install_dir, bin_file_name)
233
+ ##
234
+ # Creates the symlinks to run the applications in the gem. Moves
235
+ # the symlink if the gem being installed has a newer version.
236
+ #
237
+ def generate_bin_symlink(filename, bindir)
238
+ if Config::CONFIG["arch"] =~ /dos|win32/i then
239
+ alert_warning "Unable to use symlinks on win32, installing wrapper"
240
+ generate_bin_script filename, bindir
241
+ return
242
+ end
243
+
244
+ src = File.join @gem_dir, 'bin', filename
245
+ dst = File.join bindir, File.basename(filename)
246
+
247
+ if File.exist? dst then
248
+ if File.symlink? dst then
249
+ link = File.readlink(dst).split File::SEPARATOR
250
+ cur_version = Gem::Version.create(link[-3].sub(/^.*-/, ''))
251
+ return if @spec.version < cur_version
247
252
  end
253
+ File.unlink dst
248
254
  end
249
255
 
250
- def shebang_default(spec, install_dir, bin_file_name)
251
- path = File.join(install_dir, "gems", spec.full_name, spec.bindir, bin_file_name)
256
+ File.symlink src, dst
257
+ end
258
+
259
+ ##
260
+ # Generates a #! line for +bin_file_name+'s wrapper copying arguments if
261
+ # necessary.
262
+ def shebang(bin_file_name)
263
+ if @env_shebang then
264
+ "#!/usr/bin/env ruby"
265
+ else
266
+ path = File.join @gem_dir, @spec.bindir, bin_file_name
267
+
252
268
  File.open(path, "rb") do |file|
253
- first_line = file.readlines("\n").first
254
- path_to_ruby = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
255
- if first_line =~ /^#!/
269
+ first_line = file.gets
270
+ if first_line =~ /^#!/ then
256
271
  # Preserve extra words on shebang line, like "-w". Thanks RPA.
257
- shebang = first_line.sub(/\A\#!\s*\S*ruby\S*/, "#!" + path_to_ruby)
272
+ shebang = first_line.sub(/\A\#!.*?ruby\S*/, "#!#{Gem.ruby}")
258
273
  else
259
274
  # Create a plain shebang line.
260
- shebang = "#!" + path_to_ruby
275
+ shebang = "#!#{Gem.ruby}"
261
276
  end
262
- return shebang.strip # Avoid nasty ^M issues.
263
- end
264
- end
265
277
 
266
- def shebang_env
267
- return "#!/usr/bin/env ruby"
278
+ shebang.strip # Avoid nasty ^M issues.
279
+ end
268
280
  end
281
+ end
269
282
 
270
- # Return the text for an application file.
271
- def app_script_text(spec, install_dir, filename)
272
- text = <<-TEXT
273
- #{shebang(spec, install_dir, filename)}
283
+ # Return the text for an application file.
284
+ def app_script_text(bin_file_name)
285
+ <<-TEXT
286
+ #{shebang bin_file_name}
274
287
  #
275
288
  # This file was generated by RubyGems.
276
289
  #
277
- # The application '#{spec.name}' is installed as part of a gem, and
278
- # this file is here to facilitate running it.
290
+ # The application '#{@spec.name}' is installed as part of a gem, and
291
+ # this file is here to facilitate running it.
279
292
  #
280
293
 
281
294
  require 'rubygems'
282
- version = "> 0"
295
+
296
+ version = "#{Gem::Requirement.default}"
297
+
283
298
  if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
284
299
  version = $1
285
300
  ARGV.shift
286
301
  end
287
- gem '#{spec.name}', version
288
- load '#{filename}'
302
+
303
+ gem '#{@spec.name}', version
304
+ load '#{bin_file_name}'
289
305
  TEXT
290
- text
291
- end
306
+ end
292
307
 
293
- def build_extensions(directory, spec)
294
- return unless spec.extensions.size > 0
295
- say "Building native extensions. This could take a while..."
296
- start_dir = Dir.pwd
297
- dest_path = File.join(directory, spec.require_paths[0])
298
- ran_rake = false # only run rake once
299
-
300
- spec.extensions.each do |extension|
301
- break if ran_rake
302
- results = []
303
-
304
- case extension
305
- when /extconf/ then
306
- builder = ExtExtConfBuilder
307
- when /configure/ then
308
- builder = ExtConfigureBuilder
309
- when /rakefile/i, /mkrf_conf/i then
310
- builder = ExtRakeBuilder
311
- ran_rake = true
312
- else
313
- builder = nil
314
- results = ["No builder for extension '#{extension}'"]
315
- end
308
+ # return the stub script text used to launch the true ruby script
309
+ def windows_stub_script(bindir, bin_file_name)
310
+ <<-TEXT
311
+ @ECHO OFF
312
+ IF NOT "%~f0" == "~f0" GOTO :WinNT
313
+ @"#{Gem.ruby}" "#{File.join(bindir, bin_file_name)}" %1 %2 %3 %4 %5 %6 %7 %8 %9
314
+ GOTO :EOF
315
+ :WinNT
316
+ "%~dp0ruby.exe" "%~dpn0" %*
317
+ TEXT
318
+ end
316
319
 
317
- begin
318
- Dir.chdir File.join(directory, File.dirname(extension))
319
- results = builder.build(extension, directory, dest_path, results)
320
- rescue => ex
321
- results = results.join "\n"
320
+ # Builds extensions. Valid types of extensions are extconf.rb files,
321
+ # configure scripts and rakefiles or mkrf_conf files.
322
+ def build_extensions
323
+ return if @spec.extensions.empty?
324
+ say "Building native extensions. This could take a while..."
325
+ start_dir = Dir.pwd
326
+ dest_path = File.join @gem_dir, @spec.require_paths.first
327
+ ran_rake = false # only run rake once
328
+
329
+ @spec.extensions.each do |extension|
330
+ break if ran_rake
331
+ results = []
332
+
333
+ builder = case extension
334
+ when /extconf/ then
335
+ Gem::Ext::ExtConfBuilder
336
+ when /configure/ then
337
+ Gem::Ext::ConfigureBuilder
338
+ when /rakefile/i, /mkrf_conf/i then
339
+ ran_rake = true
340
+ Gem::Ext::RakeBuilder
341
+ else
342
+ results = ["No builder for extension '#{extension}'"]
343
+ nil
344
+ end
322
345
 
323
- File.open('gem_make.out', 'wb') { |f| f.puts results }
346
+ begin
347
+ Dir.chdir File.join(@gem_dir, File.dirname(extension))
348
+ results = builder.build(extension, @gem_dir, dest_path, results)
349
+ rescue => ex
350
+ results = results.join "\n"
324
351
 
325
- message = <<-EOF
352
+ File.open('gem_make.out', 'wb') { |f| f.puts results }
353
+
354
+ message = <<-EOF
326
355
  ERROR: Failed to build gem native extension.
327
356
 
328
357
  #{results}
329
358
 
330
- Gem files will remain installed in #{directory} for inspection.
359
+ Gem files will remain installed in #{@gem_dir} for inspection.
331
360
  Results logged to #{File.join(Dir.pwd, 'gem_make.out')}
332
- EOF
361
+ EOF
333
362
 
334
- raise ExtensionBuildError, message
335
- ensure
336
- Dir.chdir start_dir
337
- end
338
- end
339
- end
340
-
341
- ##
342
- # Reads the YAML file index and then extracts each file
343
- # into the supplied directory, building directories for the
344
- # extracted files as needed.
345
- #
346
- # directory:: [String] The root directory to extract files into
347
- # file:: [IO] The IO that contains the file data
348
- #
349
- def extract_files(directory, format)
350
- directory = expand_and_validate(directory)
351
- raise ArgumentError, "format required to extract from" if format.nil?
352
-
353
- format.file_entries.each do |entry, file_data|
354
- path = entry['path'].untaint
355
- if path =~ /\A\// then # for extra sanity
356
- raise Gem::InstallError,
357
- "attempt to install file into #{entry['path'].inspect}"
358
- end
359
- path = File.expand_path File.join(directory, path)
360
- if path !~ /\A#{Regexp.escape directory}/ then
361
- msg = "attempt to install file into %p under %p" %
362
- [entry['path'], directory]
363
- raise Gem::InstallError, msg
364
- end
365
- FileUtils.mkdir_p File.dirname(path)
366
- File.open(path, "wb") do |out|
367
- out.write file_data
368
- end
369
- end
370
- end
371
-
372
- private
373
- def expand_and_validate(directory)
374
- directory = Pathname.new(directory).expand_path
375
- unless directory.absolute?
376
- raise ArgumentError, "install directory %p not absolute" % directory
363
+ raise ExtensionBuildError, message
364
+ ensure
365
+ Dir.chdir start_dir
377
366
  end
378
- directory.to_str
379
367
  end
380
- end # class Installer
368
+ end
381
369
 
382
370
  ##
383
- # The Uninstaller class uninstalls a Gem
371
+ # Reads the file index and extracts each file into the gem directory.
384
372
  #
385
- class Uninstaller
386
-
387
- include UserInteraction
388
-
389
- ##
390
- # Constructs an Uninstaller instance
391
- #
392
- # gem:: [String] The Gem name to uninstall
393
- #
394
- def initialize(gem, options)
395
- @gem = gem
396
- @version = options[:version] || "> 0"
397
- @force_executables = options[:executables]
398
- @force_all = options[:all]
399
- @force_ignore = options[:ignore]
400
- end
373
+ # Ensures that files can't be installed outside the gem directory.
374
+ def extract_files
375
+ expand_and_validate_gem_dir
401
376
 
402
- ##
403
- # Performs the uninstall of the Gem. This removes the spec, the
404
- # Gem directory, and the cached .gem file,
405
- #
406
- # Application stubs are (or should be) removed according to what
407
- # is still installed.
408
- #
409
- # XXX: Application stubs refer to specific gem versions, which
410
- # means things may get inconsistent after an uninstall
411
- # (i.e. referring to a version that no longer exists).
412
- #
413
- def uninstall
414
- list = Gem.source_index.search(/^#{@gem}$/, @version)
415
- if list.empty?
416
- raise Gem::InstallError, "Unknown gem #{@gem}-#{@version}"
417
- elsif list.size > 1 && @force_all
418
- remove_all(list.dup)
419
- remove_executables(list.last)
420
- elsif list.size > 1
421
- say
422
- gem_names = list.collect {|gem| gem.full_name} + ["All versions"]
423
- gem_name, index =
424
- choose_from_list("Select gem to uninstall:", gem_names)
425
- if index == list.size
426
- remove_all(list.dup)
427
- remove_executables(list.last)
428
- elsif index >= 0 && index < list.size
429
- to_remove = list[index]
430
- remove(to_remove, list)
431
- remove_executables(to_remove)
432
- else
433
- say "Error: must enter a number [1-#{list.size+1}]"
434
- end
435
- else
436
- remove(list[0], list.dup)
437
- remove_executables(list.last)
438
- end
439
- end
440
-
441
- ##
442
- # Remove executables and batch files (windows only) for the gem as
443
- # it is being installed
444
- #
445
- # gemspec::[Specification] the gem whose executables need to be removed.
446
- #
447
- def remove_executables(gemspec)
448
- return if gemspec.nil?
449
- if(gemspec.executables.size > 0)
450
- raise Gem::FilePermissionError.new(Gem.bindir) unless
451
- File.writable?(Gem.bindir)
452
- list = Gem.source_index.search(gemspec.name).delete_if { |spec|
453
- spec.version == gemspec.version
454
- }
455
- executables = gemspec.executables.clone
456
- list.each do |spec|
457
- spec.executables.each do |exe_name|
458
- executables.delete(exe_name)
459
- end
460
- end
461
- return if executables.size == 0
462
- answer = @force_executables || ask_yes_no(
463
- "Remove executables and scripts for\n" +
464
- "'#{gemspec.executables.join(", ")}' in addition to the gem?",
465
- true) # " # appease ruby-mode - don't ask
466
- unless answer
467
- say "Executables and scripts will remain installed."
468
- return
469
- else
470
- gemspec.executables.each do |exe_name|
471
- say "Removing #{exe_name}"
472
- File.unlink File.join(Gem.bindir, exe_name) rescue nil
473
- File.unlink File.join(Gem.bindir, exe_name + ".cmd") rescue nil
474
- end
475
- end
476
- end
477
- end
478
-
479
- #
480
- # list:: the list of all gems to remove
481
- #
482
- # Warning: this method modifies the +list+ parameter. Once it has
483
- # uninstalled a gem, it is removed from that list.
484
- #
485
- def remove_all(list)
486
- list.dup.each { |gem| remove(gem, list) }
487
- end
377
+ raise ArgumentError, "format required to extract from" if @format.nil?
488
378
 
489
- #
490
- # spec:: the spec of the gem to be uninstalled
491
- # list:: the list of all such gems
492
- #
493
- # Warning: this method modifies the +list+ parameter. Once it has
494
- # uninstalled a gem, it is removed from that list.
495
- #
496
- def remove(spec, list)
497
- if( ! ok_to_remove?(spec)) then
498
- raise DependencyRemovalException.new(
499
- "Uninstallation aborted due to dependent gem(s)")
500
- end
501
- raise Gem::FilePermissionError.new(spec.installation_path) unless
502
- File.writable?(spec.installation_path)
503
- FileUtils.rm_rf spec.full_gem_path
504
- FileUtils.rm_rf File.join(
505
- spec.installation_path,
506
- 'specifications',
507
- "#{spec.full_name}.gemspec")
508
- FileUtils.rm_rf File.join(
509
- spec.installation_path,
510
- 'cache',
511
- "#{spec.full_name}.gem")
512
- DocManager.new(spec).uninstall_doc
513
- #remove_stub_files(spec, list - [spec])
514
- say "Successfully uninstalled #{spec.name} version #{spec.version}"
515
- list.delete(spec)
516
- end
517
-
518
- def ok_to_remove?(spec)
519
- return true if @force_ignore
520
- srcindex= Gem::SourceIndex.from_installed_gems
521
- deplist = Gem::DependencyList.from_source_index(srcindex)
522
- deplist.ok_to_remove?(spec.full_name) ||
523
- ask_if_ok(spec)
524
- end
525
-
526
- def ask_if_ok(spec)
527
- msg = ['']
528
- msg << 'You have requested to uninstall the gem:'
529
- msg << "\t#{spec.full_name}"
530
- spec.dependent_gems.each do |gem,dep,satlist|
531
- msg <<
532
- ("#{gem.name}-#{gem.version} depends on " +
533
- "[#{dep.name} (#{dep.version_requirements})]")
534
- end
535
- msg << 'If you remove this gems, one or more dependencies will not be met.'
536
- msg << 'Continue with Uninstall?'
537
- return ask_yes_no(msg.join("\n"), true)
538
- end
539
-
540
- private
541
-
542
- ##
543
- # Remove application stub files. These are detected by the line
544
- # # This file was generated by RubyGems.
545
- #
546
- # spec:: the spec of the gem that is being uninstalled
547
- # other_specs:: any other installed specs for this gem
548
- # (i.e. different versions)
549
- #
550
- # Both parameters are necessary to ensure that the correct files
551
- # are uninstalled. It is assumed that +other_specs+ contains only
552
- # *installed* gems, except the one that's about to be uninstalled.
553
- #
554
- def remove_stub_files(spec, other_specs)
555
- remove_app_stubs(spec, other_specs)
556
- end
379
+ @format.file_entries.each do |entry, file_data|
380
+ path = entry['path'].untaint
557
381
 
558
- def remove_app_stubs(spec, other_specs)
559
- # App stubs are tricky, because each version of an app gem could
560
- # install different applications. We need to make sure that
561
- # what we delete isn't needed by any remaining versions of the
562
- # gem.
563
- #
564
- # There's extra trickiness, too, because app stubs 'gem'
565
- # a specific version of the gem. If we uninstall the latest
566
- # gem, we should ensure that there is a sensible app stub(s)
567
- # installed after the removal of the current one.
568
- #
569
- # Perhaps the best way to approach this is:
570
- # * remove all application stubs for this gemspec
571
- # * regenerate the app stubs for the latest remaining version
572
- # (you always want to have the latest version of an app,
573
- # don't you?)
574
- #
575
- # The Installer class doesn't really support this approach very
576
- # well at the moment.
577
- end
578
-
579
- end # class Uninstaller
580
-
581
- class ExtBuilder
582
-
583
- def self.class_name
584
- name =~ /Ext(.*)Builder/
585
- $1.downcase
586
- end
587
-
588
- def self.make(dest_path, results)
589
- unless File.exist? 'Makefile' then
590
- raise Gem::InstallError, "Makefile not found:\n\n#{results.join "\n"}"
382
+ if path =~ /\A\// then # for extra sanity
383
+ raise Gem::InstallError,
384
+ "attempt to install file into #{entry['path'].inspect}"
591
385
  end
592
386
 
593
- mf = File.read('Makefile')
594
- mf = mf.gsub(/^RUBYARCHDIR\s*=\s*\$[^$]*/, "RUBYARCHDIR = #{dest_path}")
595
- mf = mf.gsub(/^RUBYLIBDIR\s*=\s*\$[^$]*/, "RUBYLIBDIR = #{dest_path}")
596
-
597
- File.open('Makefile', 'wb') {|f| f.print mf}
387
+ path = File.expand_path File.join(@gem_dir, path)
598
388
 
599
- make_program = ENV['make']
600
- unless make_program then
601
- make_program = (/mswin/ =~ RUBY_PLATFORM) ? 'nmake' : 'make'
389
+ if path !~ /\A#{Regexp.escape @gem_dir}/ then
390
+ msg = "attempt to install file into %p under %p" %
391
+ [entry['path'], @gem_dir]
392
+ raise Gem::InstallError, msg
602
393
  end
603
394
 
604
- ['', ' install'].each do |target|
605
- cmd = "#{make_program}#{target}"
606
- results << cmd
607
- results << `#{cmd} #{redirector}`
395
+ FileUtils.mkdir_p File.dirname(path)
608
396
 
609
- raise Gem::InstallError, "make#{target} failed:\n\n#{results}" unless
610
- $?.exitstatus.zero?
397
+ File.open(path, "wb") do |out|
398
+ out.write file_data
611
399
  end
612
400
  end
613
-
614
- def self.redirector
615
- '2>&1'
616
- end
617
-
618
- def self.run(command, results)
619
- results << command
620
- results << `#{command} #{redirector}`
621
-
622
- unless $?.exitstatus.zero? then
623
- raise Gem::InstallError, "#{class_name} failed:\n\n#{results.join "\n"}"
624
- end
625
- end
626
-
627
401
  end
628
402
 
629
- class ExtConfigureBuilder < ExtBuilder
630
- def self.build(extension, directory, dest_path, results)
631
- unless File.exist?('Makefile') then
632
- cmd = "sh ./configure --prefix=#{dest_path}"
403
+ private
633
404
 
634
- run cmd, results
635
- end
636
-
637
- make dest_path, results
638
-
639
- results
640
- end
405
+ # HACK Pathname is broken on windows.
406
+ def absolute_path? pathname
407
+ pathname.absolute? or (Gem.win_platform? and pathname.to_s =~ /\A[a-z]:/i)
641
408
  end
642
409
 
643
- class ExtExtConfBuilder < ExtBuilder
644
- def self.build(extension, directory, dest_path, results)
645
- cmd = "#{Gem.ruby} #{File.basename extension}"
646
- cmd << " #{ARGV.join " "}" unless ARGV.empty?
410
+ def expand_and_validate_gem_dir
411
+ @gem_dir = Pathname.new(@gem_dir).expand_path
647
412
 
648
- run cmd, results
649
-
650
- make dest_path, results
651
-
652
- results
413
+ unless absolute_path?(@gem_dir) then # HACK is this possible after #expand_path?
414
+ raise ArgumentError, "install directory %p not absolute" % @gem_dir
653
415
  end
654
- end
655
-
656
- class ExtRakeBuilder < ExtBuilder
657
- def ExtRakeBuilder.build(ext, directory, dest_path, results)
658
- cmd = ENV['rake'] || 'rake'
659
- cmd << " RUBYARCHDIR=#{dest_path} RUBYLIBDIR=#{dest_path} extension"
660
416
 
661
- run cmd, results
662
-
663
- results
664
- end
417
+ @gem_dir = @gem_dir.to_s
665
418
  end
666
419
 
667
- end # module Gem
420
+ end
421
+