Commit 5a6d71d1 authored by Stan Hu's avatar Stan Hu

Merge branch 'custom-hook-output' into 'master'

Prevent blocking custom hook output streams

Based on https://gitlab.com/gitlab-org/gitlab-shell/merge_requests/49

Fixes https://gitlab.com/gitlab-org/gitlab-ce/issues/1458

See merge request !67
parents cab00513 b6625587
...@@ -25,37 +25,24 @@ class GitlabCustomHook ...@@ -25,37 +25,24 @@ class GitlabCustomHook
private private
def call_receive_hook(hook, changes) def call_receive_hook(hook, changes)
# function will return true if succesful # Prepare the hook subprocess. Attach a pipe to its stdin, and merge
exit_status = false # both its stdout and stderr into our own stdout.
stdin_reader, stdin_writer = IO.pipe
# we combine both stdout and stderr as we don't know what stream hook_pid = spawn(hook, in: stdin_reader, err: :out)
# will be used by the custom hook stdin_reader.close
Open3.popen2e(hook) do |stdin, stdout_stderr, wait_thr|
exit_status = true # Submit changes to the hook via its stdin.
stdin.sync = true begin
IO.copy_stream(StringIO.new(changes), stdin_writer)
# in git, pre- and post- receive hooks may just exit without rescue Errno::EPIPE
# reading stdin. We catch the exception to avoid a broken pipe # It is not an error if the hook does not consume all of its input.
# warning
begin
# inject all the changes as stdin to the hook
changes.lines do |line|
stdin.puts(line)
end
rescue Errno::EPIPE
end
# need to close stdin before reading stdout
stdin.close
unless wait_thr.value == 0
exit_status = false
end
stdout_stderr.each_line { |line| puts line }
end end
exit_status # Close the pipe to let the hook know there is no further input.
stdin_writer.close
Process.wait(hook_pid)
$?.success?
end end
def hook_file(hook_type, repo_path) def hook_file(hook_type, repo_path)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment