Permalink
Browse files

Replaced Thread (incompatible with inotify) by a whole dir scan after…

… each run_on_changes
  • Loading branch information...
thibaudgg committed Jan 19, 2011
1 parent 48b9c2b commit 9772e9d9c8bf2711d7fb1906084efe6e1318e790
View
@@ -1,3 +1,8 @@
+== Jan 19, 2011 [by thibaudgg]
+
+Features:
+- The whole directory are now watched after that run_on_change was launched on all guards to detect new files modifications.
+
== Dec 17, 2010 [by netzpirat]
Features:
@@ -14,7 +19,6 @@ Features:
Features:
- It's now possible to return an enumerable in the 'watch' optional blocks in the Guardfile.
-- Listener now continue to watch changed files even when guards plugin are running.
Specs:
- Guard::Watcher
View
@@ -1,59 +1,59 @@
require 'bundler'
module Guard
-
+
autoload :UI, 'guard/ui'
autoload :Dsl, 'guard/dsl'
autoload :Interactor, 'guard/interactor'
autoload :Listener, 'guard/listener'
autoload :Watcher, 'guard/watcher'
autoload :Notifier, 'guard/notifier'
-
+
class << self
attr_accessor :options, :guards, :listener
-
+
# initialize this singleton
def setup(options = {})
@options = options
@listener = Listener.select_and_init
@guards = []
self
end
-
+
def start(options = {})
setup(options)
-
+
Interactor.init_signal_traps
Dsl.evaluate_guardfile(options)
-
+
if guards.empty?
UI.error "No guards found in Guardfile, please add at least one."
else
+ listener.on_change do |files|
+ if Watcher.match_files?(guards, files)
+ run { run_on_change_for_all_guards(files) }
+ end
+ end
+
UI.info "Guard is now watching at '#{Dir.pwd}'"
- guards.each { |g| supervised_task(g, :start) }
-
- Thread.new { listener.start }
- wait_for_changes_and_launch_guards
+ guards.each { |guard| supervised_task(guard, :start) }
+ listener.start
end
end
-
- def wait_for_changes_and_launch_guards
- loop do
- if !running? && !listener.changed_files.empty?
- changed_files = listener.get_and_clear_changed_files
- if Watcher.match_files?(guards, changed_files)
- run do
- guards.each do |guard|
- paths = Watcher.match_files(guard, changed_files)
- supervised_task(guard, :run_on_change, paths) unless paths.empty?
- end
- end
- end
- end
- sleep 0.2
+
+ def run_on_change_for_all_guards(files)
+ guards.each do |guard|
+ paths = Watcher.match_files(guard, files)
+ supervised_task(guard, :run_on_change, paths) unless paths.empty?
+ end
+ # Reparse the whole directory to catch new files modified during the guards run
+ new_modified_files = listener.modified_files([Dir.pwd + '/'], :all => true)
+ listener.update_last_event
+ unless new_modified_files.empty?
+ run_on_change_for_all_guards(new_modified_files)
end
end
-
+
# Let a guard execute its task but
# fire it if his work leads to a system failure
def supervised_task(guard, task_to_supervise, *args)
@@ -64,26 +64,22 @@ def supervised_task(guard, task_to_supervise, *args)
UI.info("Guard #{guard.class.name} has just been fired")
return $!
end
-
+
def run
- @run = true
+ listener.stop
UI.clear if options[:clear]
begin
yield
rescue Interrupt
end
- @run = false
+ listener.start
end
-
- def running?
- @run == true
- end
-
+
def add_guard(name, watchers = [], options = {})
guard_class = get_guard_class(name)
@guards << guard_class.new(watchers, options)
end
-
+
def get_guard_class(name)
require "guard/#{name.downcase}"
klasses = []
@@ -94,12 +90,12 @@ def get_guard_class(name)
rescue LoadError
UI.error "Could not find gem 'guard-#{name}', please add it in your Gemfile."
end
-
+
def locate_guard(name)
`gem open guard-#{name} --latest --command echo`.chomp
rescue
UI.error "Could not find 'guard-#{name}' gem path."
end
-
+
end
end
View
@@ -1,11 +1,11 @@
module Guard
class Guard
attr_accessor :watchers, :options
-
+
def initialize(watchers = [], options = {})
@watchers, @options = watchers, options
end
-
+
# Guardfile template needed inside guard gem
def self.init(name)
if ::Guard::Dsl.guardfile_include?(name)
@@ -21,35 +21,35 @@ def self.init(name)
::Guard::UI.info "#{name} guard added to Guardfile, feel free to edit it"
end
end
-
+
# ================
# = Guard method =
# ================
-
+
# Call once when guard starts
# Please override initialize method to init stuff
def start
true
end
-
+
# Call once when guard quit
def stop
true
end
-
+
# Should be mainly used for "reload" (really!) actions like reloading passenger/spork/bundler/...
def reload
true
end
-
+
# Should be principally used for long action like running all specs/tests/...
def run_all
true
end
-
+
def run_on_change(paths)
true
end
-
+
end
end
View
@@ -1,14 +1,14 @@
require 'rbconfig'
module Guard
-
+
autoload :Darwin, 'guard/listeners/darwin'
autoload :Linux, 'guard/listeners/linux'
autoload :Polling, 'guard/listeners/polling'
-
+
class Listener
- attr_accessor :last_event, :changed_files
-
+ attr_reader :last_event
+
def self.select_and_init
if mac? && Darwin.usable?
Darwin.new
@@ -19,47 +19,107 @@ def self.select_and_init
Polling.new
end
end
-
+
def initialize
- @changed_files = []
update_last_event
end
-
- def get_and_clear_changed_files
- files = changed_files.dup
- changed_files.clear
- files.uniq
+
+ def update_last_event
+ @last_event = Time.now
end
-
- private
-
- def find_changed_files(dirs, options = {})
- files = potentially_changed_files(dirs, options).select { |path| File.file?(path) && changed_file?(path) }
+
+ def modified_files(dirs, options = {})
+ files = potentially_modified_files(dirs, options).select { |path| File.file?(path) && recent_file?(path) }
files.map! { |file| file.gsub("#{Dir.pwd}/", '') }
end
-
- def potentially_changed_files(dirs, options = {})
+
+ private
+
+ def potentially_modified_files(dirs, options = {})
match = options[:all] ? "**/*" : "*"
Dir.glob(dirs.map { |dir| "#{dir}#{match}" })
end
-
- def changed_file?(file)
+
+ def recent_file?(file)
File.mtime(file) >= last_event
rescue
false
end
-
- def update_last_event
- @last_event = Time.now
- end
-
+
+
def self.mac?
Config::CONFIG['target_os'] =~ /darwin/i
end
-
+
def self.linux?
Config::CONFIG['target_os'] =~ /linux/i
end
-
+
end
-end
+end
+
+# require 'rbconfig'
+#
+# module Guard
+#
+# autoload :Darwin, 'guard/listeners/darwin'
+# autoload :Linux, 'guard/listeners/linux'
+# autoload :Polling, 'guard/listeners/polling'
+#
+# class Listener
+# attr_accessor :last_event, :changed_files
+#
+# def self.select_and_init
+# if mac? && Darwin.usable?
+# Darwin.new
+# elsif linux? && Linux.usable?
+# Linux.new
+# else
+# UI.info "Using polling (Please help us to support your system better than that.)"
+# Polling.new
+# end
+# end
+#
+# def initialize
+# @changed_files = []
+# update_last_event
+# end
+#
+# def get_and_clear_changed_files
+# files = changed_files.dup
+# changed_files.clear
+# files.uniq
+# end
+#
+# private
+#
+# def find_changed_files(dirs, options = {})
+# files = potentially_changed_files(dirs, options).select { |path| File.file?(path) && changed_file?(path) }
+# files.map! { |file| file.gsub("#{Dir.pwd}/", '') }
+# end
+#
+# def potentially_changed_files(dirs, options = {})
+# match = options[:all] ? "**/*" : "*"
+# Dir.glob(dirs.map { |dir| "#{dir}#{match}" })
+# end
+#
+# def changed_file?(file)
+# File.mtime(file) >= last_event
+# rescue
+# false
+# end
+#
+# def update_last_event
+# @last_event = Time.now
+# end
+#
+# def self.mac?
+# Config::CONFIG['target_os'] =~ /darwin/i
+# end
+#
+# def self.linux?
+# Config::CONFIG['target_os'] =~ /linux/i
+# end
+#
+# end
+# end
Oops, something went wrong.

0 comments on commit 9772e9d

Please sign in to comment.