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
@@ -22,41 +22,41 @@
22
22
  # THE SOFTWARE.
23
23
 
24
24
  module PhusionPassenger
25
- module Utils
25
+ module Utils
26
26
 
27
- class Lock
28
- def initialize(mutex)
29
- @mutex = mutex
30
- @locked = false
31
- end
27
+ class Lock
28
+ def initialize(mutex)
29
+ @mutex = mutex
30
+ @locked = false
31
+ end
32
32
 
33
- def reset(mutex, lock_now = true)
34
- unlock if @locked
35
- @mutex = mutex
36
- lock if lock_now
37
- end
33
+ def reset(mutex, lock_now = true)
34
+ unlock if @locked
35
+ @mutex = mutex
36
+ lock if lock_now
37
+ end
38
38
 
39
- def synchronize
40
- lock if !@locked
41
- begin
42
- yield(self)
43
- ensure
44
- unlock if @locked
45
- end
46
- end
39
+ def synchronize
40
+ lock if !@locked
41
+ begin
42
+ yield(self)
43
+ ensure
44
+ unlock if @locked
45
+ end
46
+ end
47
47
 
48
- def lock
49
- raise if @locked
50
- @mutex.lock
51
- @locked = true
52
- end
48
+ def lock
49
+ raise if @locked
50
+ @mutex.lock
51
+ @locked = true
52
+ end
53
53
 
54
- def unlock
55
- raise if !@locked
56
- @mutex.unlock
57
- @locked = false
58
- end
59
- end
54
+ def unlock
55
+ raise if !@locked
56
+ @mutex.unlock
57
+ @locked = false
58
+ end
59
+ end
60
60
 
61
- end # module Utils
61
+ end # module Utils
62
62
  end # module PhusionPassenger
@@ -24,42 +24,42 @@
24
24
  PhusionPassenger.require_passenger_lib 'native_support'
25
25
 
26
26
  module PhusionPassenger
27
- module Utils
27
+ module Utils
28
28
 
29
- # Utility functions that can potentially be accelerated by native_support functions.
30
- module NativeSupportUtils
31
- extend self
29
+ # Utility functions that can potentially be accelerated by native_support functions.
30
+ module NativeSupportUtils
31
+ extend self
32
32
 
33
- if defined?(PhusionPassenger::NativeSupport)
34
- # Split the given string into an hash. Keys and values are obtained by splitting the
35
- # string using the null character as the delimitor.
36
- def split_by_null_into_hash(data)
37
- return PhusionPassenger::NativeSupport.split_by_null_into_hash(data)
38
- end
33
+ if defined?(PhusionPassenger::NativeSupport)
34
+ # Split the given string into an hash. Keys and values are obtained by splitting the
35
+ # string using the null character as the delimitor.
36
+ def split_by_null_into_hash(data)
37
+ return PhusionPassenger::NativeSupport.split_by_null_into_hash(data)
38
+ end
39
39
 
40
- # Wrapper for getrusage().
41
- def process_times
42
- return PhusionPassenger::NativeSupport.process_times
43
- end
44
- else
45
- NULL = "\0".freeze
40
+ # Wrapper for getrusage().
41
+ def process_times
42
+ return PhusionPassenger::NativeSupport.process_times
43
+ end
44
+ else
45
+ NULL = "\0".freeze
46
46
 
47
- class ProcessTimes < Struct.new(:utime, :stime)
48
- end
47
+ class ProcessTimes < Struct.new(:utime, :stime)
48
+ end
49
49
 
50
- def split_by_null_into_hash(data)
51
- args = data.split(NULL, -1)
52
- args.pop
53
- return Hash[*args]
54
- end
50
+ def split_by_null_into_hash(data)
51
+ args = data.split(NULL, -1)
52
+ args.pop
53
+ return Hash[*args]
54
+ end
55
55
 
56
- def process_times
57
- times = Process.times
58
- return ProcessTimes.new((times.utime * 1_000_000).to_i,
59
- (times.stime * 1_000_000).to_i)
60
- end
61
- end
62
- end
56
+ def process_times
57
+ times = Process.times
58
+ return ProcessTimes.new((times.utime * 1_000_000).to_i,
59
+ (times.stime * 1_000_000).to_i)
60
+ end
61
+ end
62
+ end
63
63
 
64
- end # module Utils
64
+ end # module Utils
65
65
  end # module PhusionPassenger
@@ -23,34 +23,34 @@
23
23
 
24
24
  module PhusionPassenger
25
25
 
26
- class ProgressBar
27
- THROBBLER = ["-", "\\", "|", "/", "-"]
26
+ class ProgressBar
27
+ THROBBLER = ["-", "\\", "|", "/", "-"]
28
28
 
29
- def initialize(output = STDOUT)
30
- @output = output
31
- @tty = output.tty?
32
- @throbbler_index = 0
33
- end
29
+ def initialize(output = STDOUT)
30
+ @output = output
31
+ @tty = output.tty?
32
+ @throbbler_index = 0
33
+ end
34
34
 
35
- def set(percentage)
36
- if @tty
37
- width = (percentage * 50).to_i
38
- bar = "*" * width
39
- space = " " * (50 - width)
40
- text = sprintf("[%s%s] %s", bar, space, THROBBLER[@throbbler_index])
41
- @throbbler_index = (@throbbler_index + 1) % THROBBLER.size
42
- @output.write("#{text}\r")
43
- @output.flush
44
- else
45
- @output.write(".")
46
- @output.flush
47
- end
48
- end
35
+ def set(percentage)
36
+ if @tty
37
+ width = (percentage * 50).to_i
38
+ bar = "*" * width
39
+ space = " " * (50 - width)
40
+ text = sprintf("[%s%s] %s", bar, space, THROBBLER[@throbbler_index])
41
+ @throbbler_index = (@throbbler_index + 1) % THROBBLER.size
42
+ @output.write("#{text}\r")
43
+ @output.flush
44
+ else
45
+ @output.write(".")
46
+ @output.flush
47
+ end
48
+ end
49
49
 
50
- def finish
51
- @output.write("\n")
52
- @output.flush
53
- end
54
- end
50
+ def finish
51
+ @output.write("\n")
52
+ @output.flush
53
+ end
54
+ end
55
55
 
56
56
  end # module PhusionPassenger
@@ -3,27 +3,27 @@
3
3
  require 'shellwords'
4
4
 
5
5
  if !Shellwords.respond_to?(:escape)
6
- Shellwords.class_eval do
7
- def self.escape(str)
8
- # An empty argument will be skipped, so return empty quotes.
9
- return "''" if str.empty?
10
- str = str.dup
11
- # Treat multibyte characters as is. It is caller's responsibility
12
- # to encode the string in the right encoding for the shell
13
- # environment.
14
- str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/, "\\\\\\1")
15
- # A LF cannot be escaped with a backslash because a backslash + LF
16
- # combo is regarded as line continuation and simply ignored.
17
- str.gsub!(/\n/, "'\n'")
18
- return str
19
- end
20
- end
6
+ Shellwords.class_eval do
7
+ def self.escape(str)
8
+ # An empty argument will be skipped, so return empty quotes.
9
+ return "''" if str.empty?
10
+ str = str.dup
11
+ # Treat multibyte characters as is. It is caller's responsibility
12
+ # to encode the string in the right encoding for the shell
13
+ # environment.
14
+ str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/, "\\\\\\1")
15
+ # A LF cannot be escaped with a backslash because a backslash + LF
16
+ # combo is regarded as line continuation and simply ignored.
17
+ str.gsub!(/\n/, "'\n'")
18
+ return str
19
+ end
20
+ end
21
21
  end
22
22
 
23
23
  if !Shellwords.respond_to?(:join)
24
- Shellwords.class_eval do
25
- def self.join(array)
26
- array.map { |arg| escape(arg) }.join(' ')
27
- end
28
- end
24
+ Shellwords.class_eval do
25
+ def self.join(array)
26
+ array.map { |arg| escape(arg) }.join(' ')
27
+ end
28
+ end
29
29
  end
@@ -23,210 +23,210 @@
23
23
  # THE SOFTWARE.
24
24
 
25
25
  module PhusionPassenger
26
- module Utils
27
-
28
- class TerminalChoiceMenu
29
- class Choice
30
- attr_reader :name
31
- attr_accessor :checked
32
-
33
- alias checked? checked
34
-
35
- def self.create(choice)
36
- if choice.is_a?(Choice)
37
- return choice
38
- else
39
- return Choice.new(choice)
40
- end
41
- end
42
-
43
- def initialize(name, checked = false)
44
- @name = name
45
- @checked = checked
46
- end
47
-
48
- def toggle!
49
- @checked = !@checked
50
- end
51
- end
52
-
53
- def initialize(choices)
54
- @choices = choices.map { |choice| Choice.create(choice) }
55
- @pointer = 0
56
- @index = index_choices
57
- end
58
-
59
- def display_choices
60
- display(render_to_string)
61
- end
62
-
63
- def query
64
- if STDIN.tty?
65
- done = false
66
- begin
67
- raw_no_echo_mode
68
- hide_cursor
69
- while !done
70
- display_choices
71
- done = process_input
72
- clear_screen if !done
73
- end
74
- ensure
75
- restore_mode
76
- show_cursor
77
- puts
78
- end
79
- else
80
- display_choices
81
- puts
82
- end
83
- end
84
-
85
- def [](name)
86
- return @index[name]
87
- end
88
-
89
- def selected_choices
90
- @choices.find_all{ |c| c.checked? }.map{ |c| c.name }
91
- end
92
-
93
- private
94
- JRUBY = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
95
-
96
- def index_choices
97
- index = {}
98
- @choices.each do |choice|
99
- index[choice.name] = choice
100
- end
101
- return index
102
- end
103
-
104
- def process_input
105
- case getchar(STDIN)
106
- when "\x1b"
107
- process_cursor_move
108
- return false
109
- when " "
110
- process_toggle
111
- return false
112
- when "!"
113
- process_disable_utf8
114
- return false
115
- when "\r"
116
- return true
117
- else
118
- return false
119
- end
120
- end
121
-
122
- def process_cursor_move
123
- if getchar(STDIN) == "["
124
- case getchar(STDIN)
125
- when "A" # up
126
- @pointer = [@pointer - 1, 0].max
127
- when "B" # down
128
- @pointer = [@pointer + 1, @choices.size - 1].min
129
- end
130
- end
131
- end
132
-
133
- def process_toggle
134
- @choices[@pointer].toggle!
135
- end
136
-
137
- def process_disable_utf8
138
- ENV['UTF8_MENUS'] = '0'
139
- end
140
-
141
- def render_to_string
142
- str = ""
143
- @choices.each_with_index do |choice, i|
144
- pointer = render_pointer(i)
145
- checkbox = render_checkbox(choice.checked)
146
- str << " #{pointer} #{checkbox} #{choice.name}\r\n"
147
- end
148
- str.chomp!
149
- return str
150
- end
151
-
152
- def render_pointer(index)
153
- return @pointer == index ? maybe_utf8("‣", ">") : " "
154
- end
155
-
156
- def render_checkbox(checked)
157
- return checked ? maybe_utf8("⬢", "(*)") : maybe_utf8("⬡", "( )")
158
- end
159
-
160
- def display(str)
161
- STDOUT.write(str)
162
- STDOUT.flush
163
- end
164
-
165
- def clear_screen
166
- number_of_lines = render_to_string.split("\n").size
167
- display("\r")
168
- (number_of_lines - 1).times do
169
- display(move_up)
170
- end
171
- end
172
-
173
- def maybe_utf8(utf8, plain)
174
- if ENV['UTF8_MENUS'] == '0'
175
- return plain
176
- else
177
- return utf8
178
- end
179
- end
180
-
181
- def hide_cursor
182
- display("\x1b[?25l")
183
- end
184
-
185
- def show_cursor
186
- display("\x1b[?25h")
187
- end
188
-
189
- def move_up
190
- return "\x1b[0A"
191
- end
192
-
193
- def getchar(io)
194
- char = io.getc
195
- char = char.chr if char.is_a?(Integer)
196
- return char
197
- end
198
-
199
- if JRUBY
200
- require 'java'
201
- require 'readline'
202
- java_import 'jline.console.ConsoleReader'
203
-
204
- def raw_no_echo_mode
205
- input = STDIN.to_inputstream
206
- output = STDOUT.to_outputstream
207
- @console = ConsoleReader.new(input, output)
208
- @console.set_history_enabled(false)
209
- @console.set_bell_enabled(true)
210
- @console.set_pagination_enabled(false)
211
- @terminal_state = @console.getEchoCharacter
212
- @console.setEchoCharacter(0)
213
- end
214
-
215
- def restore_mode
216
- @console.setEchoCharacter(@terminal_state)
217
- @console.get_terminal.restore
218
- end
219
- else
220
- def raw_no_echo_mode
221
- @terminal_state = `stty -g`
222
- system("stty raw -echo -icanon isig")
223
- end
224
-
225
- def restore_mode
226
- system("stty #{@terminal_state}")
227
- end
228
- end
229
- end
230
-
231
- end # module Utils
26
+ module Utils
27
+
28
+ class TerminalChoiceMenu
29
+ class Choice
30
+ attr_reader :name
31
+ attr_accessor :checked
32
+
33
+ alias checked? checked
34
+
35
+ def self.create(choice)
36
+ if choice.is_a?(Choice)
37
+ return choice
38
+ else
39
+ return Choice.new(choice)
40
+ end
41
+ end
42
+
43
+ def initialize(name, checked = false)
44
+ @name = name
45
+ @checked = checked
46
+ end
47
+
48
+ def toggle!
49
+ @checked = !@checked
50
+ end
51
+ end
52
+
53
+ def initialize(choices)
54
+ @choices = choices.map { |choice| Choice.create(choice) }
55
+ @pointer = 0
56
+ @index = index_choices
57
+ end
58
+
59
+ def display_choices
60
+ display(render_to_string)
61
+ end
62
+
63
+ def query
64
+ if STDIN.tty?
65
+ done = false
66
+ begin
67
+ raw_no_echo_mode
68
+ hide_cursor
69
+ while !done
70
+ display_choices
71
+ done = process_input
72
+ clear_screen if !done
73
+ end
74
+ ensure
75
+ restore_mode
76
+ show_cursor
77
+ puts
78
+ end
79
+ else
80
+ display_choices
81
+ puts
82
+ end
83
+ end
84
+
85
+ def [](name)
86
+ return @index[name]
87
+ end
88
+
89
+ def selected_choices
90
+ @choices.find_all{ |c| c.checked? }.map{ |c| c.name }
91
+ end
92
+
93
+ private
94
+ JRUBY = defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
95
+
96
+ def index_choices
97
+ index = {}
98
+ @choices.each do |choice|
99
+ index[choice.name] = choice
100
+ end
101
+ return index
102
+ end
103
+
104
+ def process_input
105
+ case getchar(STDIN)
106
+ when "\x1b"
107
+ process_cursor_move
108
+ return false
109
+ when " "
110
+ process_toggle
111
+ return false
112
+ when "!"
113
+ process_disable_utf8
114
+ return false
115
+ when "\r"
116
+ return true
117
+ else
118
+ return false
119
+ end
120
+ end
121
+
122
+ def process_cursor_move
123
+ if getchar(STDIN) == "["
124
+ case getchar(STDIN)
125
+ when "A" # up
126
+ @pointer = [@pointer - 1, 0].max
127
+ when "B" # down
128
+ @pointer = [@pointer + 1, @choices.size - 1].min
129
+ end
130
+ end
131
+ end
132
+
133
+ def process_toggle
134
+ @choices[@pointer].toggle!
135
+ end
136
+
137
+ def process_disable_utf8
138
+ ENV['UTF8_MENUS'] = '0'
139
+ end
140
+
141
+ def render_to_string
142
+ str = ""
143
+ @choices.each_with_index do |choice, i|
144
+ pointer = render_pointer(i)
145
+ checkbox = render_checkbox(choice.checked)
146
+ str << " #{pointer} #{checkbox} #{choice.name}\r\n"
147
+ end
148
+ str.chomp!
149
+ return str
150
+ end
151
+
152
+ def render_pointer(index)
153
+ return @pointer == index ? maybe_utf8("‣", ">") : " "
154
+ end
155
+
156
+ def render_checkbox(checked)
157
+ return checked ? maybe_utf8("⬢", "(*)") : maybe_utf8("⬡", "( )")
158
+ end
159
+
160
+ def display(str)
161
+ STDOUT.write(str)
162
+ STDOUT.flush
163
+ end
164
+
165
+ def clear_screen
166
+ number_of_lines = render_to_string.split("\n").size
167
+ display("\r")
168
+ (number_of_lines - 1).times do
169
+ display(move_up)
170
+ end
171
+ end
172
+
173
+ def maybe_utf8(utf8, plain)
174
+ if ENV['UTF8_MENUS'] == '0'
175
+ return plain
176
+ else
177
+ return utf8
178
+ end
179
+ end
180
+
181
+ def hide_cursor
182
+ display("\x1b[?25l")
183
+ end
184
+
185
+ def show_cursor
186
+ display("\x1b[?25h")
187
+ end
188
+
189
+ def move_up
190
+ return "\x1b[0A"
191
+ end
192
+
193
+ def getchar(io)
194
+ char = io.getc
195
+ char = char.chr if char.is_a?(Integer)
196
+ return char
197
+ end
198
+
199
+ if JRUBY
200
+ require 'java'
201
+ require 'readline'
202
+ java_import 'jline.console.ConsoleReader'
203
+
204
+ def raw_no_echo_mode
205
+ input = STDIN.to_inputstream
206
+ output = STDOUT.to_outputstream
207
+ @console = ConsoleReader.new(input, output)
208
+ @console.set_history_enabled(false)
209
+ @console.set_bell_enabled(true)
210
+ @console.set_pagination_enabled(false)
211
+ @terminal_state = @console.getEchoCharacter
212
+ @console.setEchoCharacter(0)
213
+ end
214
+
215
+ def restore_mode
216
+ @console.setEchoCharacter(@terminal_state)
217
+ @console.get_terminal.restore
218
+ end
219
+ else
220
+ def raw_no_echo_mode
221
+ @terminal_state = `stty -g`
222
+ system("stty raw -echo -icanon isig")
223
+ end
224
+
225
+ def restore_mode
226
+ system("stty #{@terminal_state}")
227
+ end
228
+ end
229
+ end
230
+
231
+ end # module Utils
232
232
  end # module PhusionPassenger