class Snowglobe::CommandRunner
Constants
- TimeoutError
Attributes
args[R]
command_prefix[RW]
env[R]
options[R]
reader[R]
retries[RW]
run_quickly[RW]
run_successfully[RW]
status[R]
timeout[RW]
wrapper[R]
writer[R]
Public Class Methods
new( *args, env: {}, directory: Dir.pwd, run_successfully: false, **options ) { |self| ... }
click to toggle source
# File lib/snowglobe/command_runner.rb, line 23 def initialize( *args, env: {}, directory: Dir.pwd, run_successfully: false, **options ) @reader, @writer = IO.pipe @options = options.merge(err: [:child, :out], out: writer) @args = args @env = normalize_env(env) self.directory = directory @run_successfully = run_successfully @wrapper = ->(block) { block.call } @command_prefix = "" @run_quickly = false @retries = 1 @num_times_run = 0 @timeout = 20 yield self if block_given? end
run(*args, **options, &block)
click to toggle source
# File lib/snowglobe/command_runner.rb, line 11 def self.run(*args, **options, &block) new(*args, **options, &block).tap(&:call) end
run!(*args, **options, &block)
click to toggle source
# File lib/snowglobe/command_runner.rb, line 15 def self.run!(*args, **options, &block) run(*args, run_successfully: true, **options, &block) end
Public Instance Methods
around_command(&block)
click to toggle source
# File lib/snowglobe/command_runner.rb, line 60 def around_command(&block) @wrapper = block end
call()
click to toggle source
# File lib/snowglobe/command_runner.rb, line 70 def call possibly_retrying do possibly_running_quickly do run_with_debugging if run_successfully && !success? fail! end end end self end
directory()
click to toggle source
# File lib/snowglobe/command_runner.rb, line 48 def directory options[:chdir] end
directory=(directory)
click to toggle source
# File lib/snowglobe/command_runner.rb, line 52 def directory=(directory) if directory.nil? raise ArgumentError, "Must provide a directory" end options[:chdir] = directory end
elided_output()
click to toggle source
# File lib/snowglobe/command_runner.rb, line 97 def elided_output lines = output.split(/\n/) new_lines = lines[0..4] if lines.size > 10 new_lines << "(...#{lines.size - 10} more lines...)" end new_lines << lines[-5..-1] new_lines.join("\n") end
exit_status()
click to toggle source
# File lib/snowglobe/command_runner.rb, line 111 def exit_status status.exitstatus end
fail!()
click to toggle source
# File lib/snowglobe/command_runner.rb, line 115 def fail! raise <<-MESSAGE Command #{formatted_command.inspect} exited with status #{exit_status}. Output: #{divider("START") + output + divider("END")} MESSAGE end
formatted_command()
click to toggle source
# File lib/snowglobe/command_runner.rb, line 64 def formatted_command [formatted_env, Shellwords.join(command)]. reject(&:empty?). join(" ") end
has_output?(expected_output)
click to toggle source
# File lib/snowglobe/command_runner.rb, line 123 def has_output?(expected_output) if expected_output.is_a?(Regexp) output =~ expected_output else output.include?(expected_output) end end
output()
click to toggle source
# File lib/snowglobe/command_runner.rb, line 90 def output @_output ||= begin stop without_colors(reader.read) end end
stop()
click to toggle source
# File lib/snowglobe/command_runner.rb, line 84 def stop unless writer.closed? writer.close end end
Private Instance Methods
command()
click to toggle source
# File lib/snowglobe/command_runner.rb, line 143 def command ([command_prefix] + args).flatten.flat_map do |word| Shellwords.split(word) end end
debug() { || ... }
click to toggle source
# File lib/snowglobe/command_runner.rb, line 226 def debug if debugging_enabled? puts yield end end
debugging_enabled?()
click to toggle source
# File lib/snowglobe/command_runner.rb, line 222 def debugging_enabled? ENV["DEBUG_COMMANDS"] == "1" end
divider(title = "")
click to toggle source
# File lib/snowglobe/command_runner.rb, line 206 def divider(title = "") total_length = 72 start_length = 3 string = "" string << ("-" * start_length) string << title string << "-" * (total_length - start_length - title.length) string << "\n" string end
formatted_env()
click to toggle source
# File lib/snowglobe/command_runner.rb, line 149 def formatted_env env.map { |key, value| "#{key}=#{value.inspect}" }.join(" ") end
normalize_env(env)
click to toggle source
# File lib/snowglobe/command_runner.rb, line 137 def normalize_env(env) env.reduce({}) do |hash, (key, value)| hash.merge(key.to_s => value) end end
possibly_retrying() { || ... }
click to toggle source
# File lib/snowglobe/command_runner.rb, line 192 def possibly_retrying @num_times_run += 1 yield rescue StandardError => error debug { "#{error.class}: #{error.message}" } if @num_times_run < @retries sleep @num_times_run retry else raise error end end
possibly_running_quickly() { || ... }
click to toggle source
# File lib/snowglobe/command_runner.rb, line 172 def possibly_running_quickly(&block) if run_quickly begin Timeout.timeout(timeout, &block) rescue Timeout::Error stop message = "Command timed out after #{timeout} seconds: " + "#{formatted_command}\n" + "Output:\n" + output raise TimeoutError, message end else yield end end
run()
click to toggle source
# File lib/snowglobe/command_runner.rb, line 153 def run pid = spawn(env, *command, options) Process.waitpid(pid) @status = $? end
run_with_debugging()
click to toggle source
# File lib/snowglobe/command_runner.rb, line 163 def run_with_debugging debug { "\n\e[33mChanging to directory:\e[0m #{directory}" } debug { "\e[32mRunning command:\e[0m #{formatted_command}" } run_with_wrapper debug { "\n" + divider("START") + output + divider("END") } end
run_with_wrapper()
click to toggle source
# File lib/snowglobe/command_runner.rb, line 159 def run_with_wrapper wrapper.call(method(:run)) end
without_colors(string)
click to toggle source
# File lib/snowglobe/command_runner.rb, line 218 def without_colors(string) string.gsub(/\e\[\d+(?:;\d+)?m(.+?)\e\[0m/, '\1') end