lib/github/markup/command_implementation.rb (58 lines of code) (raw):
require "open3"
require "github/markup/implementation"
module GitHub
module Markup
class CommandError < RuntimeError
end
class CommandImplementation < Implementation
DEFAULT_GITLAB_MARKUP_TIMEOUT = '10'.freeze
attr_reader :command, :block, :name
def initialize(regexp, command, name, &block)
super regexp
@command = command.to_s
@block = block
@name = name
end
def render(content)
rendered = execute(command, content)
rendered = rendered.to_s.empty? ? content : rendered
call_block(rendered, content)
end
private
def call_block(rendered, content)
if block && block.arity == 2
block.call(rendered, content)
elsif block
block.call(rendered)
else
rendered
end
end
def timeout_in_seconds
ENV.fetch('GITLAB_MARKUP_TIMEOUT', DEFAULT_GITLAB_MARKUP_TIMEOUT).to_i
end
def prepend_command_timeout_prefix(command)
timeout_command_prefix = "timeout -s KILL #{timeout_in_seconds}"
# Preserve existing support for command being either a String or an Array
if command.is_a?(String)
"#{timeout_command_prefix} #{command}"
else
timeout_command_prefix.split(' ') + command
end
end
def execute(command, target)
command_with_timeout_prefix = prepend_command_timeout_prefix(command)
stdout_str, stderr_str, status = Open3.capture3(*command_with_timeout_prefix, stdin_data: target)
if status.success?
sanitize(stdout_str, target.encoding)
elsif status.termsig == Signal.list['KILL']
raise TimeoutError.new("Command was killed, probably due to exceeding GITLAB_MARKUP_TIMEOUT limit of #{timeout_in_seconds} seconds")
else
raise CommandError.new(stderr_str.strip)
end
end
def sanitize(input, encoding)
input.gsub("\r", '').force_encoding(encoding)
end
end
end
end