Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

executable file 196 lines (157 sloc) 4.713 kb
#!/usr/bin/env ruby
require 'logger'
require 'optparse'
require 'readline'
require 'shellwords'
require 'rubygems'
require 'einhorn'
module Einhorn
class EinhornSH
class EinhornSHExit < StandardError
end
def initialize(path_to_socket)
@path_to_socket = path_to_socket
@request_id = 0
reconnect
end
def send_command(hash)
begin
@client.send_command(hash)
while response = @client.receive_message
if response.kind_of?(Hash)
yield response['message']
return unless response['wait']
else
puts "Invalid response type #{response.class}: #{response.inspect}"
end
end
rescue Errno::EPIPE => e
emit("einhornsh: Error communicating with Einhorn: #{e} (#{e.class})")
emit("einhornsh: Attempting to reconnect...")
reconnect
retry
end
end
def run
emit("Enter 'help' if you're not sure what to do.")
emit
emit('Type "quit" or "exit" to quit at any time')
while command_line_sequence = Readline.readline('> ', true)
run_command_line_sequence(command_line_sequence)
end
end
def run_command_line_sequence(command_line_sequence)
command_lines = command_line_sequence.split(";")
command_lines.each do |command_line|
run_command_line(command_line)
end
end
def run_command_line(command_line)
command, args = parse_command_line(command_line)
if command.nil?
return
elsif ['quit', 'exit'].include?(command)
emit("Goodbye!")
raise EinhornSHExit
end
send_command({'id' => request_id, 'command' => command, 'args' => args}) do |message|
$stdout.puts message
$stdout.flush
end
end
def request_id
@request_id += 1
end
def parse_command_line(command_line)
command, *args = Shellwords.shellsplit(command_line)
[command, args]
end
def reconnect
begin
@client = Einhorn::Client.for_path(@path_to_socket)
rescue Errno::ENOENT => e
# TODO: The exit here is a biit of a layering violation.
Einhorn::EinhornSH.emit(<<EOF, true)
Could not connect to Einhorn master process:
#{e}
HINT: Are you sure you are running an Einhorn master? If so, you
should pass einhornsh the cmd_name (-c argument) provided to Einhorn.
EOF
exit(1)
end
ehlo if interactive?
end
def ehlo
send_command({'command' => "ehlo", 'user' => ENV['USER']}) do |message|
emit(message)
end
end
def self.emit(message=nil, force=false)
$stderr.puts(message || '') if interactive? || force
end
def self.interactive?
$stdin.isatty
end
def emit(*args)
self.class.emit(*args)
end
def interactive?
self.class.interactive?
end
end
end
def main
options = {}
optparse = OptionParser.new do |opts|
opts.banner = "Usage: #{$0} [options] [cmd_name]
Welcome to Einhornsh: the Einhorn shell.
Pass the cmd_name of the Einhorn master you are connecting to either
as a positional argument or using `-c`. If you're running your Einhorn
with a `-d`, provide the same argument here."
opts.on('-h', '--help', 'Display this message') do
Einhorn::EinhornSH.emit(opts, true)
exit(1)
end
opts.on('-c CMD_NAME', '--command-name CMD_NAME', 'Connect to the Einhorn master with this cmd_name') do |cmd_name|
options[:cmd_name] = cmd_name
end
opts.on('-d PATH', '--socket-path PATH', 'Path to the Einhorn command socket') do |path|
options[:socket_path] = path
end
opts.on('-e CMD_LINE_SEQ', '--execute CMD_LINE_SEQ', 'Execute this command outside of interactive mode') do |cmd_line_seq|
options[:cmd_line_seq] = cmd_line_seq
end
end
optparse.parse!
if ARGV.length > 1
Einhorn::EinhornSH.emit(optparse, true)
return 1
end
Signal.trap("INT") do
Einhorn::EinhornSH.emit
exit(0)
end
path_to_socket = options[:socket_path]
unless path_to_socket
cmd_name = options[:cmd_name] || ARGV[0]
path_to_socket = Einhorn::Command::Interface.default_socket_path(cmd_name)
end
sh = Einhorn::EinhornSH.new(path_to_socket)
cmd_line_seq = options[:cmd_line_seq]
begin
cmd_line_seq ? sh.run_command_line_sequence(cmd_line_seq) : sh.run
rescue Einhorn::EinhornSH::EinhornSHExit => e
return 0
end
return 0
end
# Would be nice if this could be loadable rather than always
# executing, but when run under gem it's a bit hard to do so.
if true # $0 == __FILE__
ret = main
begin
exit(ret)
rescue TypeError
exit(0)
end
end
Jump to Line
Something went wrong with that request. Please try again.