Merge pull request #436 from middleman/rack_reloader
Rely on Webrick directly for preview, makes quick app reloading simple.
This commit is contained in:
commit
c117415913
|
@ -123,7 +123,7 @@ module Middleman
|
||||||
include Middleman::CoreExtensions::Extensions
|
include Middleman::CoreExtensions::Extensions
|
||||||
|
|
||||||
# Basic Rack Request Handling
|
# Basic Rack Request Handling
|
||||||
register Middleman::CoreExtensions::Request
|
include Middleman::CoreExtensions::Request
|
||||||
|
|
||||||
# Handle exceptions
|
# Handle exceptions
|
||||||
register Middleman::CoreExtensions::ShowExceptions
|
register Middleman::CoreExtensions::ShowExceptions
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
require "middleman-core/watcher"
|
require "middleman-core/preview_server"
|
||||||
|
|
||||||
# CLI Module
|
# CLI Module
|
||||||
module Middleman::Cli
|
module Middleman::Cli
|
||||||
|
@ -50,7 +50,7 @@ module Middleman::Cli
|
||||||
}
|
}
|
||||||
|
|
||||||
puts "== The Middleman is loading"
|
puts "== The Middleman is loading"
|
||||||
Middleman::Watcher.start(params)
|
Middleman::PreviewServer.start(params)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ module Middleman
|
||||||
# Register extension
|
# Register extension
|
||||||
class << self
|
class << self
|
||||||
# @private
|
# @private
|
||||||
def included(app)
|
def registered(app)
|
||||||
# Using for version parsing
|
# Using for version parsing
|
||||||
require "rubygems"
|
require "rubygems"
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ module Middleman
|
||||||
app.send :include, InstanceMethods
|
app.send :include, InstanceMethods
|
||||||
app.delegate :configure, :to => :"self.class"
|
app.delegate :configure, :to => :"self.class"
|
||||||
end
|
end
|
||||||
|
alias :included :registered
|
||||||
end
|
end
|
||||||
|
|
||||||
# Class methods
|
# Class methods
|
||||||
|
|
|
@ -1,29 +1,40 @@
|
||||||
|
require "find"
|
||||||
|
require "set"
|
||||||
|
|
||||||
# API for watching file change events
|
# API for watching file change events
|
||||||
module Middleman
|
module Middleman
|
||||||
module CoreExtensions
|
module CoreExtensions
|
||||||
module FileWatcher
|
module FileWatcher
|
||||||
|
|
||||||
|
IGNORE_LIST = [
|
||||||
|
/^\.sass-cache\//,
|
||||||
|
/^\.git\//,
|
||||||
|
/^\.gitignore$/,
|
||||||
|
/^\.DS_Store$/,
|
||||||
|
/^build\//,
|
||||||
|
/^\.rbenv-.*$/,
|
||||||
|
/^Gemfile$/,
|
||||||
|
/^Gemfile\.lock$/,
|
||||||
|
/~$/
|
||||||
|
]
|
||||||
|
|
||||||
# Setup extension
|
# Setup extension
|
||||||
class << self
|
class << self
|
||||||
|
|
||||||
# Once registered
|
# Once registered
|
||||||
def registered(app)
|
def registered(app)
|
||||||
require "find"
|
|
||||||
require "middleman-core/watcher"
|
|
||||||
require "set"
|
|
||||||
|
|
||||||
app.extend ClassMethods
|
app.extend ClassMethods
|
||||||
app.send :include, InstanceMethods
|
app.send :include, InstanceMethods
|
||||||
|
|
||||||
# Before parsing config, load the data/ directory
|
# Before parsing config, load the data/ directory
|
||||||
app.before_configuration do
|
app.before_configuration do
|
||||||
data_path = File.join(self.root, self.data_dir)
|
data_path = File.join(root, data_dir)
|
||||||
self.files.reload_path(data_path) if File.exists?(data_path)
|
files.reload_path(data_path) if File.exists?(data_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
# After config, load everything else
|
# After config, load everything else
|
||||||
app.ready do
|
app.ready do
|
||||||
self.files.reload_path(self.root)
|
files.reload_path(root)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
alias :included :registered
|
alias :included :registered
|
||||||
|
@ -45,19 +56,20 @@ module Middleman
|
||||||
# Access the file api
|
# Access the file api
|
||||||
# @return [Middleman::CoreExtensions::FileWatcher::API]
|
# @return [Middleman::CoreExtensions::FileWatcher::API]
|
||||||
def files
|
def files
|
||||||
api = self.class.files
|
@_files_api ||= API.new(self)
|
||||||
api.instance ||= self
|
|
||||||
api
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Core File Change API class
|
# Core File Change API class
|
||||||
class API
|
class API
|
||||||
attr_accessor :instance, :known_paths
|
|
||||||
|
|
||||||
# Initialize api and internal path cache
|
# Initialize api and internal path cache
|
||||||
def initialize
|
def initialize(app)
|
||||||
self.known_paths = Set.new
|
@app = app
|
||||||
|
@known_paths = Set.new
|
||||||
|
|
||||||
|
@_changed = []
|
||||||
|
@_deleted = []
|
||||||
end
|
end
|
||||||
|
|
||||||
# Add callback to be run on file change
|
# Add callback to be run on file change
|
||||||
|
@ -65,7 +77,6 @@ module Middleman
|
||||||
# @param [nil,Regexp] matcher A Regexp to match the change path against
|
# @param [nil,Regexp] matcher A Regexp to match the change path against
|
||||||
# @return [Array<Proc>]
|
# @return [Array<Proc>]
|
||||||
def changed(matcher=nil, &block)
|
def changed(matcher=nil, &block)
|
||||||
@_changed ||= []
|
|
||||||
@_changed << [block, matcher] if block_given?
|
@_changed << [block, matcher] if block_given?
|
||||||
@_changed
|
@_changed
|
||||||
end
|
end
|
||||||
|
@ -75,7 +86,6 @@ module Middleman
|
||||||
# @param [nil,Regexp] matcher A Regexp to match the deleted path against
|
# @param [nil,Regexp] matcher A Regexp to match the deleted path against
|
||||||
# @return [Array<Proc>]
|
# @return [Array<Proc>]
|
||||||
def deleted(matcher=nil, &block)
|
def deleted(matcher=nil, &block)
|
||||||
@_deleted ||= []
|
|
||||||
@_deleted << [block, matcher] if block_given?
|
@_deleted << [block, matcher] if block_given?
|
||||||
@_deleted
|
@_deleted
|
||||||
end
|
end
|
||||||
|
@ -85,8 +95,9 @@ module Middleman
|
||||||
# @param [String] path The file that changed
|
# @param [String] path The file that changed
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def did_change(path)
|
def did_change(path)
|
||||||
puts "== File Change: #{path}" if instance.logging? && !::Middleman::Watcher.ignore_list.any? { |r| path.match(r) }
|
return if IGNORE_LIST.any? { |r| path.match(r) }
|
||||||
self.known_paths << path
|
puts "== File Change: #{path}" if @app.logging?
|
||||||
|
@known_paths << path
|
||||||
self.run_callbacks(path, :changed)
|
self.run_callbacks(path, :changed)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -95,8 +106,9 @@ module Middleman
|
||||||
# @param [String] path The file that was deleted
|
# @param [String] path The file that was deleted
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def did_delete(path)
|
def did_delete(path)
|
||||||
puts "== File Deletion: #{path}" if instance.logging? && !::Middleman::Watcher.ignore_list.any? { |r| path.match(r) }
|
return if IGNORE_LIST.any? { |r| path.match(r) }
|
||||||
self.known_paths.delete(path)
|
puts "== File Deletion: #{path}" if @app.logging?
|
||||||
|
@known_paths.delete(path)
|
||||||
self.run_callbacks(path, :deleted)
|
self.run_callbacks(path, :deleted)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -105,13 +117,12 @@ module Middleman
|
||||||
# @param [String] path The path to reload
|
# @param [String] path The path to reload
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def reload_path(path)
|
def reload_path(path)
|
||||||
relative_path = path.sub("#{self.instance.root}/", "")
|
relative_path = path.sub("#{@app.root}/", "")
|
||||||
subset = self.known_paths.select { |p| p.match(%r{^#{relative_path}}) }
|
subset = @known_paths.select { |p| p.match(%r{^#{relative_path}}) }
|
||||||
|
|
||||||
Find.find(path) do |path|
|
Find.find(path) do |path|
|
||||||
next if File.directory?(path)
|
next if File.directory?(path)
|
||||||
next if Middleman::Watcher.ignore_list.any? { |r| path.match(r) }
|
relative_path = path.sub("#{@app.root}/", "")
|
||||||
relative_path = path.sub("#{self.instance.root}/", "")
|
|
||||||
subset.delete(relative_path)
|
subset.delete(relative_path)
|
||||||
self.did_change(relative_path)
|
self.did_change(relative_path)
|
||||||
end if File.exists?(path)
|
end if File.exists?(path)
|
||||||
|
@ -126,13 +137,12 @@ module Middleman
|
||||||
# @param [String] path The path to reload
|
# @param [String] path The path to reload
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def find_new_files(path)
|
def find_new_files(path)
|
||||||
relative_path = path.sub("#{self.instance.root}/", "")
|
relative_path = path.sub("#{@app.root}/", "")
|
||||||
subset = self.known_paths.select { |p| p.match(%r{^#{relative_path}}) }
|
subset = @known_paths.select { |p| p.match(%r{^#{relative_path}}) }
|
||||||
|
|
||||||
Find.find(path) do |file|
|
Find.find(path) do |file|
|
||||||
next if File.directory?(file)
|
next if File.directory?(file)
|
||||||
next if Middleman::Watcher.ignore_list.any? { |r| path.match(r) }
|
relative_path = file.sub("#{@app.root}/", "")
|
||||||
relative_path = file.sub("#{self.instance.root}/", "")
|
|
||||||
self.did_change(relative_path) unless subset.include?(relative_path)
|
self.did_change(relative_path) unless subset.include?(relative_path)
|
||||||
end if File.exists?(path)
|
end if File.exists?(path)
|
||||||
end
|
end
|
||||||
|
@ -144,12 +154,10 @@ module Middleman
|
||||||
# @param [Symbol] callbacks_name The name of the callbacks method
|
# @param [Symbol] callbacks_name The name of the callbacks method
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def run_callbacks(path, callbacks_name)
|
def run_callbacks(path, callbacks_name)
|
||||||
return if ::Middleman::Watcher.ignore_list.any? { |r| path.match(r) }
|
|
||||||
|
|
||||||
self.send(callbacks_name).each do |callback, matcher|
|
self.send(callbacks_name).each do |callback, matcher|
|
||||||
next if path.match(%r{^#{self.instance.build_dir}/})
|
next if path.match(%r{^#{@app.build_dir}/})
|
||||||
next unless matcher.nil? || path.match(matcher)
|
next unless matcher.nil? || path.match(matcher)
|
||||||
self.instance.instance_exec(path, &callback)
|
@app.instance_exec(path, &callback)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
# Built on Rack
|
||||||
|
require "rack"
|
||||||
|
require "rack/file"
|
||||||
|
|
||||||
module Middleman
|
module Middleman
|
||||||
module CoreExtensions
|
module CoreExtensions
|
||||||
|
|
||||||
|
@ -8,9 +12,6 @@ module Middleman
|
||||||
class << self
|
class << self
|
||||||
# @private
|
# @private
|
||||||
def registered(app)
|
def registered(app)
|
||||||
# Built on Rack
|
|
||||||
require "rack"
|
|
||||||
require "rack/file"
|
|
||||||
|
|
||||||
# CSSPIE HTC File
|
# CSSPIE HTC File
|
||||||
::Rack::Mime::MIME_TYPES['.html'] = 'text/x-component'
|
::Rack::Mime::MIME_TYPES['.html'] = 'text/x-component'
|
||||||
|
@ -18,7 +19,6 @@ module Middleman
|
||||||
# Let's serve all HTML as UTF-8
|
# Let's serve all HTML as UTF-8
|
||||||
::Rack::Mime::MIME_TYPES['.html'] = 'text/html;charset=utf8'
|
::Rack::Mime::MIME_TYPES['.html'] = 'text/html;charset=utf8'
|
||||||
::Rack::Mime::MIME_TYPES['.htm'] = 'text/html;charset=utf8'
|
::Rack::Mime::MIME_TYPES['.htm'] = 'text/html;charset=utf8'
|
||||||
|
|
||||||
|
|
||||||
app.extend ClassMethods
|
app.extend ClassMethods
|
||||||
app.extend ServerMethods
|
app.extend ServerMethods
|
||||||
|
@ -133,30 +133,8 @@ module Middleman
|
||||||
@@servercounter += 1
|
@@servercounter += 1
|
||||||
const_set("MiddlemanApplication#{@@servercounter}", Class.new(Middleman::Application))
|
const_set("MiddlemanApplication#{@@servercounter}", Class.new(Middleman::Application))
|
||||||
end
|
end
|
||||||
|
|
||||||
# Creates a new Rack::Server
|
|
||||||
#
|
|
||||||
# @param [Hash] options to pass to Rack::Server.new
|
|
||||||
# @return [Rack::Server]
|
|
||||||
def start_server(options={})
|
|
||||||
opts = {
|
|
||||||
:Port => options[:port] || 4567,
|
|
||||||
:Host => options[:host] || "0.0.0.0",
|
|
||||||
:AccessLog => []
|
|
||||||
}
|
|
||||||
|
|
||||||
app_class = options[:app] ||= ::Middleman.server.inst
|
|
||||||
opts[:app] = app_class
|
|
||||||
|
|
||||||
require "webrick"
|
|
||||||
opts[:Logger] = WEBrick::Log::new(nil, 0) if !options[:logging]
|
|
||||||
opts[:server] = 'webrick'
|
|
||||||
|
|
||||||
server = ::Rack::Server.new(opts)
|
|
||||||
server.start
|
|
||||||
server
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Methods to be mixed-in to Middleman::Application
|
# Methods to be mixed-in to Middleman::Application
|
||||||
module InstanceMethods
|
module InstanceMethods
|
||||||
# Backwards-compatibility with old request.path signature
|
# Backwards-compatibility with old request.path signature
|
||||||
|
@ -212,22 +190,6 @@ module Middleman
|
||||||
end
|
end
|
||||||
|
|
||||||
def call(env)
|
def call(env)
|
||||||
# Keep `__middleman__` messaging to this thread
|
|
||||||
if env["PATH_INFO"] == "/__middleman__"
|
|
||||||
if env["REQUEST_METHOD"] == "POST"
|
|
||||||
req = ::Rack::Request.new(env)
|
|
||||||
if req.params.has_key?("change")
|
|
||||||
self.files.did_change(req.params["change"])
|
|
||||||
elsif req.params.has_key?("delete")
|
|
||||||
self.files.did_delete(req.params["delete"])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
res = ::Rack::Response.new
|
|
||||||
res.status = 200
|
|
||||||
return res.finish
|
|
||||||
end
|
|
||||||
|
|
||||||
dup.call!(env)
|
dup.call!(env)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
161
middleman-core/lib/middleman-core/preview_server.rb
Normal file
161
middleman-core/lib/middleman-core/preview_server.rb
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
module Middleman
|
||||||
|
|
||||||
|
WINDOWS = !!(RUBY_PLATFORM =~ /(mingw|bccwin|wince|mswin32)/i) unless const_defined?(:WINDOWS)
|
||||||
|
|
||||||
|
module PreviewServer
|
||||||
|
|
||||||
|
DEFAULT_PORT = 4567
|
||||||
|
|
||||||
|
class << self
|
||||||
|
|
||||||
|
# Start an instance of Middleman::Application
|
||||||
|
# @return [void]
|
||||||
|
def start(options={})
|
||||||
|
require "webrick"
|
||||||
|
|
||||||
|
@first_run ||= true
|
||||||
|
|
||||||
|
app = ::Middleman::Application.server.inst do
|
||||||
|
if options[:environment]
|
||||||
|
set :environment, options[:environment]
|
||||||
|
end
|
||||||
|
|
||||||
|
if options[:debug]
|
||||||
|
set :logging, true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "== The Middleman is standing watch on port #{options[:port]||4567}"
|
||||||
|
|
||||||
|
@webrick_is_running ||= false
|
||||||
|
@webrick ||= setup_webrick(
|
||||||
|
options[:host] || "0.0.0.0",
|
||||||
|
options[:port] || DEFAULT_PORT,
|
||||||
|
options[:debug] || false
|
||||||
|
)
|
||||||
|
|
||||||
|
mount_instance(app)
|
||||||
|
|
||||||
|
if @first_run
|
||||||
|
@first_run = false
|
||||||
|
|
||||||
|
register_signal_handlers unless ::Middleman::WINDOWS
|
||||||
|
|
||||||
|
start_file_watcher unless options[:"disable-watcher"]
|
||||||
|
|
||||||
|
@webrick.start
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Detach the current Middleman::Application instance
|
||||||
|
# @return [void]
|
||||||
|
def stop
|
||||||
|
puts "== The Middleman is shutting down"
|
||||||
|
unmount_instance
|
||||||
|
end
|
||||||
|
|
||||||
|
# Simply stop, then start the server
|
||||||
|
# @return [void]
|
||||||
|
def reload
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
end
|
||||||
|
|
||||||
|
# Stop the current instance, exit Webrick
|
||||||
|
# @return [void]
|
||||||
|
def shutdown
|
||||||
|
stop
|
||||||
|
@webrick.shutdown
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def start_file_watcher
|
||||||
|
preview_server = self
|
||||||
|
|
||||||
|
# Watcher Library
|
||||||
|
require "listen"
|
||||||
|
|
||||||
|
listener = Listen.to(Dir.pwd, :relative_paths => true)
|
||||||
|
|
||||||
|
listener.change do |modified, added, removed|
|
||||||
|
added_and_modified = (modified + added)
|
||||||
|
|
||||||
|
if added_and_modified.length > 0
|
||||||
|
# See if the changed file is config.rb or lib/*.rb
|
||||||
|
return reload if needs_to_reload?(added_and_modified)
|
||||||
|
|
||||||
|
# Otherwise forward to Middleman
|
||||||
|
paths.each do |path|
|
||||||
|
@app.files.did_change(path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if removed.length > 0
|
||||||
|
# See if the changed file is config.rb or lib/*.rb
|
||||||
|
return reload if needs_to_reload?(removed)
|
||||||
|
|
||||||
|
# Otherwise forward to Middleman
|
||||||
|
removed.each do |path|
|
||||||
|
@app.files.did_delete(path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Don't block this thread
|
||||||
|
listener.start(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Trap the interupt signal and shut down smoothly
|
||||||
|
# @return [void]
|
||||||
|
def register_signal_handlers
|
||||||
|
trap("INT") { shutdown }
|
||||||
|
trap("TERM") { shutdown }
|
||||||
|
trap("QUIT") { shutdown }
|
||||||
|
end
|
||||||
|
|
||||||
|
# Initialize webrick
|
||||||
|
# @return [void]
|
||||||
|
def setup_webrick(host, port, is_logging)
|
||||||
|
@host = host
|
||||||
|
@port = port
|
||||||
|
|
||||||
|
http_opts = {
|
||||||
|
:BindAddress => @host,
|
||||||
|
:Port => @port,
|
||||||
|
:AccessLog => []
|
||||||
|
}
|
||||||
|
|
||||||
|
unless is_logging
|
||||||
|
http_opts[:Logger] = ::WEBrick::Log::new(nil, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
::WEBrick::HTTPServer.new(http_opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Attach a new Middleman::Application instance
|
||||||
|
# @param [Middleman::Application] app
|
||||||
|
# @return [void]
|
||||||
|
def mount_instance(app)
|
||||||
|
@app = app
|
||||||
|
@webrick.mount "/", ::Rack::Handler::WEBrick, @app.class.to_rack_app
|
||||||
|
end
|
||||||
|
|
||||||
|
# Detach the current Middleman::Application instance
|
||||||
|
# @return [void]
|
||||||
|
def unmount_instance
|
||||||
|
@webrick.unmount "/"
|
||||||
|
@app = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
# Whether the passed files are config.rb, lib/*.rb or helpers
|
||||||
|
# @param [Array<String>] paths Array of paths to check
|
||||||
|
# @return [Boolean] Whether the server needs to reload
|
||||||
|
def needs_to_reload?(paths)
|
||||||
|
paths.any? do |path|
|
||||||
|
path.match(%{^config\.rb}) || path.match(%r{^lib/^[^\.](.*)\.rb$}) || path.match(%r{^helpers/^[^\.](.*)_helper\.rb$})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,149 +0,0 @@
|
||||||
# File changes are forwarded to the currently running app via HTTP
|
|
||||||
require "net/http"
|
|
||||||
require "fileutils"
|
|
||||||
|
|
||||||
module Middleman
|
|
||||||
WINDOWS = !!(RUBY_PLATFORM =~ /(mingw|bccwin|wince|mswin32)/i) unless const_defined?(:WINDOWS)
|
|
||||||
end
|
|
||||||
|
|
||||||
module Middleman
|
|
||||||
class Watcher
|
|
||||||
class << self
|
|
||||||
attr_accessor :singleton
|
|
||||||
|
|
||||||
def start(options)
|
|
||||||
self.singleton = new(options)
|
|
||||||
self.singleton.watch! unless options[:"disable-watcher"]
|
|
||||||
self.singleton.start
|
|
||||||
end
|
|
||||||
|
|
||||||
def ignore_list
|
|
||||||
[
|
|
||||||
/^\.sass-cache\//,
|
|
||||||
/^\.git\//,
|
|
||||||
/^\.gitignore$/,
|
|
||||||
/^\.DS_Store$/,
|
|
||||||
/^build\//,
|
|
||||||
/^\.rbenv-.*$/,
|
|
||||||
/^Gemfile$/,
|
|
||||||
/^Gemfile\.lock$/,
|
|
||||||
/~$/
|
|
||||||
]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize(options)
|
|
||||||
@options = options
|
|
||||||
register_signal_handlers unless ::Middleman::WINDOWS
|
|
||||||
end
|
|
||||||
|
|
||||||
def watch!
|
|
||||||
local = self
|
|
||||||
|
|
||||||
# Watcher Library
|
|
||||||
require "listen"
|
|
||||||
|
|
||||||
listener = Listen.to(Dir.pwd, :relative_paths => true)
|
|
||||||
listener.change do |modified, added, removed|
|
|
||||||
added_and_modified = modified + added
|
|
||||||
|
|
||||||
if added_and_modified.length > 0
|
|
||||||
local.run_on_change(added_and_modified)
|
|
||||||
end
|
|
||||||
|
|
||||||
if removed.length > 0
|
|
||||||
local.run_on_deletion(removed)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
# Don't block this thread
|
|
||||||
listener.start(false)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Start an instance of Middleman::Application
|
|
||||||
# @return [void]
|
|
||||||
def start
|
|
||||||
env = (@options[:environment] || "development").to_sym
|
|
||||||
is_logging = @options.has_key?(:debug) && @options[:debug]
|
|
||||||
|
|
||||||
app = ::Middleman::Application.server.inst do
|
|
||||||
set :environment, env
|
|
||||||
set :logging, is_logging
|
|
||||||
end
|
|
||||||
|
|
||||||
app_rack = app.class.to_rack_app
|
|
||||||
|
|
||||||
opts = @options.dup
|
|
||||||
opts[:app] = app_rack
|
|
||||||
opts[:logging] = is_logging
|
|
||||||
puts "== The Middleman is standing watch on port #{opts[:port]||4567}"
|
|
||||||
::Middleman::Application.start_server(opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Stop the forked Middleman
|
|
||||||
# @return [void]
|
|
||||||
def stop
|
|
||||||
puts "== The Middleman is shutting down"
|
|
||||||
# TODO: Figure out some way to actually unload the whole thing
|
|
||||||
# or maybe just re-exec this same thing
|
|
||||||
end
|
|
||||||
|
|
||||||
# Simply stop, then start
|
|
||||||
# @return [void]
|
|
||||||
def reload
|
|
||||||
stop
|
|
||||||
start
|
|
||||||
end
|
|
||||||
|
|
||||||
# What to do on file change
|
|
||||||
# @param [Array<String>] paths Array of paths that changed
|
|
||||||
# @return [void]
|
|
||||||
def run_on_change(paths)
|
|
||||||
# See if the changed file is config.rb or lib/*.rb
|
|
||||||
return reload if needs_to_reload?(paths)
|
|
||||||
|
|
||||||
# Otherwise forward to Middleman
|
|
||||||
paths.each do |path|
|
|
||||||
tell_server(:change => path) unless self.class.ignore_list.any? { |r| path.match(r) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# What to do on file deletion
|
|
||||||
# @param [Array<String>] paths Array of paths that were removed
|
|
||||||
# @return [void]
|
|
||||||
def run_on_deletion(paths)
|
|
||||||
# See if the changed file is config.rb or lib/*.rb
|
|
||||||
return reload if needs_to_reload?(paths)
|
|
||||||
|
|
||||||
# Otherwise forward to Middleman
|
|
||||||
paths.each do |path|
|
|
||||||
tell_server(:delete => path) unless self.class.ignore_list.any? { |r| path.match(r) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
# Trap the interupt signal and shut down FSSM (and thus the server) smoothly
|
|
||||||
def register_signal_handlers
|
|
||||||
trap("INT") { stop; exit(0) }
|
|
||||||
trap("TERM") { stop }
|
|
||||||
trap("QUIT") { stop; exit(0) }
|
|
||||||
end
|
|
||||||
|
|
||||||
# Whether the passed files are config.rb, lib/*.rb or helpers
|
|
||||||
# @param [Array<String>] paths Array of paths to check
|
|
||||||
# @return [Boolean] Whether the server needs to reload
|
|
||||||
def needs_to_reload?(paths)
|
|
||||||
return false # disable reloading for now
|
|
||||||
paths.any? do |path|
|
|
||||||
path.match(%{^config\.rb}) || path.match(%r{^lib/^[^\.](.*)\.rb$}) || path.match(%r{^helpers/^[^\.](.*)_helper\.rb$})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Send a message to the running server
|
|
||||||
# @param [Hash] params Keys to be hashed and sent to server
|
|
||||||
# @return [void]
|
|
||||||
def tell_server(params={})
|
|
||||||
uri = URI.parse("http://#{@options[:host]}:#{@options[:port]}/__middleman__")
|
|
||||||
Net::HTTP.post_form(uri, {}.merge(params))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Reference in a new issue