diff --git a/middleman-core/lib/middleman-core/application.rb b/middleman-core/lib/middleman-core/application.rb index edc28ade..379d1e81 100644 --- a/middleman-core/lib/middleman-core/application.rb +++ b/middleman-core/lib/middleman-core/application.rb @@ -235,7 +235,8 @@ module Middleman :before, # Before Rack requests :before_render, :after_render, - :before_server + :before_server, + :reload ]) @middleware = Set.new diff --git a/middleman-core/lib/middleman-core/extensions/external_pipeline.rb b/middleman-core/lib/middleman-core/extensions/external_pipeline.rb index 37b6c9e5..ae5e4c3c 100644 --- a/middleman-core/lib/middleman-core/extensions/external_pipeline.rb +++ b/middleman-core/lib/middleman-core/extensions/external_pipeline.rb @@ -12,6 +12,7 @@ class Middleman::Extensions::ExternalPipeline < ::Middleman::Extension return if app.mode?(:config) + require 'servolux' require 'thread' require 'fileutils' @@ -25,31 +26,63 @@ class Middleman::Extensions::ExternalPipeline < ::Middleman::Extension latency: options[:latency], frontmatter: false + @current_thread = nil + app.reload(&method(:reload!)) + logger.info "== Executing: `#{options[:command]}`" if app.build? || options[:disable_background_execution] - watch_command! + watch_command!(false) + + @watcher.poll_once! else - ::Thread.new { watch_command! } + watch_command!(true) end end - def watch_command! - ::IO.popen(options[:command], 'r') do |pipe| - while buf = pipe.gets + def reload! + if @current_thread + logger.info "== Stopping: `#{options[:command]}`" + + @current_thread.stop + @current_thread = nil + end + end + + def watch_command!(async) + @current_thread = ::Servolux::Child.new( + command: options[:command], + suspend: 2 + ) + + @current_thread.start + + watch_thread = Thread.new do + while buf = @current_thread.io.gets without_newline = buf.sub(/\n$/, '') logger.info "== External: #{without_newline}" unless without_newline.empty? end + + @current_thread.wait + + if !@current_thread.exitstatus.nil? && @current_thread.exitstatus != 0 + logger.error '== External: Command failed with non-zero exit status' + exit(1) + end end - unless $?.success? - logger.error '== External: Command failed with non-zero exit status' - exit(1) - end - - @watcher.poll_once! + watch_thread.join unless async rescue ::Errno::ENOENT => e logger.error "== External: Command failed with message: #{e.message}" exit(1) end + + private + + def print_command(stdout) + while buf = stdout.gets + without_newline = buf.sub(/\n$/, '') + logger.info "== External: #{without_newline}" unless without_newline.empty? + end + end end diff --git a/middleman-core/lib/middleman-core/preview_server.rb b/middleman-core/lib/middleman-core/preview_server.rb index fd91ae1e..b70e9c99 100644 --- a/middleman-core/lib/middleman-core/preview_server.rb +++ b/middleman-core/lib/middleman-core/preview_server.rb @@ -103,6 +103,8 @@ module Middleman def reload app.logger.info '== The Middleman is reloading' + app.execute_callbacks(:reload) + begin app = initialize_new_app rescue => e diff --git a/middleman-core/middleman-core.gemspec b/middleman-core/middleman-core.gemspec index 80e542d7..741f5c5e 100644 --- a/middleman-core/middleman-core.gemspec +++ b/middleman-core/middleman-core.gemspec @@ -25,6 +25,7 @@ Gem::Specification.new do |s| s.add_dependency('erubis') s.add_dependency('fast_blank') s.add_dependency('parallel') + s.add_dependency('servolux') # Helpers s.add_dependency('activesupport', ['~> 4.2'])