command_utils 0.3.0 → 0.4.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
  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