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