class RSpec::Core::Bisect::Runner

@private
the given bisect server to capture the results.
Provides an API to run the suite for a set of locations, using

def bisect_environment_hash

def bisect_environment_hash
  if ENV.key?('SPEC_OPTS')
    { 'SPEC_OPTS' => spec_opts_without_bisect }
  else
    {}
  end
end

def command_for(locations)

def command_for(locations)
  parts = []
  parts << RUBY << load_path
  parts << open3_safe_escape(RSpec::Core.path_to_executable)
  parts << "--format"   << "bisect"
  parts << "--drb-port" << @server.drb_port
  parts.concat reusable_cli_options
  parts.concat locations.map { |l| open3_safe_escape(l) }
  parts.join(" ")
end

def environment_repro_parts

def environment_repro_parts
  bisect_environment_hash.map do |k, v|
    %Q(#{k}="#{v}")
  end
end

def initialize(server, original_cli_args)

def initialize(server, original_cli_args)
  @server            = server
  @original_cli_args = original_cli_args.reject { |arg| arg.start_with?("--bisect") }
end

def load_path

def load_path
  @load_path ||= "-I#{$LOAD_PATH.map { |p| open3_safe_escape(p) }.join(':')}"
end

def original_cli_args_without_locations

def original_cli_args_without_locations
  @original_cli_args_without_locations ||= begin
    files_or_dirs = parsed_original_cli_options.fetch(:files_or_directories_to_run)
    @original_cli_args - files_or_dirs
  end
end

def original_locations

def original_locations
  parsed_original_cli_options.fetch(:files_or_directories_to_run)
end

def original_results

def original_results
  @original_results ||= run_locations(original_locations)
end

def parsed_original_cli_options

def parsed_original_cli_options
  @parsed_original_cli_options ||= Parser.parse(@original_cli_args)
end

def repro_command_from(locations)

def repro_command_from(locations)
  parts = []
  parts.concat environment_repro_parts
  parts << "rspec"
  parts.concat Formatters::Helpers.organize_ids(locations)
  parts.concat original_cli_args_without_locations
  parts.join(" ")
end

def reusable_cli_options

def reusable_cli_options
  @reusable_cli_options ||= begin
    opts = original_cli_args_without_locations
    if (port = parsed_original_cli_options[:drb_port])
      opts -= %W[ --drb-port #{port} ]
    end
    parsed_original_cli_options.fetch(:formatters) { [] }.each do |(name, out)|
      opts -= %W[ --format #{name} -f -f#{name} ]
      opts -= %W[ --out #{out} -o -o#{out} ]
    end
    opts
  end
end

def run(locations)

def run(locations)
  run_locations(locations, original_results.failed_example_ids)
end

def run_command(cmd)

def run_command(cmd)
  Open3.capture2e(bisect_environment_hash, cmd).first
end

def run_command(cmd)

:nocov:
for 1.8.7
def run_command(cmd)
  out = err = nil
  original_spec_opts = ENV['SPEC_OPTS']
  ENV['SPEC_OPTS'] = spec_opts_without_bisect
  Open3.popen3(cmd) do |_, stdout, stderr|
    # Reading the streams blocks until the process is complete
    out = stdout.read
    err = stderr.read
  end
  "Stdout:\n#{out}\n\nStderr:\n#{err}"
ensure
  ENV['SPEC_OPTS'] = original_spec_opts
end

def run_locations(*capture_args)

def run_locations(*capture_args)
  @server.capture_run_results(*capture_args) do
    run_command command_for([])
  end
end

def spec_opts_without_bisect

def spec_opts_without_bisect
  Shellwords.join(
    Shellwords.split(ENV.fetch('SPEC_OPTS', '')).reject do |arg|
      arg =~ /^--bisect/
    end
  )
end