Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/niklas/guard into niklas-…
Browse files Browse the repository at this point in the history
…master

Conflicts:
	lib/guard/listener.rb
	spec/guard/listeners/linux_spec.rb
  • Loading branch information
thibaudgg committed May 28, 2011
2 parents 1628a1f + b12769d commit 6a77f01
Show file tree
Hide file tree
Showing 11 changed files with 329 additions and 301 deletions.
61 changes: 53 additions & 8 deletions lib/guard/listener.rb
Expand Up @@ -9,35 +9,80 @@ module Guard
autoload :Polling, 'guard/listeners/polling'

class Listener
attr_reader :last_event, :sha1_checksums_hash
attr_reader :last_event, :sha1_checksums_hash, :directory, :callback

def self.select_and_init
def self.select_and_init(*a)
if mac? && Darwin.usable?
Darwin.new
Darwin.new(*a)
elsif linux? && Linux.usable?
Linux.new
Linux.new(*a)
elsif windows? && Windows.usable?
Windows.new
Windows.new(*a)
else
UI.info "Using polling (Please help us to support your system better than that.)"
Polling.new
Polling.new(*a)
end
end

def initialize
def initialize(directory=Dir.pwd, options={})
@directory = directory.to_s
@sha1_checksums_hash = {}
@relativate_paths = options.fetch(:relativate_paths, true)
update_last_event
end

def start
watch directory
end

def stop
end

def on_change(&callback)
@callback = callback
end

def update_last_event
@last_event = Time.now
end

def modified_files(dirs, options = {})
# <<<<<<< HEAD
# files = potentially_modified_files(dirs, options).select { |path| File.file?(path) && file_modified?(path) }
# files.map! { |file| file.gsub("#{Dir.pwd}/", '') }
# =======
files = potentially_modified_files(dirs, options).select { |path| File.file?(path) && file_modified?(path) }
files.map! { |file| file.gsub("#{Dir.pwd}/", '') }
relativate_paths files
end

def worker
raise NotImplementedError, "should respond to #watch"
end

# register a directory to watch. must be implemented by the subclasses
def watch(directory)
raise NotImplementedError, "do whatever you want here, given the directory as only argument"
end

def all_files
potentially_modified_files [directory + '/'], :all => true
# >>>>>>> b12769d2bf385b3c69973721144cae3d5d8fbed9
end

# scopes all given paths to the current #directory
def relativate_paths(paths)
return paths unless relativate_paths?
paths.map do |path|
path.gsub(%r~^#{directory}/~, '')
end
end

attr_writer :relativate_paths
def relativate_paths?
!!@relativate_paths
end


private

def potentially_modified_files(dirs, options = {})
Expand Down
26 changes: 17 additions & 9 deletions lib/guard/listeners/darwin.rb
Expand Up @@ -2,25 +2,23 @@ module Guard
class Darwin < Listener
attr_reader :fsevent

def initialize
def initialize(*)
super
@fsevent = FSEvent.new
end

def on_change(&callback)
@fsevent.watch Dir.pwd do |modified_dirs|
files = modified_files(modified_dirs)
update_last_event
callback.call(files)
end
def worker
@fsevent
end

def start
@fsevent.run
super
fsevent.run
end

def stop
@fsevent.stop
super
fsevent.stop
end

def self.usable?
Expand All @@ -36,5 +34,15 @@ def self.usable?
false
end

private

def watch(directory)
worker.watch directory do |modified_dirs|
files = modified_files(modified_dirs)
update_last_event
callback.call(files)
end
end

end
end
32 changes: 18 additions & 14 deletions lib/guard/listeners/linux.rb
@@ -1,8 +1,8 @@
module Guard
class Linux < Listener
attr_reader :inotify, :files, :latency, :callback
attr_reader :inotify, :files, :latency

def initialize
def initialize(*)
super

@inotify = INotify::Notifier.new
Expand All @@ -12,24 +12,16 @@ def initialize

def start
@stop = false
super
watch_change unless watch_change?
end

def stop
super
@stop = true
sleep latency
end

def on_change(&callback)
@callback = callback
inotify.watch(Dir.pwd, :recursive, :modify, :create, :delete, :move) do |event|
unless event.name == "" # Event on root directory
@files << event.absolute_name
end
end
rescue Interrupt
end

def self.usable?
require 'rb-inotify'
if !defined?(INotify::VERSION) || Gem::Version.new(INotify::VERSION.join('.')) < Gem::Version.new('0.5.1')
Expand All @@ -49,6 +41,19 @@ def watch_change?

private

def worker
@inotify
end

def watch(directory)
worker.watch(directory, :recursive, :modify, :create) do |event|
unless event.name == "" # Event on root directory
@files << event.absolute_name
end
end
rescue Interrupt
end

def watch_change
@watch_change = true
until @stop
Expand All @@ -61,8 +66,7 @@ def watch_change

unless files.empty?
files.uniq!
files.map! { |file| file.gsub("#{Dir.pwd}/", '') }
callback.call(files)
callback.call( relativate_paths(files) )
files.clear
end
end
Expand Down
16 changes: 9 additions & 7 deletions lib/guard/listeners/polling.rb
@@ -1,22 +1,20 @@
module Guard
class Polling < Listener
attr_reader :callback, :latency
attr_reader :latency

def initialize
def initialize(*)
super
@latency = 1.5
end

def on_change(&callback)
@callback = callback
end

def start
@stop = false
super
watch_change
end

def stop
super
@stop = true
end

Expand All @@ -27,11 +25,15 @@ def watch_change
start = Time.now.to_f
files = modified_files([Dir.pwd + '/'], :all => true)
update_last_event
callback.call(files) unless files.empty?
callback.call(relativate_paths(files)) unless files.empty?
nap_time = latency - (Time.now.to_f - start)
sleep(nap_time) if nap_time > 0
end
end

def watch(directory)
@existing = all_files
end

end
end
26 changes: 17 additions & 9 deletions lib/guard/listeners/windows.rb
Expand Up @@ -7,20 +7,13 @@ def initialize
@fchange = FChange::Notifier.new
end

def on_change(&callback)
@fchange.watch(Dir.pwd, :all_events, :recursive) do |event|
paths = [File.expand_path(event.watcher.path) + '/']
files = modified_files(paths, {:all => true})
update_last_event
callback.call(files)
end
end

def start
super
@fchange.run
end

def stop
super
@fchange.stop
end

Expand All @@ -32,5 +25,20 @@ def self.usable?
false
end

private

def worker
@fchange
end

def watch(directory)
worker.watch(directory, :all_events, :recursive) do |event|
paths = [File.expand_path(event.watcher.path) + '/']
files = modified_files(paths, {:all => true})
update_last_event
callback.call(files)
end
end

end
end
68 changes: 68 additions & 0 deletions spec/guard/listener_spec.rb
Expand Up @@ -27,6 +27,39 @@
Guard::Linux.should_receive(:new)
subject.select_and_init
end

it "forwards its arguments to the constructor" do
subject.stub!(:mac?).and_return(true)
Guard::Darwin.stub!(:usable?).and_return(true)

path, opts = 'path', {:foo => 23}
Guard::Darwin.should_receive(:new).with(path, opts).and_return(true)
subject.select_and_init path, opts
end
end

describe "#all_files" do
subject { described_class.new(@fixture_path) }

it "should return all files" do
subject.all_files.should =~ Dir.glob("#{@fixture_path}/**/*")
end
end

describe "#relativate_paths" do
subject { described_class.new('/tmp') }
before :each do
@paths = %w( /tmp/a /tmp/a/b /tmp/a.b/c.d )
end

it "should relativate paths to the configured directory" do
subject.relativate_paths(@paths).should =~ %w( a a/b a.b/c.d )
end

it "can be disabled" do
subject.relativate_paths = false
subject.relativate_paths(@paths).should == @paths
end
end

describe "#update_last_event" do
Expand Down Expand Up @@ -91,4 +124,39 @@
end
end

describe "working directory" do

context "unspecified" do
subject { described_class.new }
it "defaults to Dir.pwd" do
subject.directory.should == Dir.pwd
end
it "can be not changed" do
subject.should_not respond_to(:directory=)
end
end

context "specified as first argument to ::new" do
before :each do
@wd = @fixture_path.join("folder1")
end
subject { described_class.new @wd }
it "can be inspected" do
subject.directory.should == @wd.to_s
end
it "can be not changed" do
subject.should_not respond_to(:directory=)
end

it "will be used to watch" do
subject.should_receive(:watch).with(@wd.to_s)
@listener = subject # indeed.
start
stop
end
end

end


end

0 comments on commit 6a77f01

Please sign in to comment.