sproc 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b21c852197676569f95bf84f37a1e2d070a06ee5fb1bbe1b627e2eb9f83500da
4
- data.tar.gz: 3f8fe794b2afcb54d50af93e774091ef1fd72e27c221eb2f38a82686ec214f89
3
+ metadata.gz: 8938c9977d79ffd99b2526dc698d66f33c0afc225121307a7cbf79fe9284acdb
4
+ data.tar.gz: 0fcd34ab808b76a121a581443b0bf9c075e8bf92633a112c406b11b11691b9ab
5
5
  SHA512:
6
- metadata.gz: e76140b5a74de9977e60a657ce8c40ad5cf070f3b8c856f954d87ecda0b2cc61a601016b8c8beafd6dd5840dc6dd4cac81eb44b85a3c811fbb38612ea97b0236
7
- data.tar.gz: e8999dfdf2a0aa3f577d9c3ed49184989595ac545088b506befcea989782f502c8776fbb851746d696679a2dd84453ef8ebce732e69c53346283c01e024e9fd6
6
+ metadata.gz: e4da5cce84127eb2b3fda62ba9cb893b588ad1e68b173ad8ef558d8c7f4945c089c74dea20e7be62e7e685bd7efbcf91a6d0616bcc413a7fb4663731151c25da
7
+ data.tar.gz: 7abf027ed86e29fbc531698feec84c318fda64d3138fa3e22bce81c1f2ef7a79b73aa255274de5f0265453c8df59964a616b912cb41cb55b8e692cd36b0d1fae
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sproc (0.1.0)
4
+ sproc (0.3.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/lib/sproc/core.rb CHANGED
@@ -7,10 +7,8 @@ module SProc
7
7
  # Defines the shell under which to invoke the sub-process
8
8
  module ShellType
9
9
  SHELL_TYPES = [
10
- # Use the default shell for the platform we're on.
11
- # - For Windows, it seems to be the 'cmd prompt'
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
@@ -58,10 +56,13 @@ module SProc
58
56
  # from the process as it is running (default nil)
59
57
  # @param stderr_callback a callback that will receive all stderr output
60
58
  # from the process as it is running (default nil)
59
+ # @param env a hash containing key/value pairs of strings that
60
+ # set the environment variable 'key' to 'value'. If value
61
+ # is nil, that env variable is unset
61
62
  #
62
63
  # example callback signature: def my_stdout_cb(line)
63
- def initialize(type = ShellType::NATIVE, stdout_callback = nil,
64
- stderr_callback = nil)
64
+ def initialize(type: ShellType::NONE, stdout_callback: nil,
65
+ stderr_callback: nil, env: {})
65
66
  @run_opts = {
66
67
  type: type,
67
68
  stdout_callback: stdout_callback,
@@ -69,10 +70,12 @@ module SProc
69
70
  }
70
71
  @runner = TaskRunner.new(@run_opts)
71
72
  @execution_thread = nil
73
+ @env = env
72
74
  end
73
75
 
74
76
  # Return the execution state of this SubProcess. Note that it is not
75
77
  # identical with the life-cycle of the underlying ProcessStatus object
78
+ #
76
79
  # @return current ExecutionState
77
80
  def execution_state
78
81
  return ExecutionState::NOT_STARTED if @execution_thread.nil?
@@ -106,18 +109,25 @@ module SProc
106
109
  raise RuntimeError("Unhandled process status: #{status.inspect}")
107
110
  end
108
111
 
109
- # Start the process non-blocking. Use one of the wait... methods
110
- # to later block on the process.
112
+ # Start the sub-process and block until it has completed.
113
+ #
114
+ #
115
+ # @cmd the command to execute
116
+ # @args an array with all arguments to the cmd
117
+ # @opts a hash with options that influence the spawned process
118
+ # the supported options are: chdir umask unsetenv_others
119
+ # See Process.spawn for definitions
120
+ #
111
121
  # @return this SubProcess instance
112
122
  def exec_sync(cmd, *args, **opts)
113
- exec(true, cmd, *args, **opts)
123
+ exec(true, @env, cmd, *args, **opts)
114
124
  end
115
125
 
116
126
  # Start the process non-blocking. Use one of the wait... methods
117
127
  # to later block on the process.
118
128
  # @return this SubProcess instance
119
129
  def exec_async(cmd, *args, **opts)
120
- exec(false, cmd, *args, **opts)
130
+ exec(false, @env, cmd, *args, **opts)
121
131
  end
122
132
 
123
133
  # check if this process has completed with exit code 0
@@ -170,7 +180,7 @@ module SProc
170
180
  # # start 3 processes asyncronously
171
181
  # nof_processes = 3
172
182
  # p_array = (1..nof_processes).collect do
173
- # SubProcess.new(SubProcess::NATIVE).exec_async('ping', ['127.0.0.1'])
183
+ # SubProcess.new(SubProcess::NONE).exec_async('ping', ['127.0.0.1'])
174
184
  # end
175
185
  #
176
186
  # # block until a process completes and then immediately start a new process
@@ -218,13 +228,13 @@ module SProc
218
228
 
219
229
  private
220
230
 
221
- def exec(synch, cmd, *args, **opts)
222
- raise RuntimeError,"Subprocess already running!" unless @execution_thread.nil? || !@execution_thread.alive?
231
+ def exec(synch, env, cmd, *args, **opts)
232
+ raise 'Subprocess already running!' unless @execution_thread.nil? || !@execution_thread.alive?
223
233
 
224
234
  # kick-off a fresh task runner and execution thread
225
235
  @runner = TaskRunner.new(@run_opts)
226
236
  @execution_thread = Thread.new do
227
- @runner.execute(cmd, *args, **opts)
237
+ @runner.execute(env, cmd, *args, **opts)
228
238
  end
229
239
  @execution_thread.join if synch
230
240
  self
@@ -238,8 +248,11 @@ module SProc
238
248
 
239
249
  include ShellType
240
250
 
251
+ # Restrict the options to Process.spawn that we support to these
252
+ SUPPORTED_SPAWN_OPTS = %i[chdir umask unsetenv_others]
253
+
241
254
  DEFAULT_OPTS = {
242
- type: NATIVE,
255
+ type: NONE,
243
256
  stdout_callback: nil,
244
257
  stderr_callback: nil
245
258
  }.freeze
@@ -250,12 +263,12 @@ module SProc
250
263
  end
251
264
 
252
265
  # Runs the process and blocks until it is completed or aborted.
253
- # The stdout and stdin streams are continuously read in parallal with
266
+ # The stdout and stdin streams are continuously read in parallel with
254
267
  # the process execution.
255
- def execute(cmd, *args, **opts)
268
+ def execute(env, cmd, *args, **opts)
256
269
  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
257
270
  begin
258
- shell_out_via_popen(cmd, *args, **opts)
271
+ shell_out_via_popen(env, cmd, *args, **opts)
259
272
  rescue StandardError => e
260
273
  @task_info[:exception] = e
261
274
  end
@@ -266,14 +279,26 @@ module SProc
266
279
 
267
280
  private
268
281
 
269
- def shell_out_via_popen(cmd, *args, **opts)
282
+ def valid_opts(**opts)
283
+ return opts if opts.nil? || opts.empty?
284
+
285
+ supported = {}
286
+ SUPPORTED_SPAWN_OPTS.each { |o| supported[o] = opts[o] if opts.has_key?(o) }
287
+ supported
288
+ end
289
+
290
+ def shell_out_via_popen(env, cmd, *args, **opts)
291
+ opts = valid_opts(**opts)
270
292
  args = case @opts[:type]
271
- when NATIVE then get_args_native(cmd, *args, **opts)
272
- when BASH then get_args_bash(cmd, *args, **opts)
293
+ when NONE then get_args_native(cmd, *args, **opts)
294
+ when BASH then get_args_bash(cmd, *args, **opts)
273
295
  else raise ArgumentError, "Unknown task type: #{@type}!!"
274
296
  end
297
+
275
298
  SProc.logger&.debug { "Start: #{task_info[:cmd_str]}" }
276
- Open3.popen3(*args) do |stdin, stdout, stderr, thread|
299
+ SProc.logger&.debug { "Supplying env: #{env}" } unless env.nil?
300
+ SProc.logger&.debug { "Spawn options: #{opts}" } unless opts.nil?
301
+ Open3.popen3(env, *args) do |stdin, stdout, stderr, thread|
277
302
  @task_info[:popen_thread] = thread
278
303
  threads = do_while_process_running(stdin, stdout, stderr)
279
304
  @task_info[:process_status] = thread.value
@@ -306,16 +331,14 @@ module SProc
306
331
  def process_output_stream(stream, stream_cache = nil,
307
332
  process_callback = nil)
308
333
  Thread.new do
309
- begin
310
- until (raw_line = stream.gets).nil?
311
- process_callback&.call(raw_line)
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 }
334
+ until (raw_line = stream.gets).nil?
335
+ process_callback&.call(raw_line)
336
+ stream_cache << raw_line unless stream_cache.nil?
318
337
  end
338
+ rescue IOError => e
339
+ l = SProc.logger
340
+ l&.warn { 'Stream closed before all output were read!' }
341
+ l&.warn { e.message }
319
342
  end
320
343
  end
321
344
  end
data/lib/sproc/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SProc
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
data/sproc.gemspec CHANGED
@@ -1,39 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "lib/sproc/version"
3
+ require_relative 'lib/sproc/version'
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = "sproc"
6
+ spec.name = 'sproc'
7
7
  spec.version = SProc::VERSION
8
- spec.authors = ["Anders Rillbert"]
9
- spec.email = ["anders.rillbert@kutso.se"]
8
+ spec.authors = ['Anders Rillbert']
9
+ spec.email = ['anders.rillbert@kutso.se']
10
10
 
11
- spec.summary = "Run subprocess asynch/synch."
12
- spec.description = "Run subprocess asynch/synch."
13
- spec.homepage = "https://github.com/rillbert/sproc"
14
- spec.license = "MIT"
15
- spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
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["allowed_push_host"] = "https://rubygems.org"
18
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
18
19
 
19
- spec.metadata["homepage_uri"] = spec.homepage
20
- spec.metadata["source_code_uri"] = spec.homepage
21
- spec.metadata["changelog_uri"] = spec.homepage
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 = "exe"
29
+ spec.bindir = 'exe'
29
30
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
- spec.require_paths = ["lib"]
31
+ spec.require_paths = ['lib']
31
32
 
32
33
  # Developer dependencies
33
- spec.add_development_dependency "minitest", "~> 5.1"
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.2.0
4
+ version: 0.3.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-02-19 00:00:00.000000000 Z
11
+ date: 2021-03-27 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: Run subprocess asynch/synch.
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: []
@@ -71,5 +72,5 @@ requirements: []
71
72
  rubygems_version: 3.1.4
72
73
  signing_key:
73
74
  specification_version: 4
74
- summary: Run subprocess asynch/synch.
75
+ summary: Spawn commands as asynch/synch subprocesses.
75
76
  test_files: []