# Gitaly note: JV: looks like this is only used by Gitlab::Git::HooksService in # app/services. We shouldn't bother migrating this until we know how # Gitlab::Git::HooksService will be migrated. module Gitlab module Git class Hook GL_PROTOCOL = 'web'.freeze attr_reader :name, :path, :repository def initialize(name, repository) @name = name @repository = repository @path = File.join(repo_path.strip, 'hooks', name) end def repo_path repository.path end def exists? File.exist?(path) end def trigger(gl_id, gl_username, oldrev, newrev, ref) return [true, nil] unless exists? Bundler.with_clean_env do case name when "pre-receive", "post-receive" call_receive_hook(gl_id, gl_username, oldrev, newrev, ref) when "update" call_update_hook(gl_id, gl_username, oldrev, newrev, ref) end end end private def call_receive_hook(gl_id, gl_username, oldrev, newrev, ref) changes = [oldrev, newrev, ref].join(" ") exit_status = false exit_message = nil vars = { 'GL_ID' => gl_id, 'GL_USERNAME' => gl_username, 'PWD' => repo_path, 'GL_PROTOCOL' => GL_PROTOCOL, 'GL_REPOSITORY' => repository.gl_repository } options = { chdir: repo_path } Open3.popen3(vars, path, 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 stdin.close unless wait_thr.value == 0 exit_status = false exit_message = retrieve_error_message(stderr, stdout) end end [exit_status, exit_message] end def call_update_hook(gl_id, gl_username, oldrev, newrev, ref) Dir.chdir(repo_path) do env = { 'GL_ID' => gl_id, 'GL_USERNAME' => gl_username } stdout, stderr, status = Open3.capture3(env, path, ref, oldrev, newrev) [status.success?, (stderr.presence || stdout).gsub(/\R/, "
").html_safe] end end def retrieve_error_message(stderr, stdout) err_message = stderr.read err_message = err_message.blank? ? stdout.read : err_message err_message.gsub(/\R/, "
").html_safe end end end end