reloading fixes

This commit is contained in:
Thomas Reynolds 2012-09-13 10:13:57 -07:00
parent 266e24e03e
commit 345e7787b5
3 changed files with 73 additions and 35 deletions

View file

@ -1,6 +1,15 @@
Master Master
=== ===
3.0.3
====
* Add reload_paths to server CLI to add additional paths to reload MM on change.
* Re-organize app reloading code, don't need to restart listen every time.
3.0.2
====
* Logger has no such method .warning. Closes #582
3.0.1 3.0.1
==== ====
* HTML5 Boilerplate version 4.0.0 * HTML5 Boilerplate version 4.0.0

View file

@ -37,6 +37,10 @@ module Middleman::Cli
:type => :boolean, :type => :boolean,
:default => false, :default => false,
:desc => 'Generate profiling report for server startup' :desc => 'Generate profiling report for server startup'
method_option :reload_paths,
:type => :string,
:default => false,
:desc => 'Additional paths to auto-reload when files change'
# Start the server # Start the server
def server def server
@ -56,7 +60,8 @@ module Middleman::Cli
:environment => options["environment"], :environment => options["environment"],
:debug => options["verbose"], :debug => options["verbose"],
:instrumenting => options["instrument"], :instrumenting => options["instrument"],
:"disable-watcher" => options["disable-watcher"] :"disable-watcher" => options["disable-watcher"],
:reload_paths => options["reload_paths"]
} }
puts "== The Middleman is loading" puts "== The Middleman is loading"

View file

@ -9,33 +9,19 @@ module Middleman
DEFAULT_PORT = 4567 DEFAULT_PORT = 4567
class << self class << self
attr_reader :app attr_reader :app, :port
delegate :logger, :to => :app delegate :logger, :to => :app
# Start an instance of Middleman::Application # Start an instance of Middleman::Application
# @return [void] # @return [void]
def start(options={}) def start(opts={})
@app = ::Middleman::Application.server.inst do @options = opts
if options[:environment] @port = @options[:port] || DEFAULT_PORT
set :environment, options[:environment].to_sym
end
logger(options[:debug] ? 0 : 1, options[:instrumenting] || false)
end
port = options[:port] || DEFAULT_PORT
mount_instance
logger.info "== The Middleman is standing watch on port #{port}" logger.info "== The Middleman is standing watch on port #{port}"
@webrick ||= setup_webrick( start_file_watcher unless @options[:"disable-watcher"]
options[:host] || "0.0.0.0",
port,
options[:debug] || false
)
mount_instance(app)
start_file_watcher unless options[:"disable-watcher"]
@initialized ||= false @initialized ||= false
unless @initialized unless @initialized
@ -43,9 +29,8 @@ module Middleman
register_signal_handlers unless ::Middleman::WINDOWS register_signal_handlers unless ::Middleman::WINDOWS
# Save the last-used options so it may be re-used when # Save the last-used @options so it may be re-used when
# reloading later on. # reloading later on.
@last_options = options
::Middleman::Profiling.report("server_start") ::Middleman::Profiling.report("server_start")
@webrick.start @webrick.start
@ -66,8 +51,12 @@ module Middleman
# Simply stop, then start the server # Simply stop, then start the server
# @return [void] # @return [void]
def reload def reload
stop logger.info "== The Middleman is reloading"
start @last_options
unmount_instance
mount_instance
logger.info "== The Middleman is standing watch on port #{port}"
end end
# Stop the current instance, exit Webrick # Stop the current instance, exit Webrick
@ -78,6 +67,16 @@ module Middleman
end end
private private
def new_app
opts = @options
@app =::Middleman::Application.server.inst do
if opts[:environment]
set :environment, opts[:environment].to_sym
end
logger(opts[:debug] ? 0 : 1, opts[:instrumenting] || false)
end
end
def start_file_watcher def start_file_watcher
# Watcher Library # Watcher Library
@ -99,7 +98,7 @@ module Middleman
# Otherwise forward to Middleman # Otherwise forward to Middleman
added_and_modified.each do |path| added_and_modified.each do |path|
@app.files.did_change(path) app.files.did_change(path)
end end
end end
@ -112,7 +111,7 @@ module Middleman
# Otherwise forward to Middleman # Otherwise forward to Middleman
removed.each do |path| removed.each do |path|
@app.files.did_delete(path) app.files.did_delete(path)
end end
end end
end end
@ -131,13 +130,12 @@ module Middleman
# Initialize webrick # Initialize webrick
# @return [void] # @return [void]
def setup_webrick(host, port, is_logging) def setup_webrick(host, is_logging)
@host = host @host = host
@port = port
http_opts = { http_opts = {
:BindAddress => @host, :BindAddress => @host,
:Port => @port, :Port => port,
:AccessLog => [] :AccessLog => []
} }
@ -147,15 +145,27 @@ module Middleman
http_opts[:Logger] = ::WEBrick::Log.new(nil, 0) http_opts[:Logger] = ::WEBrick::Log.new(nil, 0)
end end
::WEBrick::HTTPServer.new(http_opts) begin
::WEBrick::HTTPServer.new(http_opts)
rescue Errno::EADDRINUSE => e
logger.error "== Port #{port} is unavailable. Either close the instance of Middleman already running on #{port} or start this Middleman on a new port with: --port=#{port.to_i+1}"
exit(1)
end
end end
# Attach a new Middleman::Application instance # Attach a new Middleman::Application instance
# @param [Middleman::Application] app # @param [Middleman::Application] app
# @return [void] # @return [void]
def mount_instance(app) def mount_instance
@app = app @app = new_app
@webrick.mount "/", ::Rack::Handler::WEBrick, @app.class.to_rack_app @webrick ||= setup_webrick(
@options[:host] || "0.0.0.0",
@options[:debug] || false
)
@app = new_app
@webrick.mount "/", ::Rack::Handler::WEBrick, app.class.to_rack_app
end end
# Detach the current Middleman::Application instance # Detach the current Middleman::Application instance
@ -169,8 +179,22 @@ module Middleman
# @param [Array<String>] paths Array of paths to check # @param [Array<String>] paths Array of paths to check
# @return [Boolean] Whether the server needs to reload # @return [Boolean] Whether the server needs to reload
def needs_to_reload?(paths) def needs_to_reload?(paths)
match_against = [
%r{^config\.rb},
%r{^lib/^[^\.](.*)\.rb$},
%r{^helpers/^[^\.](.*)_helper\.rb$}
]
if @options[:reload_paths]
@options[:reload_paths].split(',').each do |part|
match_against << %r{^#{part}}
end
end
paths.any? do |path| paths.any? do |path|
path.match(%{^config\.rb}) || path.match(%r{^lib/^[^\.](.*)\.rb$}) || path.match(%r{^helpers/^[^\.](.*)_helper\.rb$}) match_against.any? do |matcher|
path.match(matcher)
end
end end
end end
end end