lib/hookit/resource/execute.rb in hookit-0.10.0 vs lib/hookit/resource/execute.rb in hookit-0.11.0
- old
+ new
@@ -1,6 +1,7 @@
require 'timeout'
+require 'open3'
module Hookit
module Resource
class Execute < Base
@@ -11,10 +12,12 @@
field :path
field :returns
field :timeout
field :stream
field :on_data
+ field :on_stdout
+ field :on_stderr
field :on_exit
field :validator
field :ignore_exit
actions :run
@@ -64,34 +67,58 @@
validate! res
end
end
def stream!
+ exit_status = 0
result = ""
STDOUT.sync = STDERR.sync = true # don't buffer stdout/stderr
- ::IO.popen(cmd, :err=>[:child, :out]) do |out|
- eof = false
- until eof do
- begin
- chunk = out.readpartial(4096)
- if on_data and on_data.respond_to? :call
- on_data.call(chunk)
+ Open3.popen3 cmd do |stdin, stdout, stderr, wait_thr|
+ stdout_eof = false
+ stderr_eof = false
+
+ until stdout_eof and stderr_eof do
+ (ready_pipes, dummy, dummy) = IO.select([stdout, stderr])
+ ready_pipes.each_with_index do |socket|
+ if socket == stdout
+ begin
+ chunk = socket.readpartial(4096)
+ if on_data and on_data.respond_to? :call
+ on_data.call(chunk)
+ end
+ if on_stdout and on_stdout.respond_to? :call
+ on_stdout.call(chunk)
+ end
+ rescue EOFError
+ stdout_eof = true
+ end
+ result << chunk.to_s
+ elsif socket == stderr
+ begin
+ chunk = socket.readpartial(4096)
+ if on_data and on_data.respond_to? :call
+ on_data.call(chunk)
+ end
+ if on_stderr and on_stderr.respond_to? :call
+ on_stderr.call(chunk)
+ end
+ rescue EOFError
+ stderr_eof = true
+ end
+ result << chunk.to_s
end
- rescue EOFError
- eof = true
end
- result << chunk.to_s
end
+
+ exit_status = wait_thr.value.to_s.match(/exit (\d+)/)[1].to_i
end
- code = $?.exitstatus
-
if on_exit and on_exit.respond_to? :call
- on_exit.call(code)
+ on_exit.call(exit_status)
else
- unexpected_exit(code) unless code == returns
+ unexpected_exit(exit_status) unless exit_status == returns
end
validate! result
end
\ No newline at end of file