Dir.glob now ignores files that don't need to be watched

By default, we don't watch ., .., .bundle, .git (this is HUGE), log, tmp and vendor (this is also HUGE). Also don't append '/' to the dir given to Guard::Listener#potentially_modified_files, the method now handles it internally.

In my case, Guard::Listener#potentially_modified_files was taking ~56 seconds (in a big Rails project), it takes now... less than 1 second.

Enjoy.
This commit is contained in:
Rémy Coutable 2011-07-21 01:40:40 +02:00
parent 9cc1cf64d1
commit 06be2107af
9 changed files with 35 additions and 27 deletions

View File

@ -61,7 +61,7 @@ module Guard
end
def all_files
potentially_modified_files [directory + '/'], :all => true
potentially_modified_files([@directory], :all => true)
end
# scopes all given paths to the current #directory
@ -78,9 +78,23 @@ module Guard
private
def potentially_modified_files(dirs, options = {})
match = options[:all] ? "**/*" : "*"
Dir.glob(dirs.map { |dir| "#{dir}#{match}" }, File::FNM_DOTMATCH).select { |file| File.file?(file) }
def potentially_modified_files(dirs, options={})
paths = Dir.glob(dirs.map { |d| "#{d.sub(%r{/+$}, '')}/*" }, File::FNM_DOTMATCH).reject do |path|
%w[. .. .bundle .git log tmp vendor].include?(File.basename(path))
end
if options[:all]
paths.inject([]) do |array, path|
if File.file?(path)
array << path
else
array += Dir.glob("#{path}/**/*", File::FNM_DOTMATCH).select { |p| File.file?(p) }
end
array
end
else
paths.select { |path| File.file?(path) }
end
end
# Depending on the filesystem, mtime is probably only precise to the second, so round

View File

@ -22,7 +22,7 @@ module Guard
def watch_change
until @stop
start = Time.now.to_f
files = modified_files([Dir.pwd + '/'], :all => true)
files = modified_files([Dir.pwd], :all => true)
@callback.call(files) unless files.empty?
nap_time = @latency - (Time.now.to_f - start)
sleep(nap_time) if nap_time > 0

View File

@ -33,7 +33,6 @@ module Guard
def watch(directory)
worker.watch(directory, :all_events, :recursive) do |event|
paths = [File.expand_path(event.watcher.path) + '/']
paths = [File.expand_path(event.watcher.path)]
files = modified_files(paths, :all => true)
@callback.call(files) unless files.empty?

View File

@ -32,9 +32,9 @@ describe Guard::Listener do
subject.stub!(:mac?).and_return(true)
Guard::Darwin.stub!(:usable?).and_return(true)
path, opts = 'path', {:foo => 23}
path, opts = 'path', { :foo => 23 }
Guard::Darwin.should_receive(:new).with(path, opts).and_return(true)
subject.select_and_init path, opts
subject.select_and_init(path, opts)
end
end
@ -90,24 +90,24 @@ describe Guard::Listener do
context "without the :all option" do
it "finds modified files only in the directory supplied" do
FileUtils.touch([file1, file2, file3])
subject.modified_files([@fixture_path.join("folder1/")], {}).should =~ ["spec/fixtures/folder1/deletedfile1.txt", "spec/fixtures/folder1/file1.txt"]
subject.modified_files([@fixture_path.join("folder1")], {}).should =~ ["spec/fixtures/folder1/deletedfile1.txt", "spec/fixtures/folder1/file1.txt"]
end
end
context "with the :all options" do
it "finds modified files within subdirectories" do
FileUtils.touch([file1, file2, file3])
subject.modified_files([@fixture_path.join("folder1/")], { :all => true }).should =~ ["spec/fixtures/folder1/deletedfile1.txt", "spec/fixtures/folder1/file1.txt", "spec/fixtures/folder1/folder2/file2.txt"]
subject.modified_files([@fixture_path.join("folder1")], { :all => true }).should =~ ["spec/fixtures/folder1/deletedfile1.txt", "spec/fixtures/folder1/file1.txt", "spec/fixtures/folder1/folder2/file2.txt"]
end
end
context "without updating the content" do
it "ignores the files for the second time" do
FileUtils.touch([file1, file2, file3])
subject.modified_files([@fixture_path.join("folder1/")], {}).should =~ ["spec/fixtures/folder1/deletedfile1.txt", "spec/fixtures/folder1/file1.txt"]
subject.modified_files([@fixture_path.join("folder1")], {}).should =~ ["spec/fixtures/folder1/deletedfile1.txt", "spec/fixtures/folder1/file1.txt"]
subject.update_last_event
FileUtils.touch([file1, file2, file3])
subject.modified_files([@fixture_path.join("folder1/")], {}).should == []
subject.modified_files([@fixture_path.join("folder1")], {}).should be_empty
sleep 1
end
end
@ -117,11 +117,11 @@ describe Guard::Listener do
it "identifies the files for the second time" do
FileUtils.touch([file1, file2, file3])
subject.modified_files([@fixture_path.join("folder1/")], {}).should =~ ["spec/fixtures/folder1/deletedfile1.txt", "spec/fixtures/folder1/file1.txt"]
subject.modified_files([@fixture_path.join("folder1")], {}).should =~ ["spec/fixtures/folder1/deletedfile1.txt", "spec/fixtures/folder1/file1.txt"]
subject.update_last_event
FileUtils.touch([file2, file3])
File.open(file1, "w") { |f| f.write("changed content") }
subject.modified_files([@fixture_path.join("folder1/")], {}).should =~ ["spec/fixtures/folder1/file1.txt"]
subject.modified_files([@fixture_path.join("folder1")], {}).should =~ ["spec/fixtures/folder1/file1.txt"]
sleep 1
end
end

View File

@ -23,7 +23,5 @@ describe Guard::Darwin do
it_should_behave_like "a listener that reacts to #on_change"
it_should_behave_like "a listener scoped to a specific directory"
end
end

View File

@ -74,5 +74,4 @@ describe Guard::Linux do
end
end
end

View File

@ -2,10 +2,8 @@ require 'spec_helper'
require 'guard/listeners/polling'
describe Guard::Polling do
subject { Guard::Polling }
it_should_behave_like "a listener that reacts to #on_change"
it_should_behave_like "a listener scoped to a specific directory"
end

View File

@ -25,5 +25,4 @@ describe Guard::Windows do
it_should_behave_like "a listener scoped to a specific directory"
end
end

View File

@ -53,7 +53,7 @@ shared_examples_for 'a listener that reacts to #on_change' do
file = @fixture_path.join("folder1/file1.txt")
File.exists?(file).should be_true
start
File.open(file, 'w') {|f| f.write('') }
File.open(file, 'w') { |f| f.write('') }
stop
results.should =~ ['spec/fixtures/folder1/file1.txt']
end
@ -62,7 +62,7 @@ shared_examples_for 'a listener that reacts to #on_change' do
file = @fixture_path.join(".dotfile")
File.exists?(file).should be_true
start
File.open(file, 'w') {|f| f.write('') }
File.open(file, 'w') { |f| f.write('') }
stop
results.should =~ ['spec/fixtures/.dotfile']
end
@ -73,8 +73,8 @@ shared_examples_for 'a listener that reacts to #on_change' do
File.exists?(file1).should be_true
File.exists?(file2).should be_true
start
File.open(file1, 'w') {|f| f.write('') }
File.open(file2, 'w') {|f| f.write('') }
File.open(file1, 'w') { |f| f.write('') }
File.open(file2, 'w') { |f| f.write('') }
stop
results.should =~ ['spec/fixtures/folder1/file1.txt', 'spec/fixtures/folder1/folder2/file2.txt']
end
@ -108,6 +108,7 @@ shared_examples_for "a listener scoped to a specific directory" do
@wd = @fixture_path.join("folder1")
@listener = described_class.new @wd
end
it "should base paths within this directory" do
record_results
new_file = @wd.join("folder2/newfile.rb")
@ -116,7 +117,7 @@ shared_examples_for "a listener scoped to a specific directory" do
File.exists?(new_file).should be_false
start
FileUtils.touch new_file
File.open(modified, 'w') {|f| f.write('') }
File.open(modified, 'w') { |f| f.write('') }
stop
File.delete new_file
results.should =~ ["folder2/newfile.rb", 'file1.txt']