diff options
Diffstat (limited to 'activesupport/lib/active_support/file_update_checker.rb')
-rw-r--r-- | activesupport/lib/active_support/file_update_checker.rb | 92 |
1 files changed, 56 insertions, 36 deletions
diff --git a/activesupport/lib/active_support/file_update_checker.rb b/activesupport/lib/active_support/file_update_checker.rb index 1fa9335080..98aceabe21 100644 --- a/activesupport/lib/active_support/file_update_checker.rb +++ b/activesupport/lib/active_support/file_update_checker.rb @@ -1,3 +1,5 @@ +require "active_support/core_ext/time/calculations" + module ActiveSupport # FileUpdateChecker specifies the API used by Rails to watch files # and control reloading. The API depends on four methods: @@ -23,7 +25,7 @@ module ActiveSupport # I18n.reload! # end # - # ActionDispatch::Reloader.to_prepare do + # ActiveSupport::Reloader.to_prepare do # i18n_reloader.execute_if_updated # end class FileUpdateChecker @@ -81,6 +83,7 @@ module ActiveSupport # Execute the block given if updated. def execute_if_updated if updated? + yield if block_given? execute true else @@ -90,48 +93,65 @@ module ActiveSupport private - def watched - @watched || begin - all = @files.select { |f| File.exist?(f) } - all.concat(Dir[@glob]) if @glob - all + def watched + @watched || begin + all = @files.select { |f| File.exist?(f) } + all.concat(Dir[@glob]) if @glob + all + end end - end - def updated_at(paths) - @updated_at || max_mtime(paths) || Time.at(0) - end + def updated_at(paths) + @updated_at || max_mtime(paths) || Time.at(0) + end - # This method returns the maximum mtime of the files in +paths+, or +nil+ - # if the array is empty. - # - # Files with a mtime in the future are ignored. Such abnormal situation - # can happen for example if the user changes the clock by hand. It is - # healthy to consider this edge case because with mtimes in the future - # reloading is not triggered. - def max_mtime(paths) - time_now = Time.now - paths.map {|path| File.mtime(path)}.reject {|mtime| time_now < mtime}.max - end + # This method returns the maximum mtime of the files in +paths+, or +nil+ + # if the array is empty. + # + # Files with a mtime in the future are ignored. Such abnormal situation + # can happen for example if the user changes the clock by hand. It is + # healthy to consider this edge case because with mtimes in the future + # reloading is not triggered. + def max_mtime(paths) + time_now = Time.now + max_mtime = nil + + # Time comparisons are performed with #compare_without_coercion because + # AS redefines these operators in a way that is much slower and does not + # bring any benefit in this particular code. + # + # Read t1.compare_without_coercion(t2) < 0 as t1 < t2. + paths.each do |path| + mtime = File.mtime(path) - def compile_glob(hash) - hash.freeze # Freeze so changes aren't accidentally pushed - return if hash.empty? + next if time_now.compare_without_coercion(mtime) < 0 + + if max_mtime.nil? || max_mtime.compare_without_coercion(mtime) < 0 + max_mtime = mtime + end + end - globs = hash.map do |key, value| - "#{escape(key)}/**/*#{compile_ext(value)}" + max_mtime end - "{#{globs.join(",")}}" - end - def escape(key) - key.gsub(',','\,') - end + def compile_glob(hash) + hash.freeze # Freeze so changes aren't accidentally pushed + return if hash.empty? - def compile_ext(array) - array = Array(array) - return if array.empty? - ".{#{array.join(",")}}" - end + globs = hash.map do |key, value| + "#{escape(key)}/**/*#{compile_ext(value)}" + end + "{#{globs.join(",")}}" + end + + def escape(key) + key.gsub(",",'\,') + end + + def compile_ext(array) + array = Array(array) + return if array.empty? + ".{#{array.join(",")}}" + end end end |