Skip to content

Commit

Permalink
Fix the calls to pre- and post-receive custom hooks
Browse files Browse the repository at this point in the history
- Reset G_ID if the custom pre-receive hook fails
- Use a pipe to feed stdin to the custom pre- and post-receive
  hooks, in the same way that the standalone git works
  • Loading branch information
jkbzh authored and Drew Blessing committed Nov 6, 2014
1 parent 3ef7cdf commit b6d84f6
Showing 1 changed file with 41 additions and 14 deletions.
55 changes: 41 additions & 14 deletions lib/gitlab_custom_hook.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
require 'open3'

class GitlabCustomHook
def pre_receive(refs, repo_path)
if receive('pre-receive', refs, repo_path)
def pre_receive(changes, repo_path)
hook = hook_file('pre-receive', repo_path)
return true if hook.nil?
if call_receive_hook(hook, changes)
return true
else
# reset GL_ID env since we stop git push here
Expand All @@ -9,29 +13,52 @@ def pre_receive(refs, repo_path)
end
end

def post_receive(refs, repo_path)
receive('post-receive', refs, repo_path)
def post_receive(changes, repo_path)
hook = hook_file('post-receive', repo_path)
return true if hook.nil?
call_receive_hook(hook, changes) ? true : false
end

def update(ref_name, old_value, new_value, repo_path)
hook = hook_file('update', repo_path)
return true if hook.nil?
system(*hook, ref_name, old_value, new_value) ? true : false
system(hook, ref_name, old_value, new_value) ? true : false
end

private

def receive(type, refs, repo_path)
unless type == 'pre-receive' || type == 'post-receive'
puts 'GitLab: An unexpected error occurred ' \
'(invalid pre/post-receive hook type)'
return false
def call_receive_hook(hook, changes)
# function will return true if succesful
exit_status = false

# we combine both stdout and stderr as we don't know what stream
# will be used by the custom hook
Open3.popen2e (hook) do |stdin, stdout_stderr, wait_thr|
exit_status = true
stdin.sync = true

# in git, pre- and post- receive hooks may just exit without
# reading stdin. We catch the exception to avoid a broken pipe
# 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

# only output stdut_stderr if scripts doesn't return 0
unless wait_thr.value == 0
exit_status = false
stdout_stderr.each_line { |line| puts line }
end
end

hook = hook_file(type, repo_path)
return true if hook.nil?
cmd = "#{hook} #{refs}"
system(*cmd) ? true : false
exit_status
end

def hook_file(hook_type, repo_path)
Expand Down

0 comments on commit b6d84f6

Please sign in to comment.