command_utils 0.3.0 → 0.4.0

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: 3845dc2af885cf859dbc3f1afc1c2a0dd7ef31e4
4
- data.tar.gz: 3359ba253daa038a08d4d3247ccd40c2a48d16ac
3
+ metadata.gz: 43313ab411781575b5f54cd723d95189d6ef8cfd
4
+ data.tar.gz: 9f7aeb3db8f866314c1d0c59efcf9a7a29e6d681
5
5
  SHA512:
6
- metadata.gz: c79aa92e07443ddcaf7b986347d5facfccceb2bc1a7d5f70cc7bf3cbdb79ee0234e8eee773697d303364dc605ad533f8d6313f84fde299ac9e3ef2936f075942
7
- data.tar.gz: a18f88fc4fcfb06266e7102e958040472a413ca50e6baf68e6a67abd58c513e695e9a767376fb8627620a3d0433526c7404acd24c69bd8c842df18327ebd5ee5
6
+ metadata.gz: 0f1175dd3ab6259546955779aefca5375a5e7da16c65d00f1af6265ac8874e5a1ee2b9d8ab2d0993dc0550779856ff702e663f578b810ab2a55ffb388dd2f040
7
+ data.tar.gz: 31be009f839f09db332d9012a71a3e9ef6cd82cf701a1474938bb4c5e75794b4691f2cc424f1cf05ecc6214e8465eea4c58d19448ce609aef7fe558bcac9e92b
data/lib/command_utils.rb CHANGED
@@ -1,10 +1,11 @@
1
- require_relative 'command_utils/non_zero_status'
2
1
  require_relative 'command_utils/line_buffer'
3
2
 
4
3
  # Class to assist calling external commands, while processing its output and return code.
5
- # All methods which execute given command, raise NonZeroStatus if its return is not 0.
6
4
  class CommandUtils
7
5
 
6
+ # PID of currently running process.
7
+ attr_reader :pid
8
+
8
9
  # call-seq:
9
10
  # new([env,] command...)
10
11
  #
@@ -24,29 +25,30 @@ class CommandUtils
24
25
  yield self if block_given?
25
26
  end
26
27
 
27
- # Execute command, yielding to given block, each time there is output available.
28
+ # Execute command, yielding to given block, each time there is output available (not line buffered):
28
29
  # stream:: either +:stdout+ or +:stderr+.
29
30
  # data:: data read from respective stream.
30
- def each_output # :yields: stream, data
31
- run do
32
- loop do
33
- io_list = [@stdout_read, @stderr_read].keep_if{|io| not io.closed?}
34
- break if io_list.empty?
35
- IO.select(io_list).first.each do |io|
36
- if io.eof?
37
- io.close
38
- next
39
- end
40
- label = case io
41
- when @stdout_read
42
- :stdout
43
- when @stderr_read
44
- :stderr
45
- end
46
- yield label, io.read
31
+ # Raises CommandUtils::StatusError class exception if command execution is not successfull.
32
+ def each_output &block # :yields: stream, data
33
+ spawn
34
+ loop do
35
+ io_list = [@stdout_read, @stderr_read].keep_if{|io| not io.closed?}
36
+ break if io_list.empty?
37
+ IO.select(io_list).first.each do |io|
38
+ if io.eof?
39
+ io.close
40
+ next
47
41
  end
42
+ label = case io
43
+ when @stdout_read
44
+ :stdout
45
+ when @stderr_read
46
+ :stderr
47
+ end
48
+ yield label, io.read
48
49
  end
49
50
  end
51
+ process_status
50
52
  end
51
53
 
52
54
  # call-seq:
@@ -57,9 +59,10 @@ class CommandUtils
57
59
  self.new(*args).each_output(&block)
58
60
  end
59
61
 
60
- # Execute command, yielding to given block, each time there is a new line available.
62
+ # Execute command, yielding to given block, each time there is a new line available (does line buffering):
61
63
  # stream:: either +:stdout+ or +:stderr+.
62
64
  # data:: data read from respective stream.
65
+ # Raises CommandUtils::StatusError class exception if command execution is not successfull.
63
66
  def each_line &block # :yields: stream, data
64
67
  stdout_lb = LineBuffer.new(
65
68
  proc do |data|
@@ -99,6 +102,7 @@ class CommandUtils
99
102
  # and optionally:
100
103
  # +:stdout_prefix+:: Prefix to use for all stdout messages.
101
104
  # +:stderr_prefix+:: Prefix to use for all stderr messages.
105
+ # Raises CommandUtils::StatusError class exception if command execution is not successfull.
102
106
  def logger_exec options
103
107
  each_line do |stream, data|
104
108
  level = options["#{stream}_level".to_sym]
@@ -117,12 +121,9 @@ class CommandUtils
117
121
 
118
122
  private
119
123
 
120
- def run
121
- spawn
122
- yield
123
- process_status
124
- end
125
-
124
+ # Process.spawn a new process with @env and @command.
125
+ #
126
+ # Sets @pid, @stdout_write and @stderr_write.
126
127
  def spawn
127
128
  @stdout_read, @stdout_write = IO.pipe
128
129
  @stderr_read, @stderr_write = IO.pipe
@@ -142,14 +143,47 @@ class CommandUtils
142
143
  @stderr_write.close
143
144
  end
144
145
 
146
+ # Parent class for all status errors.
147
+ class StatusError < StandardError
148
+ # Process::Status
149
+ attr_accessor :status
150
+ # Command as passed to Process#spawn
151
+ attr_accessor :command
152
+ def initialize message, status, command
153
+ super message
154
+ @status, @command = status, command
155
+ end
156
+ end
157
+
158
+ # Raised when process exited with non zero status.
159
+ class NonZeroExit < StatusError ; end
160
+ # Raised when process was signaled.
161
+ class Signaled < StatusError ; end
162
+ # Raised when process was stopped.
163
+ class Stopped < StatusError ; end
164
+ # Raised when process exited with unknown status.
165
+ class Unknown < StatusError ; end
166
+
167
+ # Wait for process termination, then process its status.
145
168
  def process_status
146
- Process.wait @pid
147
- unless (status = $?.exitstatus) == 0
148
- raise NonZeroStatus.new(
149
- "Command exited with #{status}.",
150
- status,
151
- @command
152
- )
169
+ flags = Process::WNOHANG|Process::WUNTRACED
170
+ pid, status = Process.wait2(@pid, flags)
171
+ if status.exited?
172
+ unless status.exitstatus == 0
173
+ message = "Command exited with #{status.exitstatus}."
174
+ raise NonZeroExit.new(message, status, @command)
175
+ end
176
+ elsif status.signaled?
177
+ message = "Command was signaled with #{status.termsig}."
178
+ message += " Core dump generated." if status.coredump?
179
+ raise Signaled.new(message, status, @command)
180
+ elsif status.stopped?
181
+ message = "Command was stopped with signal #{status.stopsig}, PID=#{pid}."
182
+ raise Stopped.new(message, status, @command)
183
+ else
184
+ message = "Unknown return status."
185
+ raise Unknown.new(message, status, @command)
153
186
  end
154
187
  end
188
+
155
189
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: command_utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fabio Pugliese Ornellas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-18 00:00:00.000000000 Z
11
+ date: 2015-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -16,48 +16,48 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '3.2'
19
+ version: '3.3'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '3.2'
26
+ version: '3.3'
27
27
  - !ruby/object:Gem::Dependency
28
- name: guard-rspec
28
+ name: guard-rdoc
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '4.5'
33
+ version: '1.0'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 1.0.3
34
37
  type: :development
35
38
  prerelease: false
36
39
  version_requirements: !ruby/object:Gem::Requirement
37
40
  requirements:
38
41
  - - "~>"
39
42
  - !ruby/object:Gem::Version
40
- version: '4.5'
43
+ version: '1.0'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 1.0.3
41
47
  - !ruby/object:Gem::Dependency
42
- name: guard-rdoc
48
+ name: guard-rspec
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
51
  - - "~>"
46
52
  - !ruby/object:Gem::Version
47
- version: '1.0'
48
- - - ">="
49
- - !ruby/object:Gem::Version
50
- version: 1.0.3
53
+ version: '4.6'
51
54
  type: :development
52
55
  prerelease: false
53
56
  version_requirements: !ruby/object:Gem::Requirement
54
57
  requirements:
55
58
  - - "~>"
56
59
  - !ruby/object:Gem::Version
57
- version: '1.0'
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: 1.0.3
60
+ version: '4.6'
61
61
  description: This Gem will help you call external commands, process its stdout and
62
62
  stderr, to your own fit, and at the end, validate its return code.
63
63
  email: fabio.ornellas@gmail.com
@@ -67,7 +67,6 @@ extra_rdoc_files: []
67
67
  files:
68
68
  - lib/command_utils.rb
69
69
  - lib/command_utils/line_buffer.rb
70
- - lib/command_utils/non_zero_status.rb
71
70
  homepage: https://github.com/fornellas/command_utils
72
71
  licenses:
73
72
  - GPL
@@ -1,18 +0,0 @@
1
- class CommandUtils
2
-
3
- # Raised when executed command does not return 0
4
- class NonZeroStatus < RuntimeError
5
-
6
- # Command exit status
7
- attr_accessor :status
8
- # Command as passed to Process#spawn
9
- attr_accessor :command
10
-
11
- def initialize message, status, command
12
- super message
13
- @status, @command = status, command
14
- end
15
-
16
- end
17
-
18
- end