Use pathname consistently in file watcher

This commit is contained in:
Thomas Reynolds 2012-05-25 18:18:51 -07:00
parent c3c662cf44
commit 2e5b0d75a9
7 changed files with 59 additions and 52 deletions

View file

@ -12,7 +12,7 @@ require "pathname"
# Recursive method to find config.rb # Recursive method to find config.rb
def locate_root(cwd = Pathname.new(Dir.pwd)) def locate_root(cwd = Pathname.new(Dir.pwd))
return cwd.to_s if File.exists?(File.join(cwd, 'config.rb')) return cwd.to_s if (cwd + 'config.rb').exists?
return false if cwd.root? return false if cwd.root?
locate_root(cwd.parent) locate_root(cwd.parent)
end end

View file

@ -72,6 +72,11 @@ module Middleman
# @return [String] # @return [String]
set :root, ENV["MM_ROOT"] || Dir.pwd set :root, ENV["MM_ROOT"] || Dir.pwd
# Pathname-addressed root
def root_path
@_root_path ||= Pathname.new(root)
end
# Name of the source directory # Name of the source directory
# @return [String] # @return [String]
set :source, "source" set :source, "source"

View file

@ -210,7 +210,7 @@ module Middleman::Cli
puts "== Checking for Compass sprites" if @app.logging? puts "== Checking for Compass sprites" if @app.logging?
# Double-check for compass sprites # Double-check for compass sprites
@app.files.find_new_files(File.join(@app.source_dir, @app.images_dir)) @app.files.find_new_files(Pathname.new(@app.source_dir) + @app.images_dir)
# Sort paths to be built by the above order. This is primarily so Compass can # Sort paths to be built by the above order. This is primarily so Compass can
# find files in the build folder when it needs to generate sprites for the # find files in the build folder when it needs to generate sprites for the

View file

@ -1,4 +1,4 @@
require "find" require "pathname"
require "set" require "set"
# API for watching file change events # API for watching file change events
@ -7,6 +7,7 @@ module Middleman
module FileWatcher module FileWatcher
IGNORE_LIST = [ IGNORE_LIST = [
/^\.bundle\//,
/^\.sass-cache\//, /^\.sass-cache\//,
/^\.git\//, /^\.git\//,
/^\.gitignore$/, /^\.gitignore$/,
@ -23,33 +24,21 @@ module Middleman
# Once registered # Once registered
def registered(app) def registered(app)
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(root, data_dir) files.reload_path(root_path + data_dir)
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
files.reload_path(root) files.reload_path(root_path)
end end
end end
alias :included :registered alias :included :registered
end end
# Class methods
module ClassMethods
# Access the file api
# @return [Middleman::CoreExtensions::FileWatcher::API]
def files
@_files_api ||= API.new
end
end
# Instance methods # Instance methods
module InstanceMethods module InstanceMethods
@ -92,68 +81,77 @@ module Middleman
# Notify callbacks that a file changed # Notify callbacks that a file changed
# #
# @param [String] path The file that changed # @param [Pathname] path The file that changed
# @return [void] # @return [void]
def did_change(path) def did_change(path)
return if IGNORE_LIST.any? { |r| path.match(r) } return if ignored?(path)
puts "== File Change: #{path}" if @app.logging? puts "== File Change: #{path.relative_path_from(@app.root_path)}" if @app.logging?
@known_paths << path @known_paths << path
self.run_callbacks(path, :changed) self.run_callbacks(path, :changed)
end end
# Notify callbacks that a file was deleted # Notify callbacks that a file was deleted
# #
# @param [String] path The file that was deleted # @param [Pathname] path The file that was deleted
# @return [void] # @return [void]
def did_delete(path) def did_delete(path)
return if IGNORE_LIST.any? { |r| path.match(r) } return if ignored?(path)
puts "== File Deletion: #{path}" if @app.logging? puts "== File Deletion: #{path.relative_path_from(@app.root_path)}" if @app.logging?
@known_paths.delete(path) @known_paths.delete(path)
self.run_callbacks(path, :deleted) self.run_callbacks(path, :deleted)
end end
# Manually trigger update events # Manually trigger update events
# #
# @param [String] path The path to reload # @param [Pathname] path The path to reload
# @param [Boolean] only_new Whether we only look for new files
# @return [void] # @return [void]
def reload_path(path) def reload_path(path, only_new=false)
relative_path = path.sub("#{@app.root}/", "") return unless path.exists?
subset = @known_paths.select { |p| p.match(%r{^#{relative_path}}) }
Find.find(path) do |path| glob = "#{path}**/*"
next if File.directory?(path) subset = @known_paths.select { |p| p.fnmatch(glob) }
relative_path = path.sub("#{@app.root}/", "")
subset.delete(relative_path)
self.did_change(relative_path)
end if File.exists?(path)
subset.each do |removed_path| path.find do |filepath|
self.did_delete(removed_path) full_path = path + filepath
next if full_path.directory?
if only_new
next if subset.include?(full_path)
else
subset.delete(full_path)
end end
self.did_change(full_path)
end
subset.each(&method(:did_delete)) unless only_new
end end
# Like reload_path, but only triggers events on new files # Like reload_path, but only triggers events on new files
# #
# @param [String] path The path to reload # @param [Pathname] path The path to reload
# @return [void] # @return [void]
def find_new_files(path) def find_new_files(path)
relative_path = path.sub("#{@app.root}/", "") reload_path(path, true)
subset = @known_paths.select { |p| p.match(%r{^#{relative_path}}) }
Find.find(path) do |file|
next if File.directory?(file)
relative_path = file.sub("#{@app.root}/", "")
self.did_change(relative_path) unless subset.include?(relative_path)
end if File.exists?(path)
end end
protected protected
# Whether this path is ignored
# @param [Pathname] path
# @return [Boolean]
def ignored?(path)
path = path.relative_path_from(@app.root_path).to_s if path.is_a? Pathname
IGNORE_LIST.any? { |r| path.to_s.match(r) }
end
# Notify callbacks for a file given an array of callbacks # Notify callbacks for a file given an array of callbacks
# #
# @param [String] path The file that was changed # @param [Pathname] path The file that was changed
# @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)
path = path.relative_path_from(@app.root_path).to_s if path.is_a? Pathname
self.send(callbacks_name).each do |callback, matcher| self.send(callbacks_name).each do |callback, matcher|
next if path.match(%r{^#{@app.build_dir}/}) next if path.match(%r{^#{@app.build_dir}/})
next unless matcher.nil? || path.match(matcher) next unless matcher.nil? || path.match(matcher)

View file

@ -83,7 +83,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(@app.root_path + path)
end end
end end
@ -93,7 +93,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(@app.root_path + path)
end end
end end
end end

View file

@ -9,9 +9,9 @@ Then /^the file "([^\"]*)" is removed$/ do |path|
end end
Then /^the file "([^\"]*)" did change$/ do |path| Then /^the file "([^\"]*)" did change$/ do |path|
@server_inst.files.did_change(path) @server_inst.files.did_change(@server_inst.root_path + path)
end end
Then /^the file "([^\"]*)" did delete$/ do |path| Then /^the file "([^\"]*)" did delete$/ do |path|
@server_inst.files.did_delete(path) @server_inst.files.did_delete(@server_inst.root_path + path)
end end

View file

@ -1,8 +1,12 @@
# Using Thor's indifferent hash access # Using Thor's indifferent hash access
require "thor" require "thor"
# Core Pathname library used for traversal
require "pathname"
module Middleman module Middleman
module Util module Util
# Recursively convert a normal Hash into a HashWithIndifferentAccess # Recursively convert a normal Hash into a HashWithIndifferentAccess
# #
# @private # @private