lib/heel/server.rb in heel-2.0.0 vs lib/heel/server.rb in heel-3.0.0
- old
+ new
@@ -1,16 +1,15 @@
#--
-# Copyright (c) 2007, 2008 Jeremy Hinegardner
-# All rights reserved. Licensed under the BSD license. See LICENSE for details
+# Copyright (c) 2007 - 2013 Jeremy Hinegardner
+# All rights reserved. Licensed under the BSD license. See LICENSE for details
#++
-require 'heel'
-require 'thin'
require 'ostruct'
require 'launchy'
require 'fileutils'
require 'heel/rackapp'
+require 'puma'
module Heel
class Server
attr_accessor :options
@@ -37,38 +36,36 @@
def initialize(argv = [])
argv ||= []
set_io
- @options = default_options
- @parsed_options = ::OpenStruct.new
- @parser = option_parser
- @error_message = nil
+ @options = default_options
+ @parsed_options = ::OpenStruct.new
+ @parser = option_parser
+ @error_message = nil
begin
@parser.parse!(argv)
rescue ::OptionParser::ParseError => pe
msg = ["#{@parser.program_name}: #{pe}",
- "Try `#{@parser.program_name} --help` for more information"]
- @error_message = msg.join("\n")
+ "Try `#{@parser.program_name} --help` for more information"]
+ @error_message = msg.join("\n")
end
end
def default_options
- if @default_options.nil? then
- @default_options = ::OpenStruct.new
- @default_options.show_version = false
- @default_options.show_help = false
- @default_options.address = "0.0.0.0"
- @default_options.port = 4331
- @default_options.document_root = Dir.pwd
- @default_options.daemonize = false
- @default_options.highlighting = false
- @default_options.kill = false
- @default_options.launch_browser = true
- end
- return @default_options
+ defaults = ::OpenStruct.new
+ defaults.show_version = false
+ defaults.show_help = false
+ defaults.address = "0.0.0.0"
+ defaults.port = 4331
+ defaults.document_root = Dir.pwd
+ defaults.daemonize = false
+ defaults.highlighting = false
+ defaults.kill = false
+ defaults.launch_browser = true
+ return defaults
end
def default_directory
ENV["HEEL_DEFAULT_DIRECTORY"] || File.join(::Heel::Server.home_directory,".heel")
end
@@ -79,21 +76,30 @@
def log_file
File.join(default_directory,"heel.log")
end
+ def win?
+ RUBY_PLATFORM =~ /mswin|mingw/
+ end
+
+ def java?
+ RUBY_PLATFORM =~ /java/
+ end
+
def option_parser
OptionParser.new do |op|
op.separator ""
op.on("-a", "--address ADDRESS", "Address to bind to",
" (default: #{default_options.address})") do |add|
@parsed_options.address = add
- end
+ end
op.on("-d", "--daemonize", "Run daemonized in the background") do
- raise ::OptionParser::ParseError, "Daemonizing is not supported on windows" if Thin.win?
+ raise ::OptionParser::ParseError, "Daemonizing is not supported on windows" if win?
+ raise ::OptionParser::ParseError, "Daemonizing is not supported on java" if java?
@parsed_options.daemonize = true
end
op.on("-h", "--help", "Display this text") do
@parsed_options.show_help = true
@@ -104,39 +110,37 @@
end
op.on("--[no-]highlighting", "Turn on or off syntax highlighting",
" (default: off)") do |highlighting|
@parsed_options.highlighting = highlighting
- end
+ end
op.on("--[no-]launch-browser", "Turn on or off automatic browser launch",
" (default: on)") do |l|
@parsed_options.launch_browser = l
- end
+ end
op.on("-p", "--port PORT", Integer, "Port to bind to",
" (default: #{default_options.port})") do |port|
@parsed_options.port = port
- end
+ end
op.on("-r","--root ROOT",
"Set the document root"," (default: #{default_options.document_root})") do |document_root|
@parsed_options.document_root = File.expand_path(document_root)
raise ::OptionParser::ParseError, "#{@parsed_options.document_root} is not a valid directory" if not File.directory?(@parsed_options.document_root)
- end
+ end
op.on("-v", "--version", "Show version") do
@parsed_options.show_version = true
end
end
end
def merge_options
options = default_options.marshal_dump
- @parsed_options.marshal_dump.each_pair do |key,value|
- options[key] = value
- end
+ options.merge!( @parsed_options.marshal_dump )
@options = OpenStruct.new(options)
end
# set the IO objects in a single method call. This is really only for testing
@@ -172,11 +176,11 @@
@stdout.puts "Sending TERM to process #{pid}"
Process.kill("TERM", pid)
rescue Errno::ESRCH
@stdout.puts "Unable to kill process with pid #{pid}. Process does not exist. Removing stale pid file."
File.unlink(pid_file)
- rescue Errno::EPERM
+ rescue Errno::EPERM
@stdout.puts "Unable to kill process with pid #{pid}. No permissions to kill process."
end
else
@stdout.puts "No pid file exists, no process to kill"
end
@@ -195,97 +199,106 @@
end
# make sure that if we are daemonizing the process is not running
def ensure_not_running
if options.daemonize and File.exist?(pid_file) then
- @stdout.puts "ERROR: PID File #{pid_file} already exists. Heel may already be running."
+ @stdout.puts "ERROR: PID File #{pid_file} already exists. Heel may already be running."
@stdout.puts "ERROR: Check the Log file #{log_file}"
@stdout.puts "ERROR: Heel will not start until the .pid file is cleared (`heel --kill' to clean it up)."
exit 1
end
end
def launch_browser
- Thread.new do
+ Thread.new do
print "Launching your browser"
if options.daemonize then
puts " at http://#{options.address}:#{options.port}/"
else
puts "..."
end
::Launchy.open("http://#{options.address}:#{options.port}/")
end
end
- def thin_server
- server = Thin::Server.new(options.address, options.port)
-
- # overload the name of the process so it shows up as heel not thin
- def server.name
- "heel (v#{Heel::VERSION})"
- end
-
- server.pid_file = pid_file
- server.log_file = log_file
-
+ def heel_app
app = Heel::RackApp.new({ :document_root => options.document_root,
:highlighting => options.highlighting})
-
- Heel::Logger.log_file = log_file
- server.app = Rack::Builder.new {
- use Heel::Logger
- map "/" do
+ stack = Rack::Builder.new {
+ map "/" do
run app
end
map "/heel_css" do
run Rack::File.new(Heel::Configuration.data_path( "css" ))
end
map "/heel_icons" do
run Rack::File.new(Heel::Configuration.data_path("famfamfam", "icons"))
end
-
}
-
- server.app = Thin::Stats::Adapter.new(server.app, "/heel_stats")
+ return stack.to_app
+ end
- return server
+ def start_server
+ server_thread = Thread.new do
+ if options.daemonize then
+ if cpid = fork then
+ Process.waitpid( cpid )
+ else
+ server = Rack::Server.new( server_options )
+ server.start
+ end
+ else
+ server = Rack::Server.new( server_options )
+ server.start
+ end
+ end
+ return server_thread
end
- def start_thin_server
- server = thin_server
-
+ def start_server_old
+ server = Rack::Server.new( server_options )
server_thread = Thread.new do
- begin
- if options.daemonize then
- if cpid = fork then
- # wait for the top child of the server double fork to exit
- Process.waitpid(cpid)
- else
- server.daemonize
- server.start
- end
+ if options.daemonize then
+ if cpid = fork then
+ # wait for the server to span and then move on to launching the
+ # browser
+ Process.waitpid( cpid )
else
- begin
- server.start
- rescue RuntimeError
- $stderr.puts "ERROR: Unable to start server. Heel may already be running. Please check running processes or run `heel --kill'"
- exit 1
- end
+ server.start
end
+ else
+ begin
+ server.start
+ rescue RuntimeError
+ $stderr.puts "ERROR: Unable to start server. Heel may already be running. Please check running processes or run `heel --kill'"
+ exit 1
+ end
end
end
+ return server_thread
end
-
+ def server_options
+ {
+ :app => heel_app,
+ :pid => pid_file,
+ :Port => options.port,
+ :Host => options.address,
+ :environment => 'deployment',
+ :server => 'puma',
+ :daemonize => options.daemonize
+ }
+ end
+
# run the heel server with the current options.
def run
error_version_help_kill
merge_options
setup_heel_dir
ensure_not_running
- server_thread = start_thin_server
+ server_thread = start_server
if options.launch_browser then
launch_browser.join
end
server_thread.join