passenger 5.0.0.beta3 → 5.0.0.rc1

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

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (218) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/.editorconfig +11 -5
  5. data/CHANGELOG +38 -0
  6. data/CONTRIBUTING.md +1 -4
  7. data/Gemfile +0 -1
  8. data/Gemfile.lock +0 -2
  9. data/Rakefile +33 -33
  10. data/bin/passenger +1 -1
  11. data/bin/passenger-config +1 -1
  12. data/bin/passenger-install-apache2-module +800 -800
  13. data/bin/passenger-install-nginx-module +592 -592
  14. data/bin/passenger-memory-stats +127 -127
  15. data/bin/passenger-status +216 -216
  16. data/build/agents.rb +127 -127
  17. data/build/apache2.rb +87 -87
  18. data/build/basics.rb +60 -60
  19. data/build/common_library.rb +165 -165
  20. data/build/cplusplus_support.rb +51 -51
  21. data/build/cxx_tests.rb +268 -268
  22. data/build/debian.rb +143 -143
  23. data/build/documentation.rb +58 -58
  24. data/build/integration_tests.rb +81 -81
  25. data/build/misc.rb +132 -132
  26. data/build/nginx.rb +20 -20
  27. data/build/node_tests.rb +7 -7
  28. data/build/oxt_tests.rb +14 -14
  29. data/build/packaging.rb +570 -570
  30. data/build/preprocessor.rb +260 -260
  31. data/build/rake_extensions.rb +71 -71
  32. data/build/ruby_extension.rb +29 -29
  33. data/build/ruby_tests.rb +6 -6
  34. data/build/test_basics.rb +37 -37
  35. data/debian.template/control.template +3 -5
  36. data/dev/copy_boost_headers +134 -134
  37. data/dev/install_scripts_bootstrap_code.rb +25 -25
  38. data/dev/list_tests +20 -20
  39. data/dev/ruby_server.rb +223 -223
  40. data/dev/runner +18 -18
  41. data/doc/ServerOptimizationGuide.txt.md +55 -2
  42. data/doc/Users guide Nginx.txt +0 -26
  43. data/doc/Users guide Standalone.txt +5 -1
  44. data/doc/users_guide_snippets/tips.txt +9 -0
  45. data/ext/common/ApplicationPool2/Group.h +23 -11
  46. data/ext/common/ApplicationPool2/Implementation.cpp +32 -7
  47. data/ext/common/ApplicationPool2/Pool.h +22 -17
  48. data/ext/common/ApplicationPool2/SmartSpawner.h +4 -1
  49. data/ext/common/ApplicationPool2/Spawner.h +1 -1
  50. data/ext/common/Constants.h +1 -1
  51. data/ext/common/agents/Base.cpp +35 -20
  52. data/ext/common/agents/HelperAgent/Main.cpp +8 -1
  53. data/ext/common/agents/HelperAgent/OptionParser.h +18 -4
  54. data/ext/common/agents/HelperAgent/RequestHandler.h +2 -83
  55. data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +54 -1
  56. data/ext/common/agents/HelperAgent/RequestHandler/InitRequest.cpp +7 -4
  57. data/ext/common/agents/Main.cpp +1 -1
  58. data/ext/common/agents/Watchdog/Main.cpp +54 -19
  59. data/ext/nginx/Configuration.c +7 -0
  60. data/ext/nginx/ContentHandler.c +9 -1
  61. data/helper-scripts/backtrace-sanitizer.rb +106 -87
  62. data/helper-scripts/crash-watch.rb +32 -0
  63. data/helper-scripts/download_binaries/extconf.rb +38 -38
  64. data/helper-scripts/meteor-loader.rb +107 -107
  65. data/helper-scripts/prespawn +101 -101
  66. data/helper-scripts/rack-loader.rb +96 -96
  67. data/helper-scripts/rack-preloader.rb +137 -137
  68. data/lib/phusion_passenger.rb +292 -292
  69. data/lib/phusion_passenger/abstract_installer.rb +438 -438
  70. data/lib/phusion_passenger/active_support3_extensions/init.rb +168 -170
  71. data/lib/phusion_passenger/admin_tools.rb +20 -20
  72. data/lib/phusion_passenger/admin_tools/instance.rb +178 -178
  73. data/lib/phusion_passenger/admin_tools/instance_registry.rb +61 -61
  74. data/lib/phusion_passenger/admin_tools/memory_stats.rb +267 -267
  75. data/lib/phusion_passenger/apache2/config_options.rb +182 -182
  76. data/lib/phusion_passenger/common_library.rb +479 -485
  77. data/lib/phusion_passenger/config/about_command.rb +161 -161
  78. data/lib/phusion_passenger/config/admin_command_command.rb +129 -129
  79. data/lib/phusion_passenger/config/agent_compiler.rb +121 -121
  80. data/lib/phusion_passenger/config/build_native_support_command.rb +43 -43
  81. data/lib/phusion_passenger/config/command.rb +25 -25
  82. data/lib/phusion_passenger/config/compile_agent_command.rb +62 -62
  83. data/lib/phusion_passenger/config/compile_nginx_engine_command.rb +88 -73
  84. data/lib/phusion_passenger/config/detach_process_command.rb +72 -72
  85. data/lib/phusion_passenger/config/download_agent_command.rb +246 -227
  86. data/lib/phusion_passenger/config/download_nginx_engine_command.rb +245 -224
  87. data/lib/phusion_passenger/config/install_agent_command.rb +144 -132
  88. data/lib/phusion_passenger/config/install_standalone_runtime_command.rb +205 -185
  89. data/lib/phusion_passenger/config/installation_utils.rb +204 -204
  90. data/lib/phusion_passenger/config/list_instances_command.rb +64 -64
  91. data/lib/phusion_passenger/config/main.rb +152 -152
  92. data/lib/phusion_passenger/config/nginx_engine_compiler.rb +319 -300
  93. data/lib/phusion_passenger/config/reopen_logs_command.rb +67 -67
  94. data/lib/phusion_passenger/config/restart_app_command.rb +155 -155
  95. data/lib/phusion_passenger/config/system_metrics_command.rb +13 -13
  96. data/lib/phusion_passenger/config/utils.rb +95 -95
  97. data/lib/phusion_passenger/config/validate_install_command.rb +198 -198
  98. data/lib/phusion_passenger/console_text_template.rb +25 -25
  99. data/lib/phusion_passenger/constants.rb +90 -90
  100. data/lib/phusion_passenger/debug_logging.rb +106 -106
  101. data/lib/phusion_passenger/loader_shared_helpers.rb +447 -432
  102. data/lib/phusion_passenger/message_channel.rb +312 -312
  103. data/lib/phusion_passenger/message_client.rb +176 -176
  104. data/lib/phusion_passenger/native_support.rb +369 -369
  105. data/lib/phusion_passenger/nginx/config_options.rb +297 -297
  106. data/lib/phusion_passenger/packaging.rb +131 -131
  107. data/lib/phusion_passenger/platform_info.rb +360 -360
  108. data/lib/phusion_passenger/platform_info/apache.rb +767 -767
  109. data/lib/phusion_passenger/platform_info/apache_detector.rb +199 -199
  110. data/lib/phusion_passenger/platform_info/binary_compatibility.rb +107 -107
  111. data/lib/phusion_passenger/platform_info/compiler.rb +570 -570
  112. data/lib/phusion_passenger/platform_info/curl.rb +32 -32
  113. data/lib/phusion_passenger/platform_info/cxx_portability.rb +188 -188
  114. data/lib/phusion_passenger/platform_info/depcheck.rb +372 -372
  115. data/lib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +109 -109
  116. data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +4 -4
  117. data/lib/phusion_passenger/platform_info/depcheck_specs/gems.rb +10 -34
  118. data/lib/phusion_passenger/platform_info/depcheck_specs/libs.rb +101 -101
  119. data/lib/phusion_passenger/platform_info/depcheck_specs/ruby.rb +5 -5
  120. data/lib/phusion_passenger/platform_info/depcheck_specs/utilities.rb +13 -13
  121. data/lib/phusion_passenger/platform_info/linux.rb +55 -55
  122. data/lib/phusion_passenger/platform_info/operating_system.rb +149 -149
  123. data/lib/phusion_passenger/platform_info/ruby.rb +468 -448
  124. data/lib/phusion_passenger/platform_info/zlib.rb +9 -9
  125. data/lib/phusion_passenger/plugin.rb +66 -66
  126. data/lib/phusion_passenger/preloader_shared_helpers.rb +126 -126
  127. data/lib/phusion_passenger/public_api.rb +191 -191
  128. data/lib/phusion_passenger/rack/out_of_band_gc.rb +93 -94
  129. data/lib/phusion_passenger/rack/thread_handler_extension.rb +231 -227
  130. data/lib/phusion_passenger/request_handler.rb +567 -577
  131. data/lib/phusion_passenger/request_handler/thread_handler.rb +379 -381
  132. data/lib/phusion_passenger/ruby_core_enhancements.rb +86 -86
  133. data/lib/phusion_passenger/ruby_core_io_enhancements.rb +74 -74
  134. data/lib/phusion_passenger/simple_benchmarking.rb +25 -25
  135. data/lib/phusion_passenger/standalone/app_finder.rb +153 -150
  136. data/lib/phusion_passenger/standalone/command.rb +44 -40
  137. data/lib/phusion_passenger/standalone/config_utils.rb +53 -53
  138. data/lib/phusion_passenger/standalone/control_utils.rb +38 -59
  139. data/lib/phusion_passenger/standalone/main.rb +73 -73
  140. data/lib/phusion_passenger/standalone/start_command.rb +697 -685
  141. data/lib/phusion_passenger/standalone/start_command/builtin_engine.rb +193 -155
  142. data/lib/phusion_passenger/standalone/start_command/nginx_engine.rb +162 -133
  143. data/lib/phusion_passenger/standalone/status_command.rb +64 -64
  144. data/lib/phusion_passenger/standalone/stop_command.rb +72 -72
  145. data/lib/phusion_passenger/standalone/version_command.rb +9 -9
  146. data/lib/phusion_passenger/union_station/connection.rb +32 -32
  147. data/lib/phusion_passenger/union_station/core.rb +251 -251
  148. data/lib/phusion_passenger/union_station/transaction.rb +126 -126
  149. data/lib/phusion_passenger/utils.rb +199 -167
  150. data/lib/phusion_passenger/utils/ansi_colors.rb +128 -128
  151. data/lib/phusion_passenger/utils/download.rb +196 -196
  152. data/lib/phusion_passenger/utils/file_system_watcher.rb +158 -158
  153. data/lib/phusion_passenger/utils/hosts_file_parser.rb +101 -101
  154. data/lib/phusion_passenger/utils/lock.rb +31 -31
  155. data/lib/phusion_passenger/utils/native_support_utils.rb +31 -31
  156. data/lib/phusion_passenger/utils/progress_bar.rb +26 -26
  157. data/lib/phusion_passenger/utils/shellwords.rb +20 -20
  158. data/lib/phusion_passenger/utils/terminal_choice_menu.rb +206 -206
  159. data/lib/phusion_passenger/utils/unseekable_socket.rb +272 -272
  160. data/lib/phusion_passenger/vendor/crash_watch/app.rb +129 -0
  161. data/lib/phusion_passenger/vendor/crash_watch/gdb_controller.rb +341 -0
  162. data/lib/phusion_passenger/vendor/crash_watch/version.rb +24 -0
  163. data/lib/phusion_passenger/vendor/daemon_controller.rb +877 -0
  164. data/lib/phusion_passenger/vendor/daemon_controller/lock_file.rb +127 -0
  165. data/lib/phusion_passenger/vendor/daemon_controller/spawn.rb +26 -0
  166. data/lib/phusion_passenger/vendor/daemon_controller/version.rb +29 -0
  167. data/packaging/rpm/passenger_spec/passenger.spec.template +0 -1
  168. data/passenger.gemspec +0 -1
  169. data/resources/templates/config/nginx_engine_compiler/possible_solutions_for_download_and_extraction_problems.txt.erb +27 -0
  170. data/resources/templates/standalone/config.erb +19 -15
  171. data/test/integration_tests/apache2_tests.rb +566 -566
  172. data/test/integration_tests/downloaded_binaries_tests.rb +126 -125
  173. data/test/integration_tests/native_packaging_spec.rb +296 -296
  174. data/test/integration_tests/nginx_tests.rb +393 -393
  175. data/test/integration_tests/shared/example_webapp_tests.rb +282 -280
  176. data/test/integration_tests/source_packaging_test.rb +138 -138
  177. data/test/integration_tests/spec_helper.rb +5 -5
  178. data/test/integration_tests/standalone_tests.rb +367 -367
  179. data/test/ruby/debug_logging_spec.rb +133 -133
  180. data/test/ruby/message_channel_spec.rb +186 -186
  181. data/test/ruby/rack/loader_spec.rb +28 -28
  182. data/test/ruby/rack/preloader_spec.rb +34 -34
  183. data/test/ruby/rails3.0/loader_spec.rb +12 -12
  184. data/test/ruby/rails3.0/preloader_spec.rb +18 -18
  185. data/test/ruby/rails3.1/loader_spec.rb +12 -12
  186. data/test/ruby/rails3.1/preloader_spec.rb +18 -18
  187. data/test/ruby/rails3.2/loader_spec.rb +12 -12
  188. data/test/ruby/rails3.2/preloader_spec.rb +18 -18
  189. data/test/ruby/rails4.0/loader_spec.rb +12 -12
  190. data/test/ruby/rails4.0/preloader_spec.rb +18 -18
  191. data/test/ruby/rails4.1/loader_spec.rb +12 -12
  192. data/test/ruby/rails4.1/preloader_spec.rb +18 -18
  193. data/test/ruby/request_handler_spec.rb +730 -730
  194. data/test/ruby/shared/loader_sharedspec.rb +224 -224
  195. data/test/ruby/shared/rails/union_station_extensions_sharedspec.rb +327 -327
  196. data/test/ruby/shared/ruby_loader_sharedspec.rb +47 -47
  197. data/test/ruby/spec_helper.rb +65 -65
  198. data/test/ruby/standalone/runtime_installer_spec.rb +384 -384
  199. data/test/ruby/union_station_spec.rb +276 -276
  200. data/test/ruby/utils/file_system_watcher_spec.rb +220 -220
  201. data/test/ruby/utils/hosts_file_parser.rb +248 -248
  202. data/test/ruby/utils/tee_input_spec.rb +215 -215
  203. data/test/ruby/utils/unseekable_socket_spec.rb +57 -57
  204. data/test/ruby/utils_spec.rb +21 -21
  205. data/test/stub/rack/config.ru +87 -87
  206. data/test/stub/rack/library.rb +8 -8
  207. data/test/stub/rack/start.rb +30 -30
  208. data/test/support/apache2_controller.rb +191 -191
  209. data/test/support/nginx_controller.rb +90 -99
  210. data/test/support/placebo-preloader.rb +57 -57
  211. data/test/support/test_helper.rb +435 -435
  212. metadata +11 -21
  213. metadata.gz.asc +7 -7
  214. data/lib/phusion_passenger/standalone/command2.rb +0 -292
  215. data/lib/phusion_passenger/standalone/start2_command.rb +0 -799
  216. data/resources/templates/standalone/download_tool_missing.txt.erb +0 -18
  217. data/resources/templates/standalone/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -17
  218. data/resources/templates/standalone/run_installer_as_root.txt.erb +0 -8
@@ -1,5 +1,6 @@
1
+ # encoding: binary
1
2
  # Phusion Passenger - https://www.phusionpassenger.com/
2
- # Copyright (c) 2010 Phusion
3
+ # Copyright (c) 2010-2015 Phusion
3
4
  #
4
5
  # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
5
6
  #
@@ -28,452 +29,471 @@ PhusionPassenger.require_passenger_lib 'platform_info/operating_system'
28
29
 
29
30
  module PhusionPassenger
30
31
 
31
- module PlatformInfo
32
- # Store original $GEM_HOME value so that even if the app customizes
33
- # $GEM_HOME we can still work with the original value.
34
- gem_home = ENV['GEM_HOME']
35
- if gem_home
36
- gem_home = gem_home.strip.freeze
37
- gem_home = nil if gem_home.empty?
38
- end
39
- GEM_HOME = gem_home
40
-
41
- # Ditto for $GEM_PATH
42
- gem_path = ENV['GEM_PATH']
43
- if gem_path
44
- gem_path = gem_path.strip.freeze
45
- gem_path = nil if gem_path.empty?
46
- end
47
- GEM_PATH = gem_path
48
-
49
- if defined?(::RUBY_ENGINE)
50
- RUBY_ENGINE = ::RUBY_ENGINE
51
- else
52
- RUBY_ENGINE = "ruby"
53
- end
54
-
55
- # Returns correct command for invoking the current Ruby interpreter.
56
- # In case of RVM this function will return the path to the RVM wrapper script
57
- # that executes the current Ruby interpreter in the currently active gem set.
58
- def self.ruby_command
59
- # Detect usage of gem-wrappers: https://github.com/rvm/gem-wrappers
60
- # This is currently used by RVM >= 1.25, although it's not exclusive to RVM.
61
- if GEM_HOME && File.exist?("#{GEM_HOME}/wrappers/ruby")
62
- return "#{GEM_HOME}/wrappers/ruby"
63
- end
64
-
65
- if in_rvm?
66
- # Detect old-school RVM wrapper script location.
67
- name = rvm_ruby_string
68
- dirs = rvm_paths
69
- if name && dirs
70
- dirs.each do |dir|
71
- filename = "#{dir}/wrappers/#{name}/ruby"
72
- if File.exist?(filename)
73
- contents = File.open(filename, 'rb') do |f|
74
- f.read
75
- end
76
- # Old wrapper scripts reference $HOME which causes
77
- # things to blow up when run by a different user.
78
- if contents.include?("$HOME")
79
- filename = nil
80
- end
81
- else
82
- filename = nil
83
- end
84
- if filename
85
- return filename
86
- end
87
- end
88
-
89
- # Correctness of these commands are confirmed by mpapis.
90
- # If we ever encounter a case for which this logic is not sufficient,
91
- # try mpapis' pseudo code:
92
- #
93
- # rvm_update_prefix = write_to rvm_path ? "" : "rvmsudo"
94
- # rvm_gemhome_prefix = write_to GEM_HOME ? "" : "rvmsudo"
95
- # repair_command = "#{rvm_update_prefix} rvm get stable && rvm reload && #{rvm_gemhome_prefix} rvm repair all"
96
- # wrapper_command = "#{rvm_gemhome_prefix} rvm wrapper #{rvm_ruby_string} --no-prefix --all"
97
- case rvm_installation_mode
98
- when :single
99
- repair_command = "rvm get stable && rvm reload && rvm repair all"
100
- wrapper_command = "rvm wrapper #{rvm_ruby_string} --no-prefix --all"
101
- when :multi
102
- repair_command = "rvmsudo rvm get stable && rvm reload && rvmsudo rvm repair all"
103
- wrapper_command = "rvmsudo rvm wrapper #{rvm_ruby_string} --no-prefix --all"
104
- when :mixed
105
- repair_command = "rvmsudo rvm get stable && rvm reload && rvm repair all"
106
- wrapper_command = "rvm wrapper #{rvm_ruby_string} --no-prefix --all"
107
- end
108
-
109
- STDERR.puts "Your RVM wrapper scripts are too old, or some " +
110
- "wrapper scripts are missing. Please update/regenerate " +
111
- "them first by running:\n\n" +
112
- " #{repair_command}\n\n" +
113
- "If that doesn't seem to work, please run:\n\n" +
114
- " #{wrapper_command}"
115
- exit 1
116
- else
117
- # Something's wrong with the user's RVM installation.
118
- # Raise an error so that the user knows this instead of
119
- # having things fail randomly later on.
120
- # 'name' is guaranteed to be non-nil because rvm_ruby_string
121
- # already raises an exception on error.
122
- STDERR.puts "Your RVM installation appears to be broken: the RVM " +
123
- "path cannot be found. Please fix your RVM installation " +
124
- "or contact the RVM developers for support."
125
- exit 1
126
- end
127
- else
128
- return ruby_executable
129
- end
130
- end
131
- memoize :ruby_command
132
-
133
- # Returns the full path to the current Ruby interpreter's executable file.
134
- # This might not be the actual correct command to use for invoking the Ruby
135
- # interpreter; use ruby_command instead.
136
- def self.ruby_executable
137
- @@ruby_executable ||=
138
- rb_config['bindir'] + '/' + rb_config['RUBY_INSTALL_NAME'] + rb_config['EXEEXT']
139
- end
140
-
141
- # Returns whether the Ruby interpreter supports process forking.
142
- def self.ruby_supports_fork?
143
- # MRI >= 1.9.2's respond_to? returns false for methods
144
- # that are not implemented.
145
- return Process.respond_to?(:fork) &&
146
- RUBY_ENGINE != "jruby" &&
147
- RUBY_ENGINE != "macruby" &&
148
- rb_config['target_os'] !~ /mswin|windows|mingw/
149
- end
150
-
151
- # Returns whether Phusion Passenger needs Ruby development headers to
152
- # be available for the current Ruby implementation.
153
- def self.passenger_needs_ruby_dev_header?
154
- # Too much of a trouble for JRuby. We can do without it.
155
- return RUBY_ENGINE != "jruby"
156
- end
157
-
158
- # Returns the correct 'gem' command for this Ruby interpreter.
159
- # If `:sudo => true` is given, then the gem command is prefixed by a
160
- # sudo command if filesystem permissions require this.
161
- def self.gem_command(options = {})
162
- command = locate_ruby_tool('gem')
163
- if options[:sudo] && gem_install_requires_sudo?
164
- command = "#{ruby_sudo_command} #{command}"
165
- end
166
- return command
167
- end
168
- memoize :gem_command
169
-
170
- # Returns whether running 'gem install' as the current user requires sudo.
171
- def self.gem_install_requires_sudo?
172
- `#{gem_command} env` =~ /INSTALLATION DIRECTORY: (.+)/
173
- if install_dir = $1
174
- return !File.writable?(install_dir)
175
- else
176
- return nil
177
- end
178
- end
179
- memoize :gem_install_requires_sudo?
180
-
181
- # Returns the absolute path to the Rake executable that
182
- # belongs to the current Ruby interpreter. Returns nil if it
183
- # doesn't exist.
184
- #
185
- # The return value may not be the actual correct invocation
186
- # for Rake. Use rake_command for that.
187
- def self.rake
188
- return locate_ruby_tool('rake')
189
- end
190
- memoize :rake
191
-
192
- # Returns the correct command string for invoking the Rake executable
193
- # that belongs to the current Ruby interpreter. Returns nil if Rake is
194
- # not found.
195
- def self.rake_command
196
- filename = rake
197
- # If the Rake executable is a Ruby program then we need to run
198
- # it in the correct Ruby interpreter just in case Rake doesn't
199
- # have the correct shebang line; we don't want a totally different
200
- # Ruby than the current one to be invoked.
201
- if filename && is_ruby_program?(filename)
202
- return "#{ruby_command} #{filename}"
203
- else
204
- # If it's not a Ruby program then it's probably a wrapper
205
- # script as is the case with e.g. RVM (~/.rvm/wrappers).
206
- return filename
207
- end
208
- end
209
- memoize :rake_command
210
-
211
- # Returns the absolute path to the RSpec runner program that
212
- # belongs to the current Ruby interpreter. Returns nil if it
213
- # doesn't exist.
214
- def self.rspec
215
- return locate_ruby_tool('rspec')
216
- end
217
- memoize :rspec
218
-
219
- # Returns whether the current Ruby interpreter is managed by RVM.
220
- def self.in_rvm?
221
- bindir = rb_config['bindir']
222
- return bindir.include?('/.rvm/') || bindir.include?('/rvm/')
223
- end
224
-
225
- # If the current Ruby interpreter is managed by RVM, returns all
226
- # directories in which RVM places its working files. This is usually
227
- # ~/.rvm or /usr/local/rvm, but in mixed-mode installations there
228
- # can be multiple such paths.
229
- #
230
- # Otherwise returns nil.
231
- def self.rvm_paths
232
- if in_rvm?
233
- result = []
234
- [ENV['rvm_path'], "~/.rvm", "/usr/local/rvm"].each do |path|
235
- next if path.nil?
236
- path = File.expand_path(path)
237
- rubies_path = File.join(path, 'rubies')
238
- wrappers_path = File.join(path, 'wrappers')
239
- gems_path = File.join(path, 'gems')
240
- if File.directory?(path) && (File.directory?(rubies_path) ||
241
- File.directory?(wrappers_path) || File.directory?(gems_path))
242
- result << path
243
- end
244
- end
245
- if result.empty?
246
- # Failure to locate the RVM path is probably caused by the
247
- # user customizing $rvm_path. Older RVM versions don't
248
- # export $rvm_path, making us unable to detect its value.
249
- STDERR.puts "Unable to locate the RVM path. Your RVM installation " +
250
- "is probably too old. Please update it with " +
251
- "'rvm get head && rvm reload && rvm repair all'."
252
- exit 1
253
- else
254
- return result
255
- end
256
- else
257
- return nil
258
- end
259
- end
260
- memoize :rvm_paths
261
-
262
- # If the current Ruby interpreter is managed by RVM, returns the
263
- # RVM name which identifies the current Ruby interpreter plus the
264
- # currently active gemset, e.g. something like this:
265
- # "ruby-1.9.2-p0@mygemset"
266
- #
267
- # Returns nil otherwise.
268
- def self.rvm_ruby_string
269
- if in_rvm?
270
- # RVM used to export the necessary information through
271
- # environment variables, but doesn't always do that anymore
272
- # in the latest versions in order to fight env var pollution.
273
- # Scanning $LOAD_PATH seems to be the only way to obtain
274
- # the information.
275
-
276
- # Getting the RVM name of the Ruby interpreter ("ruby-1.9.2")
277
- # isn't so hard, we can extract it from the #ruby_executable
278
- # string. Getting the gemset name is a bit harder, so let's
279
- # try various strategies...
280
-
281
- # $GEM_HOME usually contains the gem set name.
282
- # It may be something like:
283
- # /Users/hongli/.rvm/gems/ruby-1.9.3-p392
284
- # But also:
285
- # /home/bitnami/.rvm/gems/ruby-1.9.3-p385-perf@njist325/ruby/1.9.1
286
- if GEM_HOME && GEM_HOME =~ %r{rvm/gems/(.+)}
287
- return $1.sub(/\/.*/, '')
288
- end
289
-
290
- # User might have explicitly set GEM_HOME to a custom directory,
291
- # or might have nuked $GEM_HOME. Extract info from $GEM_PATH.
292
- if GEM_PATH
293
- GEM_PATH.split(':').each do |gem_path|
294
- if gem_path =~ %r{rvm/gems/(.+)}
295
- return $1.sub(/\/.*/, '')
296
- end
297
- end
298
- end
299
-
300
- # That failed too. Try extracting info from from $LOAD_PATH.
301
- matching_path = $LOAD_PATH.find_all do |item|
302
- item.include?("rvm/gems/")
303
- end
304
- if matching_path && !matching_path.empty?
305
- subpath = matching_path.to_s.gsub(/^.*rvm\/gems\//, '')
306
- result = subpath.split('/').first
307
- return result if result
308
- end
309
-
310
- # On Ruby 1.9, $LOAD_PATH does not contain any gem paths until
311
- # at least one gem has been required so the above can fail.
312
- # We're out of options now, we can't detect the gem set.
313
- # Raise an exception so that the user knows what's going on
314
- # instead of having things fail in obscure ways later.
315
- STDERR.puts "Unable to autodetect the currently active RVM gem " +
316
- "set name. This could happen if you ran this program using 'sudo' " +
317
- "instead of 'rvmsudo'. When using RVM, you're always supposed to " +
318
- "use 'rvmsudo' instead of 'sudo!'.\n\n" +
319
- "Please try rerunning this program using 'rvmsudo'. If that " +
320
- "doesn't help, please contact this program's author for support."
321
- exit 1
322
- end
323
- return nil
324
- end
325
- memoize :rvm_ruby_string
326
-
327
- # Returns the RVM installation mode:
328
- # :single - RVM is installed in single-user mode.
329
- # :multi - RVM is installed in multi-user mode.
330
- # :mixed - RVM is in a mixed-mode installation.
331
- # nil - The current Ruby interpreter is not using RVM.
332
- def self.rvm_installation_mode
333
- if in_rvm?
334
- if ENV['rvm_path'] =~ /\.rvm/
335
- return :single
336
- else
337
- if GEM_HOME =~ /\.rvm/
338
- return :mixed
339
- else
340
- return :multi
341
- end
342
- end
343
- else
344
- return nil
345
- end
346
- end
347
-
348
- # Returns either 'sudo' or 'rvmsudo' depending on whether the current
349
- # Ruby interpreter is managed by RVM.
350
- def self.ruby_sudo_command
351
- if in_rvm?
352
- return "rvmsudo"
353
- else
354
- return "sudo"
355
- end
356
- end
357
-
358
- # Returns a `sudo` or `rvmsudo` command that spawns a shell, depending
359
- # on whether the current Ruby interpreter is managed by RVM.
360
- def self.ruby_sudo_shell_command(args = nil)
361
- if in_rvm?
362
- shell = ENV['SHELL'].to_s
363
- if shell.empty?
364
- begin
365
- user = Etc.getpwuid(0)
366
- rescue ArgumentError
367
- user = nil
368
- end
369
- shell = user.shell if user
370
- shell = "bash" if !shell || shell.empty?
371
- end
372
- result = "rvmsudo "
373
- result << "#{args} " if args
374
- result << shell
375
- return result
376
- else
377
- return "sudo -s #{args}".strip
378
- end
379
- end
380
-
381
- # Locates a Ruby tool command, e.g. 'gem', 'rake', 'bundle', etc. Instead of
382
- # naively looking in $PATH, this function uses a variety of search heuristics
383
- # to find the command that's really associated with the current Ruby interpreter.
384
- # It should never locate a command that's actually associated with a different
385
- # Ruby interpreter.
386
- # Returns nil when nothing's found.
387
- def self.locate_ruby_tool(name)
388
- result = locate_ruby_tool_by_basename(name)
389
- if !result
390
- exeext = rb_config['EXEEXT']
391
- exeext = nil if exeext.empty?
392
- if exeext
393
- result = locate_ruby_tool_by_basename("#{name}#{exeext}")
394
- end
395
- if !result
396
- result = locate_ruby_tool_by_basename(transform_according_to_ruby_exec_format(name))
397
- end
398
- if !result && exeext
399
- result = locate_ruby_tool_by_basename(transform_according_to_ruby_exec_format(name) + exeext)
400
- end
401
- end
402
- return result
403
- end
404
-
405
- private
406
- def self.locate_ruby_tool_by_basename(name)
407
- if os_name == "macosx" &&
408
- ruby_command =~ %r(\A/System/Library/Frameworks/Ruby.framework/Versions/.*?/usr/bin/ruby\Z)
409
- # On OS X we must look for Ruby binaries in /usr/bin.
410
- # RubyGems puts executables (e.g. 'rake') in there, not in
411
- # /System/Libraries/(...)/bin.
412
- filename = "/usr/bin/#{name}"
413
- else
414
- filename = File.dirname(ruby_command) + "/#{name}"
415
- end
416
-
417
- if !File.file?(filename) || !File.executable?(filename)
418
- # RubyGems might put binaries in a directory other
419
- # than Ruby's bindir. Debian packaged RubyGems and
420
- # DebGem packaged RubyGems are the prime examples.
421
- begin
422
- require 'rubygems' unless defined?(Gem)
423
- filename = Gem.bindir + "/#{name}"
424
- rescue LoadError
425
- filename = nil
426
- end
427
- end
428
-
429
- if !filename || !File.file?(filename) || !File.executable?(filename)
430
- # Looks like it's not in the RubyGems bindir. Search in $PATH, but
431
- # be very careful about this because whatever we find might belong
432
- # to a different Ruby interpreter than the current one.
433
- ENV['PATH'].split(':').each do |dir|
434
- filename = "#{dir}/#{name}"
435
- if File.file?(filename) && File.executable?(filename)
436
- shebang = File.open(filename, 'rb') do |f|
437
- f.readline.strip
438
- end
439
- if shebang == "#!#{ruby_command}"
440
- # Looks good.
441
- break
442
- end
443
- end
444
-
445
- # Not found. Try next path.
446
- filename = nil
447
- end
448
- end
449
-
450
- filename
451
- end
452
- private_class_method :locate_ruby_tool_by_basename
453
-
454
- def self.is_ruby_program?(filename)
455
- File.open(filename, 'rb') do |f|
456
- return f.readline =~ /ruby/
457
- end
458
- rescue EOFError
459
- return false
460
- end
461
- private_class_method :is_ruby_program?
462
-
463
- # Deduce Ruby's --program-prefix and --program-suffix from its install name
464
- # and transforms the given input name accordingly.
465
- #
466
- # transform_according_to_ruby_exec_format("rake") => "jrake", "rake1.8", etc
467
- def self.transform_according_to_ruby_exec_format(name)
468
- install_name = rb_config['RUBY_INSTALL_NAME']
469
- if install_name.include?('ruby')
470
- format = install_name.sub('ruby', '%s')
471
- return sprintf(format, name)
472
- else
473
- return name
474
- end
475
- end
476
- private_class_method :transform_according_to_ruby_exec_format
477
- end
32
+ module PlatformInfo
33
+ # Store original $GEM_HOME value so that even if the app customizes
34
+ # $GEM_HOME we can still work with the original value.
35
+ gem_home = ENV['GEM_HOME']
36
+ if gem_home
37
+ gem_home = gem_home.strip.freeze
38
+ gem_home = nil if gem_home.empty?
39
+ end
40
+ GEM_HOME = gem_home
41
+
42
+ # Ditto for $GEM_PATH
43
+ gem_path = ENV['GEM_PATH']
44
+ if gem_path
45
+ gem_path = gem_path.strip.freeze
46
+ gem_path = nil if gem_path.empty?
47
+ end
48
+ GEM_PATH = gem_path
49
+
50
+ if defined?(::RUBY_ENGINE)
51
+ RUBY_ENGINE = ::RUBY_ENGINE
52
+ else
53
+ RUBY_ENGINE = "ruby"
54
+ end
55
+
56
+ # Returns correct command for invoking the current Ruby interpreter.
57
+ # In case of RVM this function will return the path to the RVM wrapper script
58
+ # that executes the current Ruby interpreter in the currently active gem set.
59
+ def self.ruby_command
60
+ # Detect usage of gem-wrappers: https://github.com/rvm/gem-wrappers
61
+ # This is currently used by RVM >= 1.25, although it's not exclusive to RVM.
62
+ if GEM_HOME && File.exist?("#{GEM_HOME}/wrappers/ruby")
63
+ return "#{GEM_HOME}/wrappers/ruby"
64
+ end
65
+
66
+ if in_rvm?
67
+ # Detect old-school RVM wrapper script location.
68
+ name = rvm_ruby_string
69
+ dirs = rvm_paths
70
+ if name && dirs
71
+ dirs.each do |dir|
72
+ filename = "#{dir}/wrappers/#{name}/ruby"
73
+ if File.exist?(filename)
74
+ contents = File.open(filename, 'rb') do |f|
75
+ f.read
76
+ end
77
+ # Old wrapper scripts reference $HOME which causes
78
+ # things to blow up when run by a different user.
79
+ if contents.include?("$HOME")
80
+ filename = nil
81
+ end
82
+ else
83
+ filename = nil
84
+ end
85
+ if filename
86
+ return filename
87
+ end
88
+ end
89
+
90
+ # Correctness of these commands are confirmed by mpapis.
91
+ # If we ever encounter a case for which this logic is not sufficient,
92
+ # try mpapis' pseudo code:
93
+ #
94
+ # rvm_update_prefix = write_to rvm_path ? "" : "rvmsudo"
95
+ # rvm_gemhome_prefix = write_to GEM_HOME ? "" : "rvmsudo"
96
+ # repair_command = "#{rvm_update_prefix} rvm get stable && rvm reload && #{rvm_gemhome_prefix} rvm repair all"
97
+ # wrapper_command = "#{rvm_gemhome_prefix} rvm wrapper #{rvm_ruby_string} --no-prefix --all"
98
+ case rvm_installation_mode
99
+ when :single
100
+ repair_command = "rvm get stable && rvm reload && rvm repair all"
101
+ wrapper_command = "rvm wrapper #{rvm_ruby_string} --no-prefix --all"
102
+ when :multi
103
+ repair_command = "rvmsudo rvm get stable && rvm reload && rvmsudo rvm repair all"
104
+ wrapper_command = "rvmsudo rvm wrapper #{rvm_ruby_string} --no-prefix --all"
105
+ when :mixed
106
+ repair_command = "rvmsudo rvm get stable && rvm reload && rvm repair all"
107
+ wrapper_command = "rvm wrapper #{rvm_ruby_string} --no-prefix --all"
108
+ end
109
+
110
+ STDERR.puts "Your RVM wrapper scripts are too old, or some " +
111
+ "wrapper scripts are missing. Please update/regenerate " +
112
+ "them first by running:\n\n" +
113
+ " #{repair_command}\n\n" +
114
+ "If that doesn't seem to work, please run:\n\n" +
115
+ " #{wrapper_command}"
116
+ exit 1
117
+ else
118
+ # Something's wrong with the user's RVM installation.
119
+ # Raise an error so that the user knows this instead of
120
+ # having things fail randomly later on.
121
+ # 'name' is guaranteed to be non-nil because rvm_ruby_string
122
+ # already raises an exception on error.
123
+ STDERR.puts "Your RVM installation appears to be broken: the RVM " +
124
+ "path cannot be found. Please fix your RVM installation " +
125
+ "or contact the RVM developers for support."
126
+ exit 1
127
+ end
128
+ else
129
+ return ruby_executable
130
+ end
131
+ end
132
+ memoize :ruby_command
133
+
134
+ # Returns the full path to the current Ruby interpreter's executable file.
135
+ # This might not be the actual correct command to use for invoking the Ruby
136
+ # interpreter; use ruby_command instead.
137
+ def self.ruby_executable
138
+ @@ruby_executable ||=
139
+ rb_config['bindir'] + '/' + rb_config['RUBY_INSTALL_NAME'] + rb_config['EXEEXT']
140
+ end
141
+
142
+ # Returns whether the Ruby interpreter supports process forking.
143
+ def self.ruby_supports_fork?
144
+ # MRI >= 1.9.2's respond_to? returns false for methods
145
+ # that are not implemented.
146
+ return Process.respond_to?(:fork) &&
147
+ RUBY_ENGINE != "jruby" &&
148
+ RUBY_ENGINE != "macruby" &&
149
+ rb_config['target_os'] !~ /mswin|windows|mingw/
150
+ end
151
+
152
+ # Returns whether Phusion Passenger needs Ruby development headers to
153
+ # be available for the current Ruby implementation.
154
+ def self.passenger_needs_ruby_dev_header?
155
+ # Too much of a trouble for JRuby. We can do without it.
156
+ return RUBY_ENGINE != "jruby"
157
+ end
158
+
159
+ # Returns the correct 'gem' command for this Ruby interpreter.
160
+ # If `:sudo => true` is given, then the gem command is prefixed by a
161
+ # sudo command if filesystem permissions require this.
162
+ def self.gem_command(options = {})
163
+ command = ruby_tool_command('gem')
164
+ if options[:sudo] && gem_install_requires_sudo?
165
+ command = "#{ruby_sudo_command} #{command}"
166
+ end
167
+ return command
168
+ end
169
+ memoize :gem_command
170
+
171
+ # Returns whether running 'gem install' as the current user requires sudo.
172
+ def self.gem_install_requires_sudo?
173
+ `#{gem_command} env` =~ /INSTALLATION DIRECTORY: (.+)/
174
+ if install_dir = $1
175
+ return !File.writable?(install_dir)
176
+ else
177
+ return nil
178
+ end
179
+ end
180
+ memoize :gem_install_requires_sudo?
181
+
182
+ # Returns the absolute path to the Rake executable that
183
+ # belongs to the current Ruby interpreter. Returns nil if it
184
+ # doesn't exist.
185
+ #
186
+ # The return value may not be the actual correct invocation
187
+ # for Rake. Use `rake_command` for that.
188
+ def self.rake
189
+ return locate_ruby_tool('rake')
190
+ end
191
+ memoize :rake
192
+
193
+ # Returns the correct command string for invoking the Rake executable
194
+ # that belongs to the current Ruby interpreter. Returns nil if Rake is
195
+ # not found.
196
+ def self.rake_command
197
+ ruby_tool_command('rake')
198
+ end
199
+ memoize :rake_command
200
+
201
+ # Returns the absolute path to the RSpec runner program that
202
+ # belongs to the current Ruby interpreter. Returns nil if it
203
+ # doesn't exist.
204
+ def self.rspec
205
+ return locate_ruby_tool('rspec')
206
+ end
207
+ memoize :rspec
208
+
209
+ # Returns whether the current Ruby interpreter is managed by RVM.
210
+ def self.in_rvm?
211
+ bindir = rb_config['bindir']
212
+ return bindir.include?('/.rvm/') || bindir.include?('/rvm/')
213
+ end
214
+
215
+ # If the current Ruby interpreter is managed by RVM, returns all
216
+ # directories in which RVM places its working files. This is usually
217
+ # ~/.rvm or /usr/local/rvm, but in mixed-mode installations there
218
+ # can be multiple such paths.
219
+ #
220
+ # Otherwise returns nil.
221
+ def self.rvm_paths
222
+ if in_rvm?
223
+ result = []
224
+ [ENV['rvm_path'], "~/.rvm", "/usr/local/rvm"].each do |path|
225
+ next if path.nil?
226
+ path = File.expand_path(path)
227
+ rubies_path = File.join(path, 'rubies')
228
+ wrappers_path = File.join(path, 'wrappers')
229
+ gems_path = File.join(path, 'gems')
230
+ if File.directory?(path) && (File.directory?(rubies_path) ||
231
+ File.directory?(wrappers_path) || File.directory?(gems_path))
232
+ result << path
233
+ end
234
+ end
235
+ if result.empty?
236
+ # Failure to locate the RVM path is probably caused by the
237
+ # user customizing $rvm_path. Older RVM versions don't
238
+ # export $rvm_path, making us unable to detect its value.
239
+ STDERR.puts "Unable to locate the RVM path. Your RVM installation " +
240
+ "is probably too old. Please update it with " +
241
+ "'rvm get head && rvm reload && rvm repair all'."
242
+ exit 1
243
+ else
244
+ return result
245
+ end
246
+ else
247
+ return nil
248
+ end
249
+ end
250
+ memoize :rvm_paths
251
+
252
+ # If the current Ruby interpreter is managed by RVM, returns the
253
+ # RVM name which identifies the current Ruby interpreter plus the
254
+ # currently active gemset, e.g. something like this:
255
+ # "ruby-1.9.2-p0@mygemset"
256
+ #
257
+ # Returns nil otherwise.
258
+ def self.rvm_ruby_string
259
+ if in_rvm?
260
+ # RVM used to export the necessary information through
261
+ # environment variables, but doesn't always do that anymore
262
+ # in the latest versions in order to fight env var pollution.
263
+ # Scanning $LOAD_PATH seems to be the only way to obtain
264
+ # the information.
265
+
266
+ # Getting the RVM name of the Ruby interpreter ("ruby-1.9.2")
267
+ # isn't so hard, we can extract it from the #ruby_executable
268
+ # string. Getting the gemset name is a bit harder, so let's
269
+ # try various strategies...
270
+
271
+ # $GEM_HOME usually contains the gem set name.
272
+ # It may be something like:
273
+ # /Users/hongli/.rvm/gems/ruby-1.9.3-p392
274
+ # But also:
275
+ # /home/bitnami/.rvm/gems/ruby-1.9.3-p385-perf@njist325/ruby/1.9.1
276
+ if GEM_HOME && GEM_HOME =~ %r{rvm/gems/(.+)}
277
+ return $1.sub(/\/.*/, '')
278
+ end
279
+
280
+ # User might have explicitly set GEM_HOME to a custom directory,
281
+ # or might have nuked $GEM_HOME. Extract info from $GEM_PATH.
282
+ if GEM_PATH
283
+ GEM_PATH.split(':').each do |gem_path|
284
+ if gem_path =~ %r{rvm/gems/(.+)}
285
+ return $1.sub(/\/.*/, '')
286
+ end
287
+ end
288
+ end
289
+
290
+ # That failed too. Try extracting info from from $LOAD_PATH.
291
+ matching_path = $LOAD_PATH.find_all do |item|
292
+ item.include?("rvm/gems/")
293
+ end
294
+ if matching_path && !matching_path.empty?
295
+ subpath = matching_path.to_s.gsub(/^.*rvm\/gems\//, '')
296
+ result = subpath.split('/').first
297
+ return result if result
298
+ end
299
+
300
+ # On Ruby 1.9, $LOAD_PATH does not contain any gem paths until
301
+ # at least one gem has been required so the above can fail.
302
+ # We're out of options now, we can't detect the gem set.
303
+ # Raise an exception so that the user knows what's going on
304
+ # instead of having things fail in obscure ways later.
305
+ STDERR.puts "Unable to autodetect the currently active RVM gem " +
306
+ "set name. This could happen if you ran this program using 'sudo' " +
307
+ "instead of 'rvmsudo'. When using RVM, you're always supposed to " +
308
+ "use 'rvmsudo' instead of 'sudo!'.\n\n" +
309
+ "Please try rerunning this program using 'rvmsudo'. If that " +
310
+ "doesn't help, please contact this program's author for support."
311
+ exit 1
312
+ end
313
+ return nil
314
+ end
315
+ memoize :rvm_ruby_string
316
+
317
+ # Returns the RVM installation mode:
318
+ # :single - RVM is installed in single-user mode.
319
+ # :multi - RVM is installed in multi-user mode.
320
+ # :mixed - RVM is in a mixed-mode installation.
321
+ # nil - The current Ruby interpreter is not using RVM.
322
+ def self.rvm_installation_mode
323
+ if in_rvm?
324
+ if ENV['rvm_path'] =~ /\.rvm/
325
+ return :single
326
+ else
327
+ if GEM_HOME =~ /\.rvm/
328
+ return :mixed
329
+ else
330
+ return :multi
331
+ end
332
+ end
333
+ else
334
+ return nil
335
+ end
336
+ end
337
+
338
+ # Returns either 'sudo' or 'rvmsudo' depending on whether the current
339
+ # Ruby interpreter is managed by RVM.
340
+ def self.ruby_sudo_command
341
+ if in_rvm?
342
+ return "rvmsudo"
343
+ else
344
+ return "sudo"
345
+ end
346
+ end
347
+
348
+ # Returns a `sudo` or `rvmsudo` command that spawns a shell, depending
349
+ # on whether the current Ruby interpreter is managed by RVM.
350
+ def self.ruby_sudo_shell_command(args = nil)
351
+ if in_rvm?
352
+ shell = ENV['SHELL'].to_s
353
+ if shell.empty?
354
+ begin
355
+ user = Etc.getpwuid(0)
356
+ rescue ArgumentError
357
+ user = nil
358
+ end
359
+ shell = user.shell if user
360
+ shell = "bash" if !shell || shell.empty?
361
+ end
362
+ result = "rvmsudo "
363
+ result << "#{args} " if args
364
+ result << shell
365
+ return result
366
+ else
367
+ return "sudo -s #{args}".strip
368
+ end
369
+ end
370
+
371
+ # Locates a Ruby tool, e.g. 'gem', 'rake', 'bundle', etc. Instead of
372
+ # naively looking in $PATH, this function uses a variety of search heuristics
373
+ # to find the tool that's really associated with the current Ruby interpreter.
374
+ # It should never locate a tool that's actually associated with a different
375
+ # Ruby interpreter.
376
+ # Returns nil when nothing's found.
377
+ #
378
+ # This method only returns the path to the tool script. Running this script
379
+ # directly does not necessarily mean that it's run under the correct Ruby
380
+ # interpreter. You may have to prepend it with the Ruby command. Use
381
+ # `ruby_tool_command` if you want to get a command that you can execute.
382
+ def self.locate_ruby_tool(name)
383
+ result = locate_ruby_tool_by_basename(name)
384
+ if !result
385
+ exeext = rb_config['EXEEXT']
386
+ exeext = nil if exeext.empty?
387
+ if exeext
388
+ result = locate_ruby_tool_by_basename("#{name}#{exeext}")
389
+ end
390
+ if !result
391
+ result = locate_ruby_tool_by_basename(transform_according_to_ruby_exec_format(name))
392
+ end
393
+ if !result && exeext
394
+ result = locate_ruby_tool_by_basename(transform_according_to_ruby_exec_format(name) + exeext)
395
+ end
396
+ end
397
+ return result
398
+ end
399
+
400
+ # Locates a Ruby tool command, e.g. 'gem', 'rake', 'bundle', etc. Instead of
401
+ # naively looking in $PATH, this function uses a variety of search heuristics
402
+ # to find the command that's really associated with the current Ruby interpreter.
403
+ # It should never locate a command that's actually associated with a different
404
+ # Ruby interpreter.
405
+ # Returns nil when nothing's found.
406
+ #
407
+ # Unlike `locate_ruby_tool`, which only returns the path to the tool script,
408
+ # this method returns a full command that you can execute. The returned command
409
+ # guarantees that the tool is run under the correct Ruby interpreter.
410
+ def self.ruby_tool_command(name)
411
+ path = locate_ruby_tool(name)
412
+ if path
413
+ if is_ruby_program?(path)
414
+ "#{ruby_command} #{path}"
415
+ else
416
+ # The found tool is a wrapper script, e.g. in RVM's ~/.rvm/wrappers.
417
+ # In this case, don't include the Ruby command in the result.
418
+ path
419
+ end
420
+ else
421
+ nil
422
+ end
423
+ end
424
+
425
+ private
426
+ def self.locate_ruby_tool_by_basename(name)
427
+ if os_name == "macosx" &&
428
+ ruby_command =~ %r(\A/System/Library/Frameworks/Ruby.framework/Versions/.*?/usr/bin/ruby\Z)
429
+ # On OS X we must look for Ruby binaries in /usr/bin.
430
+ # RubyGems puts executables (e.g. 'rake') in there, not in
431
+ # /System/Libraries/(...)/bin.
432
+ filename = "/usr/bin/#{name}"
433
+ else
434
+ filename = File.dirname(ruby_command) + "/#{name}"
435
+ end
436
+
437
+ if !File.file?(filename) || !File.executable?(filename)
438
+ # RubyGems might put binaries in a directory other
439
+ # than Ruby's bindir. Debian packaged RubyGems and
440
+ # DebGem packaged RubyGems are the prime examples.
441
+ begin
442
+ require 'rubygems' unless defined?(Gem)
443
+ filename = Gem.bindir + "/#{name}"
444
+ rescue LoadError
445
+ filename = nil
446
+ end
447
+ end
448
+
449
+ if !filename || !File.file?(filename) || !File.executable?(filename)
450
+ # Looks like it's not in the RubyGems bindir. Search in $PATH, but
451
+ # be very careful about this because whatever we find might belong
452
+ # to a different Ruby interpreter than the current one.
453
+ ENV['PATH'].split(':').each do |dir|
454
+ filename = "#{dir}/#{name}"
455
+ if File.file?(filename) && File.executable?(filename)
456
+ shebang = File.open(filename, 'rb') do |f|
457
+ f.readline.strip
458
+ end
459
+ if shebang == "#!#{ruby_command}"
460
+ # Looks good.
461
+ break
462
+ end
463
+ end
464
+
465
+ # Not found. Try next path.
466
+ filename = nil
467
+ end
468
+ end
469
+
470
+ filename
471
+ end
472
+ private_class_method :locate_ruby_tool_by_basename
473
+
474
+ def self.is_ruby_program?(filename)
475
+ File.open(filename, 'rb') do |f|
476
+ return f.readline =~ /ruby/
477
+ end
478
+ rescue EOFError
479
+ return false
480
+ end
481
+ private_class_method :is_ruby_program?
482
+
483
+ # Deduce Ruby's --program-prefix and --program-suffix from its install name
484
+ # and transforms the given input name accordingly.
485
+ #
486
+ # transform_according_to_ruby_exec_format("rake") => "jrake", "rake1.8", etc
487
+ def self.transform_according_to_ruby_exec_format(name)
488
+ install_name = rb_config['RUBY_INSTALL_NAME']
489
+ if install_name.include?('ruby')
490
+ format = install_name.sub('ruby', '%s')
491
+ return sprintf(format, name)
492
+ else
493
+ return name
494
+ end
495
+ end
496
+ private_class_method :transform_according_to_ruby_exec_format
497
+ end
478
498
 
479
499
  end # module PhusionPassenger