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 +4 -4
- data/lib/command_utils.rb +68 -34
- metadata +16 -17
- data/lib/command_utils/non_zero_status.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43313ab411781575b5f54cd723d95189d6ef8cfd
|
4
|
+
data.tar.gz: 9f7aeb3db8f866314c1d0c59efcf9a7a29e6d681
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
121
|
-
|
122
|
-
|
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
|
147
|
-
|
148
|
-
|
149
|
-
|
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.
|
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-
|
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.
|
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.
|
26
|
+
version: '3.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name: guard-
|
28
|
+
name: guard-rdoc
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
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: '
|
43
|
+
version: '1.0'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.0.3
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
|
-
name: guard-
|
48
|
+
name: guard-rspec
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
44
50
|
requirements:
|
45
51
|
- - "~>"
|
46
52
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
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: '
|
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
|