pry-remote-em 0.7.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,47 @@
1
+ module PryRemoteEm
2
+ # See Readme for Sandbox using guide
3
+ class Sandbox
4
+ @@last_errors = []
5
+
6
+ attr_accessor :pry, :server
7
+
8
+ %w[puts putc print p pp].each do |method|
9
+ define_method method do |*arguments|
10
+ pry.output.puts(*arguments)
11
+ end
12
+ end
13
+
14
+ def inspect
15
+ 'sandbox'
16
+ end
17
+
18
+ def any_errors?
19
+ last_errors.any?
20
+ end
21
+
22
+ def last_error
23
+ last_errors.last
24
+ end
25
+
26
+ def last_errors
27
+ @@last_errors
28
+ end
29
+
30
+ def self.add_error(exception, source_binding = nil)
31
+ unless exception.kind_of?(Exception) && exception.backtrace && (source_binding.nil? || source_binding.kind_of?(Binding))
32
+ raise ArgumentError, 'exception with backtrace and optional binding expected'
33
+ end
34
+
35
+ return if @@last_errors.include?(exception)
36
+
37
+ exception.define_singleton_method(:source_binding) { source_binding } if source_binding
38
+
39
+ @@last_errors.push(exception)
40
+
41
+ maximum_errors = ENV['PRYEMSANDBOXERRORS'].nil? || ENV['PRYEMSANDBOXERRORS'].empty? ? MAXIMUM_ERRORS_IN_SANDBOX : ENV['PRYEMSANDBOXERRORS'].to_i
42
+ @@last_errors.shift if @@last_errors.size > maximum_errors
43
+ end
44
+
45
+ Pry.config.prompt_safe_objects.push(self)
46
+ end
47
+ end
@@ -1,8 +1,11 @@
1
1
  require 'pry'
2
+ require 'socket'
2
3
  require 'logger'
4
+ require 'securerandom'
3
5
  require 'pry-remote-em'
4
6
  require 'pry-remote-em/broker'
5
7
  require 'pry-remote-em/server/shell_cmd'
8
+ require 'pry-remote-em/sandbox'
6
9
 
7
10
  # How it works with Pry
8
11
  #
@@ -34,7 +37,7 @@ require 'pry-remote-em/server/shell_cmd'
34
37
  # http://www.igvita.com/2010/03/22/untangling-evented-code-with-ruby-fibers/
35
38
  module PryRemoteEm
36
39
  class << self
37
- # Local PryRemoteEm EM signatures and server name indexed by url. Each
40
+ # Local PryRemoteEm servers, including EM signatures, indexed by id. Each
38
41
  # signature can be used with high level EM methods like EM.stop_server or
39
42
  # EM.get_sockname. If a server has been stopped EM.get_sockname will return
40
43
  # nil for that server's signature.
@@ -44,21 +47,23 @@ module PryRemoteEm
44
47
 
45
48
  # Safely stop one or more PryRemoteEm servers and remove them from the list
46
49
  # of servers.
47
- # @param [String] id url or name
48
- def stop_server(id)
49
- if servers[id]
50
- EM.stop_server(servers[id][0]) if EM.get_sockname(servers[id][0])
50
+ # @param [String, nil] argument id, url or name, use `nil` to stop them all
51
+ # @return [Hash] stopped servers if they were
52
+ def stop_server(argument = nil)
53
+ servers_to_stop = if argument
54
+ servers.select do |id, description|
55
+ argument == id || description[:urls].include?(argument) || argument == description[:name]
56
+ end
57
+ else
58
+ servers
59
+ end
60
+
61
+ servers_to_stop.each do |id, description|
62
+ EM.stop_server(description[:server]) if EM.get_sockname(description[:server])
51
63
  Broker.unregister(id)
52
64
  servers.delete(id)
53
- return Array(id)
54
- end
55
- servers.select{ |i, (sig, name)| name == id }.map do |i, (sig, name)|
56
- EM.stop_server(sig) if EM.get_sockname(sig)
57
- Broker.unregister(i)
58
- servers.delete(i)
59
- i
60
65
  end
61
- end # stop_server(id)
66
+ end
62
67
  end
63
68
 
64
69
  module Server
@@ -66,51 +71,41 @@ module PryRemoteEm
66
71
 
67
72
  class << self
68
73
  # Start a pry-remote-em server
69
- # @param [Object] obj the object to bind pry to
70
- # @param [String] ip the ip address to listen on
71
- # @param [Fixnum, Symbol] port the port to listen on - if :auto the next available port will be taken
72
- # @param [Hash] opts
73
- # @option opts [Boolean] :tls require SSL encryption
74
- # @option opts [Logger] :logger
75
- # @option opts [Proc, Object] :auth require user authentication - see README
76
- # @option opts [Boolean] :allow_shell_cmds
77
- def run(obj, host = DEFHOST, port = DEFPORT, opts = {:tls => false})
78
- tries = [port, opts[:port_fail]].include?(:auto) ? 100 : 1
79
- port = DEFPORT if :auto == port
80
- # TODO raise a useful exception not RuntimeError
81
- raise "root permission required for port below 1024 (#{port})" if port < 1024 && Process.euid != 0
82
- begin
83
- server = EM.start_server(host, port, PryRemoteEm::Server, obj, opts) do |pre|
84
- Fiber.new {
85
- begin
86
- yield pre if block_given?
87
- Pry.start(obj, :input => pre, :output => pre)
88
- ensure
89
- pre.close_connection
90
- end
91
- }.resume
92
- end
93
- rescue => e
94
- # EM 1.0.0.beta4's message tells us the port is in use; 0.12.10 just says, 'no acceptor'
95
- if (e.message.include?('port is in use') || e.message.include?('no acceptor')) && tries > 1
96
- tries -= 1
97
- port += 1
98
- retry
99
- end
100
- raise "can't bind to #{host}:#{port} - #{e}"
101
- end
102
- url = "#{opts[:tls] ? 'pryems' : 'pryem'}://#{host}:#{port}/"
103
- name = obj.send(:eval, 'self') rescue "#{obj}"
104
- name = Pry.view_clip(name)
105
- PryRemoteEm.servers[url] = [server, name]
106
- (opts[:logger] || ::Logger.new(STDERR)).info("[pry-remote-em] listening for connections on #{url}")
107
- Broker.run(opts[:broker_host] || ENV['PRYEMBROKER'] || DEF_BROKERHOST, opts[:broker_port] || ENV['PRYEMBROKERPORT'] || DEF_BROKERPORT, opts) do |broker|
108
- broker.register(url, name)
109
- rereg = EM::PeriodicTimer.new(15) do
110
- EM.get_sockname(server) ? broker.register(url, name) : nil #rereg.cancel
111
- end
112
- end # broker
113
- url
74
+ # @param [Hash] options
75
+ # @option options [Object] :target Object to bind Pry session, default - PryRemoteEm::Sandbox instance
76
+ # @option options [String] :host The IP-address to listen on, default - 127.0.0.1 (same as PRYEMHOST environment variable)
77
+ # @option options [Fixnum, String, Symbol] :port The port to listen on - if :auto or 'auto' the next available port will be taken, default - 6463 (same as PRYEMPORT environment variable)
78
+ # @option options [String] :id Server's UUID, will be generated automatically unless you pass it explicitly
79
+ # @option options [Boolean] :tls require SSL encryption, default - false
80
+ # @option options [Logger] :logger Logger for Pry Server, default - STDERR
81
+ # @option options [Proc, Object] :auth require user authentication - see README
82
+ # @option options [Boolean] :allow_shell_cmds Allow shell commands or not, default - true
83
+ # @option options [Integer, Symbol] :port_fail set to :auto to search for available port in range from given port to port + 100, or pass explicit integer to use instaed of 100, default - 1
84
+ # @option options [String] :name Server name to show in broker list, default - object's inspect (same as PRYEMNAME environment variable)
85
+ # @option options [String] :external_url External URL to connect behind firewall, NAT, Docket etc. in form "pryem://my.host:6463", default - use given host and port and expand it to all interfaces in case of 0.0.0.0 (same as PRYEMURL environment variable)
86
+ # @option options [Integer] :heartbeat_interval Interval to send heartbeats and updated details to broker, default - 15 (same as PRYEMHBSEND environment variable)
87
+ # @option options [Boolean] :remote_broker Connect to remote broker instead of starting local one, default - false (same as PRYEMREMOTEBROKER environment variable)
88
+ # @option options [String] :broker_host Broker host to connect to, default - localhost
89
+ # @option options [String] :broker_port Broker port to connect to, default - 6462
90
+ # @option options [Hash] :details Optional details to pass to broker and show in table (should consist of string/symbol keys and simple serializable values)
91
+ def run(options = {}, &block)
92
+ description = options.dup
93
+ description[:target] ||= PryRemoteEm::Sandbox.new
94
+ description[:host] ||= ENV['PRYEMHOST'].nil? || ENV['PRYEMHOST'].empty? ? DEFAULT_SERVER_HOST : ENV['PRYEMHOST']
95
+ determine_port_and_tries(description)
96
+ determine_name(description)
97
+ description[:id] ||= SecureRandom.uuid
98
+ description[:logger] ||= ::Logger.new(STDERR)
99
+ description[:external_url] ||= ENV['PRYEMURL'] || "#{description[:tls] ? 'pryems' : 'pryem'}://#{description[:host]}:#{description[:port]}/"
100
+ description[:details] ||= {}
101
+ description[:allow_shell_cmds] = true if description[:allow_shell_cmds].nil?
102
+ description[:heartbeat_interval] ||= ENV['PRYEMHBSEND'].nil? || ENV['PRYEMHBSEND'].empty? ? HEARTBEAT_SEND_INTERVAL : ENV['PRYEMHBSEND']
103
+ description[:urls] = expand_url(description[:external_url])
104
+ description[:server] = start_server(description, &block)
105
+ description[:logger].info("[pry-remote-em] listening for connections on #{description[:external_url]}")
106
+ PryRemoteEm.servers[description[:id]] = description
107
+ register_in_broker(description)
108
+ return description
114
109
  end
115
110
 
116
111
  # The list of pry-remote-em connections for a given object, or the list of all pry-remote-em
@@ -130,10 +125,84 @@ module PryRemoteEm
130
125
  def unregister(obj, peer)
131
126
  peers(obj).tap {|plist| true while plist.delete(peer) }
132
127
  end
128
+
129
+ private
130
+
131
+ def determine_port_and_tries(description)
132
+ description[:port] ||= ENV['PRYEMPORT'].nil? || ENV['PRYEMPORT'].empty? ? DEFAULT_SERVER_PORT : ENV['PRYEMPORT']
133
+ description[:port] = :auto if description[:port] == 'auto'
134
+ description[:port] = description[:port].to_i if description[:port].kind_of?(String)
135
+ description[:tries] = [description[:port], description[:port_fail]].include?(:auto) ? 100 : description[:port_fail] || 1
136
+ description[:port] = DEFAULT_SERVER_PORT if description[:port] == :auto
137
+ # TODO raise a useful exception not RuntimeError
138
+ raise "root permission required for port below 1024 (#{port})" if description[:port] < 1024 && Process.euid != 0
139
+ end
140
+
141
+ def determine_name(description)
142
+ description[:name] ||= ENV['PRYEMNAME']
143
+ if description[:name].nil?
144
+ object = description[:target]
145
+ inner_object = object.kind_of?(Binding) ? object.send(:eval, 'self') : object
146
+ description[:name] = Pry.view_clip(inner_object)
147
+ else
148
+ description[:custom_name] = true
149
+ end
150
+ description[:name] = description[:name].first(57) + '...' if description[:name].size > 60
151
+ end
152
+
153
+ def expand_url(url)
154
+ return Array(url) if (uri = URI.parse(url)).host != '0.0.0.0'
155
+ Socket.ip_address_list.select(&:ipv4?).map(&:ip_address).map do |ip|
156
+ uri.clone.tap { |uri_copy| uri_copy.host = ip }.to_s
157
+ end
158
+ end
159
+
160
+ def start_server(description, &block)
161
+ EM.start_server(description[:host], description[:port], PryRemoteEm::Server, description) do |pre|
162
+ Fiber.new do
163
+ begin
164
+ yield pre if block_given?
165
+ Pry.hooks.add_hook :when_started, pre do |target, options, pry|
166
+ pry.pager = false
167
+ pry.config.prompt_name = description[:name] + ' ' if description[:custom_name]
168
+ if description[:target].is_a? PryRemoteEm::Sandbox
169
+ description[:target].pry = pry
170
+ description[:target].server = description
171
+ pry.last_exception = description[:target].last_error if description[:target].any_errors?
172
+ end
173
+ description[:pry] = pry
174
+ end
175
+ Pry.start(description[:target], input: pre, output: pre)
176
+ ensure
177
+ pre.close_connection
178
+ Pry.hooks.delete_hook :when_started, pre
179
+ end
180
+ end.resume
181
+ end
182
+ rescue => error
183
+ if error.message.include?('port is in use') && description[:tries] > 1
184
+ description[:tries] -= 1
185
+ description[:port] += 1
186
+ retry
187
+ end
188
+ raise "can't bind to #{description[:host]}:#{description[:port]} - #{error}"
189
+ end
190
+
191
+ def register_in_broker(description)
192
+ broker_description = { id: description[:id], urls: description[:urls], name: description[:name], details: description[:details] }
193
+ broker_options = { tls: description[:tls], remote_broker: description[:remote_broker], logger: description[:logger] }
194
+ Broker.run(description[:broker_host], description[:broker_port], broker_options) do |broker|
195
+ broker.register(broker_description)
196
+
197
+ rereg = EM::PeriodicTimer.new(description[:heartbeat_interval]) do
198
+ EM.get_sockname(description[:server]) ? broker.register(broker_description) : nil #rereg.cancel
199
+ end
200
+ end
201
+ end
133
202
  end # class << self
134
203
 
135
- def initialize(obj, opts = {:tls => false})
136
- @obj = obj
204
+ def initialize(opts = {})
205
+ @obj = opts[:target]
137
206
  @opts = opts
138
207
  @allow_shell_cmds = opts[:allow_shell_cmds]
139
208
  @log = opts[:logger] || ::Logger.new(STDERR)
@@ -162,7 +231,7 @@ module PryRemoteEm
162
231
  return fail("auth handler must take two arguments not (#{a.method(:call).arity})") unless a.method(:call).arity == 2
163
232
  @auth = a
164
233
  else
165
- return error("auth handler objects must respond to :call, or :[]") unless a.respond_to?(:[])
234
+ return error('auth handler objects must respond to :call, or :[]') unless a.respond_to?(:[])
166
235
  @auth = lambda {|u,p| a[u] && a[u] == p }
167
236
  end
168
237
  end
@@ -174,10 +243,9 @@ module PryRemoteEm
174
243
 
175
244
  def post_init
176
245
  @lines = []
177
- Pry.config.pager, @old_pager = false, Pry.config.pager
178
246
  @auth_required = @auth
179
- port, ip = Socket.unpack_sockaddr_in(get_peername)
180
- @log.info("[pry-remote-em] received client connection from #{ip}:#{port}")
247
+ @port, @ip = Socket.unpack_sockaddr_in(get_peername)
248
+ @log.info("[pry-remote-em] received client connection from #{@ip}:#{@port}")
181
249
  # TODO include first level prompt in banner
182
250
  send_banner("PryRemoteEm #{VERSION} #{@opts[:tls] ? 'pryems' : 'pryem'}")
183
251
  @log.info("#{url} PryRemoteEm #{VERSION} #{@opts[:tls] ? 'pryems' : 'pryem'}")
@@ -197,22 +265,36 @@ module PryRemoteEm
197
265
 
198
266
  def peer_ip
199
267
  return @peer_ip if @peer_ip
200
- return "" if get_peername.nil?
268
+ return '' if get_peername.nil?
201
269
  @peer_port, @peer_ip = Socket.unpack_sockaddr_in(get_peername)
202
270
  @peer_ip
203
271
  end
204
272
 
205
273
  def peer_port
206
274
  return @peer_port if @peer_port
207
- return "" if get_peername.nil?
275
+ return '' if get_peername.nil?
208
276
  @peer_port, @peer_ip = Socket.unpack_sockaddr_in(get_peername)
209
277
  @peer_port
210
278
  end
211
279
 
280
+ def receive_clear_buffer
281
+ @opts[:pry].eval_string.replace('')
282
+ @last_prompt = @opts[:pry].select_prompt
283
+ send_last_prompt
284
+ end
285
+
212
286
  def receive_raw(d)
213
287
  return if require_auth
214
- return send_last_prompt if d.nil? || d.empty?
215
- @lines.push(*d.split("\n"))
288
+
289
+ return send_last_prompt if d.nil?
290
+
291
+ if d.empty?
292
+ @lines.push('')
293
+ else
294
+ lines = d.split("\n")
295
+ @lines.push(*lines)
296
+ end
297
+
216
298
  if @waiting
217
299
  f, @waiting = @waiting, nil
218
300
  f.resume(@lines.shift)
@@ -236,7 +318,7 @@ module PryRemoteEm
236
318
  else
237
319
  auth_fail(user, peer_ip)
238
320
  if @auth_tries <= 0
239
- msg = "max authentication attempts reached"
321
+ msg = 'max authentication attempts reached'
240
322
  send_auth(msg)
241
323
  @log.debug("[pry-remote-em] #{msg} (#{peer_ip}:#{peer_port})")
242
324
  return close_connection_after_writing
@@ -278,7 +360,7 @@ module PryRemoteEm
278
360
 
279
361
  def receive_shell_sig(type)
280
362
  return if require_auth
281
- type == :term && @shell_cmd.close_connection
363
+ @shell_cmd.close_connection if type == :int
282
364
  end
283
365
 
284
366
  def receive_unknown(j)
@@ -301,9 +383,8 @@ module PryRemoteEm
301
383
  end
302
384
 
303
385
  def unbind
304
- Pry.config.pager = @old_pager
305
386
  PryRemoteEm::Server.unregister(@obj, self)
306
- @log.debug("[pry-remote-em] remote session terminated (#{peer_ip}:#{peer_port})")
387
+ @log.debug("[pry-remote-em] remote session terminated (#{@ip}:#{@port})")
307
388
  end
308
389
 
309
390
  def peers(all = false)
@@ -324,13 +405,13 @@ module PryRemoteEm
324
405
  # Sends a chat message to the client.
325
406
  def send_message(msg, from = nil)
326
407
  msg = "#{msg} (@#{from})" unless from.nil?
327
- @auth_required ? (after_auth {send_msg(msg)}) : send_msg(msg)
408
+ @auth_required ? (after_auth {send_msg(msg)}) : send_msg(msg)
328
409
  end
329
410
  #
330
411
  # Sends a chat message to the client.
331
412
  def send_bmessage(msg, from = nil)
332
413
  msg = "#{msg} (@#{from})" unless from.nil?
333
- @auth_required ? (after_auth {send_msg_bcast(msg)}) : send_msg_bcast(msg)
414
+ @auth_required ? (after_auth {send_msg_bcast(msg)}) : send_msg_bcast(msg)
334
415
  end
335
416
 
336
417
  # Callbacks for events on the server
@@ -390,7 +471,7 @@ module PryRemoteEm
390
471
  end
391
472
  alias :write :print
392
473
 
393
- def puts(data = "")
474
+ def puts(data = '')
394
475
  s = data.to_s
395
476
  print(s[0] == "\n" ? s : s + "\n")
396
477
  end
@@ -6,7 +6,7 @@ module PryRemoteEm
6
6
  end
7
7
 
8
8
  def receive_data(d)
9
- @pryem.send_shell_cmd(d.force_encoding("utf-8"))
9
+ @pryem.send_shell_cmd(d.force_encoding('utf-8'))
10
10
  end
11
11
 
12
12
  alias :receive_stderr :receive_data
@@ -1,3 +1,3 @@
1
1
  module PryRemoteEm
2
- VERSION = '0.7.5'
2
+ VERSION = '1.0.0'
3
3
  end
metadata CHANGED
@@ -1,124 +1,134 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pry-remote-em
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.5
5
- prerelease:
4
+ version: 1.0.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Caleb Crane
8
+ - Xanders
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-02 00:00:00.000000000 Z
12
+ date: 2018-08-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: eventmachine
16
16
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
17
  requirements:
19
- - - ! '>='
18
+ - - "~>"
20
19
  - !ruby/object:Gem::Version
21
- version: '0'
20
+ version: '1'
22
21
  type: :runtime
23
22
  prerelease: false
24
23
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
24
  requirements:
27
- - - ! '>='
25
+ - - "~>"
28
26
  - !ruby/object:Gem::Version
29
- version: '0'
27
+ version: '1'
28
+ - !ruby/object:Gem::Dependency
29
+ name: msgpack
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '1'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '1'
30
42
  - !ruby/object:Gem::Dependency
31
43
  name: pry
32
44
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
45
  requirements:
35
- - - ~>
46
+ - - "~>"
36
47
  - !ruby/object:Gem::Version
37
- version: '0.9'
48
+ version: '0.11'
38
49
  type: :runtime
39
50
  prerelease: false
40
51
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
52
  requirements:
43
- - - ~>
53
+ - - "~>"
44
54
  - !ruby/object:Gem::Version
45
- version: '0.9'
55
+ version: '0.11'
46
56
  - !ruby/object:Gem::Dependency
47
57
  name: ruby-termios
48
58
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
59
  requirements:
51
- - - ~>
60
+ - - "~>"
52
61
  - !ruby/object:Gem::Version
53
- version: 0.9.6
54
- type: :development
62
+ version: '1.0'
63
+ type: :runtime
55
64
  prerelease: false
56
65
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
66
  requirements:
59
- - - ~>
67
+ - - "~>"
60
68
  - !ruby/object:Gem::Version
61
- version: 0.9.6
69
+ version: '1.0'
62
70
  - !ruby/object:Gem::Dependency
63
71
  name: highline
64
72
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
73
  requirements:
67
- - - ! '>='
74
+ - - "~>"
68
75
  - !ruby/object:Gem::Version
69
- version: '0'
76
+ version: '2.0'
70
77
  type: :runtime
71
78
  prerelease: false
72
79
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
80
  requirements:
75
- - - ! '>='
81
+ - - "~>"
76
82
  - !ruby/object:Gem::Version
77
- version: '0'
83
+ version: '2.0'
78
84
  description: Connect to Pry remotely using EventMachine with tab-completion, paging,
79
85
  user auth and SSL
80
86
  email: pry-remote-em@simulacre.org
81
87
  executables:
82
88
  - pry-remote-em
89
+ - pry-remote-em-broker
83
90
  extensions: []
84
91
  extra_rdoc_files: []
85
92
  files:
93
+ - CHANGELOG.md
94
+ - README.md
95
+ - bin/pry-remote-em
96
+ - bin/pry-remote-em-broker
97
+ - lib/pry-remote-em.rb
86
98
  - lib/pry-remote-em/broker.rb
99
+ - lib/pry-remote-em/client.rb
87
100
  - lib/pry-remote-em/client/broker.rb
88
101
  - lib/pry-remote-em/client/generic.rb
102
+ - lib/pry-remote-em/client/interactive_menu.rb
89
103
  - lib/pry-remote-em/client/keyboard.rb
90
104
  - lib/pry-remote-em/client/proxy.rb
91
- - lib/pry-remote-em/client.rb
92
105
  - lib/pry-remote-em/proto.rb
93
- - lib/pry-remote-em/server/shell_cmd.rb
106
+ - lib/pry-remote-em/sandbox.rb
94
107
  - lib/pry-remote-em/server.rb
108
+ - lib/pry-remote-em/server/shell_cmd.rb
95
109
  - lib/pry-remote-em/version.rb
96
- - lib/pry-remote-em.rb
97
- - bin/pry-remote-em
98
- - README.md
99
- homepage: http://github.com/simulacre/pry-remote-em
100
- licenses: []
110
+ homepage: https://github.com/gruis/pry-remote-em
111
+ licenses:
112
+ - Nonstandard
113
+ metadata: {}
101
114
  post_install_message:
102
115
  rdoc_options: []
103
116
  require_paths:
104
117
  - lib
105
118
  required_ruby_version: !ruby/object:Gem::Requirement
106
- none: false
107
119
  requirements:
108
- - - ! '>='
120
+ - - ">="
109
121
  - !ruby/object:Gem::Version
110
122
  version: '0'
111
123
  required_rubygems_version: !ruby/object:Gem::Requirement
112
- none: false
113
124
  requirements:
114
- - - ! '>='
125
+ - - ">="
115
126
  - !ruby/object:Gem::Version
116
127
  version: '0'
117
128
  requirements: []
118
129
  rubyforge_project:
119
- rubygems_version: 1.8.25
130
+ rubygems_version: 2.6.13
120
131
  signing_key:
121
- specification_version: 3
132
+ specification_version: 4
122
133
  summary: Connect to Pry remotely using EventMachine
123
134
  test_files: []
124
- has_rdoc: