redcar 0.3.7.1 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (246) hide show
  1. data/CHANGES +16 -0
  2. data/README.md +5 -0
  3. data/ROADMAP.md +7 -9
  4. data/Rakefile +55 -22
  5. data/lib/redcar.rb +12 -6
  6. data/lib/redcar/installer.rb +119 -44
  7. data/plugins/application/features/step_definitions/speedbar_steps.rb +62 -0
  8. data/plugins/application/features/step_definitions/tree_steps.rb +3 -3
  9. data/plugins/application/features/support/env.rb +2 -1
  10. data/plugins/application/lib/application/notebook.rb +53 -7
  11. data/plugins/application/lib/application/speedbar.rb +12 -0
  12. data/plugins/application/lib/application/tab.rb +16 -5
  13. data/plugins/application/lib/application/treebook.rb +21 -1
  14. data/plugins/application_swt/lib/application_swt.rb +12 -2
  15. data/plugins/application_swt/lib/application_swt/html_tab.rb +4 -0
  16. data/plugins/application_swt/lib/application_swt/notebook.rb +5 -3
  17. data/plugins/application_swt/lib/application_swt/speedbar.rb +15 -27
  18. data/plugins/application_swt/lib/application_swt/swt_wrapper.rb +1 -0
  19. data/plugins/application_swt/lib/application_swt/tab.rb +1 -0
  20. data/plugins/application_swt/lib/application_swt/treebook.rb +36 -8
  21. data/plugins/application_swt/lib/application_swt/window.rb +24 -18
  22. data/plugins/auto_completer/lib/auto_completer.rb +5 -20
  23. data/plugins/core/lib/core.rb +7 -4
  24. data/plugins/core/lib/core/observable_struct.rb +2 -2
  25. data/plugins/declarations/lib/declarations.rb +3 -17
  26. data/plugins/document_search/features/search.feature +163 -0
  27. data/plugins/document_search/features/support/env.rb +4 -0
  28. data/plugins/document_search/lib/document_search.rb +121 -0
  29. data/plugins/document_search/plugin.rb +8 -0
  30. data/plugins/edit_view/features/line_delimiter.feature +7 -0
  31. data/plugins/edit_view/features/step_definitions/editing_steps.rb +49 -1
  32. data/plugins/edit_view/features/step_definitions/tab_steps.rb +10 -11
  33. data/plugins/edit_view/features/switch_tabs.feature +61 -10
  34. data/plugins/edit_view/lib/edit_view.rb +4 -0
  35. data/plugins/edit_view/lib/edit_view/document.rb +56 -0
  36. data/plugins/edit_view/lib/edit_view/document/command.rb +1 -1
  37. data/plugins/edit_view/lib/edit_view/edit_tab.rb +0 -8
  38. data/plugins/edit_view_swt/lib/edit_view_swt.rb +4 -0
  39. data/plugins/html_view/lib/html_controller.rb +19 -1
  40. data/plugins/html_view/lib/html_view.rb +28 -1
  41. data/plugins/html_view/lib/html_view/html_tab.rb +10 -1
  42. data/plugins/plugin_manager_ui/lib/plugin_manager_ui.rb +3 -1
  43. data/plugins/project/features/open_directory_tree.feature +3 -3
  44. data/plugins/project/lib/project.rb +4 -6
  45. data/plugins/project/lib/project/commands.rb +17 -0
  46. data/plugins/project/lib/project/dir_controller.rb +2 -1
  47. data/plugins/project/lib/project/dir_mirror.rb +8 -0
  48. data/plugins/project/lib/project/manager.rb +2 -0
  49. data/plugins/project/plugin.rb +2 -1
  50. data/plugins/project/vendor/net-sftp/Manifest +55 -0
  51. data/plugins/project/vendor/net-sftp/Rakefile +30 -0
  52. data/plugins/project/vendor/net-sftp/lib/net/sftp.rb +70 -0
  53. data/plugins/project/vendor/net-sftp/lib/net/sftp/constants.rb +187 -0
  54. data/plugins/project/vendor/net-sftp/lib/net/sftp/errors.rb +39 -0
  55. data/plugins/project/vendor/net-sftp/lib/net/sftp/operations/dir.rb +93 -0
  56. data/plugins/project/vendor/net-sftp/lib/net/sftp/operations/download.rb +364 -0
  57. data/plugins/project/vendor/net-sftp/lib/net/sftp/operations/file.rb +176 -0
  58. data/plugins/project/vendor/net-sftp/lib/net/sftp/operations/file_factory.rb +60 -0
  59. data/plugins/project/vendor/net-sftp/lib/net/sftp/operations/upload.rb +387 -0
  60. data/plugins/project/vendor/net-sftp/lib/net/sftp/packet.rb +21 -0
  61. data/plugins/project/vendor/net-sftp/lib/net/sftp/protocol.rb +32 -0
  62. data/plugins/project/vendor/net-sftp/lib/net/sftp/protocol/01/attributes.rb +315 -0
  63. data/plugins/project/vendor/net-sftp/lib/net/sftp/protocol/01/base.rb +268 -0
  64. data/plugins/project/vendor/net-sftp/lib/net/sftp/protocol/01/name.rb +43 -0
  65. data/plugins/project/vendor/net-sftp/lib/net/sftp/protocol/02/base.rb +31 -0
  66. data/plugins/project/vendor/net-sftp/lib/net/sftp/protocol/03/base.rb +35 -0
  67. data/plugins/project/vendor/net-sftp/lib/net/sftp/protocol/04/attributes.rb +152 -0
  68. data/plugins/project/vendor/net-sftp/lib/net/sftp/protocol/04/base.rb +94 -0
  69. data/plugins/project/vendor/net-sftp/lib/net/sftp/protocol/04/name.rb +67 -0
  70. data/plugins/project/vendor/net-sftp/lib/net/sftp/protocol/05/base.rb +66 -0
  71. data/plugins/project/vendor/net-sftp/lib/net/sftp/protocol/06/attributes.rb +107 -0
  72. data/plugins/project/vendor/net-sftp/lib/net/sftp/protocol/06/base.rb +63 -0
  73. data/plugins/project/vendor/net-sftp/lib/net/sftp/protocol/base.rb +50 -0
  74. data/plugins/project/vendor/net-sftp/lib/net/sftp/request.rb +91 -0
  75. data/plugins/project/vendor/net-sftp/lib/net/sftp/response.rb +76 -0
  76. data/plugins/project/vendor/net-sftp/lib/net/sftp/session.rb +951 -0
  77. data/plugins/project/vendor/net-sftp/lib/net/sftp/version.rb +18 -0
  78. data/plugins/project/vendor/net-sftp/setup.rb +1331 -0
  79. data/plugins/project/vendor/net-sftp/test/common.rb +171 -0
  80. data/plugins/project/vendor/net-sftp/test/protocol/01/test_attributes.rb +97 -0
  81. data/plugins/project/vendor/net-sftp/test/protocol/01/test_base.rb +210 -0
  82. data/plugins/project/vendor/net-sftp/test/protocol/01/test_name.rb +27 -0
  83. data/plugins/project/vendor/net-sftp/test/protocol/02/test_base.rb +26 -0
  84. data/plugins/project/vendor/net-sftp/test/protocol/03/test_base.rb +27 -0
  85. data/plugins/project/vendor/net-sftp/test/protocol/04/test_attributes.rb +148 -0
  86. data/plugins/project/vendor/net-sftp/test/protocol/04/test_base.rb +74 -0
  87. data/plugins/project/vendor/net-sftp/test/protocol/04/test_name.rb +53 -0
  88. data/plugins/project/vendor/net-sftp/test/protocol/05/test_base.rb +62 -0
  89. data/plugins/project/vendor/net-sftp/test/protocol/06/test_attributes.rb +124 -0
  90. data/plugins/project/vendor/net-sftp/test/protocol/06/test_base.rb +51 -0
  91. data/plugins/project/vendor/net-sftp/test/protocol/test_base.rb +42 -0
  92. data/plugins/project/vendor/net-sftp/test/test_all.rb +7 -0
  93. data/plugins/project/vendor/net-sftp/test/test_dir.rb +47 -0
  94. data/plugins/project/vendor/net-sftp/test/test_download.rb +252 -0
  95. data/plugins/project/vendor/net-sftp/test/test_file.rb +159 -0
  96. data/plugins/project/vendor/net-sftp/test/test_file_factory.rb +48 -0
  97. data/plugins/project/vendor/net-sftp/test/test_packet.rb +9 -0
  98. data/plugins/project/vendor/net-sftp/test/test_protocol.rb +17 -0
  99. data/plugins/project/vendor/net-sftp/test/test_request.rb +71 -0
  100. data/plugins/project/vendor/net-sftp/test/test_response.rb +53 -0
  101. data/plugins/project/vendor/net-sftp/test/test_session.rb +741 -0
  102. data/plugins/project/vendor/net-sftp/test/test_upload.rb +219 -0
  103. data/plugins/project/vendor/net-ssh/Manifest +110 -0
  104. data/plugins/project/vendor/net-ssh/Rakefile +85 -0
  105. data/plugins/project/vendor/net-ssh/Rudyfile +96 -0
  106. data/plugins/project/vendor/net-ssh/lib/net/ssh.rb +215 -0
  107. data/plugins/project/vendor/net-ssh/lib/net/ssh/authentication/agent.rb +179 -0
  108. data/plugins/project/vendor/net-ssh/lib/net/ssh/authentication/constants.rb +18 -0
  109. data/plugins/project/vendor/net-ssh/lib/net/ssh/authentication/key_manager.rb +193 -0
  110. data/plugins/project/vendor/net-ssh/lib/net/ssh/authentication/methods/abstract.rb +60 -0
  111. data/plugins/project/vendor/net-ssh/lib/net/ssh/authentication/methods/hostbased.rb +71 -0
  112. data/plugins/project/vendor/net-ssh/lib/net/ssh/authentication/methods/keyboard_interactive.rb +66 -0
  113. data/plugins/project/vendor/net-ssh/lib/net/ssh/authentication/methods/password.rb +39 -0
  114. data/plugins/project/vendor/net-ssh/lib/net/ssh/authentication/methods/publickey.rb +92 -0
  115. data/plugins/project/vendor/net-ssh/lib/net/ssh/authentication/pageant.rb +183 -0
  116. data/plugins/project/vendor/net-ssh/lib/net/ssh/authentication/session.rb +134 -0
  117. data/plugins/project/vendor/net-ssh/lib/net/ssh/buffer.rb +340 -0
  118. data/plugins/project/vendor/net-ssh/lib/net/ssh/buffered_io.rb +198 -0
  119. data/plugins/project/vendor/net-ssh/lib/net/ssh/config.rb +202 -0
  120. data/plugins/project/vendor/net-ssh/lib/net/ssh/connection/channel.rb +630 -0
  121. data/plugins/project/vendor/net-ssh/lib/net/ssh/connection/constants.rb +33 -0
  122. data/plugins/project/vendor/net-ssh/lib/net/ssh/connection/session.rb +597 -0
  123. data/plugins/project/vendor/net-ssh/lib/net/ssh/connection/term.rb +178 -0
  124. data/plugins/project/vendor/net-ssh/lib/net/ssh/errors.rb +85 -0
  125. data/plugins/project/vendor/net-ssh/lib/net/ssh/key_factory.rb +102 -0
  126. data/plugins/project/vendor/net-ssh/lib/net/ssh/known_hosts.rb +129 -0
  127. data/plugins/project/vendor/net-ssh/lib/net/ssh/loggable.rb +61 -0
  128. data/plugins/project/vendor/net-ssh/lib/net/ssh/packet.rb +102 -0
  129. data/plugins/project/vendor/net-ssh/lib/net/ssh/prompt.rb +93 -0
  130. data/plugins/project/vendor/net-ssh/lib/net/ssh/proxy/command.rb +75 -0
  131. data/plugins/project/vendor/net-ssh/lib/net/ssh/proxy/errors.rb +14 -0
  132. data/plugins/project/vendor/net-ssh/lib/net/ssh/proxy/http.rb +94 -0
  133. data/plugins/project/vendor/net-ssh/lib/net/ssh/proxy/socks4.rb +70 -0
  134. data/plugins/project/vendor/net-ssh/lib/net/ssh/proxy/socks5.rb +142 -0
  135. data/plugins/project/vendor/net-ssh/lib/net/ssh/ruby_compat.rb +43 -0
  136. data/plugins/project/vendor/net-ssh/lib/net/ssh/service/forward.rb +288 -0
  137. data/plugins/project/vendor/net-ssh/lib/net/ssh/test.rb +89 -0
  138. data/plugins/project/vendor/net-ssh/lib/net/ssh/test/channel.rb +129 -0
  139. data/plugins/project/vendor/net-ssh/lib/net/ssh/test/extensions.rb +152 -0
  140. data/plugins/project/vendor/net-ssh/lib/net/ssh/test/kex.rb +44 -0
  141. data/plugins/project/vendor/net-ssh/lib/net/ssh/test/local_packet.rb +51 -0
  142. data/plugins/project/vendor/net-ssh/lib/net/ssh/test/packet.rb +81 -0
  143. data/plugins/project/vendor/net-ssh/lib/net/ssh/test/remote_packet.rb +38 -0
  144. data/plugins/project/vendor/net-ssh/lib/net/ssh/test/script.rb +157 -0
  145. data/plugins/project/vendor/net-ssh/lib/net/ssh/test/socket.rb +64 -0
  146. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/algorithms.rb +384 -0
  147. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/cipher_factory.rb +97 -0
  148. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/constants.rb +30 -0
  149. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/hmac.rb +31 -0
  150. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/hmac/abstract.rb +79 -0
  151. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/hmac/md5.rb +12 -0
  152. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/hmac/md5_96.rb +11 -0
  153. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/hmac/none.rb +15 -0
  154. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/hmac/sha1.rb +13 -0
  155. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/hmac/sha1_96.rb +11 -0
  156. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/identity_cipher.rb +55 -0
  157. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/kex.rb +13 -0
  158. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +208 -0
  159. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +77 -0
  160. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/openssl.rb +128 -0
  161. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/packet_stream.rb +235 -0
  162. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/server_version.rb +71 -0
  163. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/session.rb +276 -0
  164. data/plugins/project/vendor/net-ssh/lib/net/ssh/transport/state.rb +206 -0
  165. data/plugins/project/vendor/net-ssh/lib/net/ssh/verifiers/lenient.rb +30 -0
  166. data/plugins/project/vendor/net-ssh/lib/net/ssh/verifiers/null.rb +12 -0
  167. data/plugins/project/vendor/net-ssh/lib/net/ssh/verifiers/strict.rb +53 -0
  168. data/plugins/project/vendor/net-ssh/lib/net/ssh/version.rb +62 -0
  169. data/plugins/project/vendor/net-ssh/net-ssh.gemspec +138 -0
  170. data/plugins/project/vendor/net-ssh/setup.rb +1585 -0
  171. data/plugins/project/vendor/net-ssh/support/arcfour_check.rb +20 -0
  172. data/plugins/project/vendor/net-ssh/support/ssh_tunnel_bug.rb +65 -0
  173. data/plugins/project/vendor/net-ssh/test/README.txt +42 -0
  174. data/plugins/project/vendor/net-ssh/test/authentication/methods/common.rb +28 -0
  175. data/plugins/project/vendor/net-ssh/test/authentication/methods/test_abstract.rb +51 -0
  176. data/plugins/project/vendor/net-ssh/test/authentication/methods/test_hostbased.rb +114 -0
  177. data/plugins/project/vendor/net-ssh/test/authentication/methods/test_keyboard_interactive.rb +98 -0
  178. data/plugins/project/vendor/net-ssh/test/authentication/methods/test_password.rb +50 -0
  179. data/plugins/project/vendor/net-ssh/test/authentication/methods/test_publickey.rb +127 -0
  180. data/plugins/project/vendor/net-ssh/test/authentication/test_agent.rb +205 -0
  181. data/plugins/project/vendor/net-ssh/test/authentication/test_key_manager.rb +105 -0
  182. data/plugins/project/vendor/net-ssh/test/authentication/test_session.rb +93 -0
  183. data/plugins/project/vendor/net-ssh/test/common.rb +107 -0
  184. data/plugins/project/vendor/net-ssh/test/configs/eqsign +3 -0
  185. data/plugins/project/vendor/net-ssh/test/configs/exact_match +8 -0
  186. data/plugins/project/vendor/net-ssh/test/configs/host_plus +10 -0
  187. data/plugins/project/vendor/net-ssh/test/configs/multihost +4 -0
  188. data/plugins/project/vendor/net-ssh/test/configs/nohost +19 -0
  189. data/plugins/project/vendor/net-ssh/test/configs/numeric_host +4 -0
  190. data/plugins/project/vendor/net-ssh/test/configs/wild_cards +14 -0
  191. data/plugins/project/vendor/net-ssh/test/connection/test_channel.rb +467 -0
  192. data/plugins/project/vendor/net-ssh/test/connection/test_session.rb +488 -0
  193. data/plugins/project/vendor/net-ssh/test/manual/test_forward.rb +185 -0
  194. data/plugins/project/vendor/net-ssh/test/test_all.rb +9 -0
  195. data/plugins/project/vendor/net-ssh/test/test_buffer.rb +336 -0
  196. data/plugins/project/vendor/net-ssh/test/test_buffered_io.rb +63 -0
  197. data/plugins/project/vendor/net-ssh/test/test_config.rb +117 -0
  198. data/plugins/project/vendor/net-ssh/test/test_key_factory.rb +67 -0
  199. data/plugins/project/vendor/net-ssh/test/transport/hmac/test_md5.rb +39 -0
  200. data/plugins/project/vendor/net-ssh/test/transport/hmac/test_md5_96.rb +25 -0
  201. data/plugins/project/vendor/net-ssh/test/transport/hmac/test_none.rb +34 -0
  202. data/plugins/project/vendor/net-ssh/test/transport/hmac/test_sha1.rb +34 -0
  203. data/plugins/project/vendor/net-ssh/test/transport/hmac/test_sha1_96.rb +25 -0
  204. data/plugins/project/vendor/net-ssh/test/transport/kex/test_diffie_hellman_group1_sha1.rb +146 -0
  205. data/plugins/project/vendor/net-ssh/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +92 -0
  206. data/plugins/project/vendor/net-ssh/test/transport/test_algorithms.rb +302 -0
  207. data/plugins/project/vendor/net-ssh/test/transport/test_cipher_factory.rb +213 -0
  208. data/plugins/project/vendor/net-ssh/test/transport/test_hmac.rb +34 -0
  209. data/plugins/project/vendor/net-ssh/test/transport/test_identity_cipher.rb +40 -0
  210. data/plugins/project/vendor/net-ssh/test/transport/test_packet_stream.rb +441 -0
  211. data/plugins/project/vendor/net-ssh/test/transport/test_server_version.rb +78 -0
  212. data/plugins/project/vendor/net-ssh/test/transport/test_session.rb +315 -0
  213. data/plugins/project/vendor/net-ssh/test/transport/test_state.rb +173 -0
  214. data/plugins/redcar/plugin.rb +3 -1
  215. data/plugins/redcar/redcar.rb +108 -121
  216. data/plugins/redcar_debug/lib/redcar_debug.rb +2 -0
  217. data/plugins/runnables/lib/runnables.rb +80 -23
  218. data/plugins/runnables/lib/runnables/command_output_controller.rb +102 -0
  219. data/plugins/runnables/lib/runnables/running_process_checker.rb +34 -0
  220. data/plugins/runnables/{plugin_no_load.rb → plugin.rb} +2 -1
  221. data/plugins/runnables/vendor/session-2.4.0/HISTORY +73 -0
  222. data/plugins/runnables/vendor/session-2.4.0/README +89 -0
  223. data/plugins/runnables/vendor/session-2.4.0/TODO +3 -0
  224. data/plugins/runnables/vendor/session-2.4.0/VERSION +1 -0
  225. data/plugins/runnables/vendor/session-2.4.0/gemspec.rb +22 -0
  226. data/plugins/runnables/vendor/session-2.4.0/install.rb +143 -0
  227. data/plugins/runnables/vendor/session-2.4.0/lib/session.rb +757 -0
  228. data/plugins/runnables/vendor/session-2.4.0/sample/bash.rb +60 -0
  229. data/plugins/runnables/vendor/session-2.4.0/sample/driver.rb +47 -0
  230. data/plugins/runnables/vendor/session-2.4.0/sample/session_idl.rb +25 -0
  231. data/plugins/runnables/vendor/session-2.4.0/sample/session_sh.rb +29 -0
  232. data/plugins/runnables/vendor/session-2.4.0/sample/sh0.rb +23 -0
  233. data/plugins/runnables/vendor/session-2.4.0/sample/stdin.rb +17 -0
  234. data/plugins/runnables/vendor/session-2.4.0/sample/threadtest.rb +42 -0
  235. data/plugins/runnables/vendor/session-2.4.0/session-2.4.0.gem +0 -0
  236. data/plugins/runnables/vendor/session-2.4.0/test/session.rb +227 -0
  237. data/plugins/runnables/views/command_output.html.erb +32 -0
  238. data/plugins/task_manager/lib/task_manager.rb +2 -0
  239. data/plugins/textmate/lib/textmate/plist.rb +1 -1
  240. data/plugins/textmate/lib/textmate/snippet.rb +1 -0
  241. data/plugins/tree/lib/tree/mirror.rb +8 -1
  242. data/plugins/tree_view_swt/lib/tree_view_swt.rb +29 -2
  243. metadata +191 -6
  244. data/plugins/declarations/TODO +0 -3
  245. data/plugins/redcar/spec/redcar/redcar_spec.rb +0 -70
  246. data/plugins/redcar/spec/spec_helper.rb +0 -4
@@ -0,0 +1,757 @@
1
+ require 'open3'
2
+ require 'tmpdir'
3
+ require 'thread'
4
+ require 'yaml'
5
+ require 'tempfile'
6
+
7
+ module Session
8
+ #--{{{
9
+ VERSION = '2.4.0'
10
+
11
+ @track_history = ENV['SESSION_HISTORY'] || ENV['SESSION_TRACK_HISTORY']
12
+ @use_spawn = ENV['SESSION_USE_SPAWN']
13
+ @use_open3 = ENV['SESSION_USE_OPEN3']
14
+ @use_open4 = ENV['SESSION_USE_OPEN4']
15
+ @debug = ENV['SESSION_DEBUG']
16
+
17
+ class << self
18
+ #--{{{
19
+ attr :track_history, true
20
+ attr :use_spawn, true
21
+ attr :use_open3, true
22
+ attr :use_open4, true
23
+ attr :debug, true
24
+ def new(*a, &b)
25
+ #--{{{
26
+ Sh::new(*a, &b)
27
+ #--}}}
28
+ end
29
+ alias [] new
30
+ #--}}}
31
+ end
32
+
33
+ class PipeError < StandardError; end
34
+ class ExecutionError < StandardError; end
35
+
36
+ class History
37
+ #--{{{
38
+ def initialize; @a = []; end
39
+ def method_missing(m,*a,&b); @a.send(m,*a,&b); end
40
+ def to_yaml(*a,&b); @a.to_yaml(*a,&b); end
41
+ alias to_s to_yaml
42
+ alias to_str to_yaml
43
+ #--}}}
44
+ end # class History
45
+ class Command
46
+ #--{{{
47
+ class << self
48
+ #--{{{
49
+ def cmdno; @cmdno ||= 0; end
50
+ def cmdno= n; @cmdno = n; end
51
+ #--}}}
52
+ end
53
+
54
+ # attributes
55
+ #--{{{
56
+ attr :cmd
57
+ attr :cmdno
58
+ attr :out,true
59
+ attr :err,true
60
+ attr :cid
61
+ attr :begin_out
62
+ attr :end_out
63
+ attr :begin_out_pat
64
+ attr :end_out_pat
65
+ attr :begin_err
66
+ attr :end_err
67
+ attr :begin_err_pat
68
+ attr :end_err_pat
69
+ #--}}}
70
+
71
+ def initialize(command)
72
+ #--{{{
73
+ @cmd = command.to_s
74
+ @cmdno = self.class.cmdno
75
+ self.class.cmdno += 1
76
+ @err = ''
77
+ @out = ''
78
+ @cid = "%d_%d_%d" % [$$, cmdno, rand(Time.now.usec)]
79
+ @begin_out = "__CMD_OUT_%s_BEGIN__" % cid
80
+ @end_out = "__CMD_OUT_%s_END__" % cid
81
+ @begin_out_pat = %r/#{ Regexp.escape(@begin_out) }/
82
+ @end_out_pat = %r/#{ Regexp.escape(@end_out) }/
83
+ @begin_err = "__CMD_ERR_%s_BEGIN__" % cid
84
+ @end_err = "__CMD_ERR_%s_END__" % cid
85
+ @begin_err_pat = %r/#{ Regexp.escape(@begin_err) }/
86
+ @end_err_pat = %r/#{ Regexp.escape(@end_err) }/
87
+ #--}}}
88
+ end
89
+ def to_hash
90
+ #--{{{
91
+ %w(cmdno cmd out err cid).inject({}){|h,k| h.update k => send(k) }
92
+ #--}}}
93
+ end
94
+ def to_yaml(*a,&b)
95
+ #--{{{
96
+ to_hash.to_yaml(*a,&b)
97
+ #--}}}
98
+ end
99
+ alias to_s to_yaml
100
+ alias to_str to_yaml
101
+ #--}}}
102
+ end # class Command
103
+ class AbstractSession
104
+ #--{{{
105
+
106
+ # class methods
107
+ class << self
108
+ #--{{{
109
+ def default_prog
110
+ #--{{{
111
+ return @default_prog if defined? @default_prog and @default_prog
112
+ if defined? self::DEFAULT_PROG
113
+ return @default_prog = self::DEFAULT_PROG
114
+ else
115
+ @default_prog = ENV["SESSION_#{ self }_PROG"]
116
+ end
117
+ nil
118
+ #--}}}
119
+ end
120
+ def default_prog= prog
121
+ #--{{{
122
+ @default_prog = prog
123
+ #--}}}
124
+ end
125
+ attr :track_history, true
126
+ attr :use_spawn, true
127
+ attr :use_open3, true
128
+ attr :use_open4, true
129
+ attr :debug, true
130
+ def init
131
+ #--{{{
132
+ @track_history = nil
133
+ @use_spawn = nil
134
+ @use_open3 = nil
135
+ @use_open4 = nil
136
+ @debug = nil
137
+ #--}}}
138
+ end
139
+ alias [] new
140
+ #--}}}
141
+ end
142
+
143
+ # class init
144
+ init
145
+
146
+ # attributes
147
+ #--{{{
148
+ attr :opts
149
+ attr :prog
150
+ attr :stdin
151
+ alias i stdin
152
+ attr :stdout
153
+ alias o stdout
154
+ attr :stderr
155
+ alias e stderr
156
+ attr :history
157
+ attr :track_history
158
+ attr :outproc, true
159
+ attr :errproc, true
160
+ attr :use_spawn
161
+ attr :use_open3
162
+ attr :use_open4
163
+ attr :debug, true
164
+ alias debug? debug
165
+ attr :threads
166
+ attr :pid
167
+ #--}}}
168
+
169
+ # instance methods
170
+ def initialize(*args)
171
+ #--{{{
172
+ @opts = hashify(*args)
173
+
174
+ @prog = getopt('prog', opts, getopt('program', opts, self.class::default_prog))
175
+
176
+ raise(ArgumentError, "no program specified") unless @prog
177
+
178
+ @track_history = nil
179
+ @track_history = Session::track_history unless Session::track_history.nil?
180
+ @track_history = self.class::track_history unless self.class::track_history.nil?
181
+ @track_history = getopt('history', opts) if hasopt('history', opts)
182
+ @track_history = getopt('track_history', opts) if hasopt('track_history', opts)
183
+
184
+ @use_spawn = nil
185
+ @use_spawn = Session::use_spawn unless Session::use_spawn.nil?
186
+ @use_spawn = self.class::use_spawn unless self.class::use_spawn.nil?
187
+ @use_spawn = getopt('use_spawn', opts) if hasopt('use_spawn', opts)
188
+
189
+ @use_open3 = nil
190
+ @use_open3 = Session::use_open3 unless Session::use_open3.nil?
191
+ @use_open3 = self.class::use_open3 unless self.class::use_open3.nil?
192
+ @use_open3 = getopt('use_open3', opts) if hasopt('use_open3', opts)
193
+
194
+ @use_open4 = nil
195
+ @use_open4 = Session::use_open4 unless Session::use_open4.nil?
196
+ @use_open4 = self.class::use_open4 unless self.class::use_open4.nil?
197
+ @use_open4 = getopt('use_open4', opts) if hasopt('use_open4', opts)
198
+
199
+ @debug = nil
200
+ @debug = Session::debug unless Session::debug.nil?
201
+ @debug = self.class::debug unless self.class::debug.nil?
202
+ @debug = getopt('debug', opts) if hasopt('debug', opts)
203
+
204
+ @history = nil
205
+ @history = History::new if @track_history
206
+
207
+ @outproc = nil
208
+ @errproc = nil
209
+
210
+ if @use_open4
211
+ @pid, @stdin, @stdout, @stderr = IO::popen4 @prog
212
+ else
213
+ if @use_spawn
214
+ Spawn::spawn @prog
215
+ elsif @use_open3
216
+ Open3::popen3 @prog
217
+ else
218
+ __popen3 @prog
219
+ end
220
+ end
221
+ @threads = []
222
+
223
+ clear
224
+
225
+ if block_given?
226
+ ret = nil
227
+ begin
228
+ ret = yield self
229
+ ensure
230
+ self.close!
231
+ end
232
+ return ret
233
+ end
234
+
235
+ return self
236
+ #--}}}
237
+ end
238
+ def getopt opt, hash, default = nil
239
+ #--{{{
240
+ key = opt
241
+ return hash[key] if hash.has_key? key
242
+ key = "#{ key }"
243
+ return hash[key] if hash.has_key? key
244
+ key = key.intern
245
+ return hash[key] if hash.has_key? key
246
+ return default
247
+ #--}}}
248
+ end
249
+ def hasopt opt, hash
250
+ #--{{{
251
+ key = opt
252
+ return key if hash.has_key? key
253
+ key = "#{ key }"
254
+ return key if hash.has_key? key
255
+ key = key.intern
256
+ return key if hash.has_key? key
257
+ return false
258
+ #--}}}
259
+ end
260
+ def __popen3(*cmd)
261
+ #--{{{
262
+ pw = IO::pipe # pipe[0] for read, pipe[1] for write
263
+ pr = IO::pipe
264
+ pe = IO::pipe
265
+
266
+ pid =
267
+ __fork{
268
+ # child
269
+ pw[1].close
270
+ STDIN.reopen(pw[0])
271
+ pw[0].close
272
+
273
+ pr[0].close
274
+ STDOUT.reopen(pr[1])
275
+ pr[1].close
276
+
277
+ pe[0].close
278
+ STDERR.reopen(pe[1])
279
+ pe[1].close
280
+
281
+ exec(*cmd)
282
+ }
283
+
284
+ Process::detach pid # avoid zombies
285
+
286
+ pw[0].close
287
+ pr[1].close
288
+ pe[1].close
289
+ pi = [pw[1], pr[0], pe[0]]
290
+ pw[1].sync = true
291
+ if defined? yield
292
+ begin
293
+ return yield(*pi)
294
+ ensure
295
+ pi.each{|p| p.close unless p.closed?}
296
+ end
297
+ end
298
+ pi
299
+ #--}}}
300
+ end
301
+ def __fork(*a, &b)
302
+ #--{{{
303
+ verbose = $VERBOSE
304
+ begin
305
+ $VERBOSE = nil
306
+ Kernel::fork(*a, &b)
307
+ ensure
308
+ $VERBOSE = verbose
309
+ end
310
+ #--}}}
311
+ end
312
+
313
+ # abstract methods
314
+ def clear
315
+ #--{{{
316
+ raise NotImplementedError
317
+ #--}}}
318
+ end
319
+ alias flush clear
320
+ def path
321
+ #--{{{
322
+ raise NotImplementedError
323
+ #--}}}
324
+ end
325
+ def path=
326
+ #--{{{
327
+ raise NotImplementedError
328
+ #--}}}
329
+ end
330
+ def send_command cmd
331
+ #--{{{
332
+ raise NotImplementedError
333
+ #--}}}
334
+ end
335
+
336
+ # concrete methods
337
+ def track_history= bool
338
+ #--{{{
339
+ @history ||= History::new
340
+ @track_history = bool
341
+ #--}}}
342
+ end
343
+ def ready?
344
+ #--{{{
345
+ (stdin and stdout and stderr) and
346
+ (IO === stdin and IO === stdout and IO === stderr) and
347
+ (not (stdin.closed? or stdout.closed? or stderr.closed?))
348
+ #--}}}
349
+ end
350
+ def close!
351
+ #--{{{
352
+ [stdin, stdout, stderr].each{|pipe| pipe.close}
353
+ stdin, stdout, stderr = nil, nil, nil
354
+ true
355
+ #--}}}
356
+ end
357
+ alias close close!
358
+ def hashify(*a)
359
+ #--{{{
360
+ a.inject({}){|o,h| o.update(h)}
361
+ #--}}}
362
+ end
363
+ private :hashify
364
+ def execute(command, redirects = {})
365
+ #--{{{
366
+ $session_command = command if @debug
367
+
368
+ raise(PipeError, command) unless ready?
369
+
370
+ # clear buffers
371
+ clear
372
+
373
+ # setup redirects
374
+ rerr = redirects[:e] || redirects[:err] || redirects[:stderr] ||
375
+ redirects['stderr'] || redirects['e'] || redirects['err'] ||
376
+ redirects[2] || redirects['2']
377
+
378
+ rout = redirects[:o] || redirects[:out] || redirects[:stdout] ||
379
+ redirects['stdout'] || redirects['o'] || redirects['out'] ||
380
+ redirects[1] || redirects['1']
381
+
382
+ # create cmd object and add to history
383
+ cmd = Command::new command.to_s
384
+
385
+ # store cmd if tracking history
386
+ history << cmd if track_history
387
+
388
+ # mutex for accessing shared data
389
+ mutex = Mutex::new
390
+
391
+ # io data for stderr and stdout
392
+ err = {
393
+ :io => stderr,
394
+ :cmd => cmd.err,
395
+ :name => 'stderr',
396
+ :begin => false,
397
+ :end => false,
398
+ :begin_pat => cmd.begin_err_pat,
399
+ :end_pat => cmd.end_err_pat,
400
+ :redirect => rerr,
401
+ :proc => errproc,
402
+ :yield => lambda{|buf| yield(nil, buf)},
403
+ :mutex => mutex,
404
+ }
405
+ out = {
406
+ :io => stdout,
407
+ :cmd => cmd.out,
408
+ :name => 'stdout',
409
+ :begin => false,
410
+ :end => false,
411
+ :begin_pat => cmd.begin_out_pat,
412
+ :end_pat => cmd.end_out_pat,
413
+ :redirect => rout,
414
+ :proc => outproc,
415
+ :yield => lambda{|buf| yield(buf, nil)},
416
+ :mutex => mutex,
417
+ }
418
+
419
+ begin
420
+ # send command in the background so we can begin processing output
421
+ # immediately - thanks to tanaka akira for this suggestion
422
+ threads << Thread::new { send_command cmd }
423
+
424
+ # init
425
+ main = Thread::current
426
+ exceptions = []
427
+
428
+ # fire off reader threads
429
+ [err, out].each do |iodat|
430
+ threads <<
431
+ Thread::new(iodat, main) do |iodat, main|
432
+
433
+ loop do
434
+ main.raise(PipeError, command) unless ready?
435
+ main.raise ExecutionError, iodat[:name] if iodat[:end] and not iodat[:begin]
436
+
437
+ break if iodat[:end] or iodat[:io].eof?
438
+
439
+ line = iodat[:io].gets
440
+
441
+ buf = nil
442
+
443
+ case line
444
+ when iodat[:end_pat]
445
+ iodat[:end] = true
446
+ # handle the special case of non-newline terminated output
447
+ if((m = %r/(.+)__CMD/o.match(line)) and (pre = m[1]))
448
+ buf = pre
449
+ end
450
+ when iodat[:begin_pat]
451
+ iodat[:begin] = true
452
+ else
453
+ next unless iodat[:begin] and not iodat[:end] # ignore chaff
454
+ buf = line
455
+ end
456
+
457
+ if buf
458
+ iodat[:mutex].synchronize do
459
+ iodat[:cmd] << buf
460
+ iodat[:redirect] << buf if iodat[:redirect]
461
+ iodat[:proc].call buf if iodat[:proc]
462
+ iodat[:yield].call buf if block_given?
463
+ end
464
+ end
465
+ end
466
+
467
+ true
468
+ end
469
+ end
470
+ ensure
471
+ # reap all threads - accumulating and rethrowing any exceptions
472
+ begin
473
+ while((t = threads.shift))
474
+ t.join
475
+ raise ExecutionError, 'iodat thread failure' unless t.value
476
+ end
477
+ rescue => e
478
+ exceptions << e
479
+ retry unless threads.empty?
480
+ ensure
481
+ unless exceptions.empty?
482
+ meta_message = '<' << exceptions.map{|e| "#{ e.message } - (#{ e.class })"}.join('|') << '>'
483
+ meta_backtrace = exceptions.map{|e| e.backtrace}.flatten
484
+ raise ExecutionError, meta_message, meta_backtrace
485
+ end
486
+ end
487
+ end
488
+
489
+ # this should only happen if eof was reached before end pat
490
+ [err, out].each do |iodat|
491
+ raise ExecutionError, iodat[:name] unless iodat[:begin] and iodat[:end]
492
+ end
493
+
494
+
495
+ # get the exit status
496
+ get_status if respond_to? :get_status
497
+
498
+ out = err = iodat = nil
499
+
500
+ return [cmd.out, cmd.err]
501
+ #--}}}
502
+ end
503
+ #--}}}
504
+ end # class AbstractSession
505
+ class Sh < AbstractSession
506
+ #--{{{
507
+ DEFAULT_PROG = 'sh'
508
+ ECHO = 'echo'
509
+
510
+ attr :status
511
+ alias exit_status status
512
+ alias exitstatus status
513
+
514
+ def clear
515
+ #--{{{
516
+ stdin.puts "#{ ECHO } __clear__ 1>&2"
517
+ stdin.puts "#{ ECHO } __clear__"
518
+ stdin.flush
519
+ while((line = stderr.gets) and line !~ %r/__clear__/o); end
520
+ while((line = stdout.gets) and line !~ %r/__clear__/o); end
521
+ self
522
+ #--}}}
523
+ end
524
+ def send_command cmd
525
+ #--{{{
526
+ stdin.printf "%s '%s' 1>&2\n", ECHO, cmd.begin_err
527
+ stdin.printf "%s '%s' \n", ECHO, cmd.begin_out
528
+
529
+ stdin.printf "%s\n", cmd.cmd
530
+ stdin.printf "export __exit_status__=$?\n"
531
+
532
+ stdin.printf "%s '%s' 1>&2\n", ECHO, cmd.end_err
533
+ stdin.printf "%s '%s' \n", ECHO, cmd.end_out
534
+
535
+ stdin.flush
536
+ #--}}}
537
+ end
538
+ def get_status
539
+ #--{{{
540
+ @status = get_var '__exit_status__'
541
+ unless @status =~ /^\s*\d+\s*$/o
542
+ raise ExecutionError, "could not determine exit status from <#{ @status.inspect }>"
543
+ end
544
+
545
+ @status = Integer @status
546
+ #--}}}
547
+ end
548
+ def set_var name, value
549
+ #--{{{
550
+ stdin.puts "export #{ name }=#{ value }"
551
+ stdin.flush
552
+ #--}}}
553
+ end
554
+ def get_var name
555
+ #--{{{
556
+ stdin.puts "#{ ECHO } \"#{ name }=${#{ name }}\""
557
+ stdin.flush
558
+
559
+ var = nil
560
+ while((line = stdout.gets))
561
+ m = %r/#{ name }\s*=\s*(.*)/.match line
562
+ if m
563
+ var = m[1]
564
+ raise ExecutionError, "could not determine <#{ name }> from <#{ line.inspect }>" unless var
565
+ break
566
+ end
567
+ end
568
+
569
+ var
570
+ #--}}}
571
+ end
572
+ def path
573
+ #--{{{
574
+ var = get_var 'PATH'
575
+ var.strip.split %r/:/o
576
+ #--}}}
577
+ end
578
+ def path= arg
579
+ #--{{{
580
+ case arg
581
+ when Array
582
+ arg = arg.join ':'
583
+ else
584
+ arg = arg.to_s.strip
585
+ end
586
+
587
+ set_var 'PATH', "'#{ arg }'"
588
+ self.path
589
+ #--}}}
590
+ end
591
+ def execute(command, redirects = {}, &block)
592
+ #--{{{
593
+ # setup redirect on stdin
594
+ rin = redirects[:i] || redirects[:in] || redirects[:stdin] ||
595
+ redirects['stdin'] || redirects['i'] || redirects['in'] ||
596
+ redirects[0] || redirects['0']
597
+
598
+ if rin
599
+ tmp =
600
+ begin
601
+ Tempfile::new rand.to_s
602
+ rescue
603
+ Tempfile::new rand.to_s
604
+ end
605
+
606
+ begin
607
+ tmp.write(
608
+ if rin.respond_to? 'read'
609
+ rin.read
610
+ elsif rin.respond_to? 'to_s'
611
+ rin.to_s
612
+ else
613
+ rin
614
+ end
615
+ )
616
+ tmp.flush
617
+ command = "{ #{ command } ;} < #{ tmp.path }"
618
+ #puts command
619
+ super(command, redirects, &block)
620
+ ensure
621
+ tmp.close! if tmp
622
+ end
623
+
624
+ else
625
+ super
626
+ end
627
+ #--}}}
628
+ end
629
+ #--}}}
630
+ end # class Sh
631
+ class Bash < Sh
632
+ #--{{{
633
+ DEFAULT_PROG = 'bash'
634
+ class Login < Bash
635
+ DEFAULT_PROG = 'bash --login'
636
+ end
637
+ #--}}}
638
+ end # class Bash
639
+ class Shell < Bash; end
640
+ # IDL => interactive data language - see http://www.rsinc.com/
641
+ class IDL < AbstractSession
642
+ #--{{{
643
+ class LicenseManagerError < StandardError; end
644
+ DEFAULT_PROG = 'idl'
645
+ MAX_TRIES = 32
646
+ def initialize(*args)
647
+ #--{{{
648
+ tries = 0
649
+ ret = nil
650
+ begin
651
+ ret = super
652
+ rescue LicenseManagerError => e
653
+ tries += 1
654
+ if tries < MAX_TRIES
655
+ sleep 1
656
+ retry
657
+ else
658
+ raise LicenseManagerError, "<#{ MAX_TRIES }> attempts <#{ e.message }>"
659
+ end
660
+ end
661
+ ret
662
+ #--}}}
663
+ end
664
+ def clear
665
+ #--{{{
666
+ stdin.puts "retall"
667
+ stdin.puts "printf, -2, '__clear__'"
668
+ stdin.puts "printf, -1, '__clear__'"
669
+ stdin.flush
670
+ while((line = stderr.gets) and line !~ %r/__clear__/o)
671
+ raise LicenseManagerError, line if line =~ %r/license\s*manager/io
672
+ end
673
+ while((line = stdout.gets) and line !~ %r/__clear__/o)
674
+ raise LicenseManagerError, line if line =~ %r/license\s*manager/io
675
+ end
676
+ self
677
+ #--}}}
678
+ end
679
+ def send_command cmd
680
+ #--{{{
681
+ stdin.printf "printf, -2, '%s'\n", cmd.begin_err
682
+ stdin.printf "printf, -1, '%s'\n", cmd.begin_out
683
+
684
+ stdin.printf "%s\n", cmd.cmd
685
+ stdin.printf "retall\n"
686
+
687
+ stdin.printf "printf, -2, '%s'\n", cmd.end_err
688
+ stdin.printf "printf, -1, '%s'\n", cmd.end_out
689
+ stdin.flush
690
+ #--}}}
691
+ end
692
+ def path
693
+ #--{{{
694
+ stdout, stderr = execute "print, !path"
695
+ stdout.strip.split %r/:/o
696
+ #--}}}
697
+ end
698
+ def path= arg
699
+ #--{{{
700
+ case arg
701
+ when Array
702
+ arg = arg.join ':'
703
+ else
704
+ arg = arg.to_s.strip
705
+ end
706
+ stdout, stderr = execute "!path='#{ arg }'"
707
+
708
+ self.path
709
+ #--}}}
710
+ end
711
+ #--}}}
712
+ end # class IDL
713
+ module Spawn
714
+ #--{{{
715
+ class << self
716
+ def spawn command
717
+ #--{{{
718
+ ipath = tmpfifo
719
+ opath = tmpfifo
720
+ epath = tmpfifo
721
+
722
+ cmd = "#{ command } < #{ ipath } 1> #{ opath } 2> #{ epath } &"
723
+ system cmd
724
+
725
+ i = open ipath, 'w'
726
+ o = open opath, 'r'
727
+ e = open epath, 'r'
728
+
729
+ [i,o,e]
730
+ #--}}}
731
+ end
732
+ def tmpfifo
733
+ #--{{{
734
+ path = nil
735
+ 42.times do |i|
736
+ tpath = File::join(Dir::tmpdir, "#{ $$ }.#{ rand }.#{ i }")
737
+ v = $VERBOSE
738
+ begin
739
+ $VERBOSE = nil
740
+ system "mkfifo #{ tpath }"
741
+ ensure
742
+ $VERBOSE = v
743
+ end
744
+ next unless $? == 0
745
+ path = tpath
746
+ at_exit{ File::unlink(path) rescue STDERR.puts("rm <#{ path }> failed") }
747
+ break
748
+ end
749
+ raise "could not generate tmpfifo" unless path
750
+ path
751
+ #--}}}
752
+ end
753
+ end
754
+ #--}}}
755
+ end # module Spawn
756
+ #--}}}
757
+ end # module Session