aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/file_evented_update_checker.rb
diff options
context:
space:
mode:
authorXavier Noria <fxn@hashref.com>2015-10-18 23:07:03 +0200
committerXavier Noria <fxn@hashref.com>2015-11-08 22:49:49 -0800
commit07369448d3c7b62c98abc0f497c497d1e4e5e799 (patch)
tree0de7a929c998ba8a2c9084a2a282e3fef98c044a /activesupport/lib/active_support/file_evented_update_checker.rb
parent087a79ab2fe4dfbe1cf1daafe91be5c9ef39be0c (diff)
downloadrails-07369448d3c7b62c98abc0f497c497d1e4e5e799.tar.gz
rails-07369448d3c7b62c98abc0f497c497d1e4e5e799.tar.bz2
rails-07369448d3c7b62c98abc0f497c497d1e4e5e799.zip
revises the implementation of the evented file monitor
Diffstat (limited to 'activesupport/lib/active_support/file_evented_update_checker.rb')
-rw-r--r--activesupport/lib/active_support/file_evented_update_checker.rb89
1 files changed, 65 insertions, 24 deletions
diff --git a/activesupport/lib/active_support/file_evented_update_checker.rb b/activesupport/lib/active_support/file_evented_update_checker.rb
index d45576bb00..5a7e0d2794 100644
--- a/activesupport/lib/active_support/file_evented_update_checker.rb
+++ b/activesupport/lib/active_support/file_evented_update_checker.rb
@@ -1,19 +1,26 @@
require 'listen'
+require 'set'
+require 'pathname'
module ActiveSupport
class FileEventedUpdateChecker
attr_reader :listener
- def initialize(files, directories={}, &block)
- @files = files.map { |f| File.expand_path(f)}.to_set
- @dirs = Hash.new
- directories.each do |key,value|
- @dirs[File.expand_path(key)] = Array(value) if !Array(value).empty?
+
+ def initialize(files, dirs={}, &block)
+ @files = files.map {|f| expand_path(f)}.to_set
+
+ @dirs = {}
+ dirs.each do |dir, exts|
+ @dirs[expand_path(dir)] = Array(exts).map(&:to_s)
end
+
@block = block
@modified = false
- watch_dirs = base_directories
- @listener = Listen.to(*watch_dirs,&method(:changed)) if !watch_dirs.empty?
- @listener.start if @listener
+
+ if (watch_dirs = base_directories).any?
+ @listener = Listen.to(*watch_dirs, &method(:changed))
+ @listener.start
+ end
end
def updated?
@@ -30,38 +37,72 @@ module ActiveSupport
if updated?
execute
true
- else
- false
end
end
private
- def watching?(file)
- return true if @files.include?(file)
- cfile = file
- while !cfile.eql? "/"
- cfile = File.expand_path("#{cfile}/..")
- if !@dirs[cfile].nil? and file.end_with?(*(@dirs[cfile].map {|ext| ".#{ext.to_s}"}))
- return true
- end
- end
- false
+ def expand_path(fname)
+ File.expand_path(fname)
end
def changed(modified, added, removed)
return if updated?
- if (modified + added + removed).any? { |f| watching? f }
+
+ if (modified + added + removed).any? {|f| watching?(f)}
@modified = true
end
end
+ def watching?(file)
+ file = expand_path(file)
+ return true if @files.member?(file)
+
+ file = Pathname.new(file)
+ return false if file.directory?
+
+ ext = file.extname.sub(/\A\./, '')
+ dir = file.dirname
+
+ loop do
+ if @dirs.fetch(dir.to_path, []).include?(ext)
+ break true
+ else
+ if dir.root? # TODO: find a common parent directory in initialize
+ break false
+ end
+ dir = dir.parent
+ end
+ end
+ end
+
+ # TODO: Better return a list of non-nested directories.
def base_directories
- (@files.map { |f| existing_parent(File.expand_path("#{f}/..")) } + @dirs.keys.map {|dir| existing_parent(dir)}).uniq
+ [].tap do |bd|
+ bd.concat @files.map {|f| existing_parent(File.dirname(f))}
+ bd.concat @dirs.keys.map {|dir| existing_parent(dir)}
+ bd.compact!
+ bd.uniq!
+ end
end
- def existing_parent(path)
- File.exist?(path) ? path : existing_parent(File.expand_path("#{path}/.."))
+ def existing_parent(dir)
+ dir = Pathname.new(File.expand_path(dir))
+
+ loop do
+ if dir.directory?
+ break dir.to_path
+ else
+ if dir.root?
+ # Edge case in which not even the root exists. For example, Windows
+ # paths could have a non-existing drive letter. Since the parent of
+ # root is root, we need to break to prevent an infinite loop.
+ break
+ else
+ dir = dir.parent
+ end
+ end
+ end
end
end
end