remote_ruby 0.3.0 → 1.0.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 +4 -4
- data/.rspec +1 -2
- data/.rubocop.yml +37 -6
- data/CHANGELOG.md +64 -0
- data/LICENSE.txt +1 -1
- data/README.md +348 -81
- data/lib/remote_ruby/adapter_builder.rb +75 -0
- data/lib/remote_ruby/cache_adapter.rb +41 -0
- data/lib/remote_ruby/{connection_adapter/caching_adapter.rb → caching_adapter.rb} +23 -13
- data/lib/remote_ruby/code_templates/compiler/main.rb.erb +17 -29
- data/lib/remote_ruby/compat_io_reader.rb +36 -0
- data/lib/remote_ruby/compat_io_writer.rb +38 -0
- data/lib/remote_ruby/compiler.rb +8 -8
- data/lib/remote_ruby/connection_adapter.rb +16 -16
- data/lib/remote_ruby/execution_context.rb +56 -74
- data/lib/remote_ruby/extensions.rb +14 -0
- data/lib/remote_ruby/parser_factory.rb +29 -0
- data/lib/remote_ruby/plugin.rb +25 -0
- data/lib/remote_ruby/{flavour/rails_flavour.rb → rails_plugin.rb} +7 -5
- data/lib/remote_ruby/remote_context.rb +52 -0
- data/lib/remote_ruby/remote_error.rb +55 -0
- data/lib/remote_ruby/source_extractor.rb +2 -12
- data/lib/remote_ruby/ssh_adapter.rb +128 -0
- data/lib/remote_ruby/stream_prefixer.rb +25 -0
- data/lib/remote_ruby/tee_writer.rb +16 -0
- data/lib/remote_ruby/text_mode_adapter.rb +63 -0
- data/lib/remote_ruby/text_mode_builder.rb +44 -0
- data/lib/remote_ruby/tmp_file_adapter.rb +62 -0
- data/lib/remote_ruby/version.rb +1 -1
- data/lib/remote_ruby.rb +57 -15
- metadata +72 -28
- data/.github/workflows/main.yml +0 -26
- data/.gitignore +0 -17
- data/Gemfile +0 -23
- data/lib/remote_ruby/connection_adapter/cache_adapter.rb +0 -41
- data/lib/remote_ruby/connection_adapter/eval_adapter.rb +0 -96
- data/lib/remote_ruby/connection_adapter/local_stdin_adapter.rb +0 -29
- data/lib/remote_ruby/connection_adapter/ssh_stdin_adapter.rb +0 -34
- data/lib/remote_ruby/connection_adapter/stdin_process_adapter.rb +0 -35
- data/lib/remote_ruby/flavour.rb +0 -27
- data/lib/remote_ruby/runner.rb +0 -55
- data/lib/remote_ruby/stream_cacher.rb +0 -36
- data/lib/remote_ruby/unmarshaler.rb +0 -59
- data/remote_ruby.gemspec +0 -36
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: remote_ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nikita Chernukhin
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-03-06 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: base64
|
@@ -30,42 +29,84 @@ dependencies:
|
|
30
29
|
requirements:
|
31
30
|
- - "~>"
|
32
31
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0
|
32
|
+
version: '1.0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.0'
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: logger
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.6'
|
34
47
|
type: :runtime
|
35
48
|
prerelease: false
|
36
49
|
version_requirements: !ruby/object:Gem::Requirement
|
37
50
|
requirements:
|
38
51
|
- - "~>"
|
39
52
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
53
|
+
version: '1.6'
|
41
54
|
- !ruby/object:Gem::Dependency
|
42
55
|
name: method_source
|
43
56
|
requirement: !ruby/object:Gem::Requirement
|
44
57
|
requirements:
|
45
58
|
- - "~>"
|
46
59
|
- !ruby/object:Gem::Version
|
47
|
-
version: '1.
|
60
|
+
version: '1.1'
|
48
61
|
type: :runtime
|
49
62
|
prerelease: false
|
50
63
|
version_requirements: !ruby/object:Gem::Requirement
|
51
64
|
requirements:
|
52
65
|
- - "~>"
|
53
66
|
- !ruby/object:Gem::Version
|
54
|
-
version: '1.
|
67
|
+
version: '1.1'
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: net-ssh
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '7.3'
|
75
|
+
type: :runtime
|
76
|
+
prerelease: false
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '7.3'
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: ostruct
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0.6'
|
89
|
+
type: :runtime
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0.6'
|
55
96
|
- !ruby/object:Gem::Dependency
|
56
97
|
name: parser
|
57
98
|
requirement: !ruby/object:Gem::Requirement
|
58
99
|
requirements:
|
59
100
|
- - "~>"
|
60
101
|
- !ruby/object:Gem::Version
|
61
|
-
version: '3.
|
102
|
+
version: '3.3'
|
62
103
|
type: :runtime
|
63
104
|
prerelease: false
|
64
105
|
version_requirements: !ruby/object:Gem::Requirement
|
65
106
|
requirements:
|
66
107
|
- - "~>"
|
67
108
|
- !ruby/object:Gem::Version
|
68
|
-
version: '3.
|
109
|
+
version: '3.3'
|
69
110
|
- !ruby/object:Gem::Dependency
|
70
111
|
name: unparser
|
71
112
|
requirement: !ruby/object:Gem::Requirement
|
@@ -87,39 +128,43 @@ executables: []
|
|
87
128
|
extensions: []
|
88
129
|
extra_rdoc_files: []
|
89
130
|
files:
|
90
|
-
- ".github/workflows/main.yml"
|
91
|
-
- ".gitignore"
|
92
131
|
- ".rspec"
|
93
132
|
- ".rubocop.yml"
|
94
|
-
-
|
133
|
+
- CHANGELOG.md
|
95
134
|
- LICENSE.txt
|
96
135
|
- README.md
|
97
136
|
- lib/remote_ruby.rb
|
137
|
+
- lib/remote_ruby/adapter_builder.rb
|
138
|
+
- lib/remote_ruby/cache_adapter.rb
|
139
|
+
- lib/remote_ruby/caching_adapter.rb
|
98
140
|
- lib/remote_ruby/code_templates/compiler/main.rb.erb
|
141
|
+
- lib/remote_ruby/compat_io_reader.rb
|
142
|
+
- lib/remote_ruby/compat_io_writer.rb
|
99
143
|
- lib/remote_ruby/compiler.rb
|
100
144
|
- lib/remote_ruby/connection_adapter.rb
|
101
|
-
- lib/remote_ruby/connection_adapter/cache_adapter.rb
|
102
|
-
- lib/remote_ruby/connection_adapter/caching_adapter.rb
|
103
|
-
- lib/remote_ruby/connection_adapter/eval_adapter.rb
|
104
|
-
- lib/remote_ruby/connection_adapter/local_stdin_adapter.rb
|
105
|
-
- lib/remote_ruby/connection_adapter/ssh_stdin_adapter.rb
|
106
|
-
- lib/remote_ruby/connection_adapter/stdin_process_adapter.rb
|
107
145
|
- lib/remote_ruby/execution_context.rb
|
108
|
-
- lib/remote_ruby/
|
109
|
-
- lib/remote_ruby/flavour/rails_flavour.rb
|
146
|
+
- lib/remote_ruby/extensions.rb
|
110
147
|
- lib/remote_ruby/locals_extractor.rb
|
111
|
-
- lib/remote_ruby/
|
148
|
+
- lib/remote_ruby/parser_factory.rb
|
149
|
+
- lib/remote_ruby/plugin.rb
|
150
|
+
- lib/remote_ruby/rails_plugin.rb
|
151
|
+
- lib/remote_ruby/remote_context.rb
|
152
|
+
- lib/remote_ruby/remote_error.rb
|
112
153
|
- lib/remote_ruby/source_extractor.rb
|
113
|
-
- lib/remote_ruby/
|
114
|
-
- lib/remote_ruby/
|
154
|
+
- lib/remote_ruby/ssh_adapter.rb
|
155
|
+
- lib/remote_ruby/stream_prefixer.rb
|
156
|
+
- lib/remote_ruby/tee_writer.rb
|
157
|
+
- lib/remote_ruby/text_mode_adapter.rb
|
158
|
+
- lib/remote_ruby/text_mode_builder.rb
|
159
|
+
- lib/remote_ruby/tmp_file_adapter.rb
|
115
160
|
- lib/remote_ruby/version.rb
|
116
|
-
- remote_ruby.gemspec
|
117
161
|
homepage: https://github.com/nu-hin/remote_ruby
|
118
162
|
licenses:
|
119
163
|
- MIT
|
120
164
|
metadata:
|
121
165
|
rubygems_mfa_required: 'true'
|
122
|
-
|
166
|
+
homepage_uri: https://github.com/nu-hin/remote_ruby
|
167
|
+
source_code_uri: https://github.com/nu-hin/remote_ruby
|
123
168
|
rdoc_options: []
|
124
169
|
require_paths:
|
125
170
|
- lib
|
@@ -127,15 +172,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
127
172
|
requirements:
|
128
173
|
- - ">="
|
129
174
|
- !ruby/object:Gem::Version
|
130
|
-
version: '2.
|
175
|
+
version: '2.7'
|
131
176
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
177
|
requirements:
|
133
178
|
- - ">="
|
134
179
|
- !ruby/object:Gem::Version
|
135
180
|
version: '0'
|
136
181
|
requirements: []
|
137
|
-
rubygems_version: 3.
|
138
|
-
signing_key:
|
182
|
+
rubygems_version: 3.6.2
|
139
183
|
specification_version: 4
|
140
184
|
summary: Execute Ruby code on the remote servers.
|
141
185
|
test_files: []
|
data/.github/workflows/main.yml
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
name: "Lint & Test"
|
2
|
-
on: [push, pull_request]
|
3
|
-
jobs:
|
4
|
-
rubocop:
|
5
|
-
runs-on: ubuntu-latest
|
6
|
-
steps:
|
7
|
-
- uses: actions/checkout@v2
|
8
|
-
- uses: ruby/setup-ruby@v1
|
9
|
-
with:
|
10
|
-
ruby-version: 3.0.2
|
11
|
-
bundler-cache: true
|
12
|
-
- run: bundle exec rubocop
|
13
|
-
rspec:
|
14
|
-
strategy:
|
15
|
-
matrix:
|
16
|
-
os: [ubuntu-latest, macos-latest]
|
17
|
-
ruby: [2.6, 2.7, 3.2, head]
|
18
|
-
runs-on: ${{ matrix.os }}
|
19
|
-
steps:
|
20
|
-
- uses: actions/checkout@v2
|
21
|
-
- uses: ruby/setup-ruby@v1
|
22
|
-
with:
|
23
|
-
ruby-version: ${{ matrix.ruby }}
|
24
|
-
bundler-cache: true
|
25
|
-
- run: bundle exec rspec
|
26
|
-
- uses: coverallsapp/github-action@v2
|
data/.gitignore
DELETED
data/Gemfile
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
source 'https://rubygems.org'
|
4
|
-
|
5
|
-
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
6
|
-
|
7
|
-
gemspec
|
8
|
-
|
9
|
-
group :development do
|
10
|
-
gem 'rubocop', '~> 1.23'
|
11
|
-
gem 'yard', '~> 0.9'
|
12
|
-
end
|
13
|
-
|
14
|
-
group :development, :test do
|
15
|
-
gem 'byebug', '~> 11.1'
|
16
|
-
gem 'pry-byebug', '~> 3.9'
|
17
|
-
gem 'rspec', '~> 3.10'
|
18
|
-
end
|
19
|
-
|
20
|
-
group :test do
|
21
|
-
gem 'simplecov', '~> 0.22'
|
22
|
-
gem 'simplecov-lcov', '~> 0.8'
|
23
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RemoteRuby
|
4
|
-
# An adapter which takes stdout and stderr from files and ignores
|
5
|
-
# all stdin. Only used to read from cache.
|
6
|
-
class CacheAdapter < ConnectionAdapter
|
7
|
-
def initialize(connection_name:, cache_path:)
|
8
|
-
super
|
9
|
-
@cache_path = cache_path
|
10
|
-
@connection_name = connection_name
|
11
|
-
end
|
12
|
-
|
13
|
-
def connection_name
|
14
|
-
"[CACHE] #{@connection_name}"
|
15
|
-
end
|
16
|
-
|
17
|
-
def open(_code)
|
18
|
-
stdout = File.open(stdout_file_path, 'r')
|
19
|
-
stderr = File.open(stderr_file_path, 'r')
|
20
|
-
|
21
|
-
yield stdout, stderr
|
22
|
-
ensure
|
23
|
-
stderr.close unless stderr.closed?
|
24
|
-
stdout.close unless stdout.closed?
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
attr_reader :cache_path
|
30
|
-
|
31
|
-
def stdout_file_path
|
32
|
-
fp = "#{cache_path}.stdout"
|
33
|
-
File.exist?(fp) ? fp : File::NULL
|
34
|
-
end
|
35
|
-
|
36
|
-
def stderr_file_path
|
37
|
-
fp = "#{cache_path}.stderr"
|
38
|
-
File.exist?(fp) ? fp : File::NULL
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,96 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RemoteRuby
|
4
|
-
# An adapter to expecute Ruby code in the current process in an isolated
|
5
|
-
# scope
|
6
|
-
class EvalAdapter < ConnectionAdapter
|
7
|
-
attr_reader :async, :working_dir
|
8
|
-
|
9
|
-
def initialize(working_dir: Dir.pwd, async: false)
|
10
|
-
super
|
11
|
-
@async = async
|
12
|
-
@working_dir = working_dir
|
13
|
-
end
|
14
|
-
|
15
|
-
def connection_name
|
16
|
-
''
|
17
|
-
end
|
18
|
-
|
19
|
-
def open(code, &block)
|
20
|
-
if async
|
21
|
-
run_async(code, &block)
|
22
|
-
else
|
23
|
-
run_sync(code, &block)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def run_code(code)
|
30
|
-
binder = Object.new
|
31
|
-
|
32
|
-
Dir.chdir(working_dir) do
|
33
|
-
binder.instance_eval(code)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def run_sync(code)
|
38
|
-
with_stringio do |tmp_stdout, tmp_stderr|
|
39
|
-
with_tmp_streams(tmp_stdout, tmp_stderr) do
|
40
|
-
run_code(code)
|
41
|
-
end
|
42
|
-
|
43
|
-
tmp_stdout.close_write
|
44
|
-
tmp_stderr.close_write
|
45
|
-
tmp_stdout.rewind
|
46
|
-
tmp_stderr.rewind
|
47
|
-
yield tmp_stdout, tmp_stderr
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def run_async(code)
|
52
|
-
with_pipes do |out_read, out_write, err_read, err_write|
|
53
|
-
Thread.new do
|
54
|
-
with_tmp_streams(out_write, err_write) do
|
55
|
-
run_code(code)
|
56
|
-
end
|
57
|
-
|
58
|
-
out_write.close
|
59
|
-
err_write.close
|
60
|
-
end
|
61
|
-
|
62
|
-
yield out_read, err_read
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def with_pipes
|
67
|
-
out_read, out_write = IO.pipe
|
68
|
-
err_read, err_write = IO.pipe
|
69
|
-
yield out_read, out_write, err_read, err_write
|
70
|
-
ensure
|
71
|
-
out_read.close
|
72
|
-
err_read.close
|
73
|
-
end
|
74
|
-
|
75
|
-
def with_stringio
|
76
|
-
out = StringIO.new
|
77
|
-
err = StringIO.new
|
78
|
-
|
79
|
-
yield out, err
|
80
|
-
ensure
|
81
|
-
out.close
|
82
|
-
err.close
|
83
|
-
end
|
84
|
-
|
85
|
-
def with_tmp_streams(out, err)
|
86
|
-
old_stdout = $stdout
|
87
|
-
old_stderr = $stderr
|
88
|
-
$stdout = out
|
89
|
-
$stderr = err
|
90
|
-
yield
|
91
|
-
ensure
|
92
|
-
$stdout = old_stdout
|
93
|
-
$stderr = old_stderr
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RemoteRuby
|
4
|
-
# An adapter to expecute Ruby code on the local macine
|
5
|
-
# inside a specified directory
|
6
|
-
class LocalStdinAdapter < ::RemoteRuby::StdinProcessAdapter
|
7
|
-
attr_reader :working_dir, :bundler
|
8
|
-
|
9
|
-
def initialize(working_dir: '.', bundler: false)
|
10
|
-
super
|
11
|
-
@working_dir = working_dir
|
12
|
-
@bundler = bundler
|
13
|
-
end
|
14
|
-
|
15
|
-
def connection_name
|
16
|
-
working_dir
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def command
|
22
|
-
if bundler
|
23
|
-
"cd \"#{working_dir}\" && bundle exec ruby"
|
24
|
-
else
|
25
|
-
"cd \"#{working_dir}\" && ruby"
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RemoteRuby
|
4
|
-
# An adapter to execute Ruby code on the remote server via SSH
|
5
|
-
class SSHStdinAdapter < StdinProcessAdapter
|
6
|
-
attr_reader :server, :working_dir, :user, :key_file, :bundler
|
7
|
-
|
8
|
-
def initialize(server:, working_dir: '~', user: nil, key_file: nil, bundler: false)
|
9
|
-
super
|
10
|
-
@working_dir = working_dir
|
11
|
-
@server = user.nil? ? server : "#{user}@#{server}"
|
12
|
-
@user = user
|
13
|
-
@key_file = key_file
|
14
|
-
@bundler = bundler
|
15
|
-
end
|
16
|
-
|
17
|
-
def connection_name
|
18
|
-
"#{server}:#{working_dir}"
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def command
|
24
|
-
command = 'ssh'
|
25
|
-
command = "#{command} -i #{key_file}" if key_file
|
26
|
-
|
27
|
-
if bundler
|
28
|
-
"#{command} #{server} \"cd #{working_dir} && bundle exec ruby\""
|
29
|
-
else
|
30
|
-
"#{command} #{server} \"cd #{working_dir} && ruby\""
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'open3'
|
4
|
-
|
5
|
-
module RemoteRuby
|
6
|
-
# Base class for adapters which launch an external process to execute
|
7
|
-
# Ruby code and send the code to its standard input.
|
8
|
-
class StdinProcessAdapter < ::RemoteRuby::ConnectionAdapter
|
9
|
-
include Open3
|
10
|
-
|
11
|
-
def open(code)
|
12
|
-
result = nil
|
13
|
-
|
14
|
-
popen3(command) do |stdin, stdout, stderr, wait_thr|
|
15
|
-
stdin.write(code)
|
16
|
-
stdin.close
|
17
|
-
|
18
|
-
yield stdout, stderr
|
19
|
-
|
20
|
-
result = wait_thr.value
|
21
|
-
end
|
22
|
-
|
23
|
-
return if result.success?
|
24
|
-
|
25
|
-
raise "Remote connection exited with code #{result}"
|
26
|
-
end
|
27
|
-
|
28
|
-
protected
|
29
|
-
|
30
|
-
# Command to run an external process. Override in a child class.
|
31
|
-
def command
|
32
|
-
raise NotImplementedError
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
data/lib/remote_ruby/flavour.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RemoteRuby
|
4
|
-
# Base class for Flavours: addons to execution context to insert additonal
|
5
|
-
# code to the generated remote code.
|
6
|
-
class Flavour
|
7
|
-
def self.build_flavours(args = {})
|
8
|
-
res = []
|
9
|
-
|
10
|
-
{
|
11
|
-
rails: RemoteRuby::RailsFlavour
|
12
|
-
}.each do |name, klass|
|
13
|
-
options = args.delete(name)
|
14
|
-
|
15
|
-
res << klass.new(**options) if options
|
16
|
-
end
|
17
|
-
|
18
|
-
res
|
19
|
-
end
|
20
|
-
|
21
|
-
def initialize(**args); end
|
22
|
-
|
23
|
-
def code_header; end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
require 'remote_ruby/flavour/rails_flavour'
|
data/lib/remote_ruby/runner.rb
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'colorize'
|
4
|
-
|
5
|
-
require 'remote_ruby/unmarshaler'
|
6
|
-
|
7
|
-
module RemoteRuby
|
8
|
-
# Runner class is responsible for running a prepared Ruby code with given
|
9
|
-
# connection adapter, reading output and unmarshalling result and local
|
10
|
-
# variables values.
|
11
|
-
class Runner
|
12
|
-
def initialize(code:, adapter:, out_stream: $stdout, err_stream: $stderr)
|
13
|
-
@code = code
|
14
|
-
@adapter = adapter
|
15
|
-
@out_stream = out_stream
|
16
|
-
@err_stream = err_stream
|
17
|
-
end
|
18
|
-
|
19
|
-
def run
|
20
|
-
locals = nil
|
21
|
-
|
22
|
-
adapter.open(code) do |stdout, stderr|
|
23
|
-
out_thread = read_stream(stdout, out_stream, :green)
|
24
|
-
err_thread = read_stream(stderr, err_stream, :red)
|
25
|
-
[out_thread, err_thread].each(&:join)
|
26
|
-
locals = out_thread[:locals]
|
27
|
-
end
|
28
|
-
|
29
|
-
{ result: locals[:__return_val__], locals: locals }
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
attr_reader :code, :adapter, :out_stream, :err_stream
|
35
|
-
|
36
|
-
def read_stream(read_from, write_to, color)
|
37
|
-
Thread.new do
|
38
|
-
until read_from.eof?
|
39
|
-
line = read_from.readline
|
40
|
-
|
41
|
-
if line.start_with?('%%%MARSHAL')
|
42
|
-
Thread.current[:locals] ||= unmarshal(read_from)
|
43
|
-
else
|
44
|
-
write_to.puts "#{adapter.connection_name.send(color)}>\t#{line}"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def unmarshal(stdout)
|
51
|
-
unmarshaler = RemoteRuby::Unmarshaler.new(stdout)
|
52
|
-
unmarshaler.unmarshal
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RemoteRuby
|
4
|
-
# Decorates the source stream and writes to the cache stream as
|
5
|
-
# the source is being read
|
6
|
-
class StreamCacher
|
7
|
-
def initialize(source_stream, cache_stream)
|
8
|
-
@source_stream = source_stream
|
9
|
-
@cache_stream = cache_stream
|
10
|
-
end
|
11
|
-
|
12
|
-
def read(*args)
|
13
|
-
res = source_stream.read(*args)
|
14
|
-
cache_stream.write(res)
|
15
|
-
res
|
16
|
-
end
|
17
|
-
|
18
|
-
def readline
|
19
|
-
res = source_stream.readline
|
20
|
-
cache_stream.write(res)
|
21
|
-
res
|
22
|
-
end
|
23
|
-
|
24
|
-
def eof?
|
25
|
-
source_stream.eof?
|
26
|
-
end
|
27
|
-
|
28
|
-
def close
|
29
|
-
source_stream.close
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
attr_reader :source_stream, :cache_stream
|
35
|
-
end
|
36
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RemoteRuby
|
4
|
-
# Unmarshals variables from given stream
|
5
|
-
class Unmarshaler
|
6
|
-
UnmarshalError = Class.new(StandardError)
|
7
|
-
|
8
|
-
def initialize(stream, terminator = nil)
|
9
|
-
@stream = stream
|
10
|
-
@terminator = terminator
|
11
|
-
end
|
12
|
-
|
13
|
-
def unmarshal
|
14
|
-
res = {}
|
15
|
-
|
16
|
-
until stream.eof?
|
17
|
-
line = stream.readline
|
18
|
-
|
19
|
-
break if terminator && line == terminator
|
20
|
-
|
21
|
-
var = read_var(line)
|
22
|
-
res[var.first] = var[1]
|
23
|
-
end
|
24
|
-
|
25
|
-
res
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
attr_reader :stream, :terminator
|
31
|
-
|
32
|
-
def read_var(line)
|
33
|
-
varname, length = read_var_header(line)
|
34
|
-
data = read_var_data(length)
|
35
|
-
[varname.to_sym, data]
|
36
|
-
rescue ArgumentError => e
|
37
|
-
raise UnmarshalError,
|
38
|
-
"Could not resolve type for #{varname} variable: #{e.message}"
|
39
|
-
rescue TypeError
|
40
|
-
raise UnmarshalError, 'Incorrect data format'
|
41
|
-
end
|
42
|
-
|
43
|
-
def read_var_header(line)
|
44
|
-
varname, length = line.split(':')
|
45
|
-
|
46
|
-
raise UnmarshalError, "Incorrect header '#{line}'" \
|
47
|
-
if varname.nil? || length.nil?
|
48
|
-
|
49
|
-
[varname, length]
|
50
|
-
end
|
51
|
-
|
52
|
-
# rubocop:disable Security/MarshalLoad
|
53
|
-
def read_var_data(length)
|
54
|
-
data = stream.read(length.to_i)
|
55
|
-
Marshal.load(data)
|
56
|
-
end
|
57
|
-
# rubocop:enable Security/MarshalLoad
|
58
|
-
end
|
59
|
-
end
|