aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/file_evented_update_checker.rb
diff options
context:
space:
mode:
authorXavier Noria <fxn@hashref.com>2015-10-12 20:41:14 +0200
committerXavier Noria <fxn@hashref.com>2015-11-08 22:49:49 -0800
commit785adabc4b8d892b6e06fca2f259e9c5147e9ca5 (patch)
tree3f6aa360466928f1ecbe59870944d879abb454c4 /activesupport/lib/active_support/file_evented_update_checker.rb
parent823d3a8de0ccfe2301e51ac1e06e106035edb8e6 (diff)
downloadrails-785adabc4b8d892b6e06fca2f259e9c5147e9ca5.tar.gz
rails-785adabc4b8d892b6e06fca2f259e9c5147e9ca5.tar.bz2
rails-785adabc4b8d892b6e06fca2f259e9c5147e9ca5.zip
implements an evented file update checker [Puneet Agarwal]
This is the implementation of the file update checker written by Puneet Agarwal for GSoC 2015 (except for the tiny version of the listen gem, which was 3.0.2 in the original patch). Puneet's branch became too out of sync with upstream. This is the final work in one single clean commit. Credit goes in the first line using a convention understood by the contrib app.
Diffstat (limited to 'activesupport/lib/active_support/file_evented_update_checker.rb')
-rw-r--r--activesupport/lib/active_support/file_evented_update_checker.rb67
1 files changed, 67 insertions, 0 deletions
diff --git a/activesupport/lib/active_support/file_evented_update_checker.rb b/activesupport/lib/active_support/file_evented_update_checker.rb
new file mode 100644
index 0000000000..d45576bb00
--- /dev/null
+++ b/activesupport/lib/active_support/file_evented_update_checker.rb
@@ -0,0 +1,67 @@
+require 'listen'
+
+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?
+ end
+ @block = block
+ @modified = false
+ watch_dirs = base_directories
+ @listener = Listen.to(*watch_dirs,&method(:changed)) if !watch_dirs.empty?
+ @listener.start if @listener
+ end
+
+ def updated?
+ @modified
+ end
+
+ def execute
+ @block.call
+ ensure
+ @modified = false
+ end
+
+ def execute_if_updated
+ 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
+ end
+
+ def changed(modified, added, removed)
+ return if updated?
+ if (modified + added + removed).any? { |f| watching? f }
+ @modified = true
+ end
+ end
+
+ def base_directories
+ (@files.map { |f| existing_parent(File.expand_path("#{f}/..")) } + @dirs.keys.map {|dir| existing_parent(dir)}).uniq
+ end
+
+ def existing_parent(path)
+ File.exist?(path) ? path : existing_parent(File.expand_path("#{path}/.."))
+ end
+ end
+end