Replaced Thread (incompatible with inotify) by a whole dir scan after each run_on_changes
This commit is contained in:
parent
48b9c2b824
commit
9772e9d9c8
@ -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]
|
== Dec 17, 2010 [by netzpirat]
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
@ -14,7 +19,6 @@ Features:
|
|||||||
|
|
||||||
Features:
|
Features:
|
||||||
- It's now possible to return an enumerable in the 'watch' optional blocks in the Guardfile.
|
- 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:
|
Specs:
|
||||||
- Guard::Watcher
|
- Guard::Watcher
|
||||||
|
72
lib/guard.rb
72
lib/guard.rb
@ -1,17 +1,17 @@
|
|||||||
require 'bundler'
|
require 'bundler'
|
||||||
|
|
||||||
module Guard
|
module Guard
|
||||||
|
|
||||||
autoload :UI, 'guard/ui'
|
autoload :UI, 'guard/ui'
|
||||||
autoload :Dsl, 'guard/dsl'
|
autoload :Dsl, 'guard/dsl'
|
||||||
autoload :Interactor, 'guard/interactor'
|
autoload :Interactor, 'guard/interactor'
|
||||||
autoload :Listener, 'guard/listener'
|
autoload :Listener, 'guard/listener'
|
||||||
autoload :Watcher, 'guard/watcher'
|
autoload :Watcher, 'guard/watcher'
|
||||||
autoload :Notifier, 'guard/notifier'
|
autoload :Notifier, 'guard/notifier'
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
attr_accessor :options, :guards, :listener
|
attr_accessor :options, :guards, :listener
|
||||||
|
|
||||||
# initialize this singleton
|
# initialize this singleton
|
||||||
def setup(options = {})
|
def setup(options = {})
|
||||||
@options = options
|
@options = options
|
||||||
@ -19,41 +19,41 @@ module Guard
|
|||||||
@guards = []
|
@guards = []
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
def start(options = {})
|
def start(options = {})
|
||||||
setup(options)
|
setup(options)
|
||||||
|
|
||||||
Interactor.init_signal_traps
|
Interactor.init_signal_traps
|
||||||
Dsl.evaluate_guardfile(options)
|
Dsl.evaluate_guardfile(options)
|
||||||
|
|
||||||
if guards.empty?
|
if guards.empty?
|
||||||
UI.error "No guards found in Guardfile, please add at least one."
|
UI.error "No guards found in Guardfile, please add at least one."
|
||||||
else
|
else
|
||||||
UI.info "Guard is now watching at '#{Dir.pwd}'"
|
listener.on_change do |files|
|
||||||
guards.each { |g| supervised_task(g, :start) }
|
if Watcher.match_files?(guards, files)
|
||||||
|
run { run_on_change_for_all_guards(files) }
|
||||||
Thread.new { listener.start }
|
|
||||||
wait_for_changes_and_launch_guards
|
|
||||||
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
|
||||||
end
|
end
|
||||||
sleep 0.2
|
|
||||||
|
UI.info "Guard is now watching at '#{Dir.pwd}'"
|
||||||
|
guards.each { |guard| supervised_task(guard, :start) }
|
||||||
|
listener.start
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
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
|
# Let a guard execute its task but
|
||||||
# fire it if his work leads to a system failure
|
# fire it if his work leads to a system failure
|
||||||
def supervised_task(guard, task_to_supervise, *args)
|
def supervised_task(guard, task_to_supervise, *args)
|
||||||
@ -64,26 +64,22 @@ module Guard
|
|||||||
UI.info("Guard #{guard.class.name} has just been fired")
|
UI.info("Guard #{guard.class.name} has just been fired")
|
||||||
return $!
|
return $!
|
||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
@run = true
|
listener.stop
|
||||||
UI.clear if options[:clear]
|
UI.clear if options[:clear]
|
||||||
begin
|
begin
|
||||||
yield
|
yield
|
||||||
rescue Interrupt
|
rescue Interrupt
|
||||||
end
|
end
|
||||||
@run = false
|
listener.start
|
||||||
end
|
end
|
||||||
|
|
||||||
def running?
|
|
||||||
@run == true
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_guard(name, watchers = [], options = {})
|
def add_guard(name, watchers = [], options = {})
|
||||||
guard_class = get_guard_class(name)
|
guard_class = get_guard_class(name)
|
||||||
@guards << guard_class.new(watchers, options)
|
@guards << guard_class.new(watchers, options)
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_guard_class(name)
|
def get_guard_class(name)
|
||||||
require "guard/#{name.downcase}"
|
require "guard/#{name.downcase}"
|
||||||
klasses = []
|
klasses = []
|
||||||
@ -94,12 +90,12 @@ module Guard
|
|||||||
rescue LoadError
|
rescue LoadError
|
||||||
UI.error "Could not find gem 'guard-#{name}', please add it in your Gemfile."
|
UI.error "Could not find gem 'guard-#{name}', please add it in your Gemfile."
|
||||||
end
|
end
|
||||||
|
|
||||||
def locate_guard(name)
|
def locate_guard(name)
|
||||||
`gem open guard-#{name} --latest --command echo`.chomp
|
`gem open guard-#{name} --latest --command echo`.chomp
|
||||||
rescue
|
rescue
|
||||||
UI.error "Could not find 'guard-#{name}' gem path."
|
UI.error "Could not find 'guard-#{name}' gem path."
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -1,11 +1,11 @@
|
|||||||
module Guard
|
module Guard
|
||||||
class Guard
|
class Guard
|
||||||
attr_accessor :watchers, :options
|
attr_accessor :watchers, :options
|
||||||
|
|
||||||
def initialize(watchers = [], options = {})
|
def initialize(watchers = [], options = {})
|
||||||
@watchers, @options = watchers, options
|
@watchers, @options = watchers, options
|
||||||
end
|
end
|
||||||
|
|
||||||
# Guardfile template needed inside guard gem
|
# Guardfile template needed inside guard gem
|
||||||
def self.init(name)
|
def self.init(name)
|
||||||
if ::Guard::Dsl.guardfile_include?(name)
|
if ::Guard::Dsl.guardfile_include?(name)
|
||||||
@ -21,35 +21,35 @@ module Guard
|
|||||||
::Guard::UI.info "#{name} guard added to Guardfile, feel free to edit it"
|
::Guard::UI.info "#{name} guard added to Guardfile, feel free to edit it"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# ================
|
# ================
|
||||||
# = Guard method =
|
# = Guard method =
|
||||||
# ================
|
# ================
|
||||||
|
|
||||||
# Call once when guard starts
|
# Call once when guard starts
|
||||||
# Please override initialize method to init stuff
|
# Please override initialize method to init stuff
|
||||||
def start
|
def start
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
# Call once when guard quit
|
# Call once when guard quit
|
||||||
def stop
|
def stop
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
# Should be mainly used for "reload" (really!) actions like reloading passenger/spork/bundler/...
|
# Should be mainly used for "reload" (really!) actions like reloading passenger/spork/bundler/...
|
||||||
def reload
|
def reload
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
# Should be principally used for long action like running all specs/tests/...
|
# Should be principally used for long action like running all specs/tests/...
|
||||||
def run_all
|
def run_all
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_on_change(paths)
|
def run_on_change(paths)
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -1,14 +1,14 @@
|
|||||||
require 'rbconfig'
|
require 'rbconfig'
|
||||||
|
|
||||||
module Guard
|
module Guard
|
||||||
|
|
||||||
autoload :Darwin, 'guard/listeners/darwin'
|
autoload :Darwin, 'guard/listeners/darwin'
|
||||||
autoload :Linux, 'guard/listeners/linux'
|
autoload :Linux, 'guard/listeners/linux'
|
||||||
autoload :Polling, 'guard/listeners/polling'
|
autoload :Polling, 'guard/listeners/polling'
|
||||||
|
|
||||||
class Listener
|
class Listener
|
||||||
attr_accessor :last_event, :changed_files
|
attr_reader :last_event
|
||||||
|
|
||||||
def self.select_and_init
|
def self.select_and_init
|
||||||
if mac? && Darwin.usable?
|
if mac? && Darwin.usable?
|
||||||
Darwin.new
|
Darwin.new
|
||||||
@ -19,47 +19,107 @@ module Guard
|
|||||||
Polling.new
|
Polling.new
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@changed_files = []
|
|
||||||
update_last_event
|
update_last_event
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_and_clear_changed_files
|
def update_last_event
|
||||||
files = changed_files.dup
|
@last_event = Time.now
|
||||||
changed_files.clear
|
|
||||||
files.uniq
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
def modified_files(dirs, options = {})
|
||||||
|
files = potentially_modified_files(dirs, options).select { |path| File.file?(path) && recent_file?(path) }
|
||||||
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}/", '') }
|
files.map! { |file| file.gsub("#{Dir.pwd}/", '') }
|
||||||
end
|
end
|
||||||
|
|
||||||
def potentially_changed_files(dirs, options = {})
|
private
|
||||||
|
|
||||||
|
def potentially_modified_files(dirs, options = {})
|
||||||
match = options[:all] ? "**/*" : "*"
|
match = options[:all] ? "**/*" : "*"
|
||||||
Dir.glob(dirs.map { |dir| "#{dir}#{match}" })
|
Dir.glob(dirs.map { |dir| "#{dir}#{match}" })
|
||||||
end
|
end
|
||||||
|
|
||||||
def changed_file?(file)
|
def recent_file?(file)
|
||||||
File.mtime(file) >= last_event
|
File.mtime(file) >= last_event
|
||||||
rescue
|
rescue
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_last_event
|
|
||||||
@last_event = Time.now
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.mac?
|
def self.mac?
|
||||||
Config::CONFIG['target_os'] =~ /darwin/i
|
Config::CONFIG['target_os'] =~ /darwin/i
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.linux?
|
def self.linux?
|
||||||
Config::CONFIG['target_os'] =~ /linux/i
|
Config::CONFIG['target_os'] =~ /linux/i
|
||||||
end
|
end
|
||||||
|
|
||||||
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
|
@ -1,28 +1,28 @@
|
|||||||
module Guard
|
module Guard
|
||||||
class Darwin < Listener
|
class Darwin < Listener
|
||||||
attr_reader :fsevent
|
attr_reader :fsevent
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super
|
super
|
||||||
@fsevent = FSEvent.new
|
@fsevent = FSEvent.new
|
||||||
fsevent.watch Dir.pwd do |modified_dirs|
|
end
|
||||||
@changed_files += find_changed_files(modified_dirs)
|
|
||||||
|
def on_change(&callback)
|
||||||
|
@fsevent.watch Dir.pwd do |modified_dirs|
|
||||||
|
files = modified_files(modified_dirs)
|
||||||
update_last_event
|
update_last_event
|
||||||
|
callback.call(files)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def start
|
def start
|
||||||
# keep relaunching fsevent.run if not stopped by Guard
|
@fsevent.run
|
||||||
while @stop != true
|
|
||||||
fsevent.run
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def stop
|
def stop
|
||||||
@stop = true
|
@fsevent.stop
|
||||||
fsevent.stop
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.usable?
|
def self.usable?
|
||||||
require 'rb-fsevent'
|
require 'rb-fsevent'
|
||||||
if !defined?(FSEvent::VERSION) || Gem::Version.new(FSEvent::VERSION) < Gem::Version.new('0.3.9')
|
if !defined?(FSEvent::VERSION) || Gem::Version.new(FSEvent::VERSION) < Gem::Version.new('0.3.9')
|
||||||
@ -35,6 +35,6 @@ module Guard
|
|||||||
UI.info "Please install rb-fsevent gem for Mac OSX FSEvents support"
|
UI.info "Please install rb-fsevent gem for Mac OSX FSEvents support"
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,25 +1,35 @@
|
|||||||
module Guard
|
module Guard
|
||||||
class Linux < Listener
|
class Linux < Listener
|
||||||
attr_reader :inotify
|
attr_reader :inotify, :files, :latency, :callback
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super
|
super
|
||||||
|
|
||||||
@inotify = INotify::Notifier.new
|
@inotify = INotify::Notifier.new
|
||||||
|
@files = []
|
||||||
|
@latency = 0.5
|
||||||
|
end
|
||||||
|
|
||||||
|
def start
|
||||||
|
@stop = false
|
||||||
|
watch_change unless watch_change?
|
||||||
|
end
|
||||||
|
|
||||||
|
def stop
|
||||||
|
@stop = true
|
||||||
|
sleep latency
|
||||||
|
end
|
||||||
|
|
||||||
|
def on_change(&callback)
|
||||||
|
@callback = callback
|
||||||
inotify.watch(Dir.pwd, :recursive, :modify, :create, :delete, :move) do |event|
|
inotify.watch(Dir.pwd, :recursive, :modify, :create, :delete, :move) do |event|
|
||||||
unless event.name == "" # Event on root directory
|
unless event.name == "" # Event on root directory
|
||||||
@changed_files << event.absolute_name.gsub("#{Dir.pwd}/", '')
|
@files << event.absolute_name
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
rescue Interrupt
|
||||||
end
|
end
|
||||||
|
|
||||||
def start
|
|
||||||
inotify.run
|
|
||||||
end
|
|
||||||
|
|
||||||
def stop
|
|
||||||
inotify.stop
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.usable?
|
def self.usable?
|
||||||
require 'rb-inotify'
|
require 'rb-inotify'
|
||||||
if !defined?(INotify::VERSION) || Gem::Version.new(INotify::VERSION.join('.')) < Gem::Version.new('0.5.1')
|
if !defined?(INotify::VERSION) || Gem::Version.new(INotify::VERSION.join('.')) < Gem::Version.new('0.5.1')
|
||||||
@ -32,6 +42,32 @@ module Guard
|
|||||||
UI.info "Please install rb-inotify gem for Linux inotify support"
|
UI.info "Please install rb-inotify gem for Linux inotify support"
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def watch_change?
|
||||||
|
!!@watch_change
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def watch_change
|
||||||
|
@watch_change = true
|
||||||
|
while !@stop
|
||||||
|
if Config::CONFIG['build'] =~ /java/ || IO.select([inotify.to_io], [], [], latency)
|
||||||
|
break if @stop
|
||||||
|
|
||||||
|
sleep latency
|
||||||
|
inotify.process
|
||||||
|
update_last_event
|
||||||
|
|
||||||
|
unless files.empty?
|
||||||
|
files.map! { |file| file.gsub("#{Dir.pwd}/", '') }
|
||||||
|
callback.call(files)
|
||||||
|
files.clear
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
@watch_change = false
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,34 +1,37 @@
|
|||||||
module Guard
|
module Guard
|
||||||
class Polling < Listener
|
class Polling < Listener
|
||||||
attr_reader :callback, :latency
|
attr_reader :callback, :latency
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super
|
super
|
||||||
@latency = 1.5
|
@latency = 1.5
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def on_change(&callback)
|
||||||
|
@callback = callback
|
||||||
|
end
|
||||||
|
|
||||||
def start
|
def start
|
||||||
@stop = false
|
@stop = false
|
||||||
watch_change
|
watch_change
|
||||||
end
|
end
|
||||||
|
|
||||||
def stop
|
def stop
|
||||||
@stop = true
|
@stop = true
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def watch_change
|
def watch_change
|
||||||
while !@stop
|
while !@stop
|
||||||
start = Time.now.to_f
|
start = Time.now.to_f
|
||||||
if files = find_changed_files([Dir.pwd + '/'], :all => true)
|
files = modified_files([Dir.pwd + '/'], :all => true)
|
||||||
update_last_event
|
update_last_event
|
||||||
@changed_files += files
|
callback.call(files) unless files.empty?
|
||||||
end
|
|
||||||
nap_time = latency - (Time.now.to_f - start)
|
nap_time = latency - (Time.now.to_f - start)
|
||||||
sleep(nap_time) if nap_time > 0
|
sleep(nap_time) if nap_time > 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -2,25 +2,25 @@ require 'spec_helper'
|
|||||||
|
|
||||||
describe Guard::Listener do
|
describe Guard::Listener do
|
||||||
subject { described_class }
|
subject { described_class }
|
||||||
|
|
||||||
describe ".select_and_init" do
|
describe ".select_and_init" do
|
||||||
before(:each) { @target_os = Config::CONFIG['target_os'] }
|
before(:each) { @target_os = Config::CONFIG['target_os'] }
|
||||||
after(:each) { Config::CONFIG['target_os'] = @target_os }
|
after(:each) { Config::CONFIG['target_os'] = @target_os }
|
||||||
|
|
||||||
it "should use darwin listener on Mac OS X" do
|
it "should use darwin listener on Mac OS X" do
|
||||||
Config::CONFIG['target_os'] = 'darwin10.4.0'
|
Config::CONFIG['target_os'] = 'darwin10.4.0'
|
||||||
Guard::Darwin.stub(:usable?).and_return(true)
|
Guard::Darwin.stub(:usable?).and_return(true)
|
||||||
Guard::Darwin.should_receive(:new)
|
Guard::Darwin.should_receive(:new)
|
||||||
subject.select_and_init
|
subject.select_and_init
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should use polling listener on Windows" do
|
it "should use polling listener on Windows" do
|
||||||
Config::CONFIG['target_os'] = 'win32'
|
Config::CONFIG['target_os'] = 'win32'
|
||||||
Guard::Polling.stub(:usable?).and_return(true)
|
Guard::Polling.stub(:usable?).and_return(true)
|
||||||
Guard::Polling.should_receive(:new)
|
Guard::Polling.should_receive(:new)
|
||||||
subject.select_and_init
|
subject.select_and_init
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should use linux listener on Linux" do
|
it "should use linux listener on Linux" do
|
||||||
Config::CONFIG['target_os'] = 'linux'
|
Config::CONFIG['target_os'] = 'linux'
|
||||||
Guard::Linux.stub(:usable?).and_return(true)
|
Guard::Linux.stub(:usable?).and_return(true)
|
||||||
@ -28,16 +28,16 @@ describe Guard::Listener do
|
|||||||
subject.select_and_init
|
subject.select_and_init
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#get_and_clear_changed_files" do
|
describe "#update_last_event" do
|
||||||
subject { Guard::Listener.new }
|
subject { described_class.new }
|
||||||
|
|
||||||
it "should return uniq changed files and clear it" do
|
it "should update last_event with time.now" do
|
||||||
subject.changed_files = ["foo", "bar", "bar"]
|
time = Time.now
|
||||||
subject.get_and_clear_changed_files.should == ["foo", "bar"]
|
subject.update_last_event
|
||||||
subject.changed_files.should be_empty
|
subject.last_event.should >= time
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
@ -3,21 +3,27 @@ require 'guard/listeners/darwin'
|
|||||||
|
|
||||||
describe Guard::Darwin do
|
describe Guard::Darwin do
|
||||||
subject { Guard::Darwin }
|
subject { Guard::Darwin }
|
||||||
|
|
||||||
if linux?
|
if linux?
|
||||||
it "should not be usable on linux" do
|
it "should not be usable on linux" do
|
||||||
subject.should_not be_usable
|
subject.should_not be_usable
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if mac?
|
if mac?
|
||||||
it "should be usable on 10.6" do
|
it "should be usable on 10.6" do
|
||||||
subject.should be_usable
|
subject.should be_usable
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "watch" do
|
describe "watch" do
|
||||||
subject { Guard::Darwin.new }
|
before(:each) do
|
||||||
|
@results = []
|
||||||
|
@listener = Guard::Darwin.new
|
||||||
|
@listener.on_change do |files|
|
||||||
|
@results += files
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it "should catch new file" do
|
it "should catch new file" do
|
||||||
file = @fixture_path.join("newfile.rb")
|
file = @fixture_path.join("newfile.rb")
|
||||||
File.exists?(file).should be_false
|
File.exists?(file).should be_false
|
||||||
@ -25,18 +31,18 @@ describe Guard::Darwin do
|
|||||||
FileUtils.touch file
|
FileUtils.touch file
|
||||||
stop
|
stop
|
||||||
File.delete file
|
File.delete file
|
||||||
subject.changed_files.should == ['spec/fixtures/newfile.rb']
|
@results.should == ['spec/fixtures/newfile.rb']
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should catch file update" do
|
it "should catch file update" do
|
||||||
file = @fixture_path.join("folder1/file1.txt")
|
file = @fixture_path.join("folder1/file1.txt")
|
||||||
File.exists?(file).should be_true
|
File.exists?(file).should be_true
|
||||||
start
|
start
|
||||||
FileUtils.touch file
|
FileUtils.touch file
|
||||||
stop
|
stop
|
||||||
subject.changed_files.should == ['spec/fixtures/folder1/file1.txt']
|
@results.should == ['spec/fixtures/folder1/file1.txt']
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should catch files update" do
|
it "should catch files update" do
|
||||||
file1 = @fixture_path.join("folder1/file1.txt")
|
file1 = @fixture_path.join("folder1/file1.txt")
|
||||||
file2 = @fixture_path.join("folder1/folder2/file2.txt")
|
file2 = @fixture_path.join("folder1/folder2/file2.txt")
|
||||||
@ -46,22 +52,22 @@ describe Guard::Darwin do
|
|||||||
FileUtils.touch file1
|
FileUtils.touch file1
|
||||||
FileUtils.touch file2
|
FileUtils.touch file2
|
||||||
stop
|
stop
|
||||||
subject.changed_files.should == ['spec/fixtures/folder1/file1.txt', 'spec/fixtures/folder1/folder2/file2.txt']
|
@results.should == ['spec/fixtures/folder1/file1.txt', 'spec/fixtures/folder1/folder2/file2.txt']
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def start
|
def start
|
||||||
sleep 1
|
sleep 1
|
||||||
Thread.new { subject.start }
|
Thread.new { @listener.start }
|
||||||
sleep 1
|
sleep 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def stop
|
def stop
|
||||||
sleep 1
|
sleep 1
|
||||||
subject.stop
|
@listener.stop
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
@ -4,21 +4,51 @@ require 'guard/listeners/linux'
|
|||||||
|
|
||||||
describe Guard::Linux do
|
describe Guard::Linux do
|
||||||
subject { Guard::Linux }
|
subject { Guard::Linux }
|
||||||
|
|
||||||
if mac?
|
if mac?
|
||||||
it "should not be usable on 10.6" do
|
it "should not be usable on 10.6" do
|
||||||
subject.should_not be_usable
|
subject.should_not be_usable
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if linux?
|
if linux?
|
||||||
it "should be usable on linux" do
|
it "should be usable on linux" do
|
||||||
subject.should be_usable
|
subject.should be_usable
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "start" do
|
||||||
|
before(:each) do
|
||||||
|
@listener = Guard::Linux.new
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should call watch_change if first start" do
|
||||||
|
@listener.should_receive(:watch_change)
|
||||||
|
start
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not call watch_change if start after stop" do
|
||||||
|
@listener.stub!(:stop)
|
||||||
|
start
|
||||||
|
stop
|
||||||
|
@listener.should be_watch_change
|
||||||
|
@listener.should_not_receive(:watch_change)
|
||||||
|
start
|
||||||
|
@listener.unstub!(:stop)
|
||||||
|
stop
|
||||||
|
@listener.should_not be_watch_change
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
describe "watch" do
|
describe "watch" do
|
||||||
subject { Guard::Linux.new }
|
before(:each) do
|
||||||
|
@results = []
|
||||||
|
@listener = Guard::Linux.new
|
||||||
|
@listener.on_change do |files|
|
||||||
|
@results += files
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it "should catch new file" do
|
it "should catch new file" do
|
||||||
file = @fixture_path.join("newfile.rb")
|
file = @fixture_path.join("newfile.rb")
|
||||||
File.exists?(file).should be_false
|
File.exists?(file).should be_false
|
||||||
@ -26,18 +56,18 @@ describe Guard::Linux do
|
|||||||
FileUtils.touch file
|
FileUtils.touch file
|
||||||
stop
|
stop
|
||||||
File.delete file
|
File.delete file
|
||||||
subject.changed_files.should == ['spec/fixtures/newfile.rb']
|
@results.should == ['spec/fixtures/newfile.rb']
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should catch file update" do
|
it "should catch file update" do
|
||||||
file = @fixture_path.join("folder1/file1.txt")
|
file = @fixture_path.join("folder1/file1.txt")
|
||||||
File.exists?(file).should be_true
|
File.exists?(file).should be_true
|
||||||
start
|
start
|
||||||
File.open(file, 'w') {|f| f.write('') }
|
File.open(file, 'w') {|f| f.write('') }
|
||||||
stop
|
stop
|
||||||
subject.changed_files.should == ['spec/fixtures/folder1/file1.txt']
|
@results.should == ['spec/fixtures/folder1/file1.txt']
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should catch files update" do
|
it "should catch files update" do
|
||||||
file1 = @fixture_path.join("folder1/file1.txt")
|
file1 = @fixture_path.join("folder1/file1.txt")
|
||||||
file2 = @fixture_path.join("folder1/folder2/file2.txt")
|
file2 = @fixture_path.join("folder1/folder2/file2.txt")
|
||||||
@ -47,9 +77,9 @@ describe Guard::Linux do
|
|||||||
File.open(file1, 'w') {|f| f.write('') }
|
File.open(file1, 'w') {|f| f.write('') }
|
||||||
File.open(file2, 'w') {|f| f.write('') }
|
File.open(file2, 'w') {|f| f.write('') }
|
||||||
stop
|
stop
|
||||||
subject.changed_files.should == ['spec/fixtures/folder1/file1.txt', 'spec/fixtures/folder1/folder2/file2.txt']
|
@results.should == ['spec/fixtures/folder1/file1.txt', 'spec/fixtures/folder1/folder2/file2.txt']
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should catch deleted file" do
|
it "should catch deleted file" do
|
||||||
file = @fixture_path.join("folder1/file1.txt")
|
file = @fixture_path.join("folder1/file1.txt")
|
||||||
File.exists?(file).should be_true
|
File.exists?(file).should be_true
|
||||||
@ -57,9 +87,9 @@ describe Guard::Linux do
|
|||||||
File.delete file
|
File.delete file
|
||||||
stop
|
stop
|
||||||
FileUtils.touch file
|
FileUtils.touch file
|
||||||
subject.changed_files.should == ['spec/fixtures/folder1/file1.txt']
|
@results.should == ['spec/fixtures/folder1/file1.txt']
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should catch moved file" do
|
it "should catch moved file" do
|
||||||
file1 = @fixture_path.join("folder1/file1.txt")
|
file1 = @fixture_path.join("folder1/file1.txt")
|
||||||
file2 = @fixture_path.join("folder1/movedfile1.txt")
|
file2 = @fixture_path.join("folder1/movedfile1.txt")
|
||||||
@ -69,32 +99,32 @@ describe Guard::Linux do
|
|||||||
FileUtils.mv file1, file2
|
FileUtils.mv file1, file2
|
||||||
stop
|
stop
|
||||||
FileUtils.mv file2, file1
|
FileUtils.mv file2, file1
|
||||||
subject.changed_files.should == ['spec/fixtures/folder1/file1.txt', 'spec/fixtures/folder1/movedfile1.txt']
|
@results.should == ['spec/fixtures/folder1/file1.txt', 'spec/fixtures/folder1/movedfile1.txt']
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not process change if stopped" do
|
||||||
|
file = @fixture_path.join("folder1/file1.txt")
|
||||||
|
File.exists?(file).should be_true
|
||||||
|
start
|
||||||
|
@listener.inotify.should_not_receive(:process)
|
||||||
|
stop
|
||||||
|
File.open(file, 'w') {|f| f.write('') }
|
||||||
end
|
end
|
||||||
|
|
||||||
# it "should not process change if stopped" do
|
|
||||||
# file = @fixture_path.join("folder1/file1.txt")
|
|
||||||
# File.exists?(file).should be_true
|
|
||||||
# start
|
|
||||||
# subject.changed_files.inotify.should_not_receive(:process)
|
|
||||||
# stop
|
|
||||||
# File.open(file, 'w') {|f| f.write('') }
|
|
||||||
# end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def start
|
def start
|
||||||
sleep 1
|
sleep 1
|
||||||
Thread.new { subject.start }
|
Thread.new { @listener.start }
|
||||||
sleep 1
|
sleep 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def stop
|
def stop
|
||||||
sleep 1
|
sleep 1
|
||||||
subject.stop
|
@listener.stop
|
||||||
sleep 1
|
sleep 1
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
@ -2,8 +2,15 @@ require 'spec_helper'
|
|||||||
require 'guard/listeners/polling'
|
require 'guard/listeners/polling'
|
||||||
|
|
||||||
describe Guard::Polling do
|
describe Guard::Polling do
|
||||||
subject { Guard::Polling.new }
|
|
||||||
|
before(:each) do
|
||||||
|
@results = []
|
||||||
|
@listener = Guard::Polling.new
|
||||||
|
@listener.on_change do |files|
|
||||||
|
@results += files
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it "should catch new file" do
|
it "should catch new file" do
|
||||||
file = @fixture_path.join("newfile.rb")
|
file = @fixture_path.join("newfile.rb")
|
||||||
File.exists?(file).should be_false
|
File.exists?(file).should be_false
|
||||||
@ -11,18 +18,18 @@ describe Guard::Polling do
|
|||||||
FileUtils.touch file
|
FileUtils.touch file
|
||||||
stop
|
stop
|
||||||
File.delete file
|
File.delete file
|
||||||
subject.changed_files.should == ['spec/fixtures/newfile.rb']
|
@results.should == ['spec/fixtures/newfile.rb']
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should catch file update" do
|
it "should catch file update" do
|
||||||
file = @fixture_path.join("folder1/file1.txt")
|
file = @fixture_path.join("folder1/file1.txt")
|
||||||
File.exists?(file).should be_true
|
File.exists?(file).should be_true
|
||||||
start
|
start
|
||||||
FileUtils.touch file
|
FileUtils.touch file
|
||||||
stop
|
stop
|
||||||
subject.changed_files.should == ['spec/fixtures/folder1/file1.txt']
|
@results.should == ['spec/fixtures/folder1/file1.txt']
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should catch files update" do
|
it "should catch files update" do
|
||||||
file1 = @fixture_path.join("folder1/file1.txt")
|
file1 = @fixture_path.join("folder1/file1.txt")
|
||||||
file2 = @fixture_path.join("folder1/folder2/file2.txt")
|
file2 = @fixture_path.join("folder1/folder2/file2.txt")
|
||||||
@ -32,19 +39,19 @@ describe Guard::Polling do
|
|||||||
FileUtils.touch file1
|
FileUtils.touch file1
|
||||||
FileUtils.touch file2
|
FileUtils.touch file2
|
||||||
stop
|
stop
|
||||||
subject.changed_files.sort.should == ['spec/fixtures/folder1/file1.txt', 'spec/fixtures/folder1/folder2/file2.txt']
|
@results.sort.should == ['spec/fixtures/folder1/file1.txt', 'spec/fixtures/folder1/folder2/file2.txt']
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def start
|
def start
|
||||||
Thread.new { subject.start }
|
Thread.new { @listener.start }
|
||||||
sleep 1
|
sleep 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def stop
|
def stop
|
||||||
sleep 1
|
sleep 1
|
||||||
subject.stop
|
@listener.stop
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
Loading…
Reference in New Issue
Block a user