From 99585a738cdf119ca59ce932b4ac0f278f6fda88 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Date: Mon, 10 Aug 2015 10:54:42 +0200 Subject: [PATCH] Trigger post-receive hoooks when commits are made by GitLab Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> --- app/services/post_commit_service.rb | 65 ++++++++++++++++++++++++++++- app/workers/post_receive.rb | 2 +- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/app/services/post_commit_service.rb b/app/services/post_commit_service.rb index 7d7e5fbc32e..aa9a807b7d2 100644 --- a/app/services/post_commit_service.rb +++ b/app/services/post_commit_service.rb @@ -1,8 +1,71 @@ class PostCommitService < BaseService + include Gitlab::Popen + + attr_reader :changes + def execute(sha, branch) commit = repository.commit(sha) full_ref = 'refs/heads/' + branch old_sha = commit.parent_id || Gitlab::Git::BLANK_SHA - GitPushService.new.execute(project, current_user, old_sha, sha, full_ref) + + @changes = "#{old_sha} #{sha} #{full_ref}" + post_receive(@changes, repository.path_to_repo) + end + + private + + 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 call_receive_hook(hook, changes) + # function will return true if succesful + exit_status = false + + vars = { + 'GL_ID' => Gitlab::ShellEnv.gl_id(current_user), + 'PWD' => repository.path_to_repo + } + + options = { + chdir: repository.path_to_repo + } + + # we combine both stdout and stderr as we don't know what stream + # will be used by the custom hook + Open3.popen2e(vars, hook, options) 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 + + exit_status + end + + def hook_file(hook_type, repo_path) + hook_path = File.join(repo_path.strip, 'hooks') + hook_file = "#{hook_path}/#{hook_type}" + hook_file if File.exist?(hook_file) end end diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb index 33d8cc8861b..994b8e8ed38 100644 --- a/app/workers/post_receive.rb +++ b/app/workers/post_receive.rb @@ -45,7 +45,7 @@ class PostReceive def utf8_encode_changes(changes) changes = changes.dup - + changes.force_encoding("UTF-8") return changes if changes.valid_encoding? -- 2.30.9