toys-core 0.4.2 → 0.4.3
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/CHANGELOG.md +5 -0
- data/lib/toys/core_version.rb +1 -1
- data/lib/toys/standard_mixins/exec.rb +60 -26
- data/lib/toys/standard_mixins/terminal.rb +1 -0
- data/lib/toys/utils/exec.rb +132 -71
- data/lib/toys/utils/terminal.rb +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a85fbb6170bb1609f304cc0b1a62d4743437802b64c796372d569856bdd1e256
|
4
|
+
data.tar.gz: 8291edf5cd82f0bbbcafb83878351415a28f8d0a21e058332184534c08e29751
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 701ff10d98b0ae6f2b8c9d758c8dcb1769622a59dc3e86b85fedfae327811403c3ae514b05060eb91b701948cd275d94c86fa20973724864fc9c2b4aae355f90
|
7
|
+
data.tar.gz: b042cb80c9fb0f9d0d0132b546384179efc69873e4d060c20b7e2bc1b7c6e36721d27655e4efa4b77960cc899e726bbc47e92cbdbfd5cf2c18289dcde0b8e3cb
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# Release History
|
2
2
|
|
3
|
+
### 0.4.3 / 2018-07-13
|
4
|
+
|
5
|
+
* IMPROVED: Utils::Exec methods can now spawn subprocesses in the background
|
6
|
+
* IMPROVED: Utils::Exec capture methods can now yield a controller
|
7
|
+
|
3
8
|
### 0.4.2 / 2018-07-08
|
4
9
|
|
5
10
|
* FIXED: Raise an error rather than cause unexpected behavior if a mixin is included twice.
|
data/lib/toys/core_version.rb
CHANGED
@@ -100,8 +100,8 @@ module Toys
|
|
100
100
|
# Execute a command. The command may be given as a single string to pass
|
101
101
|
# to a shell, or an array of strings indicating a posix command.
|
102
102
|
#
|
103
|
-
# If
|
104
|
-
#
|
103
|
+
# If the process is not set to run in the background, and a block is
|
104
|
+
# provided, a {Toys::Utils::Exec::Controller} will be yielded to it.
|
105
105
|
#
|
106
106
|
# @param [String,Array<String>] cmd The command to execute.
|
107
107
|
# @param [Hash] opts The command options. All options listed in the
|
@@ -110,8 +110,9 @@ module Toys
|
|
110
110
|
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller for
|
111
111
|
# the subprocess streams.
|
112
112
|
#
|
113
|
-
# @return [Toys::Utils::Exec::Result] The
|
114
|
-
#
|
113
|
+
# @return [Toys::Utils::Exec::Controller,Toys::Utils::Exec::Result] The
|
114
|
+
# subprocess controller or result, depending on whether the process
|
115
|
+
# is running in the background or foreground.
|
115
116
|
#
|
116
117
|
def exec(cmd, opts = {}, &block)
|
117
118
|
self[KEY].exec(cmd, Exec._setup_exec_opts(opts, self), &block)
|
@@ -120,8 +121,8 @@ module Toys
|
|
120
121
|
##
|
121
122
|
# Spawn a ruby process and pass the given arguments to it.
|
122
123
|
#
|
123
|
-
# If
|
124
|
-
#
|
124
|
+
# If the process is not set to run in the background, and a block is
|
125
|
+
# provided, a {Toys::Utils::Exec::Controller} will be yielded to it.
|
125
126
|
#
|
126
127
|
# @param [String,Array<String>] args The arguments to ruby.
|
127
128
|
# @param [Hash] opts The command options. All options listed in the
|
@@ -130,8 +131,9 @@ module Toys
|
|
130
131
|
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller for
|
131
132
|
# for the subprocess streams.
|
132
133
|
#
|
133
|
-
# @return [Toys::Utils::Exec::Result] The
|
134
|
-
#
|
134
|
+
# @return [Toys::Utils::Exec::Controller,Toys::Utils::Exec::Result] The
|
135
|
+
# subprocess controller or result, depending on whether the process
|
136
|
+
# is running in the background or foreground.
|
135
137
|
#
|
136
138
|
def exec_ruby(args, opts = {}, &block)
|
137
139
|
self[KEY].exec_ruby(args, Exec._setup_exec_opts(opts, self), &block)
|
@@ -141,8 +143,8 @@ module Toys
|
|
141
143
|
##
|
142
144
|
# Execute a proc in a subprocess.
|
143
145
|
#
|
144
|
-
# If
|
145
|
-
#
|
146
|
+
# If the process is not set to run in the background, and a block is
|
147
|
+
# provided, a {Toys::Utils::Exec::Controller} will be yielded to it.
|
146
148
|
#
|
147
149
|
# @param [Proc] func The proc to call.
|
148
150
|
# @param [Hash] opts The command options. Most options listed in the
|
@@ -151,8 +153,9 @@ module Toys
|
|
151
153
|
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
152
154
|
# for the subprocess streams.
|
153
155
|
#
|
154
|
-
# @return [Toys::Utils::Exec::Result] The
|
155
|
-
#
|
156
|
+
# @return [Toys::Utils::Exec::Controller,Toys::Utils::Exec::Result] The
|
157
|
+
# subprocess controller or result, depending on whether the process
|
158
|
+
# is running in the background or foreground.
|
156
159
|
#
|
157
160
|
def exec_proc(func, opts = {}, &block)
|
158
161
|
self[KEY].exec_proc(func, Exec._setup_exec_opts(opts, self), &block)
|
@@ -162,8 +165,8 @@ module Toys
|
|
162
165
|
# Execute a tool. The command may be given as a single string or an array
|
163
166
|
# of strings, representing the tool to run and the arguments to pass.
|
164
167
|
#
|
165
|
-
# If
|
166
|
-
#
|
168
|
+
# If the process is not set to run in the background, and a block is
|
169
|
+
# provided, a {Toys::Utils::Exec::Controller} will be yielded to it.
|
167
170
|
#
|
168
171
|
# @param [String,Array<String>] cmd The tool to execute.
|
169
172
|
# @param [Hash] opts The command options. Most options listed in the
|
@@ -172,8 +175,9 @@ module Toys
|
|
172
175
|
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
173
176
|
# for the subprocess streams.
|
174
177
|
#
|
175
|
-
# @return [Toys::Utils::Exec::Result] The
|
176
|
-
#
|
178
|
+
# @return [Toys::Utils::Exec::Controller,Toys::Utils::Exec::Result] The
|
179
|
+
# subprocess controller or result, depending on whether the process
|
180
|
+
# is running in the background or foreground.
|
177
181
|
#
|
178
182
|
def exec_tool(cmd, opts = {}, &block)
|
179
183
|
func = Exec._make_tool_caller(cmd)
|
@@ -185,48 +189,66 @@ module Toys
|
|
185
189
|
# to a shell, or an array of strings indicating a posix command.
|
186
190
|
#
|
187
191
|
# Captures standard out and returns it as a string.
|
192
|
+
# Cannot be run in the background.
|
193
|
+
#
|
194
|
+
# If a block is provided, a {Toys::Utils::Exec::Controller} will be
|
195
|
+
# yielded to it.
|
188
196
|
#
|
189
197
|
# @param [String,Array<String>] cmd The command to execute.
|
190
198
|
# @param [Hash] opts The command options. All options listed in the
|
191
199
|
# {Toys::Utils::Exec} documentation are supported, plus the
|
192
200
|
# `exit_on_nonzero_status` option.
|
201
|
+
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
202
|
+
# for the subprocess streams.
|
193
203
|
#
|
194
204
|
# @return [String] What was written to standard out.
|
195
205
|
#
|
196
|
-
def capture(cmd, opts = {})
|
197
|
-
self[KEY].capture(cmd, Exec._setup_exec_opts(opts, self))
|
206
|
+
def capture(cmd, opts = {}, &block)
|
207
|
+
self[KEY].capture(cmd, Exec._setup_exec_opts(opts, self), &block)
|
198
208
|
end
|
199
209
|
|
200
210
|
##
|
201
211
|
# Spawn a ruby process and pass the given arguments to it.
|
202
212
|
#
|
203
213
|
# Captures standard out and returns it as a string.
|
214
|
+
# Cannot be run in the background.
|
215
|
+
#
|
216
|
+
# If a block is provided, a {Toys::Utils::Exec::Controller} will be
|
217
|
+
# yielded to it.
|
204
218
|
#
|
205
219
|
# @param [String,Array<String>] args The arguments to ruby.
|
206
220
|
# @param [Hash] opts The command options. All options listed in the
|
207
221
|
# {Toys::Utils::Exec} documentation are supported, plus the
|
208
222
|
# `exit_on_nonzero_status` option.
|
223
|
+
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
224
|
+
# for the subprocess streams.
|
209
225
|
#
|
210
226
|
# @return [String] What was written to standard out.
|
211
227
|
#
|
212
|
-
def capture_ruby(args, opts = {})
|
213
|
-
self[KEY].capture_ruby(args, Exec._setup_exec_opts(opts, self))
|
228
|
+
def capture_ruby(args, opts = {}, &block)
|
229
|
+
self[KEY].capture_ruby(args, Exec._setup_exec_opts(opts, self), &block)
|
214
230
|
end
|
215
231
|
|
216
232
|
##
|
217
233
|
# Execute a proc in a subprocess.
|
218
234
|
#
|
219
235
|
# Captures standard out and returns it as a string.
|
236
|
+
# Cannot be run in the background.
|
237
|
+
#
|
238
|
+
# If a block is provided, a {Toys::Utils::Exec::Controller} will be
|
239
|
+
# yielded to it.
|
220
240
|
#
|
221
241
|
# @param [Proc] func The proc to call.
|
222
242
|
# @param [Hash] opts The command options. Most options listed in the
|
223
243
|
# {Toys::Utils::Exec} documentation are supported, plus the
|
224
244
|
# `exit_on_nonzero_status` option.
|
245
|
+
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
246
|
+
# for the subprocess streams.
|
225
247
|
#
|
226
248
|
# @return [String] What was written to standard out.
|
227
249
|
#
|
228
|
-
def capture_proc(func, opts = {})
|
229
|
-
self[KEY].capture_proc(func, Exec._setup_exec_opts(opts, self))
|
250
|
+
def capture_proc(func, opts = {}, &block)
|
251
|
+
self[KEY].capture_proc(func, Exec._setup_exec_opts(opts, self), &block)
|
230
252
|
end
|
231
253
|
|
232
254
|
##
|
@@ -234,31 +256,43 @@ module Toys
|
|
234
256
|
# of strings, representing the tool to run and the arguments to pass.
|
235
257
|
#
|
236
258
|
# Captures standard out and returns it as a string.
|
259
|
+
# Cannot be run in the background.
|
260
|
+
#
|
261
|
+
# If a block is provided, a {Toys::Utils::Exec::Controller} will be
|
262
|
+
# yielded to it.
|
237
263
|
#
|
238
264
|
# @param [String,Array<String>] cmd The tool to execute.
|
239
265
|
# @param [Hash] opts The command options. Most options listed in the
|
240
266
|
# {Toys::Utils::Exec} documentation are supported, plus the
|
241
267
|
# `exit_on_nonzero_status` option.
|
268
|
+
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
269
|
+
# for the subprocess streams.
|
242
270
|
#
|
243
271
|
# @return [String] What was written to standard out.
|
244
272
|
#
|
245
|
-
def capture_tool(cmd, opts = {})
|
273
|
+
def capture_tool(cmd, opts = {}, &block)
|
246
274
|
func = Exec._make_tool_caller(cmd)
|
247
|
-
self[KEY].capture_proc(func, Exec._setup_exec_opts(opts, self))
|
275
|
+
self[KEY].capture_proc(func, Exec._setup_exec_opts(opts, self), &block)
|
248
276
|
end
|
249
277
|
|
250
278
|
##
|
251
279
|
# Execute the given string in a shell. Returns the exit code.
|
280
|
+
# Cannot be run in the background.
|
281
|
+
#
|
282
|
+
# If a block is provided, a {Toys::Utils::Exec::Controller} will be
|
283
|
+
# yielded to it.
|
252
284
|
#
|
253
285
|
# @param [String] cmd The shell command to execute.
|
254
286
|
# @param [Hash] opts The command options. All options listed in the
|
255
287
|
# {Toys::Utils::Exec} documentation are supported, plus the
|
256
288
|
# `exit_on_nonzero_status` option.
|
289
|
+
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
290
|
+
# for the subprocess streams.
|
257
291
|
#
|
258
292
|
# @return [Integer] The exit code
|
259
293
|
#
|
260
|
-
def sh(cmd, opts = {})
|
261
|
-
self[KEY].sh(cmd, Exec._setup_exec_opts(opts, self))
|
294
|
+
def sh(cmd, opts = {}, &block)
|
295
|
+
self[KEY].sh(cmd, Exec._setup_exec_opts(opts, self), &block)
|
262
296
|
end
|
263
297
|
|
264
298
|
##
|
data/lib/toys/utils/exec.rb
CHANGED
@@ -50,6 +50,8 @@ module Toys
|
|
50
50
|
# If not present, the command is not logged.
|
51
51
|
# * **:log_level** (Integer) Log level for logging the actual command.
|
52
52
|
# Defaults to Logger::INFO if not present.
|
53
|
+
# * **:background** (Boolean) Runs the process in the background,
|
54
|
+
# returning a controller object instead of a result object.
|
53
55
|
# * **:in** Connects the input stream of the subprocess. See the section
|
54
56
|
# on stream handling.
|
55
57
|
# * **:out** Connects the standard output stream of the subprocess. See
|
@@ -95,7 +97,11 @@ module Toys
|
|
95
97
|
# `Process#spawn`.
|
96
98
|
# * **Redirect to null:** You may redirect to a null stream by passing
|
97
99
|
# `:null` as the option value. This connects to a stream that is not
|
98
|
-
# closed but contains no data, i.e. `/dev/null` on unix systems.
|
100
|
+
# closed but contains no data, i.e. `/dev/null` on unix systems. This is
|
101
|
+
# the default if the subprocess is run in the background.
|
102
|
+
# * **Inherit parent stream:** You may inherit the corresponding stream in
|
103
|
+
# the parent process by passing `:inherit` as the option value. This is
|
104
|
+
# the default if the subprocess is *not* run in the background.
|
99
105
|
# * **Redirect to a file:** You may redirect to a file. This reads from an
|
100
106
|
# existing file when connected to `:in`, and creates or appends to a
|
101
107
|
# file when connected to `:out` or `:err`. To specify a file, use the
|
@@ -147,8 +153,8 @@ module Toys
|
|
147
153
|
# Execute a command. The command may be given as a single string to pass
|
148
154
|
# to a shell, or an array of strings indicating a posix command.
|
149
155
|
#
|
150
|
-
# If
|
151
|
-
#
|
156
|
+
# If the process is not set to run in the background, and a block is
|
157
|
+
# provided, a {Toys::Utils::Exec::Controller} will be yielded to it.
|
152
158
|
#
|
153
159
|
# @param [String,Array<String>] cmd The command to execute.
|
154
160
|
# @param [Hash] opts The command options. See the section on
|
@@ -156,8 +162,9 @@ module Toys
|
|
156
162
|
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
157
163
|
# for the subprocess streams.
|
158
164
|
#
|
159
|
-
# @return [Toys::Utils::Exec::Result] The
|
160
|
-
#
|
165
|
+
# @return [Toys::Utils::Exec::Controller,Toys::Utils::Exec::Result] The
|
166
|
+
# subprocess controller or result, depending on whether the process
|
167
|
+
# is running in the background or foreground.
|
161
168
|
#
|
162
169
|
def exec(cmd, opts = {}, &block)
|
163
170
|
exec_opts = Opts.new(@default_opts).add(opts)
|
@@ -171,15 +178,15 @@ module Toys
|
|
171
178
|
else
|
172
179
|
[cmd]
|
173
180
|
end
|
174
|
-
executor = Executor.new(exec_opts, spawn_cmd)
|
175
|
-
executor.execute
|
181
|
+
executor = Executor.new(exec_opts, spawn_cmd, block)
|
182
|
+
executor.execute
|
176
183
|
end
|
177
184
|
|
178
185
|
##
|
179
186
|
# Spawn a ruby process and pass the given arguments to it.
|
180
187
|
#
|
181
|
-
# If
|
182
|
-
#
|
188
|
+
# If the process is not set to run in the background, and a block is
|
189
|
+
# provided, a {Toys::Utils::Exec::Controller} will be yielded to it.
|
183
190
|
#
|
184
191
|
# @param [String,Array<String>] args The arguments to ruby.
|
185
192
|
# @param [Hash] opts The command options. See the section on
|
@@ -187,8 +194,9 @@ module Toys
|
|
187
194
|
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
188
195
|
# for the subprocess streams.
|
189
196
|
#
|
190
|
-
# @return [Toys::Utils::Exec::Result] The
|
191
|
-
#
|
197
|
+
# @return [Toys::Utils::Exec::Controller,Toys::Utils::Exec::Result] The
|
198
|
+
# subprocess controller or result, depending on whether the process
|
199
|
+
# is running in the background or foreground.
|
192
200
|
#
|
193
201
|
def exec_ruby(args, opts = {}, &block)
|
194
202
|
cmd = args.is_a?(::Array) ? [::RbConfig.ruby] + args : "#{::RbConfig.ruby} #{args}"
|
@@ -200,8 +208,8 @@ module Toys
|
|
200
208
|
##
|
201
209
|
# Execute a proc in a fork.
|
202
210
|
#
|
203
|
-
# If
|
204
|
-
#
|
211
|
+
# If the process is not set to run in the background, and a block is
|
212
|
+
# provided, a {Toys::Utils::Exec::Controller} will be yielded to it.
|
205
213
|
#
|
206
214
|
# @param [Proc] func The proc to call.
|
207
215
|
# @param [Hash] opts The command options. See the section on
|
@@ -209,13 +217,14 @@ module Toys
|
|
209
217
|
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
210
218
|
# for the subprocess streams.
|
211
219
|
#
|
212
|
-
# @return [Toys::Utils::Exec::Result] The
|
213
|
-
#
|
220
|
+
# @return [Toys::Utils::Exec::Controller,Toys::Utils::Exec::Result] The
|
221
|
+
# subprocess controller or result, depending on whether the process
|
222
|
+
# is running in the background or foreground.
|
214
223
|
#
|
215
224
|
def exec_proc(func, opts = {}, &block)
|
216
225
|
exec_opts = Opts.new(@default_opts).add(opts)
|
217
|
-
executor = Executor.new(exec_opts, func)
|
218
|
-
executor.execute
|
226
|
+
executor = Executor.new(exec_opts, func, block)
|
227
|
+
executor.execute
|
219
228
|
end
|
220
229
|
|
221
230
|
##
|
@@ -223,58 +232,79 @@ module Toys
|
|
223
232
|
# to a shell, or an array of strings indicating a posix command.
|
224
233
|
#
|
225
234
|
# Captures standard out and returns it as a string.
|
235
|
+
# Cannot be run in the background.
|
236
|
+
#
|
237
|
+
# If a block is provided, a {Toys::Utils::Exec::Controller} will be
|
238
|
+
# yielded to it.
|
226
239
|
#
|
227
240
|
# @param [String,Array<String>] cmd The command to execute.
|
228
241
|
# @param [Hash] opts The command options. See the section on
|
229
242
|
# configuration options in the {Toys::Utils::Exec} module docs.
|
243
|
+
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
244
|
+
# for the subprocess streams.
|
230
245
|
#
|
231
246
|
# @return [String] What was written to standard out.
|
232
247
|
#
|
233
|
-
def capture(cmd, opts = {})
|
234
|
-
exec(cmd, opts.merge(out: :capture)).captured_out
|
248
|
+
def capture(cmd, opts = {}, &block)
|
249
|
+
exec(cmd, opts.merge(out: :capture, background: false), &block).captured_out
|
235
250
|
end
|
236
251
|
|
237
252
|
##
|
238
253
|
# Spawn a ruby process and pass the given arguments to it.
|
239
254
|
#
|
240
255
|
# Captures standard out and returns it as a string.
|
256
|
+
# Cannot be run in the background.
|
257
|
+
#
|
258
|
+
# If a block is provided, a {Toys::Utils::Exec::Controller} will be
|
259
|
+
# yielded to it.
|
241
260
|
#
|
242
261
|
# @param [String,Array<String>] args The arguments to ruby.
|
243
262
|
# @param [Hash] opts The command options. See the section on
|
244
263
|
# configuration options in the {Toys::Utils::Exec} module docs.
|
264
|
+
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
265
|
+
# for the subprocess streams.
|
245
266
|
#
|
246
267
|
# @return [String] What was written to standard out.
|
247
268
|
#
|
248
|
-
def capture_ruby(args, opts = {})
|
249
|
-
ruby(args, opts.merge(out: :capture)).captured_out
|
269
|
+
def capture_ruby(args, opts = {}, &block)
|
270
|
+
ruby(args, opts.merge(out: :capture, background: false), &block).captured_out
|
250
271
|
end
|
251
272
|
|
252
273
|
##
|
253
274
|
# Execute a proc in a fork.
|
254
275
|
#
|
255
276
|
# Captures standard out and returns it as a string.
|
277
|
+
# Cannot be run in the background.
|
278
|
+
#
|
279
|
+
# If a block is provided, a {Toys::Utils::Exec::Controller} will be
|
280
|
+
# yielded to it.
|
256
281
|
#
|
257
282
|
# @param [Proc] func The proc to call.
|
258
283
|
# @param [Hash] opts The command options. See the section on
|
259
284
|
# configuration options in the {Toys::Utils::Exec} module docs.
|
285
|
+
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
286
|
+
# for the subprocess streams.
|
260
287
|
#
|
261
288
|
# @return [String] What was written to standard out.
|
262
289
|
#
|
263
|
-
def capture_proc(func, opts = {})
|
264
|
-
exec_proc(func, opts.merge(out: :capture)).captured_out
|
290
|
+
def capture_proc(func, opts = {}, &block)
|
291
|
+
exec_proc(func, opts.merge(out: :capture, background: false), &block).captured_out
|
265
292
|
end
|
266
293
|
|
267
294
|
##
|
268
295
|
# Execute the given string in a shell. Returns the exit code.
|
296
|
+
# Cannot be run in the background.
|
269
297
|
#
|
270
298
|
# @param [String] cmd The shell command to execute.
|
271
299
|
# @param [Hash] opts The command options. See the section on
|
272
300
|
# configuration options in the {Toys::Utils::Exec} module docs.
|
301
|
+
# @yieldparam controller [Toys::Utils::Exec::Controller] A controller
|
302
|
+
# for the subprocess streams.
|
273
303
|
#
|
274
304
|
# @return [Integer] The exit code
|
275
305
|
#
|
276
|
-
def sh(cmd, opts = {})
|
277
|
-
exec(cmd, opts).exit_code
|
306
|
+
def sh(cmd, opts = {}, &block)
|
307
|
+
exec(cmd, opts.merge(background: false), &block).exit_code
|
278
308
|
end
|
279
309
|
|
280
310
|
##
|
@@ -288,6 +318,7 @@ module Toys
|
|
288
318
|
#
|
289
319
|
CONFIG_KEYS = %i[
|
290
320
|
argv0
|
321
|
+
background
|
291
322
|
cli
|
292
323
|
env
|
293
324
|
err
|
@@ -356,17 +387,24 @@ module Toys
|
|
356
387
|
end
|
357
388
|
|
358
389
|
##
|
359
|
-
# An object
|
390
|
+
# An object that controls a subprocess. This object is returned from an
|
391
|
+
# execution running in the background, or is yielded to a control block
|
392
|
+
# for an execution running in the foreground.
|
360
393
|
# You may use this object to interact with the subcommand's streams,
|
361
|
-
#
|
394
|
+
# send signals to the process, and get its result.
|
362
395
|
#
|
363
396
|
class Controller
|
364
397
|
## @private
|
365
|
-
def initialize(
|
366
|
-
@in =
|
367
|
-
@out = out
|
368
|
-
@err = err
|
398
|
+
def initialize(controller_streams, captures, pid, join_threads, nonzero_status_handler)
|
399
|
+
@in = controller_streams[:in]
|
400
|
+
@out = controller_streams[:out]
|
401
|
+
@err = controller_streams[:err]
|
402
|
+
@captures = captures
|
369
403
|
@pid = pid
|
404
|
+
@join_threads = join_threads
|
405
|
+
@nonzero_status_handler = nonzero_status_handler
|
406
|
+
@wait_thread = ::Process.detach(pid)
|
407
|
+
@result = nil
|
370
408
|
end
|
371
409
|
|
372
410
|
##
|
@@ -408,6 +446,47 @@ module Toys
|
|
408
446
|
def kill(signal)
|
409
447
|
::Process.kill(signal, pid)
|
410
448
|
end
|
449
|
+
|
450
|
+
##
|
451
|
+
# Determine whether the subcommand is still executing
|
452
|
+
#
|
453
|
+
# @return [Boolean]
|
454
|
+
#
|
455
|
+
def executing?
|
456
|
+
@wait_thread.status ? true : false
|
457
|
+
end
|
458
|
+
|
459
|
+
##
|
460
|
+
# Wait for the subcommand to complete, and return a result object.
|
461
|
+
#
|
462
|
+
# @param [Numeric,nil] timeout The timeout in seconds, or `nil` to
|
463
|
+
# wait indefinitely.
|
464
|
+
# @return [Toys::Utils::Exec::Result,nil] The result object, or `nil`
|
465
|
+
# if a timeout occurred.
|
466
|
+
#
|
467
|
+
def result(timeout: nil)
|
468
|
+
return nil unless @wait_thread.join(timeout)
|
469
|
+
@result ||= begin
|
470
|
+
close_streams
|
471
|
+
@join_threads.each(&:join)
|
472
|
+
status = @wait_thread.value
|
473
|
+
if @nonzero_status_handler && status.exitstatus != 0
|
474
|
+
@nonzero_status_handler.call(status)
|
475
|
+
end
|
476
|
+
Result.new(@captures[:out], @captures[:err], status)
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
##
|
481
|
+
# Close all the controller's streams.
|
482
|
+
# @private
|
483
|
+
#
|
484
|
+
def close_streams
|
485
|
+
@in.close if @in && !@in.closed?
|
486
|
+
@out.close if @out && !@out.closed?
|
487
|
+
@err.close if @err && !@err.closed?
|
488
|
+
self
|
489
|
+
end
|
411
490
|
end
|
412
491
|
|
413
492
|
##
|
@@ -471,7 +550,7 @@ module Toys
|
|
471
550
|
# @private
|
472
551
|
#
|
473
552
|
class Executor
|
474
|
-
def initialize(exec_opts, spawn_cmd)
|
553
|
+
def initialize(exec_opts, spawn_cmd, block)
|
475
554
|
@fork_func = spawn_cmd.respond_to?(:call) ? spawn_cmd : nil
|
476
555
|
@spawn_cmd = spawn_cmd.respond_to?(:call) ? nil : spawn_cmd
|
477
556
|
@config_opts = exec_opts.config_opts
|
@@ -481,18 +560,26 @@ module Toys
|
|
481
560
|
@join_threads = []
|
482
561
|
@child_streams = []
|
483
562
|
@parent_streams = []
|
563
|
+
@block = block
|
564
|
+
@default_stream = @config_opts[:background] ? :null : :inherit
|
484
565
|
end
|
485
566
|
|
486
|
-
def execute
|
567
|
+
def execute
|
487
568
|
setup_in_stream
|
488
|
-
setup_out_stream(:out
|
489
|
-
setup_out_stream(:err
|
569
|
+
setup_out_stream(:out)
|
570
|
+
setup_out_stream(:err)
|
490
571
|
log_command
|
491
572
|
pid = @fork_func ? start_fork : start_process
|
492
573
|
@child_streams.each(&:close)
|
493
|
-
|
494
|
-
|
495
|
-
|
574
|
+
controller = Controller.new(@controller_streams, @captures, pid, @join_threads,
|
575
|
+
@config_opts[:nonzero_status_handler])
|
576
|
+
return controller if @config_opts[:background]
|
577
|
+
begin
|
578
|
+
@block&.call(controller)
|
579
|
+
ensure
|
580
|
+
controller.close_streams
|
581
|
+
end
|
582
|
+
controller.result
|
496
583
|
end
|
497
584
|
|
498
585
|
private
|
@@ -613,34 +700,8 @@ module Toys
|
|
613
700
|
end
|
614
701
|
end
|
615
702
|
|
616
|
-
def control_process(wait_thread)
|
617
|
-
begin
|
618
|
-
if block_given?
|
619
|
-
controller = Controller.new(
|
620
|
-
@controller_streams[:in], @controller_streams[:out], @controller_streams[:err],
|
621
|
-
wait_thread.pid
|
622
|
-
)
|
623
|
-
yield controller
|
624
|
-
end
|
625
|
-
ensure
|
626
|
-
@controller_streams.each_value(&:close)
|
627
|
-
end
|
628
|
-
@join_threads.each(&:join)
|
629
|
-
wait_thread.value
|
630
|
-
end
|
631
|
-
|
632
|
-
def create_result(status)
|
633
|
-
nonzero_status_handler = @config_opts[:nonzero_status_handler]
|
634
|
-
nonzero_status_handler.call(status) if nonzero_status_handler && status.exitstatus != 0
|
635
|
-
Result.new(@captures[:out], @captures[:err], status)
|
636
|
-
end
|
637
|
-
|
638
703
|
def setup_in_stream
|
639
|
-
setting = @config_opts[:in]
|
640
|
-
if setting.nil?
|
641
|
-
return if $stdin.respond_to?(:fileno) && $stdin.fileno.zero?
|
642
|
-
setting = $stdin
|
643
|
-
end
|
704
|
+
setting = @config_opts[:in] || @default_stream
|
644
705
|
return unless setting
|
645
706
|
case setting
|
646
707
|
when ::Symbol
|
@@ -683,6 +744,8 @@ module Toys
|
|
683
744
|
@controller_streams[:in] = make_in_pipe
|
684
745
|
when :null
|
685
746
|
make_null_stream(:in, "r")
|
747
|
+
when :inherit
|
748
|
+
@spawn_opts[:in] = :in
|
686
749
|
when :close
|
687
750
|
@spawn_opts[:in] = type
|
688
751
|
when :parent
|
@@ -705,12 +768,8 @@ module Toys
|
|
705
768
|
@spawn_opts[:in] = args + [::File::RDONLY]
|
706
769
|
end
|
707
770
|
|
708
|
-
def setup_out_stream(key
|
709
|
-
setting = @config_opts[key]
|
710
|
-
if setting.nil?
|
711
|
-
return if setting.respond_to?(:fileno) && setting.fileno == stdfileno
|
712
|
-
setting = stdstream
|
713
|
-
end
|
771
|
+
def setup_out_stream(key)
|
772
|
+
setting = @config_opts[key] || @default_stream
|
714
773
|
case setting
|
715
774
|
when ::Symbol
|
716
775
|
setup_out_stream_of_type(key, setting, [])
|
@@ -752,6 +811,8 @@ module Toys
|
|
752
811
|
@controller_streams[key] = make_out_pipe(key)
|
753
812
|
when :null
|
754
813
|
make_null_stream(key, "w")
|
814
|
+
when :inherit
|
815
|
+
@spawn_opts[key] = key
|
755
816
|
when :close, :out, :err
|
756
817
|
@spawn_opts[key] = type
|
757
818
|
when :parent
|
data/lib/toys/utils/terminal.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: toys-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Azuma
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-07-
|
11
|
+
date: 2018-07-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: highline
|