sproc 0.2.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/sproc.rb +1 -0
- data/lib/sproc/core.rb +89 -63
- data/lib/sproc/osinfo.rb +55 -0
- data/lib/sproc/reporting.rb +196 -0
- data/lib/sproc/version.rb +1 -1
- data/sproc.gemspec +18 -17
- metadata +7 -5
- data/lib/sproc/utils.rb +0 -53
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a736ea3eebf9855455803021aa1dd57589e1784f92f841f63984d64c1bb5cce2
|
4
|
+
data.tar.gz: 0ead0dc9e4609cb8adc976dd743f427bbe9d8ee9be39d78b6ab743804b0c13d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ee15b0602c7b22c813a47aca5c0c3a824624ad0794145aaa9382763e6f6ce54eaf5418fe0df9b2974c7c1945609c74d8f6f32630bc987e10eaa5bed137a8fffb
|
7
|
+
data.tar.gz: ac59da1176212f4d34b9100ba6353bb81923a059fbd7229c91622386e320e1a96514319deacf920ad3b0347796e6adf15f856422d987fb63bdd29935e2fb9dc3
|
data/Gemfile.lock
CHANGED
data/lib/sproc.rb
CHANGED
data/lib/sproc/core.rb
CHANGED
@@ -7,17 +7,16 @@ module SProc
|
|
7
7
|
# Defines the shell under which to invoke the sub-process
|
8
8
|
module ShellType
|
9
9
|
SHELL_TYPES = [
|
10
|
-
#
|
11
|
-
|
12
|
-
# - For current ubuntu, it seems to be 'dash'
|
13
|
-
NATIVE = 0,
|
10
|
+
# Start the process without any shell
|
11
|
+
NONE = 0,
|
14
12
|
# Will create a 'bash' instance and run the subprocess
|
15
13
|
# within that instance.
|
16
14
|
BASH = 1
|
17
15
|
].freeze
|
18
16
|
end
|
19
17
|
|
20
|
-
# The
|
18
|
+
# The available execution states of a the subprocess
|
19
|
+
# running within an SProc instance.
|
21
20
|
module ExecutionState
|
22
21
|
NOT_STARTED = 0
|
23
22
|
RUNNING = 1
|
@@ -58,10 +57,13 @@ module SProc
|
|
58
57
|
# from the process as it is running (default nil)
|
59
58
|
# @param stderr_callback a callback that will receive all stderr output
|
60
59
|
# from the process as it is running (default nil)
|
60
|
+
# @param env a hash containing key/value pairs of strings that
|
61
|
+
# set the environment variable 'key' to 'value'. If value
|
62
|
+
# is nil, that env variable is unset
|
61
63
|
#
|
62
64
|
# example callback signature: def my_stdout_cb(line)
|
63
|
-
def initialize(type
|
64
|
-
stderr_callback
|
65
|
+
def initialize(type: ShellType::NONE, stdout_callback: nil,
|
66
|
+
stderr_callback: nil, env: {})
|
65
67
|
@run_opts = {
|
66
68
|
type: type,
|
67
69
|
stdout_callback: stdout_callback,
|
@@ -69,10 +71,50 @@ module SProc
|
|
69
71
|
}
|
70
72
|
@runner = TaskRunner.new(@run_opts)
|
71
73
|
@execution_thread = nil
|
74
|
+
@env = env
|
75
|
+
end
|
76
|
+
|
77
|
+
# Start the sub-process and block until it has completed.
|
78
|
+
#
|
79
|
+
#
|
80
|
+
# @cmd the command to execute
|
81
|
+
# @args an array with all arguments to the cmd
|
82
|
+
# @opts a hash with options that influence the spawned process
|
83
|
+
# the supported options are: chdir umask unsetenv_others
|
84
|
+
# See Process.spawn for definitions
|
85
|
+
#
|
86
|
+
# @return this SubProcess instance
|
87
|
+
def exec_sync(cmd, *args, **opts)
|
88
|
+
exec(true, @env, cmd, *args, **opts)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Start the process non-blocking. Use one of the wait... methods
|
92
|
+
# to later block on the process.
|
93
|
+
# @return this SubProcess instance
|
94
|
+
def exec_async(cmd, *args, **opts)
|
95
|
+
exec(false, @env, cmd, *args, **opts)
|
96
|
+
end
|
97
|
+
|
98
|
+
# check if this process has completed with exit code 0
|
99
|
+
# (success) or not
|
100
|
+
def exit_zero?
|
101
|
+
return false unless execution_state == ExecutionState::COMPLETED
|
102
|
+
|
103
|
+
task_info[:process_status].exitstatus.zero?
|
104
|
+
end
|
105
|
+
|
106
|
+
# Block caller until this subprocess has completed or aborted
|
107
|
+
# @return the TaskInfo struct of the completed process
|
108
|
+
def wait_on_completion
|
109
|
+
return if @execution_thread.nil?
|
110
|
+
|
111
|
+
@execution_thread.join
|
112
|
+
task_info
|
72
113
|
end
|
73
114
|
|
74
115
|
# Return the execution state of this SubProcess. Note that it is not
|
75
116
|
# identical with the life-cycle of the underlying ProcessStatus object
|
117
|
+
#
|
76
118
|
# @return current ExecutionState
|
77
119
|
def execution_state
|
78
120
|
return ExecutionState::NOT_STARTED if @execution_thread.nil?
|
@@ -106,35 +148,10 @@ module SProc
|
|
106
148
|
raise RuntimeError("Unhandled process status: #{status.inspect}")
|
107
149
|
end
|
108
150
|
|
109
|
-
#
|
110
|
-
#
|
111
|
-
|
112
|
-
|
113
|
-
exec(true, cmd, *args, **opts)
|
114
|
-
end
|
115
|
-
|
116
|
-
# Start the process non-blocking. Use one of the wait... methods
|
117
|
-
# to later block on the process.
|
118
|
-
# @return this SubProcess instance
|
119
|
-
def exec_async(cmd, *args, **opts)
|
120
|
-
exec(false, cmd, *args, **opts)
|
121
|
-
end
|
122
|
-
|
123
|
-
# check if this process has completed with exit code 0
|
124
|
-
# (success) or not
|
125
|
-
def exit_zero?
|
126
|
-
return false unless execution_state == ExecutionState::COMPLETED
|
127
|
-
|
128
|
-
task_info[:process_status].exitstatus.zero?
|
129
|
-
end
|
130
|
-
|
131
|
-
# Block caller until this subprocess has completed or aborted
|
132
|
-
# @return the TaskInfo struct of the completed process
|
133
|
-
def wait_on_completion
|
134
|
-
return if @execution_thread.nil?
|
135
|
-
|
136
|
-
@execution_thread.join
|
137
|
-
task_info
|
151
|
+
# @return the TaskInfo representing this SubProcess, nil if
|
152
|
+
# process has not started
|
153
|
+
def task_info
|
154
|
+
@runner.task_info
|
138
155
|
end
|
139
156
|
|
140
157
|
# blocks until all processes in the given array are completed/aborted.
|
@@ -170,7 +187,7 @@ module SProc
|
|
170
187
|
# # start 3 processes asyncronously
|
171
188
|
# nof_processes = 3
|
172
189
|
# p_array = (1..nof_processes).collect do
|
173
|
-
# SubProcess.new(SubProcess::
|
190
|
+
# SubProcess.new(SubProcess::NONE).exec_async('ping', ['127.0.0.1'])
|
174
191
|
# end
|
175
192
|
#
|
176
193
|
# # block until a process completes and then immediately start a new process
|
@@ -201,12 +218,6 @@ module SProc
|
|
201
218
|
all_proc
|
202
219
|
end
|
203
220
|
|
204
|
-
# @return the TaskInfo representing this SubProcess, nil if
|
205
|
-
# process has not started
|
206
|
-
def task_info
|
207
|
-
@runner.task_info
|
208
|
-
end
|
209
|
-
|
210
221
|
# return processes that are no longer running
|
211
222
|
def self.get_finished(running_proc)
|
212
223
|
running_proc.select do |p|
|
@@ -218,13 +229,15 @@ module SProc
|
|
218
229
|
|
219
230
|
private
|
220
231
|
|
221
|
-
|
222
|
-
|
232
|
+
# a helper method that supports both synch/async execution
|
233
|
+
# depending on the supplied args
|
234
|
+
def exec(synch, env, cmd, *args, **opts)
|
235
|
+
raise 'Subprocess already running!' unless @execution_thread.nil? || !@execution_thread.alive?
|
223
236
|
|
224
237
|
# kick-off a fresh task runner and execution thread
|
225
238
|
@runner = TaskRunner.new(@run_opts)
|
226
239
|
@execution_thread = Thread.new do
|
227
|
-
@runner.execute(cmd, *args, **opts)
|
240
|
+
@runner.execute(env, cmd, *args, **opts)
|
228
241
|
end
|
229
242
|
@execution_thread.join if synch
|
230
243
|
self
|
@@ -238,8 +251,11 @@ module SProc
|
|
238
251
|
|
239
252
|
include ShellType
|
240
253
|
|
254
|
+
# Restrict the options to Process.spawn that we support to these
|
255
|
+
SUPPORTED_SPAWN_OPTS = %i[chdir umask unsetenv_others]
|
256
|
+
|
241
257
|
DEFAULT_OPTS = {
|
242
|
-
type:
|
258
|
+
type: NONE,
|
243
259
|
stdout_callback: nil,
|
244
260
|
stderr_callback: nil
|
245
261
|
}.freeze
|
@@ -250,12 +266,12 @@ module SProc
|
|
250
266
|
end
|
251
267
|
|
252
268
|
# Runs the process and blocks until it is completed or aborted.
|
253
|
-
# The stdout and stdin streams are continuously read in
|
269
|
+
# The stdout and stdin streams are continuously read in parallel with
|
254
270
|
# the process execution.
|
255
|
-
def execute(cmd, *args, **opts)
|
271
|
+
def execute(env, cmd, *args, **opts)
|
256
272
|
start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
257
273
|
begin
|
258
|
-
shell_out_via_popen(cmd, *args, **opts)
|
274
|
+
shell_out_via_popen(env, cmd, *args, **opts)
|
259
275
|
rescue StandardError => e
|
260
276
|
@task_info[:exception] = e
|
261
277
|
end
|
@@ -266,14 +282,26 @@ module SProc
|
|
266
282
|
|
267
283
|
private
|
268
284
|
|
269
|
-
def
|
285
|
+
def valid_opts(**opts)
|
286
|
+
return opts if opts.nil? || opts.empty?
|
287
|
+
|
288
|
+
supported = {}
|
289
|
+
SUPPORTED_SPAWN_OPTS.each { |o| supported[o] = opts[o] if opts.has_key?(o) }
|
290
|
+
supported
|
291
|
+
end
|
292
|
+
|
293
|
+
def shell_out_via_popen(env, cmd, *args, **opts)
|
294
|
+
opts = valid_opts(**opts)
|
270
295
|
args = case @opts[:type]
|
271
|
-
when
|
272
|
-
when BASH
|
296
|
+
when NONE then get_args_native(cmd, *args, **opts)
|
297
|
+
when BASH then get_args_bash(cmd, *args, **opts)
|
273
298
|
else raise ArgumentError, "Unknown task type: #{@type}!!"
|
274
299
|
end
|
300
|
+
|
275
301
|
SProc.logger&.debug { "Start: #{task_info[:cmd_str]}" }
|
276
|
-
|
302
|
+
SProc.logger&.debug { "Supplying env: #{env}" } unless env.nil?
|
303
|
+
SProc.logger&.debug { "Spawn options: #{opts}" } unless opts.nil?
|
304
|
+
Open3.popen3(env, *args) do |stdin, stdout, stderr, thread|
|
277
305
|
@task_info[:popen_thread] = thread
|
278
306
|
threads = do_while_process_running(stdin, stdout, stderr)
|
279
307
|
@task_info[:process_status] = thread.value
|
@@ -306,16 +334,14 @@ module SProc
|
|
306
334
|
def process_output_stream(stream, stream_cache = nil,
|
307
335
|
process_callback = nil)
|
308
336
|
Thread.new do
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
stream_cache << raw_line unless stream_cache.nil?
|
313
|
-
end
|
314
|
-
rescue IOError => e
|
315
|
-
l = SProc.logger
|
316
|
-
l&.warn { 'Stream closed before all output were read!' }
|
317
|
-
l&.warn { e.message }
|
337
|
+
until (raw_line = stream.gets).nil?
|
338
|
+
process_callback&.call(raw_line)
|
339
|
+
stream_cache << raw_line unless stream_cache.nil?
|
318
340
|
end
|
341
|
+
rescue IOError => e
|
342
|
+
l = SProc.logger
|
343
|
+
l&.warn { 'Stream closed before all output were read!' }
|
344
|
+
l&.warn { e.message }
|
319
345
|
end
|
320
346
|
end
|
321
347
|
end
|
data/lib/sproc/osinfo.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
|
3
|
+
# helper methods to find out os and execution environment
|
4
|
+
module SProc
|
5
|
+
module OSInfo
|
6
|
+
# the supported exec environments
|
7
|
+
module OS
|
8
|
+
WINDOWS = 0
|
9
|
+
LINUX = 1
|
10
|
+
MINGW = 2
|
11
|
+
CYGWIN = 3
|
12
|
+
OSX = 4
|
13
|
+
BSD = 5
|
14
|
+
UNKNOWN = 100
|
15
|
+
end
|
16
|
+
|
17
|
+
# returns the current execution environment
|
18
|
+
def self.os_context
|
19
|
+
case RbConfig::CONFIG['host_os']
|
20
|
+
when /mswin/ then OS::WINDOWS
|
21
|
+
when /mingw/ then OS::MINGW
|
22
|
+
when /cygwin/ then OS::CYGWIN
|
23
|
+
when /darwin/ then OS::OSX
|
24
|
+
when /linux/ then OS::LINUX
|
25
|
+
when /bsd/ then OS::BSD
|
26
|
+
else OS::UNKNOWN
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# return the current underlying operating system
|
31
|
+
def self.host_os
|
32
|
+
if [OS::WINDOWS, OS::MINGW, OS::CYGWIN].include?(os_context)
|
33
|
+
OS::WINDOWS
|
34
|
+
else
|
35
|
+
os_context
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def on_windows?
|
40
|
+
host_os == OS::WINDOWS
|
41
|
+
end
|
42
|
+
|
43
|
+
def on_linux?
|
44
|
+
os_context == OS::LINUX
|
45
|
+
end
|
46
|
+
|
47
|
+
def on_bsd?
|
48
|
+
os_context == OS::BSD
|
49
|
+
end
|
50
|
+
|
51
|
+
def on_osx?
|
52
|
+
os_context == OS::OSX
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
require_relative 'core'
|
2
|
+
|
3
|
+
# This module is written to provide sub-process
|
4
|
+
# execution with some human readable logging of process start/stop/errors
|
5
|
+
#
|
6
|
+
# It wraps SProc instances and execution with calls to logging methods
|
7
|
+
# that tries to make the resulting log user friendly
|
8
|
+
module SProc
|
9
|
+
module Reporting
|
10
|
+
class << self
|
11
|
+
attr_accessor :logger
|
12
|
+
end
|
13
|
+
|
14
|
+
def logger
|
15
|
+
Reporting.logger
|
16
|
+
end
|
17
|
+
|
18
|
+
# Run a process synchronuously via the native shell and log
|
19
|
+
# output suitable for a build log
|
20
|
+
#
|
21
|
+
# @param cmd_name a String containing a descriptive
|
22
|
+
# name for what the process will do.
|
23
|
+
# @param cmd, args, opts see SProc.exec_sync
|
24
|
+
#
|
25
|
+
# @return the SProc instance containing the completed process
|
26
|
+
def report_sync(cmd_name, cmd, *args, **opts)
|
27
|
+
p = create_proc_and_log(cmd_name,
|
28
|
+
ShellType::NONE, :exec_sync,
|
29
|
+
cmd, args, opts)
|
30
|
+
report_completed(p)
|
31
|
+
p
|
32
|
+
end
|
33
|
+
|
34
|
+
# Run a process asynchronuously via the native shell and log
|
35
|
+
# output suitable for a build log
|
36
|
+
#
|
37
|
+
# @param cmd_name a String containing a descriptive
|
38
|
+
# name for what the process will do.
|
39
|
+
# @param cmd, args, opts see SProc.exec_sync
|
40
|
+
#
|
41
|
+
# @return the created SProc instance
|
42
|
+
def report_async(cmd_name, cmd, *args, **opts)
|
43
|
+
create_proc_and_log(cmd_name,
|
44
|
+
ShellType::NONE, :exec_async,
|
45
|
+
cmd, args, opts)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Run a process asynchronuously via the Bash shell and log
|
49
|
+
# output suitable for a build log
|
50
|
+
#
|
51
|
+
# @param cmd_name a String containing a descriptive
|
52
|
+
# name for what the process will do.
|
53
|
+
# @param cmd, args, opts see SProc.exec_sync
|
54
|
+
#
|
55
|
+
# @return the created SProc instance
|
56
|
+
def report_async_within_bash(cmd_name, cmd, *args, **opts)
|
57
|
+
create_proc_and_log(cmd_name,
|
58
|
+
ShellType::BASH, :exec_async,
|
59
|
+
cmd, args, opts)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Log output from a completed/aborted process
|
63
|
+
#
|
64
|
+
# @param process the SProc instance that has run
|
65
|
+
# @return true/false corresponding to process success
|
66
|
+
def report_completed(process)
|
67
|
+
friendly_name = if @log_friendly_name_map&.key?(process)
|
68
|
+
"#{@log_friendly_name_map[process]}"
|
69
|
+
else
|
70
|
+
process.task_info[:cmd_str][0,10] + "..."
|
71
|
+
end
|
72
|
+
started_ok = true
|
73
|
+
case process.execution_state
|
74
|
+
when ExecutionState::COMPLETED
|
75
|
+
process.exit_zero? && log_completed_ok(friendly_name, process.task_info)
|
76
|
+
!process.exit_zero? && log_completed_err(friendly_name, process.task_info)
|
77
|
+
when ExecutionState::ABORTED
|
78
|
+
log_aborted(friendly_name, process.task_info)
|
79
|
+
started_ok = false
|
80
|
+
when ExecutionState::FAILED_TO_START
|
81
|
+
log_failed_start(friendly_name, process.task_info)
|
82
|
+
started_ok = false
|
83
|
+
else
|
84
|
+
log_unexpected(friendly_name, process.task_info)
|
85
|
+
end
|
86
|
+
started_ok && process.exit_zero?
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def create_proc_and_log(cmd_name, type, method, cmd, args, opts)
|
92
|
+
log_start(cmd_name, type, method, cmd, args, **opts)
|
93
|
+
p = SProc.new(type: type).send(method, cmd, args, **opts)
|
94
|
+
@log_friendly_name_map ||= {}
|
95
|
+
@log_friendly_name_map[p] = cmd_name
|
96
|
+
p
|
97
|
+
end
|
98
|
+
|
99
|
+
def log_method_result_ok(friendly_name, delta)
|
100
|
+
logger.info do
|
101
|
+
"#{friendly_name} completed successfully after #{delta.round(3)}s"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def log_method_result_error(friendly_name_method, delta, exc)
|
106
|
+
logger.error do
|
107
|
+
"#{friendly_name_method} aborted by #{exc.class} after #{delta.round(3)}s\n"\
|
108
|
+
"Exception info: #{exc.message}"
|
109
|
+
end
|
110
|
+
|
111
|
+
logger.debug do
|
112
|
+
exc.backtrace.to_s
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def log_start(cmd_name, type, method, cmd, *args, **opts)
|
117
|
+
logger.info do
|
118
|
+
async_str = method == :exec_async ? 'asynchronuously' : 'synchronuously'
|
119
|
+
type_str = type == ShellType::NONE ? 'without shell' : 'within the bash shell'
|
120
|
+
"'#{cmd_name}' executing #{async_str} #{type_str}..."
|
121
|
+
end
|
122
|
+
logger.debug do
|
123
|
+
msg = String.new("Starting #{cmd}")
|
124
|
+
msg << " with args: #{args.flatten.inspect}" unless args.nil? || args.empty?
|
125
|
+
msg << " and opts: #{opts.inspect}" unless opts.nil? || opts.empty?
|
126
|
+
msg
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def log_one_dll(regex, cmd_str, time)
|
131
|
+
m = regex.match(cmd_str)
|
132
|
+
s = m.nil? ? cmd_str : m[1]
|
133
|
+
max = 45
|
134
|
+
s = s.length > max ? s.slice(0..max - 1) : s.ljust(max)
|
135
|
+
logger.info { "#{s} took #{time.round(3)}s." }
|
136
|
+
end
|
137
|
+
|
138
|
+
def log_aborted(friendly_name, p_info)
|
139
|
+
logger.error do
|
140
|
+
"'#{friendly_name}' aborted!\n"\
|
141
|
+
"When running: #{p_info[:cmd_str]}\n"\
|
142
|
+
"#{merge_proc_output(p_info)}"\
|
143
|
+
"#{p_info[:process_status] unless p_info[:process_status].nil?}"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def log_failed_start(friendly_name, p_info)
|
148
|
+
logger.error do
|
149
|
+
"'#{friendly_name}' not run!\n"\
|
150
|
+
"Could not start process using: #{p_info[:cmd_str]}\n"\
|
151
|
+
"#{merge_proc_output(p_info)}"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def log_completed_ok(friendly_name, p_info)
|
156
|
+
logger.info do
|
157
|
+
"'#{friendly_name}' completed successfully after #{p_info[:wall_time].round(3)}s"
|
158
|
+
end
|
159
|
+
logger.debug do
|
160
|
+
"Cmd: #{p_info[:cmd_str]}"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def log_completed_err(friendly_name, p_info)
|
165
|
+
logger.error do
|
166
|
+
"'#{friendly_name}' completed with exit code "\
|
167
|
+
"#{p_info[:process_status].exitstatus}\n"\
|
168
|
+
"When running: #{p_info[:cmd_str]}\n"\
|
169
|
+
"after #{p_info[:wall_time].round(3)}s\n"\
|
170
|
+
"#{merge_proc_output(p_info)}"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def log_unexpected(friendly_name, p_info)
|
175
|
+
logger.error do
|
176
|
+
"'#{friendly_name}' caused unexpected error!"\
|
177
|
+
' Trying to display info on a running process'\
|
178
|
+
"(#{p_info[:cmd_str]})"
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
# @return String with sections for each non-empty output stream
|
183
|
+
# and exception messages
|
184
|
+
def merge_proc_output(p_info)
|
185
|
+
inf_str = %i[stdout stderr].collect do |sym|
|
186
|
+
next('') if p_info[sym].empty?
|
187
|
+
|
188
|
+
"--- #{sym} ---\n#{p_info[sym]}"
|
189
|
+
end.join("\n")
|
190
|
+
|
191
|
+
exc = p_info[:exception]
|
192
|
+
inf_str << "--- exception ---\n#{exc}\n" unless exc.nil?
|
193
|
+
inf_str
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
data/lib/sproc/version.rb
CHANGED
data/sproc.gemspec
CHANGED
@@ -1,39 +1,40 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative 'lib/sproc/version'
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
|
-
spec.name =
|
6
|
+
spec.name = 'sproc'
|
7
7
|
spec.version = SProc::VERSION
|
8
|
-
spec.authors = [
|
9
|
-
spec.email = [
|
8
|
+
spec.authors = ['Anders Rillbert']
|
9
|
+
spec.email = ['anders.rillbert@kutso.se']
|
10
10
|
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
13
|
-
|
14
|
-
spec.
|
15
|
-
spec.
|
11
|
+
spec.summary = 'Spawn commands as asynch/synch subprocesses.'
|
12
|
+
spec.description = 'Easier invokation of asynch/synch commands with '\
|
13
|
+
'a reasonable easy and flexible interface for processing stdout and stderr'
|
14
|
+
spec.homepage = 'https://github.com/rillbert/sproc'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0')
|
16
17
|
|
17
|
-
spec.metadata[
|
18
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
18
19
|
|
19
|
-
spec.metadata[
|
20
|
-
spec.metadata[
|
21
|
-
spec.metadata[
|
20
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
21
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
22
|
+
spec.metadata['changelog_uri'] = spec.homepage
|
22
23
|
|
23
24
|
# Specify which files should be added to the gem when it is released.
|
24
25
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
26
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
26
27
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
27
28
|
end
|
28
|
-
spec.bindir =
|
29
|
+
spec.bindir = 'exe'
|
29
30
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
30
|
-
spec.require_paths = [
|
31
|
+
spec.require_paths = ['lib']
|
31
32
|
|
32
33
|
# Developer dependencies
|
33
|
-
spec.add_development_dependency
|
34
|
+
spec.add_development_dependency 'minitest', '~> 5.1'
|
34
35
|
|
35
36
|
# Uncomment to register a new dependency of your gem
|
36
|
-
# spec.add_dependency "example-gem", "~> 1.0"
|
37
|
+
# spec.add_dependency "example-gem", "~> 1.0"
|
37
38
|
|
38
39
|
# For more information and examples about making a new gem, checkout our
|
39
40
|
# guide at: https://bundler.io/guides/creating_gem.html
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sproc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anders Rillbert
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-03-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -24,7 +24,8 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '5.1'
|
27
|
-
description:
|
27
|
+
description: Easier invokation of asynch/synch commands with a reasonable easy and
|
28
|
+
flexible interface for processing stdout and stderr
|
28
29
|
email:
|
29
30
|
- anders.rillbert@kutso.se
|
30
31
|
executables: []
|
@@ -42,7 +43,8 @@ files:
|
|
42
43
|
- bin/setup
|
43
44
|
- lib/sproc.rb
|
44
45
|
- lib/sproc/core.rb
|
45
|
-
- lib/sproc/
|
46
|
+
- lib/sproc/osinfo.rb
|
47
|
+
- lib/sproc/reporting.rb
|
46
48
|
- lib/sproc/version.rb
|
47
49
|
- sproc.gemspec
|
48
50
|
homepage: https://github.com/rillbert/sproc
|
@@ -71,5 +73,5 @@ requirements: []
|
|
71
73
|
rubygems_version: 3.1.4
|
72
74
|
signing_key:
|
73
75
|
specification_version: 4
|
74
|
-
summary:
|
76
|
+
summary: Spawn commands as asynch/synch subprocesses.
|
75
77
|
test_files: []
|
data/lib/sproc/utils.rb
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'rbconfig'
|
2
|
-
|
3
|
-
# utility to find out info about our execution environment
|
4
|
-
module OSInfo
|
5
|
-
# the supported exec environments
|
6
|
-
module OS
|
7
|
-
WINDOWS = 0
|
8
|
-
LINUX = 1
|
9
|
-
MINGW = 2
|
10
|
-
CYGWIN = 3
|
11
|
-
OSX = 4
|
12
|
-
BSD = 5
|
13
|
-
UNKNOWN = 100
|
14
|
-
end
|
15
|
-
|
16
|
-
# returns the current execution environment
|
17
|
-
def self.os_context
|
18
|
-
case RbConfig::CONFIG['host_os']
|
19
|
-
when /mswin/ then OS::WINDOWS
|
20
|
-
when /mingw/ then OS::MINGW
|
21
|
-
when /cygwin/ then OS::CYGWIN
|
22
|
-
when /darwin/ then OS::OSX
|
23
|
-
when /linux/ then OS::LINUX
|
24
|
-
when /bsd/ then OS::BSD
|
25
|
-
else OS::UNKNOWN
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# return the current underlying operating system
|
30
|
-
def self.host_os
|
31
|
-
if [OS::WINDOWS, OS::MINGW, OS::CYGWIN].include?(os_context)
|
32
|
-
OS::WINDOWS
|
33
|
-
else
|
34
|
-
os_context
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def on_windows?
|
39
|
-
host_os == OS::WINDOWS
|
40
|
-
end
|
41
|
-
|
42
|
-
def on_linux?
|
43
|
-
os_context == OS::LINUX
|
44
|
-
end
|
45
|
-
|
46
|
-
def on_bsd?
|
47
|
-
os_context == OS::BSD
|
48
|
-
end
|
49
|
-
|
50
|
-
def on_osx?
|
51
|
-
os_context == OS::OSX
|
52
|
-
end
|
53
|
-
end
|