libgems 0.0.1

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.
Files changed (177) hide show
  1. data/ChangeLog +5811 -0
  2. data/History.txt +887 -0
  3. data/LICENSE.txt +51 -0
  4. data/README.md +87 -0
  5. data/Rakefile +113 -0
  6. data/lib/gauntlet_libgems.rb +50 -0
  7. data/lib/libgems.rb +1246 -0
  8. data/lib/libgems/builder.rb +102 -0
  9. data/lib/libgems/command.rb +534 -0
  10. data/lib/libgems/command_manager.rb +182 -0
  11. data/lib/libgems/commands/build_command.rb +53 -0
  12. data/lib/libgems/commands/cert_command.rb +86 -0
  13. data/lib/libgems/commands/check_command.rb +80 -0
  14. data/lib/libgems/commands/cleanup_command.rb +106 -0
  15. data/lib/libgems/commands/contents_command.rb +98 -0
  16. data/lib/libgems/commands/dependency_command.rb +195 -0
  17. data/lib/libgems/commands/environment_command.rb +133 -0
  18. data/lib/libgems/commands/fetch_command.rb +67 -0
  19. data/lib/libgems/commands/generate_index_command.rb +133 -0
  20. data/lib/libgems/commands/help_command.rb +172 -0
  21. data/lib/libgems/commands/install_command.rb +178 -0
  22. data/lib/libgems/commands/list_command.rb +35 -0
  23. data/lib/libgems/commands/lock_command.rb +110 -0
  24. data/lib/libgems/commands/mirror_command.rb +111 -0
  25. data/lib/libgems/commands/outdated_command.rb +33 -0
  26. data/lib/libgems/commands/owner_command.rb +75 -0
  27. data/lib/libgems/commands/pristine_command.rb +93 -0
  28. data/lib/libgems/commands/push_command.rb +56 -0
  29. data/lib/libgems/commands/query_command.rb +280 -0
  30. data/lib/libgems/commands/rdoc_command.rb +91 -0
  31. data/lib/libgems/commands/search_command.rb +31 -0
  32. data/lib/libgems/commands/server_command.rb +86 -0
  33. data/lib/libgems/commands/sources_command.rb +157 -0
  34. data/lib/libgems/commands/specification_command.rb +125 -0
  35. data/lib/libgems/commands/stale_command.rb +27 -0
  36. data/lib/libgems/commands/uninstall_command.rb +83 -0
  37. data/lib/libgems/commands/unpack_command.rb +121 -0
  38. data/lib/libgems/commands/update_command.rb +160 -0
  39. data/lib/libgems/commands/which_command.rb +86 -0
  40. data/lib/libgems/config_file.rb +345 -0
  41. data/lib/libgems/custom_require.rb +44 -0
  42. data/lib/libgems/defaults.rb +101 -0
  43. data/lib/libgems/dependency.rb +227 -0
  44. data/lib/libgems/dependency_installer.rb +286 -0
  45. data/lib/libgems/dependency_list.rb +208 -0
  46. data/lib/libgems/doc_manager.rb +242 -0
  47. data/lib/libgems/errors.rb +35 -0
  48. data/lib/libgems/exceptions.rb +91 -0
  49. data/lib/libgems/ext.rb +18 -0
  50. data/lib/libgems/ext/builder.rb +56 -0
  51. data/lib/libgems/ext/configure_builder.rb +25 -0
  52. data/lib/libgems/ext/ext_conf_builder.rb +24 -0
  53. data/lib/libgems/ext/rake_builder.rb +39 -0
  54. data/lib/libgems/format.rb +81 -0
  55. data/lib/libgems/gem_openssl.rb +92 -0
  56. data/lib/libgems/gem_path_searcher.rb +100 -0
  57. data/lib/libgems/gem_runner.rb +79 -0
  58. data/lib/libgems/gemcutter_utilities.rb +49 -0
  59. data/lib/libgems/indexer.rb +720 -0
  60. data/lib/libgems/install_update_options.rb +125 -0
  61. data/lib/libgems/installer.rb +604 -0
  62. data/lib/libgems/local_remote_options.rb +135 -0
  63. data/lib/libgems/old_format.rb +153 -0
  64. data/lib/libgems/package.rb +97 -0
  65. data/lib/libgems/package/f_sync_dir.rb +23 -0
  66. data/lib/libgems/package/tar_header.rb +266 -0
  67. data/lib/libgems/package/tar_input.rb +222 -0
  68. data/lib/libgems/package/tar_output.rb +144 -0
  69. data/lib/libgems/package/tar_reader.rb +106 -0
  70. data/lib/libgems/package/tar_reader/entry.rb +141 -0
  71. data/lib/libgems/package/tar_writer.rb +241 -0
  72. data/lib/libgems/package_task.rb +126 -0
  73. data/lib/libgems/platform.rb +183 -0
  74. data/lib/libgems/remote_fetcher.rb +414 -0
  75. data/lib/libgems/require_paths_builder.rb +18 -0
  76. data/lib/libgems/requirement.rb +153 -0
  77. data/lib/libgems/security.rb +814 -0
  78. data/lib/libgems/server.rb +872 -0
  79. data/lib/libgems/source_index.rb +597 -0
  80. data/lib/libgems/source_info_cache.rb +395 -0
  81. data/lib/libgems/source_info_cache_entry.rb +56 -0
  82. data/lib/libgems/spec_fetcher.rb +337 -0
  83. data/lib/libgems/specification.rb +1487 -0
  84. data/lib/libgems/test_utilities.rb +147 -0
  85. data/lib/libgems/text.rb +65 -0
  86. data/lib/libgems/uninstaller.rb +278 -0
  87. data/lib/libgems/user_interaction.rb +527 -0
  88. data/lib/libgems/validator.rb +240 -0
  89. data/lib/libgems/version.rb +316 -0
  90. data/lib/libgems/version_option.rb +65 -0
  91. data/lib/rbconfig/datadir.rb +20 -0
  92. data/test/bogussources.rb +8 -0
  93. data/test/data/gem-private_key.pem +27 -0
  94. data/test/data/gem-public_cert.pem +20 -0
  95. data/test/fake_certlib/openssl.rb +7 -0
  96. data/test/foo/discover.rb +0 -0
  97. data/test/gem_installer_test_case.rb +97 -0
  98. data/test/gem_package_tar_test_case.rb +132 -0
  99. data/test/gemutilities.rb +605 -0
  100. data/test/insure_session.rb +43 -0
  101. data/test/mockgemui.rb +56 -0
  102. data/test/plugin/exception/libgems_plugin.rb +2 -0
  103. data/test/plugin/load/libgems_plugin.rb +1 -0
  104. data/test/plugin/standarderror/libgems_plugin.rb +2 -0
  105. data/test/private_key.pem +27 -0
  106. data/test/public_cert.pem +20 -0
  107. data/test/rubygems_plugin.rb +21 -0
  108. data/test/simple_gem.rb +66 -0
  109. data/test/test_config.rb +12 -0
  110. data/test/test_gem.rb +780 -0
  111. data/test/test_gem_builder.rb +27 -0
  112. data/test/test_gem_command.rb +178 -0
  113. data/test/test_gem_command_manager.rb +207 -0
  114. data/test/test_gem_commands_build_command.rb +74 -0
  115. data/test/test_gem_commands_cert_command.rb +124 -0
  116. data/test/test_gem_commands_check_command.rb +18 -0
  117. data/test/test_gem_commands_contents_command.rb +156 -0
  118. data/test/test_gem_commands_dependency_command.rb +216 -0
  119. data/test/test_gem_commands_environment_command.rb +144 -0
  120. data/test/test_gem_commands_fetch_command.rb +76 -0
  121. data/test/test_gem_commands_generate_index_command.rb +135 -0
  122. data/test/test_gem_commands_install_command.rb +315 -0
  123. data/test/test_gem_commands_list_command.rb +36 -0
  124. data/test/test_gem_commands_lock_command.rb +68 -0
  125. data/test/test_gem_commands_mirror_command.rb +60 -0
  126. data/test/test_gem_commands_outdated_command.rb +40 -0
  127. data/test/test_gem_commands_owner_command.rb +105 -0
  128. data/test/test_gem_commands_pristine_command.rb +108 -0
  129. data/test/test_gem_commands_push_command.rb +81 -0
  130. data/test/test_gem_commands_query_command.rb +426 -0
  131. data/test/test_gem_commands_server_command.rb +59 -0
  132. data/test/test_gem_commands_sources_command.rb +209 -0
  133. data/test/test_gem_commands_specification_command.rb +139 -0
  134. data/test/test_gem_commands_stale_command.rb +38 -0
  135. data/test/test_gem_commands_uninstall_command.rb +83 -0
  136. data/test/test_gem_commands_unpack_command.rb +199 -0
  137. data/test/test_gem_commands_update_command.rb +207 -0
  138. data/test/test_gem_commands_which_command.rb +66 -0
  139. data/test/test_gem_config_file.rb +287 -0
  140. data/test/test_gem_dependency.rb +149 -0
  141. data/test/test_gem_dependency_installer.rb +661 -0
  142. data/test/test_gem_dependency_list.rb +230 -0
  143. data/test/test_gem_doc_manager.rb +31 -0
  144. data/test/test_gem_ext_configure_builder.rb +84 -0
  145. data/test/test_gem_ext_ext_conf_builder.rb +173 -0
  146. data/test/test_gem_ext_rake_builder.rb +81 -0
  147. data/test/test_gem_format.rb +70 -0
  148. data/test/test_gem_gem_path_searcher.rb +78 -0
  149. data/test/test_gem_gem_runner.rb +45 -0
  150. data/test/test_gem_gemcutter_utilities.rb +103 -0
  151. data/test/test_gem_indexer.rb +673 -0
  152. data/test/test_gem_install_update_options.rb +68 -0
  153. data/test/test_gem_installer.rb +857 -0
  154. data/test/test_gem_local_remote_options.rb +97 -0
  155. data/test/test_gem_package_tar_header.rb +130 -0
  156. data/test/test_gem_package_tar_input.rb +112 -0
  157. data/test/test_gem_package_tar_output.rb +97 -0
  158. data/test/test_gem_package_tar_reader.rb +46 -0
  159. data/test/test_gem_package_tar_reader_entry.rb +109 -0
  160. data/test/test_gem_package_tar_writer.rb +144 -0
  161. data/test/test_gem_package_task.rb +59 -0
  162. data/test/test_gem_platform.rb +264 -0
  163. data/test/test_gem_remote_fetcher.rb +740 -0
  164. data/test/test_gem_requirement.rb +292 -0
  165. data/test/test_gem_server.rb +356 -0
  166. data/test/test_gem_silent_ui.rb +113 -0
  167. data/test/test_gem_source_index.rb +461 -0
  168. data/test/test_gem_spec_fetcher.rb +410 -0
  169. data/test/test_gem_specification.rb +1334 -0
  170. data/test/test_gem_stream_ui.rb +218 -0
  171. data/test/test_gem_text.rb +43 -0
  172. data/test/test_gem_uninstaller.rb +146 -0
  173. data/test/test_gem_validator.rb +63 -0
  174. data/test/test_gem_version.rb +181 -0
  175. data/test/test_gem_version_option.rb +89 -0
  176. data/test/test_kernel.rb +59 -0
  177. metadata +402 -0
@@ -0,0 +1,125 @@
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 'libgems'
8
+ require 'libgems/security'
9
+
10
+ ##
11
+ # Mixin methods for install and update options for LibGems::Commands
12
+
13
+ module LibGems::InstallUpdateOptions
14
+
15
+ ##
16
+ # Add the install/update options to the option parser.
17
+
18
+ def add_install_update_options
19
+ OptionParser.accept LibGems::Security::Policy do |value|
20
+ value = LibGems::Security::Policies[value]
21
+ valid = LibGems::Security::Policies.keys.sort
22
+ message = "#{value} (#{valid.join ', '} are valid)"
23
+ raise OptionParser::InvalidArgument, message if value.nil?
24
+ value
25
+ end
26
+
27
+ add_option(:"Install/Update", '-i', '--install-dir DIR',
28
+ 'Gem repository directory to get installed',
29
+ 'gems') do |value, options|
30
+ options[:install_dir] = File.expand_path(value)
31
+ end
32
+
33
+ add_option(:"Install/Update", '-n', '--bindir DIR',
34
+ 'Directory where binary files are',
35
+ 'located') do |value, options|
36
+ options[:bin_dir] = File.expand_path(value)
37
+ end
38
+
39
+ add_option(:"Install/Update", '-d', '--[no-]rdoc',
40
+ 'Generate RDoc documentation for the gem on',
41
+ 'install') do |value, options|
42
+ options[:generate_rdoc] = value
43
+ end
44
+
45
+ add_option(:"Install/Update", '--[no-]ri',
46
+ 'Generate RI documentation for the gem on',
47
+ 'install') do |value, options|
48
+ options[:generate_ri] = value
49
+ end
50
+
51
+ add_option(:"Install/Update", '-E', '--[no-]env-shebang',
52
+ "Rewrite the shebang line on installed",
53
+ "scripts to use /usr/bin/env") do |value, options|
54
+ options[:env_shebang] = value
55
+ end
56
+
57
+ add_option(:"Install/Update", '-f', '--[no-]force',
58
+ 'Force gem to install, bypassing dependency',
59
+ 'checks') do |value, options|
60
+ options[:force] = value
61
+ end
62
+
63
+ add_option(:"Install/Update", '-t', '--[no-]test',
64
+ 'Run unit tests prior to installation') do |value, options|
65
+ options[:test] = value
66
+ end
67
+
68
+ add_option(:"Install/Update", '-w', '--[no-]wrappers',
69
+ 'Use bin wrappers for executables',
70
+ 'Not available on dosish platforms') do |value, options|
71
+ options[:wrappers] = value
72
+ end
73
+
74
+ add_option(:"Install/Update", '-P', '--trust-policy POLICY',
75
+ LibGems::Security::Policy,
76
+ 'Specify gem trust policy') do |value, options|
77
+ options[:security_policy] = value
78
+ end
79
+
80
+ add_option(:"Install/Update", '--ignore-dependencies',
81
+ 'Do not install any required dependent gems') do |value, options|
82
+ options[:ignore_dependencies] = value
83
+ end
84
+
85
+ add_option(:"Install/Update", '-y', '--include-dependencies',
86
+ 'Unconditionally install the required',
87
+ 'dependent gems') do |value, options|
88
+ options[:include_dependencies] = value
89
+ end
90
+
91
+ add_option(:"Install/Update", '--[no-]format-executable',
92
+ 'Make installed executable names match ruby.',
93
+ 'If ruby is ruby18, foo_exec will be',
94
+ 'foo_exec18') do |value, options|
95
+ options[:format_executable] = value
96
+ end
97
+
98
+ add_option(:"Install/Update", '--[no-]user-install',
99
+ 'Install in user\'s home directory instead',
100
+ 'of GEM_HOME.') do |value, options|
101
+ options[:user_install] = value
102
+ end
103
+
104
+ add_option(:"Install/Update", "--development",
105
+ "Install any additional development",
106
+ "dependencies") do |value, options|
107
+ options[:development] = true
108
+ end
109
+
110
+ add_option(:"Install/Update", "--conservative",
111
+ "Don't attempt to upgrade gems already",
112
+ "meeting version requirement") do |value, options|
113
+ options[:conservative] = true
114
+ end
115
+ end
116
+
117
+ ##
118
+ # Default options for the gem install command.
119
+
120
+ def install_update_defaults_str
121
+ '--rdoc --no-force --no-test --wrappers'
122
+ end
123
+
124
+ end
125
+
@@ -0,0 +1,604 @@
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 'rbconfig'
9
+
10
+ require 'libgems/format'
11
+ require 'libgems/ext'
12
+ require 'libgems/require_paths_builder'
13
+
14
+ ##
15
+ # The installer class processes RubyGem .gem files and installs the files
16
+ # contained in the .gem into the LibGems.path.
17
+ #
18
+ # LibGems::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
+ #
23
+ # The installer fires pre and post install hooks. Hooks can be added either
24
+ # through a rubygems_plugin.rb file in an installed gem or via a
25
+ # rubygems/defaults/#{RUBY_ENGINE}.rb or rubygems/defaults/operating_system.rb
26
+ # file. See LibGems.pre_install and LibGems.post_install for details.
27
+
28
+ class LibGems::Installer
29
+
30
+ ##
31
+ # Paths where env(1) might live. Some systems are broken and have it in
32
+ # /bin
33
+
34
+ ENV_PATHS = %w[/usr/bin/env /bin/env]
35
+
36
+ ##
37
+ # Raised when there is an error while building extensions.
38
+ #
39
+ class ExtensionBuildError < LibGems::InstallError; end
40
+
41
+ include LibGems::UserInteraction
42
+
43
+ include LibGems::RequirePathsBuilder
44
+
45
+ ##
46
+ # The directory a gem's executables will be installed into
47
+
48
+ attr_reader :bin_dir
49
+
50
+ ##
51
+ # The gem repository the gem will be installed into
52
+
53
+ attr_reader :gem_home
54
+
55
+ ##
56
+ # The LibGems::Specification for the gem being installed
57
+
58
+ attr_reader :spec
59
+
60
+ ##
61
+ # The options passed when the LibGems::Installer was instantiated.
62
+
63
+ attr_accessor :options
64
+
65
+ @path_warning = false
66
+
67
+ class << self
68
+
69
+ ##
70
+ # True if we've warned about PATH not including LibGems.bindir
71
+
72
+ attr_accessor :path_warning
73
+
74
+ attr_writer :exec_format
75
+
76
+ # Defaults to use Ruby's program prefix and suffix.
77
+ def exec_format
78
+ @exec_format ||= LibGems.default_exec_format
79
+ end
80
+
81
+ end
82
+
83
+ ##
84
+ # Constructs an Installer instance that will install the gem located at
85
+ # +gem+. +options+ is a Hash with the following keys:
86
+ #
87
+ # :env_shebang:: Use /usr/bin/env in bin wrappers.
88
+ # :force:: Overrides all version checks and security policy checks, except
89
+ # for a signed-gems-only policy.
90
+ # :ignore_dependencies:: Don't raise if a dependency is missing.
91
+ # :install_dir:: The directory to install the gem into.
92
+ # :format_executable:: Format the executable the same as the ruby executable.
93
+ # If your ruby is ruby18, foo_exec will be installed as
94
+ # foo_exec18.
95
+ # :security_policy:: Use the specified security policy. See LibGems::Security
96
+ # :wrappers:: Install wrappers if true, symlinks if false.
97
+
98
+ def initialize(gem, options={})
99
+ @gem = gem
100
+ @options = options
101
+ process_options
102
+ load_gem_file
103
+
104
+ if options[:user_install] and not options[:unpack] then
105
+ @gem_home = LibGems.user_dir
106
+ check_that_user_bin_dir_is_in_path
107
+ end
108
+
109
+ verify_gem_home(options[:unpack])
110
+
111
+ @spec = @format.spec
112
+
113
+ @gem_dir = File.join(@gem_home, "gems", @spec.full_name).untaint
114
+ end
115
+
116
+ ##
117
+ # Installs the gem and returns a loaded LibGems::Specification for the installed
118
+ # gem.
119
+ #
120
+ # The gem will be installed with the following structure:
121
+ #
122
+ # @gem_home/
123
+ # cache/<gem-version>.gem #=> a cached copy of the installed gem
124
+ # gems/<gem-version>/... #=> extracted files
125
+ # specifications/<gem-version>.gemspec #=> the LibGems::Specification
126
+
127
+ def install
128
+ # If we're forcing the install then disable security unless the security
129
+ # policy says that we only install singed gems.
130
+ @security_policy = nil if @force and @security_policy and
131
+ not @security_policy.only_signed
132
+
133
+ unless @force
134
+ ensure_required_ruby_version_met
135
+ ensure_required_rubygems_version_met
136
+ ensure_dependencies_met unless @ignore_dependencies
137
+ end
138
+
139
+ LibGems.pre_install_hooks.each do |hook|
140
+ result = hook.call self
141
+
142
+ if result == false then
143
+ location = " at #{$1}" if hook.inspect =~ /@(.*:\d+)/
144
+
145
+ message = "pre-install hook#{location} failed for #{spec.full_name}"
146
+ raise LibGems::InstallError, message
147
+ end
148
+ end
149
+
150
+ LibGems.ensure_gem_subdirectories @gem_home
151
+
152
+ FileUtils.mkdir_p @gem_dir
153
+
154
+ extract_files
155
+ build_extensions
156
+
157
+ LibGems.post_build_hooks.each do |hook|
158
+ result = hook.call self
159
+
160
+ if result == false then
161
+ FileUtils.rm_rf @gem_dir
162
+
163
+ location = " at #{$1}" if hook.inspect =~ /@(.*:\d+)/
164
+
165
+ message = "post-build hook#{location} failed for #{spec.full_name}"
166
+ raise LibGems::InstallError, message
167
+ end
168
+ end
169
+
170
+ generate_bin
171
+ write_spec
172
+
173
+ write_require_paths_file_if_needed
174
+
175
+ # HACK remove? Isn't this done in multiple places?
176
+ cached_gem = File.join @gem_home, "cache", @gem.split(/\//).pop
177
+ unless File.exist? cached_gem then
178
+ FileUtils.cp @gem, File.join(@gem_home, "cache")
179
+ end
180
+
181
+ unless @spec.post_install_message.nil?
182
+ # Only for SlimGems
183
+ if @spec.name == LibGems::GEM_NAME
184
+ lines = @spec.post_install_message.split("\n")
185
+ lines.shift if lines.first.include?("Upgraded from #{LibGems::NAME}")
186
+ say lines.join("\n")
187
+ else
188
+ say @spec.post_install_message
189
+ end
190
+ end
191
+
192
+ @spec.loaded_from = File.join(@gem_home, 'specifications', @spec.spec_name)
193
+
194
+ @source_index.add_spec @spec
195
+
196
+ LibGems.post_install_hooks.each do |hook|
197
+ hook.call self
198
+ end
199
+
200
+ return @spec
201
+ rescue Zlib::GzipFile::Error
202
+ raise LibGems::InstallError, "gzip error installing #{@gem}"
203
+ end
204
+
205
+ ##
206
+ # Ensure that the dependency is satisfied by the current installation of
207
+ # gem. If it is not an exception is raised.
208
+ #
209
+ # spec :: LibGems::Specification
210
+ # dependency :: LibGems::Dependency
211
+
212
+ def ensure_dependency(spec, dependency)
213
+ unless installation_satisfies_dependency? dependency then
214
+ raise LibGems::InstallError, "#{spec.name} requires #{dependency}"
215
+ end
216
+ true
217
+ end
218
+
219
+ ##
220
+ # True if the gems in the source_index satisfy +dependency+.
221
+
222
+ def installation_satisfies_dependency?(dependency)
223
+ @source_index.find_name(dependency.name, dependency.requirement).size > 0
224
+ end
225
+
226
+ ##
227
+ # Unpacks the gem into the given directory.
228
+
229
+ def unpack(directory)
230
+ @gem_dir = directory
231
+ @format = LibGems::Format.from_file_by_path @gem, @security_policy
232
+ extract_files
233
+ end
234
+
235
+ ##
236
+ # Writes the .gemspec specification (in Ruby) to the gem home's
237
+ # specifications directory.
238
+
239
+ def write_spec
240
+ rubycode = @spec.to_ruby
241
+
242
+ file_name = File.join @gem_home, 'specifications', @spec.spec_name
243
+
244
+ file_name.untaint
245
+
246
+ File.open(file_name, "w") do |file|
247
+ file.puts rubycode
248
+ end
249
+ end
250
+
251
+ ##
252
+ # Creates windows .bat files for easy running of commands
253
+
254
+ def generate_windows_script(filename, bindir)
255
+ if LibGems.win_platform? then
256
+ script_name = filename + ".bat"
257
+ script_path = File.join bindir, File.basename(script_name)
258
+ File.open script_path, 'w' do |file|
259
+ file.puts windows_stub_script(bindir, filename)
260
+ end
261
+
262
+ say script_path if LibGems.configuration.really_verbose
263
+ end
264
+ end
265
+
266
+ def generate_bin
267
+ return if @spec.executables.nil? or @spec.executables.empty?
268
+
269
+ # If the user has asked for the gem to be installed in a directory that is
270
+ # the system gem directory, then use the system bin directory, else create
271
+ # (or use) a new bin dir under the gem_home.
272
+ bindir = @bin_dir ? @bin_dir : LibGems.bindir(@gem_home)
273
+
274
+ Dir.mkdir bindir unless File.exist? bindir
275
+ raise LibGems::FilePermissionError.new(bindir) unless File.writable? bindir
276
+
277
+ @spec.executables.each do |filename|
278
+ filename.untaint
279
+ bin_path = File.expand_path "#{@spec.bindir}/#{filename}", @gem_dir
280
+ mode = File.stat(bin_path).mode | 0111
281
+ File.chmod mode, bin_path
282
+
283
+ if @wrappers then
284
+ generate_bin_script filename, bindir
285
+ else
286
+ generate_bin_symlink filename, bindir
287
+ end
288
+ end
289
+ end
290
+
291
+ ##
292
+ # Creates the scripts to run the applications in the gem.
293
+ #--
294
+ # The Windows script is generated in addition to the regular one due to a
295
+ # bug or misfeature in the Windows shell's pipe. See
296
+ # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/193379
297
+
298
+ def generate_bin_script(filename, bindir)
299
+ bin_script_path = File.join bindir, formatted_program_filename(filename)
300
+
301
+ File.join @gem_dir, @spec.bindir, filename
302
+
303
+ # HACK some gems don't have #! in their executables, restore 2008/06
304
+ #if File.read(exec_path, 2) == '#!' then
305
+ FileUtils.rm_f bin_script_path # prior install may have been --no-wrappers
306
+
307
+ File.open bin_script_path, 'w', 0755 do |file|
308
+ file.print app_script_text(filename)
309
+ end
310
+
311
+ say bin_script_path if LibGems.configuration.really_verbose
312
+
313
+ generate_windows_script filename, bindir
314
+ #else
315
+ # FileUtils.rm_f bin_script_path
316
+ # FileUtils.cp exec_path, bin_script_path,
317
+ # :verbose => LibGems.configuration.really_verbose
318
+ #end
319
+ end
320
+
321
+ ##
322
+ # Creates the symlinks to run the applications in the gem. Moves
323
+ # the symlink if the gem being installed has a newer version.
324
+
325
+ def generate_bin_symlink(filename, bindir)
326
+ if LibGems.win_platform? then
327
+ alert_warning "Unable to use symlinks on Windows, installing wrapper"
328
+ generate_bin_script filename, bindir
329
+ return
330
+ end
331
+
332
+ src = File.join @gem_dir, 'bin', filename
333
+ dst = File.join bindir, formatted_program_filename(filename)
334
+
335
+ if File.exist? dst then
336
+ if File.symlink? dst then
337
+ link = File.readlink(dst).split File::SEPARATOR
338
+ cur_version = LibGems::Version.create(link[-3].sub(/^.*-/, ''))
339
+ return if @spec.version < cur_version
340
+ end
341
+ File.unlink dst
342
+ end
343
+
344
+ FileUtils.symlink src, dst, :verbose => LibGems.configuration.really_verbose
345
+ end
346
+
347
+ ##
348
+ # Generates a #! line for +bin_file_name+'s wrapper copying arguments if
349
+ # necessary.
350
+
351
+ def shebang(bin_file_name)
352
+ ruby_name = LibGems::ConfigMap[:ruby_install_name] if @env_shebang
353
+ path = File.join @gem_dir, @spec.bindir, bin_file_name
354
+ first_line = File.open(path, "rb") {|file| file.gets}
355
+
356
+ if /\A#!/ =~ first_line then
357
+ # Preserve extra words on shebang line, like "-w". Thanks RPA.
358
+ shebang = first_line.sub(/\A\#!.*?ruby\S*(?=(\s+\S+))/, "#!#{LibGems.ruby}")
359
+ opts = $1
360
+ shebang.strip! # Avoid nasty ^M issues.
361
+ end
362
+
363
+ if not ruby_name then
364
+ "#!#{LibGems.ruby}#{opts}"
365
+ elsif opts then
366
+ "#!/bin/sh\n'exec' #{ruby_name.dump} '-x' \"$0\" \"$@\"\n#{shebang}"
367
+ else
368
+ # Create a plain shebang line.
369
+ @env_path ||= ENV_PATHS.find {|env_path| File.executable? env_path }
370
+ "#!#{@env_path} #{ruby_name}"
371
+ end
372
+ end
373
+
374
+ def ensure_required_ruby_version_met
375
+ if rrv = @spec.required_ruby_version then
376
+ unless rrv.satisfied_by? LibGems.ruby_version then
377
+ raise LibGems::InstallError, "#{@spec.name} requires Ruby version #{rrv}."
378
+ end
379
+ end
380
+ end
381
+
382
+ def ensure_required_rubygems_version_met
383
+ if rrgv = @spec.required_rubygems_version then
384
+ unless rrgv.satisfied_by? LibGems::Version.new(LibGems::GEM_VERSION) then
385
+ raise LibGems::InstallError,
386
+ "#{@spec.name} requires #{LibGems::NAME} version #{rrgv}. " +
387
+ "Try 'gem update --system' to update #{LibGems::NAME} itself."
388
+ end
389
+ end
390
+ end
391
+
392
+ def ensure_dependencies_met
393
+ deps = @spec.runtime_dependencies
394
+ deps |= @spec.development_dependencies if @development
395
+
396
+ deps.each do |dep_gem|
397
+ ensure_dependency @spec, dep_gem
398
+ end
399
+ end
400
+
401
+ def process_options
402
+ self.options = {
403
+ :bin_dir => nil,
404
+ :env_shebang => false,
405
+ :exec_format => false,
406
+ :force => false,
407
+ :install_dir => LibGems.dir,
408
+ :source_index => LibGems.source_index,
409
+ }.merge options
410
+
411
+ @env_shebang = options[:env_shebang]
412
+ @force = options[:force]
413
+ gem_home = options[:install_dir]
414
+ @gem_home = File.expand_path(gem_home)
415
+ @ignore_dependencies = options[:ignore_dependencies]
416
+ @format_executable = options[:format_executable]
417
+ @security_policy = options[:security_policy]
418
+ @wrappers = options[:wrappers]
419
+ @bin_dir = options[:bin_dir]
420
+ @development = options[:development]
421
+ @source_index = options[:source_index]
422
+ end
423
+
424
+ def load_gem_file
425
+ begin
426
+ @format = LibGems::Format.from_file_by_path @gem, @security_policy
427
+ rescue LibGems::Package::FormatError
428
+ raise LibGems::InstallError, "invalid gem format for #{@gem}"
429
+ end
430
+ end
431
+
432
+ def check_that_user_bin_dir_is_in_path
433
+ user_bin_dir = File.join(@gem_home, 'bin')
434
+ unless ENV['PATH'].split(File::PATH_SEPARATOR).include? user_bin_dir then
435
+ unless self.class.path_warning then
436
+ alert_warning "You don't have #{user_bin_dir} in your PATH,\n\t gem executables will not run."
437
+ self.class.path_warning = true
438
+ end
439
+ end
440
+ end
441
+
442
+ def verify_gem_home(unpack = false)
443
+ FileUtils.mkdir_p @gem_home
444
+ raise LibGems::FilePermissionError, @gem_home unless
445
+ unpack or File.writable? @gem_home
446
+ end
447
+
448
+ ##
449
+ # Return the text for an application file.
450
+
451
+ def app_script_text(bin_file_name)
452
+ <<-TEXT
453
+ #{shebang bin_file_name}
454
+ #
455
+ # This file was generated by LibGems.
456
+ #
457
+ # The application '#{@spec.name}' is installed as part of a gem, and
458
+ # this file is here to facilitate running it.
459
+ #
460
+
461
+ require 'libgems'
462
+
463
+ version = "#{LibGems::Requirement.default}"
464
+
465
+ if ARGV.first =~ /^_(.*)_$/ and LibGems::Version.correct? $1 then
466
+ version = $1
467
+ ARGV.shift
468
+ end
469
+
470
+ gem '#{@spec.name}', version
471
+ load LibGems.bin_path('#{@spec.name}', '#{bin_file_name}', version)
472
+ TEXT
473
+ end
474
+
475
+ ##
476
+ # return the stub script text used to launch the true ruby script
477
+
478
+ def windows_stub_script(bindir, bin_file_name)
479
+ <<-TEXT
480
+ @ECHO OFF
481
+ IF NOT "%~f0" == "~f0" GOTO :WinNT
482
+ @"#{File.basename(LibGems.ruby).chomp('"')}" "#{File.join(bindir, bin_file_name)}" %1 %2 %3 %4 %5 %6 %7 %8 %9
483
+ GOTO :EOF
484
+ :WinNT
485
+ @"#{File.basename(LibGems.ruby).chomp('"')}" "%~dpn0" %*
486
+ TEXT
487
+ end
488
+
489
+ ##
490
+ # Builds extensions. Valid types of extensions are extconf.rb files,
491
+ # configure scripts and rakefiles or mkrf_conf files.
492
+
493
+ def build_extensions
494
+ return if @spec.extensions.empty?
495
+ unless @spec.name == LibGems::GEM_NAME
496
+ say "Building native extensions. This could take a while..."
497
+ end
498
+ start_dir = Dir.pwd
499
+ dest_path = File.join @gem_dir, @spec.require_paths.first
500
+ ran_rake = false # only run rake once
501
+
502
+ @spec.extensions.each do |extension|
503
+ break if ran_rake
504
+ results = []
505
+
506
+ builder = case extension
507
+ when /extconf/ then
508
+ LibGems::Ext::ExtConfBuilder
509
+ when /configure/ then
510
+ LibGems::Ext::ConfigureBuilder
511
+ when /rakefile/i, /mkrf_conf/i then
512
+ ran_rake = true
513
+ LibGems::Ext::RakeBuilder
514
+ else
515
+ results = ["No builder for extension '#{extension}'"]
516
+ nil
517
+ end
518
+
519
+ begin
520
+ Dir.chdir File.join(@gem_dir, File.dirname(extension))
521
+ results = builder.build(extension, @gem_dir, dest_path, results)
522
+
523
+ say results.join("\n") if LibGems.configuration.really_verbose
524
+
525
+ rescue
526
+ results = results.join "\n"
527
+
528
+ File.open('gem_make.out', 'wb') { |f| f.puts results }
529
+
530
+ message = <<-EOF
531
+ ERROR: Failed to build gem native extension.
532
+
533
+ #{results}
534
+
535
+ Gem files will remain installed in #{@gem_dir} for inspection.
536
+ Results logged to #{File.join(Dir.pwd, 'gem_make.out')}
537
+ EOF
538
+
539
+ raise ExtensionBuildError, message
540
+ ensure
541
+ Dir.chdir start_dir
542
+ end
543
+ end
544
+ end
545
+
546
+ ##
547
+ # Reads the file index and extracts each file into the gem directory.
548
+ #
549
+ # Ensures that files can't be installed outside the gem directory.
550
+
551
+ def extract_files
552
+ @gem_dir = File.expand_path @gem_dir
553
+
554
+ raise ArgumentError, "format required to extract from" if @format.nil?
555
+
556
+ dirs = []
557
+
558
+ @format.file_entries.each do |entry, file_data|
559
+ path = entry['path'].untaint
560
+
561
+ if path =~ /\A\// then # for extra sanity
562
+ raise LibGems::InstallError,
563
+ "attempt to install file into #{entry['path'].inspect}"
564
+ end
565
+
566
+ path = File.expand_path File.join(@gem_dir, path)
567
+
568
+ if path !~ /\A#{Regexp.escape @gem_dir}/ then
569
+ msg = "attempt to install file into %p under %p" %
570
+ [entry['path'], @gem_dir]
571
+ raise LibGems::InstallError, msg
572
+ end
573
+
574
+ FileUtils.rm_rf(path) if File.exists?(path)
575
+
576
+ dir = File.dirname(path)
577
+ if !dirs.include?(dir)
578
+ dirs << dir
579
+ FileUtils.mkdir_p dir
580
+ end
581
+
582
+ File.open(path, "wb") do |out|
583
+ out.write file_data
584
+ end
585
+
586
+ FileUtils.chmod entry['mode'], path
587
+
588
+ say path if LibGems.configuration.really_verbose
589
+ end
590
+ end
591
+
592
+ ##
593
+ # Prefix and suffix the program filename the same as ruby.
594
+
595
+ def formatted_program_filename(filename)
596
+ if @format_executable then
597
+ self.class.exec_format % File.basename(filename)
598
+ else
599
+ filename
600
+ end
601
+ end
602
+
603
+ end
604
+