pray-remote 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +63 -0
- data/LICENSE +22 -0
- data/README.md +2 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/pray-remote +4 -0
- data/bin/setup +8 -0
- data/exe/pray-remote +4 -0
- data/lib/pray-remote.rb +2 -0
- data/lib/pray-remote/pray-remote.rb +596 -0
- data/lib/pray-remote/version.rb +3 -0
- data/pray-remote.gemspec +39 -0
- metadata +146 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8baf5e4d0e763ebb69e45c79fa84326b811c3b29
|
4
|
+
data.tar.gz: 57e5cc9d466ce55084e7e194ad41bb068b9abba0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e604302e34481f84d00d2904a8ce8e8e15ff15cbb5e349172b2bc42b94cec6cee0f45c77b8bd8c046f7c6022cf921ce05eedf1f52abb5257a6e21529a31613e3
|
7
|
+
data.tar.gz: d76615bcf1415adbc430b5a17732fa883d93800ff2ef15b62ce860d95f45199c40835d7c3c401963c4ace1225a2aeceee8c014cbcbfb5519fc78d699801eb53d
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
GIT
|
2
|
+
remote: https://github.com/ChaosData/drab.git
|
3
|
+
revision: 3d72bfeec0b6363a318ecce4c71307f1fc129f18
|
4
|
+
specs:
|
5
|
+
drab (0.1.0)
|
6
|
+
marshal-structure (~> 2.0)
|
7
|
+
|
8
|
+
PATH
|
9
|
+
remote: .
|
10
|
+
specs:
|
11
|
+
pray-remote (0.1.0)
|
12
|
+
drab (~> 0.1.0)
|
13
|
+
pry (~> 0.9)
|
14
|
+
slop (~> 3.0)
|
15
|
+
|
16
|
+
GEM
|
17
|
+
remote: https://rubygems.org/
|
18
|
+
specs:
|
19
|
+
coderay (1.1.1)
|
20
|
+
diff-lcs (1.3)
|
21
|
+
ffi (1.9.18-java)
|
22
|
+
marshal-structure (2.0)
|
23
|
+
method_source (0.8.2)
|
24
|
+
pry (0.10.4)
|
25
|
+
coderay (~> 1.1.0)
|
26
|
+
method_source (~> 0.8.1)
|
27
|
+
slop (~> 3.4)
|
28
|
+
pry (0.10.4-java)
|
29
|
+
coderay (~> 1.1.0)
|
30
|
+
method_source (~> 0.8.1)
|
31
|
+
slop (~> 3.4)
|
32
|
+
spoon (~> 0.0)
|
33
|
+
rake (10.5.0)
|
34
|
+
rspec (3.6.0)
|
35
|
+
rspec-core (~> 3.6.0)
|
36
|
+
rspec-expectations (~> 3.6.0)
|
37
|
+
rspec-mocks (~> 3.6.0)
|
38
|
+
rspec-core (3.6.0)
|
39
|
+
rspec-support (~> 3.6.0)
|
40
|
+
rspec-expectations (3.6.0)
|
41
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
42
|
+
rspec-support (~> 3.6.0)
|
43
|
+
rspec-mocks (3.6.0)
|
44
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
45
|
+
rspec-support (~> 3.6.0)
|
46
|
+
rspec-support (3.6.0)
|
47
|
+
slop (3.6.0)
|
48
|
+
spoon (0.0.6)
|
49
|
+
ffi
|
50
|
+
|
51
|
+
PLATFORMS
|
52
|
+
java
|
53
|
+
ruby
|
54
|
+
|
55
|
+
DEPENDENCIES
|
56
|
+
bundler (~> 1.13)
|
57
|
+
drab!
|
58
|
+
pray-remote!
|
59
|
+
rake (~> 10.0)
|
60
|
+
rspec (~> 3.0)
|
61
|
+
|
62
|
+
BUNDLED WITH
|
63
|
+
1.15.4
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
pray-remote - Copyright (c) 2012 - Mon ouïe
|
2
|
+
Copyright (c) 2017 - Jeff Dileo
|
3
|
+
|
4
|
+
This software is provided 'as-is', without any express or
|
5
|
+
implied warranty. In no event will the authors be held
|
6
|
+
liable for any damages arising from the use of this software.
|
7
|
+
|
8
|
+
Permission is granted to anyone to use this software for any purpose,
|
9
|
+
including commercial applications, and to alter it and redistribute
|
10
|
+
it freely, subject to the following restrictions:
|
11
|
+
|
12
|
+
1. The origin of this software must not be misrepresented;
|
13
|
+
you must not claim that you wrote the original software.
|
14
|
+
If you use this software in a product, an acknowledgment
|
15
|
+
in the product documentation would be appreciated but
|
16
|
+
is not required.
|
17
|
+
|
18
|
+
2. Altered source versions must be plainly marked as such,
|
19
|
+
and must not be misrepresented as being the original software.
|
20
|
+
|
21
|
+
3. This notice may not be removed or altered from any
|
22
|
+
source distribution.
|
data/README.md
ADDED
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "pray/remote"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/pray-remote
ADDED
data/bin/setup
ADDED
data/exe/pray-remote
ADDED
data/lib/pray-remote.rb
ADDED
@@ -0,0 +1,596 @@
|
|
1
|
+
require 'pry'
|
2
|
+
require 'slop'
|
3
|
+
require 'drab'
|
4
|
+
require 'readline'
|
5
|
+
require 'open3'
|
6
|
+
|
7
|
+
module PrayRemote
|
8
|
+
DefaultHost = "127.0.0.1"
|
9
|
+
DefaultPort = 9876
|
10
|
+
|
11
|
+
def self.kwargs(args)
|
12
|
+
if args.last.is_a?(Hash)
|
13
|
+
args.pop
|
14
|
+
else
|
15
|
+
{}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class StdoeWrapper
|
20
|
+
include DRab::DRabUndumped
|
21
|
+
|
22
|
+
class_variable_set(:@@drab_whitelist, [
|
23
|
+
"respond_to?", "write", "print", "eof?", "puts", "printf", "<<", "tty?",
|
24
|
+
"to_s", "nil?", "flush"
|
25
|
+
])
|
26
|
+
|
27
|
+
def initialize(o)
|
28
|
+
@stdoe = o
|
29
|
+
end
|
30
|
+
|
31
|
+
def respond_to?(*args)
|
32
|
+
case args[0]
|
33
|
+
when :_dump
|
34
|
+
true
|
35
|
+
when :marshal_dump
|
36
|
+
false
|
37
|
+
else
|
38
|
+
@stdoe.respond_to?(*args)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def flush
|
43
|
+
@stdoe.flush
|
44
|
+
end
|
45
|
+
|
46
|
+
def write(*args)
|
47
|
+
@stdoe.write(*args)
|
48
|
+
end
|
49
|
+
|
50
|
+
def print(*args)
|
51
|
+
@stdoe.print(*args)
|
52
|
+
end
|
53
|
+
|
54
|
+
def eof?
|
55
|
+
@stdoe.eof?
|
56
|
+
end
|
57
|
+
|
58
|
+
def puts(*lines)
|
59
|
+
@stdoe.puts(*lines)
|
60
|
+
end
|
61
|
+
|
62
|
+
def printf(*args)
|
63
|
+
@stdoe.printf(*args)
|
64
|
+
end
|
65
|
+
|
66
|
+
def <<(data)
|
67
|
+
@stdoe << data
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
# Some versions of Pry expect $stdout or its output objects to respond to
|
72
|
+
# this message.
|
73
|
+
def tty?
|
74
|
+
false
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
class ThreadWrapper
|
80
|
+
include DRab::DRabUndumped
|
81
|
+
|
82
|
+
class_variable_set(:@@drab_whitelist, [
|
83
|
+
"run", "nil?"
|
84
|
+
])
|
85
|
+
|
86
|
+
def initialize(o)
|
87
|
+
@thread = o
|
88
|
+
end
|
89
|
+
|
90
|
+
def run
|
91
|
+
ThreadWrapper.new(@thread.run)
|
92
|
+
end
|
93
|
+
|
94
|
+
def nil?
|
95
|
+
@thread.nil?
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# A class to represent an input object created from DRab. This is used because
|
100
|
+
# Pry checks for arity to know if a prompt should be passed to the object.
|
101
|
+
#
|
102
|
+
# @attr [#readline] input Object to proxy
|
103
|
+
InputProxy = Struct.new :input do
|
104
|
+
include DRab::DRabUndumped
|
105
|
+
|
106
|
+
class_variable_set(:@@drab_whitelist, [
|
107
|
+
"readline", "completion_proc=", "readline_arity",
|
108
|
+
])
|
109
|
+
|
110
|
+
# Reads a line from the input
|
111
|
+
def readline(prompt)
|
112
|
+
arity = readline_arity
|
113
|
+
case
|
114
|
+
when arity == 1 then
|
115
|
+
input.readline(prompt)
|
116
|
+
when arity < 0 then
|
117
|
+
input.readline(prompt)
|
118
|
+
when arity == 0 then
|
119
|
+
input.readline
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def completion_proc=(val)
|
124
|
+
input.completion_proc = val
|
125
|
+
end
|
126
|
+
|
127
|
+
def readline_arity
|
128
|
+
input.readline_arity
|
129
|
+
rescue NameError
|
130
|
+
0
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Class used to wrap inputs so that they can be sent through DRab.
|
135
|
+
#
|
136
|
+
# This is to ensure the input is used locally and not reconstructed on the
|
137
|
+
# server by DRab.
|
138
|
+
class IOUndumpedProxy
|
139
|
+
include DRab::DRabUndumped
|
140
|
+
|
141
|
+
class_variable_set(:@@drab_whitelist, [
|
142
|
+
"to_s", "completion_proc=", "completion_proc", "puts", "print", "printf",
|
143
|
+
"write", "<<", "tty?", "initialize", "method", "readline", "readline_arity"
|
144
|
+
])
|
145
|
+
|
146
|
+
def initialize(obj)
|
147
|
+
@obj = obj
|
148
|
+
@arity = obj.method(:readline).arity
|
149
|
+
end
|
150
|
+
|
151
|
+
def completion_proc=(val)
|
152
|
+
if @obj.respond_to? :completion_proc=
|
153
|
+
@obj.completion_proc = proc { |*args, &block| val.call(*args, &block) }
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def completion_proc
|
158
|
+
@obj.completion_proc if @obj.respond_to? :completion_proc
|
159
|
+
end
|
160
|
+
|
161
|
+
def readline_arity
|
162
|
+
@arity
|
163
|
+
end
|
164
|
+
|
165
|
+
def readline(prompt)
|
166
|
+
if Readline == @obj
|
167
|
+
@obj.readline(prompt, true)
|
168
|
+
elsif @arity == 1
|
169
|
+
@obj.readline(prompt)
|
170
|
+
else
|
171
|
+
$stdout.print prompt
|
172
|
+
@obj.readline
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def puts(*lines)
|
177
|
+
@obj.puts(*lines)
|
178
|
+
end
|
179
|
+
|
180
|
+
def print(*objs)
|
181
|
+
@obj.print(*objs)
|
182
|
+
end
|
183
|
+
|
184
|
+
def printf(*args)
|
185
|
+
@obj.printf(*args)
|
186
|
+
end
|
187
|
+
|
188
|
+
def write(data)
|
189
|
+
@obj.write data
|
190
|
+
end
|
191
|
+
|
192
|
+
def <<(data)
|
193
|
+
@obj << data
|
194
|
+
self
|
195
|
+
end
|
196
|
+
|
197
|
+
# Some versions of Pry expect $stdout or its output objects to respond to
|
198
|
+
# this message.
|
199
|
+
def tty?
|
200
|
+
false
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Ensure that system (shell command) output is redirected for remote session.
|
205
|
+
System = proc do |output, cmd, _|
|
206
|
+
status = nil
|
207
|
+
Open3.popen3 cmd do |stdin, stdout, stderr, wait_thr|
|
208
|
+
stdin.close # Send EOF to the process
|
209
|
+
|
210
|
+
until stdout.eof? and stderr.eof?
|
211
|
+
if res = IO.select([stdout, stderr])
|
212
|
+
res[0].each do |io|
|
213
|
+
next if io.eof?
|
214
|
+
output.write io.read_nonblock(1024)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
status = wait_thr.value
|
220
|
+
end
|
221
|
+
|
222
|
+
unless status.success?
|
223
|
+
output.puts "Error while executing command: #{cmd}"
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
# A client is used to retrieve information from the client program.
|
228
|
+
Client = Struct.new(:input, :output, :thread, :stdout, :stderr,
|
229
|
+
:editor, :mypry) do
|
230
|
+
include DRab::DRabUndumped
|
231
|
+
|
232
|
+
class_variable_set(:@@drab_whitelist, [
|
233
|
+
"wait", "kill", "input_proxy",
|
234
|
+
"input=", "output=", "thread=", "stdout=", "stderr=",
|
235
|
+
"input", "output", "thread", "stdout", "stderr", "mypry", "mypry="
|
236
|
+
])
|
237
|
+
|
238
|
+
# Waits until both an input and output are set
|
239
|
+
def wait
|
240
|
+
sleep 0.01 until input and output and thread
|
241
|
+
end
|
242
|
+
|
243
|
+
# Tells the client the session is terminated
|
244
|
+
def kill
|
245
|
+
thread.run if not thread.nil?
|
246
|
+
end
|
247
|
+
|
248
|
+
# @return [InputProxy] Proxy for the input
|
249
|
+
def input_proxy
|
250
|
+
InputProxy.new input
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
class Server
|
255
|
+
def self.run(object, *args)
|
256
|
+
options = PrayRemote.kwargs(args)
|
257
|
+
new(object, options).run
|
258
|
+
end
|
259
|
+
|
260
|
+
def initialize(object, *args)
|
261
|
+
options = PrayRemote.kwargs(args)
|
262
|
+
|
263
|
+
@host = options[:host] || DefaultHost
|
264
|
+
@port = options[:port] || DefaultPort
|
265
|
+
|
266
|
+
@unix = options[:unix] || false
|
267
|
+
@secret = ""
|
268
|
+
if options[:secret] != nil
|
269
|
+
@secret = "?secret=" + options[:secret]
|
270
|
+
end
|
271
|
+
|
272
|
+
if @unix == false
|
273
|
+
@uri = "druby://#{@host}:#{@port}#{@secret}"
|
274
|
+
@unix = ""
|
275
|
+
else
|
276
|
+
@uri = "drabunix:#{@unix}"
|
277
|
+
end
|
278
|
+
|
279
|
+
@object = object
|
280
|
+
@options = options
|
281
|
+
|
282
|
+
@client = PrayRemote::Client.new
|
283
|
+
DRab.start_service @uri, @client
|
284
|
+
end
|
285
|
+
|
286
|
+
# Code that has to be called for Pry-remote to work properly
|
287
|
+
def setup
|
288
|
+
if @client.stdout.nil?
|
289
|
+
@client.stdout = $stdout
|
290
|
+
end
|
291
|
+
if @client.stderr.nil?
|
292
|
+
@client.stderr = $stderr
|
293
|
+
end
|
294
|
+
@hooks = Pry::Hooks.new
|
295
|
+
|
296
|
+
@hooks.add_hook :before_eval, :pry_remote_capture do
|
297
|
+
capture_output
|
298
|
+
end
|
299
|
+
|
300
|
+
@hooks.add_hook :after_eval, :pry_remote_uncapture do
|
301
|
+
uncapture_output
|
302
|
+
end
|
303
|
+
|
304
|
+
@hooks.add_hook :before_session, :pry_instance_get do |output, bind, mypry|
|
305
|
+
#puts mypry.class
|
306
|
+
#puts mypry.methods
|
307
|
+
@client.mypry = mypry
|
308
|
+
end
|
309
|
+
|
310
|
+
# Before Pry starts, save the pager config.
|
311
|
+
# We want to disable this because the pager won't do anything useful in
|
312
|
+
# this case (it will run on the server).
|
313
|
+
Pry.config.pager, @old_pager = false, Pry.config.pager
|
314
|
+
|
315
|
+
# As above, but for system config
|
316
|
+
Pry.config.system, @old_system = PrayRemote::System, Pry.config.system
|
317
|
+
|
318
|
+
Pry.config.editor, @old_editor = nil, Pry.config.editor
|
319
|
+
#binding.pry # for testing attacks on clients
|
320
|
+
end
|
321
|
+
|
322
|
+
# Code that has to be called after setup to return to the initial state
|
323
|
+
def teardown
|
324
|
+
# Reset config
|
325
|
+
Pry.config.editor = @old_editor
|
326
|
+
Pry.config.pager = @old_pager
|
327
|
+
Pry.config.system = @old_system
|
328
|
+
|
329
|
+
STDOUT.puts "[pry-remote] Remote session terminated"
|
330
|
+
|
331
|
+
begin
|
332
|
+
@client.kill
|
333
|
+
rescue DRab::DRabConnError
|
334
|
+
STDOUT.puts "[pry-remote] Continuing to stop service"
|
335
|
+
ensure
|
336
|
+
STDOUT.puts "[pry-remote] Ensure stop service"
|
337
|
+
DRab.stop_service
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
# Captures $stdout and $stderr if so requested by the client.
|
342
|
+
def capture_output
|
343
|
+
$stdout = @client.stdout
|
344
|
+
$stderr = @client.stderr
|
345
|
+
end
|
346
|
+
|
347
|
+
# Resets $stdout and $stderr to their previous values.
|
348
|
+
def uncapture_output
|
349
|
+
$stdout = STDOUT
|
350
|
+
$stderr = STDOUT
|
351
|
+
end
|
352
|
+
|
353
|
+
# Actually runs pry-remote
|
354
|
+
def run
|
355
|
+
STDOUT.puts "[pry-remote] Waiting for client on #{uri}"
|
356
|
+
@client.wait
|
357
|
+
|
358
|
+
STDOUT.puts "[pry-remote] Client received, starting remote session"
|
359
|
+
setup
|
360
|
+
|
361
|
+
Pry.start(@object, @options.merge(:input => client.input_proxy,
|
362
|
+
:output => client.output,
|
363
|
+
:hooks => @hooks))
|
364
|
+
ensure
|
365
|
+
teardown
|
366
|
+
end
|
367
|
+
|
368
|
+
# @return Object to enter into
|
369
|
+
attr_reader :object
|
370
|
+
|
371
|
+
# @return [PryServer::Client] Client connecting to the pry-remote server
|
372
|
+
attr_reader :client
|
373
|
+
|
374
|
+
# @return [String] Host of the server
|
375
|
+
attr_reader :host
|
376
|
+
|
377
|
+
# @return [Integer] Port of the server
|
378
|
+
attr_reader :port
|
379
|
+
|
380
|
+
# @return [String] Unix domain socket path of the server
|
381
|
+
attr_reader :unix
|
382
|
+
|
383
|
+
# @return [String] URI for DRab
|
384
|
+
attr_reader :uri
|
385
|
+
|
386
|
+
end
|
387
|
+
|
388
|
+
# Parses arguments and allows to start the client.
|
389
|
+
class CLI
|
390
|
+
# @return [String] Host of the server
|
391
|
+
attr_reader :host
|
392
|
+
|
393
|
+
# @return [Integer] Port of the server
|
394
|
+
attr_reader :port
|
395
|
+
|
396
|
+
# @return [String] Unix domain socket path of the server
|
397
|
+
attr_reader :unix
|
398
|
+
|
399
|
+
# @return [String] URI for DRab
|
400
|
+
attr_reader :uri
|
401
|
+
|
402
|
+
# @return [String] Bind for local DRab server
|
403
|
+
attr_reader :bind
|
404
|
+
|
405
|
+
attr_reader :wait
|
406
|
+
attr_reader :persist
|
407
|
+
attr_reader :capture
|
408
|
+
alias wait? wait
|
409
|
+
alias persist? persist
|
410
|
+
alias capture? capture
|
411
|
+
|
412
|
+
def initialize(args = ARGV)
|
413
|
+
params = Slop.parse args, :help => true do
|
414
|
+
banner "#$PROGRAM_NAME [OPTIONS]"
|
415
|
+
|
416
|
+
on :s, :server=, "Host of the server (#{DefaultHost})", :argument => true,
|
417
|
+
:default => DefaultHost
|
418
|
+
on :p, :port=, "Port of the server (#{DefaultPort})", :argument => true,
|
419
|
+
:as => Integer, :default => DefaultPort
|
420
|
+
on :w, :wait, "Wait for the pry server to come up",
|
421
|
+
:default => false
|
422
|
+
on :r, :persist, "Persist the client to wait for the pry server to come up each time",
|
423
|
+
:default => false
|
424
|
+
on :c, :capture=, "Captures $stdout and $stderr from the server (true)", :argument => true,
|
425
|
+
:default => true
|
426
|
+
on :f, "Disables loading of .pryrc and its plugins, requires, and command history "
|
427
|
+
on :b, :bind=, "Local Drb bind (IP open to server and random port by default, or a Unix domain socket path)"
|
428
|
+
on :z, :bind_proto=, "Protocol for bind to override connection-based default (tcp or unix)"
|
429
|
+
on :u, :unix=, "Unix domain socket path of the server"
|
430
|
+
on :k, :secret=, "Shared secret for authenticating to the server (TCP only)"
|
431
|
+
end
|
432
|
+
|
433
|
+
exit if params.help?
|
434
|
+
|
435
|
+
@host = params[:server]
|
436
|
+
@port = params[:port]
|
437
|
+
|
438
|
+
@bind = params[:bind]
|
439
|
+
@bind_proto = params[:bind_proto]
|
440
|
+
|
441
|
+
@unix = params[:unix]
|
442
|
+
@secret = ""
|
443
|
+
if params[:secret] != nil
|
444
|
+
#@secret = "?secret=" + params[:secret]
|
445
|
+
@secret = params[:secret]
|
446
|
+
end
|
447
|
+
|
448
|
+
if @bind_proto == nil
|
449
|
+
if @unix == nil
|
450
|
+
@bind_proto = "druby://"
|
451
|
+
else
|
452
|
+
@bind_proto = "drabunix:"
|
453
|
+
end
|
454
|
+
else
|
455
|
+
if @bind_proto == "tcp"
|
456
|
+
elsif @bind_proto == "unix"
|
457
|
+
else
|
458
|
+
STDOUT.puts "[pry-remote] invalid bind protocol"
|
459
|
+
exit
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
if @unix == nil
|
464
|
+
@uri = "druby://#{@host}:#{@port}"
|
465
|
+
#@uri = "druby://#{@host}:#{@port}#{@secret}"
|
466
|
+
@unix = ""
|
467
|
+
else
|
468
|
+
if @bind == nil
|
469
|
+
STDOUT.puts "[pry-remote] bind not supplied for Unix domain socket connection"
|
470
|
+
exit
|
471
|
+
end
|
472
|
+
@uri = "drabunix:#{@unix}"
|
473
|
+
end
|
474
|
+
|
475
|
+
@wait = params[:wait]
|
476
|
+
@persist = params[:persist]
|
477
|
+
@capture = params[:capture] === "false" ? false : params[:capture]
|
478
|
+
|
479
|
+
Pry.initial_session_setup unless params[:f]
|
480
|
+
end
|
481
|
+
|
482
|
+
|
483
|
+
def run
|
484
|
+
while true
|
485
|
+
connect
|
486
|
+
break unless persist?
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
# Connects to the server
|
491
|
+
#
|
492
|
+
# @param [IO] input Object holding input for pry-remote
|
493
|
+
# @param [IO] output Object pry-debug will send its output to
|
494
|
+
def connect(input = Pry.config.input, output = Pry.config.output)
|
495
|
+
secret_str = @secret != "" ? "?secret=#{@secret}" : ""
|
496
|
+
|
497
|
+
if bind == false
|
498
|
+
local_ip = UDPSocket.open {|s| s.connect(@host, 1); s.addr.last}
|
499
|
+
DRab.start_service "druby://#{local_ip}:0#{secret_str}"
|
500
|
+
else
|
501
|
+
if @bind_proto == "tcp"
|
502
|
+
DRab.start_service "druby://#{bind}#{secret_str}"
|
503
|
+
else
|
504
|
+
DRab.start_service "drabunix:#{bind}#{secret_str}"
|
505
|
+
end
|
506
|
+
end
|
507
|
+
$client = DRabObject.new(nil, uri)
|
508
|
+
|
509
|
+
begin
|
510
|
+
$client.input = IOUndumpedProxy.new(input)
|
511
|
+
$client.output = IOUndumpedProxy.new(output)
|
512
|
+
rescue DRab::DRabConnError => ex
|
513
|
+
if wait? || persist?
|
514
|
+
sleep 1
|
515
|
+
retry
|
516
|
+
else
|
517
|
+
raise ex
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
if capture?
|
522
|
+
$client.stdout = StdoeWrapper.new($stdout)
|
523
|
+
$client.stderr = StdoeWrapper.new($stderr)
|
524
|
+
end
|
525
|
+
|
526
|
+
$client.thread = ThreadWrapper.new(Thread.current)
|
527
|
+
|
528
|
+
# solved by using own object mapper, leaving this here though for future reference
|
529
|
+
#GC.disable # spooky stuff happens causing the client to garbage collect the StdoeWrappers
|
530
|
+
|
531
|
+
|
532
|
+
# currently not able to properly pass :control_c/emulate it
|
533
|
+
# just preventing accidental close for now
|
534
|
+
def set_trap
|
535
|
+
Signal.trap("INT") do
|
536
|
+
begin
|
537
|
+
#Thread.new {
|
538
|
+
# begin
|
539
|
+
# puts $client.mypry.repl.to_s
|
540
|
+
# $client.mypry.repl.output.puts ""
|
541
|
+
# $client.mypry.reset_eval_string
|
542
|
+
# rescue Exception => e
|
543
|
+
# puts e
|
544
|
+
# puts e.backtrace
|
545
|
+
# end
|
546
|
+
#}
|
547
|
+
Thread.new {
|
548
|
+
begin
|
549
|
+
$client.mypry.to_s
|
550
|
+
rescue Exception => e
|
551
|
+
exit(1)
|
552
|
+
end
|
553
|
+
}
|
554
|
+
rescue Exception => e
|
555
|
+
puts e
|
556
|
+
puts e.backtrace
|
557
|
+
end
|
558
|
+
set_trap
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
begin
|
563
|
+
set_trap
|
564
|
+
sleep
|
565
|
+
ensure
|
566
|
+
DRab.stop_service
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
end
|
571
|
+
end
|
572
|
+
|
573
|
+
class Object
|
574
|
+
# Starts a remote Pry session
|
575
|
+
#
|
576
|
+
# @param [String] host Host of the server (legacy)
|
577
|
+
# @param [Integer] port Port of the server (legacy)
|
578
|
+
# @param [Hash] options Options to be passed to Pry.start
|
579
|
+
def remote_pry(*args)
|
580
|
+
options = PrayRemote.kwargs(args)
|
581
|
+
if args.length == 3
|
582
|
+
options[:secret] = args.pop
|
583
|
+
end
|
584
|
+
if args.length == 2
|
585
|
+
options[:port] = args.pop
|
586
|
+
end
|
587
|
+
if args.length == 1
|
588
|
+
options[:host] = args.pop
|
589
|
+
end
|
590
|
+
PrayRemote::Server.new(self, options).run
|
591
|
+
end
|
592
|
+
|
593
|
+
# a handy alias as many people may think the method is named after the gem
|
594
|
+
# (pry-remote)
|
595
|
+
alias pry_remote remote_pry
|
596
|
+
end
|
data/pray-remote.gemspec
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'pray-remote/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "pray-remote"
|
8
|
+
spec.version = PrayRemote::VERSION
|
9
|
+
spec.authors = ["Mon-Ouie", "Jeff Dileo"]
|
10
|
+
spec.email = ["mon.ouie@gmail.com", "jtdileo@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = "Connect to Pry remotely"
|
13
|
+
spec.description = "Connect to Pry remotely"
|
14
|
+
spec.homepage = "https://github.com/chaosdata/pray-remote"
|
15
|
+
spec.licenses = ['zlib-acknowledgement']
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
18
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
19
|
+
if spec.respond_to?(:metadata)
|
20
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
21
|
+
else
|
22
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
23
|
+
"public gem pushes."
|
24
|
+
end
|
25
|
+
|
26
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
27
|
+
f.match(%r{^(test|spec|features)/})
|
28
|
+
end
|
29
|
+
spec.bindir = "exe"
|
30
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
31
|
+
spec.require_paths = ["lib"]
|
32
|
+
|
33
|
+
spec.add_dependency "drab", "~> 0.1.0"
|
34
|
+
spec.add_dependency "slop", "~> 3.0"
|
35
|
+
spec.add_dependency "pry", "~> 0.9"
|
36
|
+
spec.add_development_dependency "bundler", "~> 1.13"
|
37
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
38
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
39
|
+
end
|
metadata
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pray-remote
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mon-Ouie
|
8
|
+
- Jeff Dileo
|
9
|
+
autorequire:
|
10
|
+
bindir: exe
|
11
|
+
cert_chain: []
|
12
|
+
date: 2017-09-16 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: drab
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 0.1.0
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 0.1.0
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: slop
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '3.0'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '3.0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: pry
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0.9'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0.9'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: bundler
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '1.13'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1.13'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: rake
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '10.0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '10.0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: rspec
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '3.0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '3.0'
|
98
|
+
description: Connect to Pry remotely
|
99
|
+
email:
|
100
|
+
- mon.ouie@gmail.com
|
101
|
+
- jtdileo@gmail.com
|
102
|
+
executables:
|
103
|
+
- pray-remote
|
104
|
+
extensions: []
|
105
|
+
extra_rdoc_files: []
|
106
|
+
files:
|
107
|
+
- ".gitignore"
|
108
|
+
- Gemfile
|
109
|
+
- Gemfile.lock
|
110
|
+
- LICENSE
|
111
|
+
- README.md
|
112
|
+
- Rakefile
|
113
|
+
- bin/console
|
114
|
+
- bin/pray-remote
|
115
|
+
- bin/setup
|
116
|
+
- exe/pray-remote
|
117
|
+
- lib/pray-remote.rb
|
118
|
+
- lib/pray-remote/pray-remote.rb
|
119
|
+
- lib/pray-remote/version.rb
|
120
|
+
- pray-remote.gemspec
|
121
|
+
homepage: https://github.com/chaosdata/pray-remote
|
122
|
+
licenses:
|
123
|
+
- zlib-acknowledgement
|
124
|
+
metadata:
|
125
|
+
allowed_push_host: https://rubygems.org
|
126
|
+
post_install_message:
|
127
|
+
rdoc_options: []
|
128
|
+
require_paths:
|
129
|
+
- lib
|
130
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
requirements: []
|
141
|
+
rubyforge_project:
|
142
|
+
rubygems_version: 2.6.11
|
143
|
+
signing_key:
|
144
|
+
specification_version: 4
|
145
|
+
summary: Connect to Pry remotely
|
146
|
+
test_files: []
|