komenda 0.0.4 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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.