Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
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.