Skip to content
This repository has been archived by the owner on Sep 20, 2019. It is now read-only.

PTY support #5

Merged
merged 7 commits into from Oct 15, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions LICENSE.txt
@@ -1,4 +1,5 @@
Copyright (c) 2012 Keiji, Yoshimi
Copyright (c) 2012 Wu Jun <quark@lihdd.net>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
Expand Down
80 changes: 80 additions & 0 deletions README.md
@@ -0,0 +1,80 @@
# rrails

Preload rails environment in Remote server to make rails/rake commands faster.

## Requirements

* non-Windows OS
* Ruby 1.9.3

## Usage

Start server:

$ cd ~/rails_project
$ export RAILS_ENV=development # optionally
$ bundle exec rrails-server

Run rails/rake commands using rrails:

$ export RAILS_ENV=development # optionally
$ rrails -- rails generate model Yakiniku
$ rrails -- rake db:migrate
$ rrails -- rake routes
$ rrails -- rails server
$ rrails -- rails console
$ rrails -- pry # start pry as rails console

# If you need an interactive console for non rails *console
# commands, you may want to add '--pty' option.
# This makes sure that interactive things (like line editing)
# work correctly, but it also redirect all STDERR to STDOUT
# and keys like ^C may not work correctly.
$ rrails --pty -- rails server # use debugger

You may want to add following code to your shell rc file:

rrails-exec() {
if pgrep -f rrails-server >/dev/null && grep -q rrails Gemfile.lock &>/dev/null; then
rrails -- "$@"
else
command "$@"
fi
}
alias rails='rrails-exec rails'
alias rake='rrails-exec rake'

## Description

rails command is too slow. and rake command is too slow under rails environment.
So, rrails can run rails/rake commands by preloaded daemon.

rails-sh is very good solution for this issue. But

* it can't run "rake -T"
* it can't use zsh's histroy.

So I wrote rrails.

## See Also

* guard-rrails: https://github.com/walf443/guard-rrails
* rails-sh: https://github.com/jugyo/rails-sh

## Contributing to rrails

* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
* Fork the project.
* Start a feature/bugfix branch.
* Commit and push until you are happy with your contribution.
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.

## Copyright

Copyright (c) 2012 Keiji, Yoshimi. <br>
Copyright (c) 2012 Wu Jun.

See LICENSE.txt for further details.

51 changes: 0 additions & 51 deletions README.rdoc

This file was deleted.

83 changes: 66 additions & 17 deletions lib/rrails/client.rb
Expand Up @@ -2,50 +2,99 @@
require 'rrails'
require 'shellwords'
require 'optparse'
require 'io/console'

module RemoteRails
#
# client for RemoteRails::Server.
#
# @example
# client = RemoteRails::Client.new({
# :cmd => "rails generate model Sushi",
# :rails_env => "development",
# :port => 5656,
# :host => 'localhost'
# })
# client.run
#
class Client
def self.opts_parser(options = {})
opts = OptionParser.new
opts.banner = 'Usage: rrails [options] [[--] commands]'
opts.on('-h', '--host=s', 'RRails server hostname. Default value is "localhost".') {|v| options[:host] = v }
opts.on('-p', '--port=i', 'RRails server port. Default value is decided from RAILS_ENV.') {|v| options[:port] = v }
opts.on('-t', '--[no-]pty', "Prepare a PTY. Default value is decided by commands.") {|v| options[:pty] = v }
return opts
end

def self.new_with_options(argv)
options = {}
opts = OptionParser.new
opts.on('-E', '--rails_env=s') {|v| options[:rails_env] = v }
opts.on('-p', '--port=i') {|v| options[:port] = v }
opts.parse!(argv)
opts_parser(options).parse!(argv)

cmd = Shellwords.join(argv)
options[:cmd] = cmd == "" ? nil : cmd
self.new(options)
end

def initialize(options={})
@cmd = options[:cmd] || "rails"
@rails_env = options[:rails_env] || 'development'
@cmd = options[:cmd] || ""
@host = options[:host] || 'localhost'
@port = options[:port] || DEFAULT_PORT[@rails_env]
@port = options[:port] || DEFAULT_PORT[ENV['RAILS_ENV'] || 'development']
@use_pty = options[:pty]
if @use_pty.nil?
# decide use_pty from cmd
case @cmd
when /^rails (?:c(?:onsole)?|db(?:console)?)$/, 'pry'
@use_pty = true
end
end
end

def run
if @cmd.empty?
STDERR.puts Client.opts_parser
return
end

sock = TCPSocket.open(@host, @port)
sock.puts(@cmd)
while line = sock.gets
if line =~ /^FINISHED\t(.+)/
$stdout.puts("\nfinished (#{$1}sec)")
return
elsif line =~ /^OUT\t(.+)$/
$stdout.puts($1)
elsif line =~ /^ERROR\t(.+)$/
$stderr.puts($1)
sock.puts("#{@use_pty ? 'P' : ' '}#@cmd")
running = true

begin
# input thread
thread = Thread.start do
while running do
begin
input = @use_pty ? STDIN.getch : STDIN.gets
sock.write(input)
sock.flush
rescue
running = false
sock.close unless sock.closed?
end
end
end

while running && line = sock.gets
case line.chomp
when /^EXIT\t(.+)$/
exit($1.to_i)
when /^OUT\t(.+)$/
STDOUT.write($1.split(',').map(&:to_i).pack('c*'))
when /^ERR\t(.+)$/
STDERR.write($1.split(',').map(&:to_i).pack('c*'))
end
end

rescue EOFError
running = false
rescue Interrupt
running = false
exit 130
end

STDERR.puts "\nERROR: RRails server disconnected"
exit -1
end

end
end