diff --git a/README.md b/README.md index 3871fc9..aa8fa1e 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,13 @@ Install via [RubyGems](http://rubygems.org/pages/download): $ gem install stasis +By default, Stasis uses [DirectoryWatcher](http://rubygems.org/gems/directory_watcher) to monitor file changes. DirectoryWatcher scans the file system at periodic intervals looking for changes. If you are on OSX, you can install the [rb-fsevent](https://rubygems.org/gems/rb-fsevent) gem to tie into OSX's file event API and reduce the impact on your hard drive and CPU. + + + + $ gem install rb-fsevent + + Example ------- @@ -270,4 +277,4 @@ Stasis uses [Tilt](https://github.com/rtomayko/tilt) to support the following te ### This Web Site -[Take a look at the Stasis project](https://github.com/winton/stasis/tree/master/site) that automatically generated this web site from the project [README](https://github.com/winton/stasis/blob/master/README.md). \ No newline at end of file +[Take a look at the Stasis project](https://github.com/winton/stasis/tree/master/site) that automatically generated this web site from the project [README](https://github.com/winton/stasis/blob/master/README.md). diff --git a/lib/stasis/dev_mode.rb b/lib/stasis/dev_mode.rb index aba0f34..cf0665d 100644 --- a/lib/stasis/dev_mode.rb +++ b/lib/stasis/dev_mode.rb @@ -1,5 +1,10 @@ -gem 'directory_watcher', '1.4.1' -require 'directory_watcher' +begin + gem 'rb-fsevent' + require 'rb-fsevent' +rescue LoadError + gem 'directory_watcher', '1.4.1' + require 'directory_watcher' +end require 'logger' require 'webrick' @@ -18,27 +23,12 @@ def initialize(dir, options={}) @stasis = Stasis.new(*[ dir, @options[:public], @options ].compact) - glob = - Dir.chdir(@stasis.root) do - # If destination is within root - if @stasis.destination[0..@stasis.root.length] == "#{@stasis.root}/" - relative = @stasis.destination[@stasis.root.length+1..-1] rescue nil - Dir["*"].inject(["*"]) do |array, path| - if File.directory?(path) && path != relative - array.push("#{path}/**/*") - end - array - end - else - [ "*", "**/*" ] - end - end + if defined?(FSEvent) + watch_directory_with_fsevent + else + watch_directory_with_directory_watcher + end - dw = DirectoryWatcher.new(@stasis.root) - dw.add_observer { render } - dw.glob = glob - dw.interval = 0.1 - dw.start if @options[:development].is_a?(::Integer) mime_types = WEBrick::HTTPUtils::DefaultMimeTypes @@ -66,6 +56,51 @@ def initialize(dir, options={}) private + def watch_directory_with_fsevent + Thread.new do + fsevent = FSEvent.new + @last_render_at = Time.now.to_i + fsevent.watch(@stasis.root, :latency => 0.1) do |directories| + # remove any directory elements that are in public + directories.reject!{|d| d.start_with?(@stasis.destination + '/')} + # if the only remaining directory is the root, check to see if any files were updated + directories.clear if directories.size == 1 && + directories.first == @stasis.root + '/' && + Dir["#{@stasis.root}/*"].none?{|p| File.file?(p) && File.mtime(p).to_i > @last_render_at} + # only if we have something to do, do it. + unless directories.empty? + render + @last_render_at = Time.now.to_i + end + end + fsevent.run + end + end + + def watch_directory_with_directory_watcher + glob = + Dir.chdir(@stasis.root) do + # If destination is within root + if @stasis.destination[0..@stasis.root.length] == "#{@stasis.root}/" + relative = @stasis.destination[@stasis.root.length+1..-1] rescue nil + Dir["*"].inject(["*"]) do |array, path| + if File.directory?(path) && path != relative + array.push("#{path}/**/*") + end + array + end + else + [ "*", "**/*" ] + end + end + + dw = DirectoryWatcher.new(@stasis.root) + dw.add_observer { render } + dw.glob = glob + dw.interval = 0.1 + dw.start + end + def render puts "\n[#{Time.now.strftime("%Y-%m-%d %H:%M:%S")}]" + " Regenerating #{@options[:only] ? @options[:only].join(', ') : 'project'}...".yellow begin