komenda 0.0.4 → 0.1.1

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
  SHA1:
3
- metadata.gz: 7e9f8fb8dbfd89bfe6f02a03ab9b9916152cd9a1
4
- data.tar.gz: ccd5136b7c00ee0da50df39d6845985242d0c414
3
+ metadata.gz: 1dc95e01539e2ccbbc00044df4c47da92578c9c3
4
+ data.tar.gz: 72b97381c230e7bb19d7507c495c6c3abc311a57
5
5
  SHA512:
6
- metadata.gz: 936da7f196c29f3d145731f74ac98e29344c0478c506dcd45aecdb8ef717fbe37f2b9049c07feefa3d2201f5874a07efb8a6d5b6747bea16082cc6686a67d92a
7
- data.tar.gz: c968d4eeafd91c117e94a4de47eb2399136f8e560a119dc00aefa55f32dce2336353dc7d9dd2349e38d9d0bfd2631d4378bd923cfe0dae8b4329bc318ec64232
6
+ metadata.gz: 2d2edf563c747a5816d878a0a972880a1da1b27275ba54bbbf9c3432841532aba04fbffce3f0da2d68ac35fdd4a6c1e697f9bac1b5560ae35c15f73b6bf97796
7
+ data.tar.gz: 440e085f88b4324f055ce0b5a222e6efd083acaf01efa6b83fae13be65067509b0d380e16bcd158e118ee87ad3d7b7fe02e81f4c92f02005e835c84299853d4f
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
- Komenda [![Build Status](https://travis-ci.org/cargomedia/komenda.svg)](https://travis-ci.org/cargomedia/komenda)
1
+ Komenda
2
2
  =======
3
- Komenda is a convenience wrapper around `Open3` to run shell commands in Ruby.
3
+ Komenda is a convenience wrapper to run shell commands in Ruby.
4
+
5
+ [![Build Status](https://img.shields.io/travis/cargomedia/komenda/master.svg)](https://travis-ci.org/cargomedia/komenda)
6
+ [![Gem Version](https://img.shields.io/gem/v/komenda.svg)](https://rubygems.org/gems/komenda)
4
7
 
5
8
  Usage
6
9
  -----
@@ -1,12 +1,11 @@
1
1
  require 'open3'
2
- require 'event_emitter'
2
+ require 'events'
3
3
 
4
4
  require 'komenda/process_builder'
5
5
  require 'komenda/process'
6
6
  require 'komenda/result'
7
7
 
8
8
  module Komenda
9
-
10
9
  # @param [String] command
11
10
  # @param [Hash] options
12
11
  # @return [Komenda::Process]
@@ -22,5 +21,4 @@ module Komenda
22
21
  process_builder = Komenda::ProcessBuilder.new(command, options)
23
22
  process_builder.create.run
24
23
  end
25
-
26
24
  end
@@ -1,16 +1,14 @@
1
1
  module Komenda
2
2
  class Process
3
-
4
3
  attr_reader :output
5
4
 
6
- include EventEmitter
5
+ include Events::Emitter
7
6
 
8
7
  # @param [ProcessBuilder] process_builder
9
8
  def initialize(process_builder)
10
9
  @process_builder = process_builder
11
- @output = {:stdout => '', :stderr => '', :combined => ''}
12
- @exit_status = nil
13
- @thread = nil
10
+ @output = { stdout: '', stderr: '', combined: '' }
11
+ @exit_status = @thread = @pid = nil
14
12
 
15
13
  on(:stdout) { |data| @output[:stdout] += data }
16
14
  on(:stderr) { |data| @output[:stderr] += data }
@@ -22,88 +20,107 @@ module Komenda
22
20
 
23
21
  # @return [Thread]
24
22
  def start
25
- raise 'Already started' if is_started?
23
+ fail 'Already started' if started?
26
24
  @thread = Thread.new { run_process(@process_builder) }
27
25
  end
28
26
 
29
27
  # @return [Komenda::Result]
30
28
  def wait_for
31
- raise 'Process not started' unless is_started?
29
+ fail 'Process not started' unless started?
32
30
  @thread.join
33
31
  result
34
32
  end
35
33
 
36
34
  # @return [Komenda::Result]
37
35
  def run
38
- start unless is_started?
36
+ start unless started?
39
37
  wait_for
40
38
  end
41
39
 
40
+ # @return [Integer]
41
+ def pid
42
+ fail 'No PID available' if @pid.nil?
43
+ @pid
44
+ end
45
+
46
+ # @param [Integer, String]
47
+ def kill(signal = 'TERM')
48
+ ::Process.kill(signal, pid)
49
+ end
50
+
42
51
  # @return [TrueClass, FalseClass]
43
52
  def running?
44
- raise 'Process not started' unless is_started?
45
- @thread.alive?
53
+ started? && !@pid.nil? && @thread.alive?
46
54
  end
47
55
 
48
56
  # @return [Komenda::Result]
49
57
  def result
50
- raise 'Process not started' unless is_started?
51
- raise 'Process not finished' unless is_finished?
58
+ fail 'Process not started' unless started?
59
+ fail 'Process not finished' unless finished?
52
60
  Komenda::Result.new(@output, @exit_status)
53
61
  end
54
62
 
55
63
  private
56
64
 
57
65
  # @return [TrueClass, FalseClass]
58
- def is_started?
66
+ def started?
59
67
  !@thread.nil?
60
68
  end
61
69
 
62
70
  # @return [TrueClass, FalseClass]
63
- def is_finished?
71
+ def finished?
64
72
  !@exit_status.nil?
65
73
  end
66
74
 
67
75
  # @param [ProcessBuilder] process_builder
68
76
  def run_process(process_builder)
69
- begin
70
- if process_builder.cwd.nil?
71
- run_popen3(process_builder)
72
- else
73
- Dir.chdir(process_builder.cwd) { run_popen3(process_builder) }
74
- end
75
- rescue Exception => exception
76
- emit(:error, exception)
77
- raise exception
77
+ if process_builder.cwd.nil?
78
+ run_popen3(process_builder)
79
+ else
80
+ Dir.chdir(process_builder.cwd) { run_popen3(process_builder) }
78
81
  end
82
+ rescue Exception => exception
83
+ emit(:error, exception)
84
+ raise exception
79
85
  end
80
86
 
81
87
  # @param [ProcessBuilder] process_builder
82
88
  def run_popen3(process_builder)
83
89
  Open3.popen3(process_builder.env, *process_builder.command) do |stdin, stdout, stderr, wait_thr|
90
+ @pid = wait_thr.pid
84
91
  stdin.close
85
-
86
- streams_read_open = [stdout, stderr]
87
- begin
88
- streams_read_available, _, _ = IO.select(streams_read_open)
89
-
90
- streams_read_available.each do |stream|
91
- if stream.eof?
92
- stream.close
93
- streams_read_open.delete(stream)
94
- else
95
- data = stream.readpartial(4096)
96
- emit(:stdout, data) if stdout === stream
97
- emit(:stderr, data) if stderr === stream
98
- emit(:output, data)
99
- end
100
- end
101
- end until streams_read_open.empty?
102
-
92
+ read_streams([stdout, stderr]) do |data, stream|
93
+ emit(:output, data)
94
+ emit(:stdout, data) if stdout == stream
95
+ emit(:stderr, data) if stderr == stream
96
+ end
103
97
  @exit_status = wait_thr.value
104
98
  emit(:exit, result)
105
99
  end
106
100
  end
107
101
 
102
+ # @param [Array<IO>] streams
103
+ def read_streams(streams)
104
+ select_streams(streams) do |stream|
105
+ if stream.eof?
106
+ stream.close
107
+ else
108
+ data = stream.readpartial(4096)
109
+ yield(data, stream)
110
+ end
111
+ end
112
+ end
113
+
114
+ # @param [Array<IO>] streams
115
+ def select_streams(streams)
116
+ loop do
117
+ streams_available, = IO.select(streams)
118
+ streams_available.each do |stream|
119
+ yield(stream)
120
+ end
121
+ streams.reject!(&:closed?)
122
+ break if streams.empty?
123
+ end
124
+ end
108
125
  end
109
126
  end
@@ -1,6 +1,5 @@
1
1
  module Komenda
2
2
  class ProcessBuilder
3
-
4
3
  attr_reader :command
5
4
  attr_reader :env
6
5
  attr_reader :cwd
@@ -10,16 +9,16 @@ module Komenda
10
9
  # @param [Hash] options
11
10
  def initialize(command, options = {})
12
11
  defaults = {
13
- :env => ENV.to_hash,
14
- :cwd => nil,
15
- :events => {},
12
+ env: ENV.to_hash,
13
+ cwd: nil,
14
+ events: {}
16
15
  }
17
16
  options = defaults.merge(options)
18
17
 
19
- @command = command.is_a?(Array) ? command.map { |v| String(v) } : String(command)
20
- @env = Hash[options[:env].to_hash.map { |k, v| [String(k), String(v)] }]
21
- @cwd = options[:cwd].nil? ? nil : String(options[:cwd])
22
- @events = Hash[options[:events].to_hash.map { |k, v| [k.to_sym, v.to_proc] }]
18
+ self.command = command
19
+ self.env = options[:env]
20
+ self.cwd = options[:cwd]
21
+ self.events = options[:events]
23
22
  end
24
23
 
25
24
  # @return [Komenda::Process]
@@ -27,5 +26,28 @@ module Komenda
27
26
  Komenda::Process.new(self)
28
27
  end
29
28
 
29
+ # @param [String, Array<String>] command
30
+ def command=(command)
31
+ if command.is_a?(Array)
32
+ @command = command.map { |v| String(v) }
33
+ else
34
+ @command = String(command)
35
+ end
36
+ end
37
+
38
+ # @param [Hash] env
39
+ def env=(env)
40
+ @env = Hash[env.to_hash.map { |k, v| [String(k), String(v)] }]
41
+ end
42
+
43
+ # @param [String] cwd
44
+ def cwd=(cwd = nil)
45
+ @cwd = cwd.nil? ? nil : String(cwd)
46
+ end
47
+
48
+ # @param [Hash<Symbol, Proc>]
49
+ def events=(events)
50
+ @events = Hash[events.to_hash.map { |k, v| [k.to_sym, v.to_proc] }]
51
+ end
30
52
  end
31
53
  end
@@ -1,6 +1,5 @@
1
1
  module Komenda
2
2
  class Result
3
-
4
3
  # @param [Hash] output
5
4
  # @option output_streams [String] :stdout
6
5
  # @option output_streams [String] :stderr
@@ -35,6 +34,5 @@ module Komenda
35
34
  def pid
36
35
  @status.pid
37
36
  end
38
-
39
37
  end
40
38
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: komenda
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cargo Media
@@ -9,22 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-11-27 00:00:00.000000000 Z
12
+ date: 2015-12-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: event_emitter
15
+ name: events
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
18
  - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: '0.2'
20
+ version: 0.9.8
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: '0.2'
27
+ version: 0.9.8
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: bundler
30
30
  requirement: !ruby/object:Gem::Requirement
@@ -67,6 +67,34 @@ dependencies:
67
67
  - - "~>"
68
68
  - !ruby/object:Gem::Version
69
69
  version: '2.0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: rspec-wait
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: 0.0.8
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: 0.0.8
84
+ - !ruby/object:Gem::Dependency
85
+ name: rubocop
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '0.35'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '0.35'
70
98
  description: Convenience wrapper around `Open3` to run shell commands in Ruby.
71
99
  email: hello@cargomedia.ch
72
100
  executables: []
@@ -99,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
99
127
  version: '0'
100
128
  requirements: []
101
129
  rubyforge_project:
102
- rubygems_version: 2.4.8
130
+ rubygems_version: 2.5.0
103
131
  signing_key:
104
132
  specification_version: 4
105
133
  summary: Convenience wrapper around `Open3` to run shell commands in Ruby.