Guard no more automatically convert String into Regexp in "watch" method patterns.

It allows to define:

watch("foo_bar.rb") without meaning /foo_bar.rb/ (where "foo_bar_rb.rb" would have been matched)

However, during the deprecation phase, strings that look like a regexes (e.g. "^foo_bar.rb", "foo_bar.rb$", "foo_.*bar.rb" or "foo_(bar|baz).rb" are converted automatically to Regexp and a *very annoying* deprecation message is displayed.
This commit is contained in:
Rémy Coutable 2010-12-16 01:22:42 +01:00
parent 62f9cd5311
commit 1831bf752f
6 changed files with 117 additions and 54 deletions

View File

@ -1,3 +1,9 @@
== Dec 16, 2010 [by rymai]
Features:
- 'watch' patterns are now more strict: Strings are matched with '==', Regexp are matched with Regexp#match.
- A deprecation warning is displayed if your Guardfile contains String that look like Regexp (bad!).
== Nov 26, 2010 [by rymai] == Nov 26, 2010 [by rymai]
Features: Features:

View File

@ -1,5 +1,5 @@
guard('rspec', :version => 2) do guard('rspec', :version => 2) do
watch(%|^spec/(.*)_spec\.rb|) watch(%r{^spec/(.*)_spec\.rb})
watch(%|^lib/(.*)\.rb|) { |m| "spec/#{m[1]}_spec.rb" } watch(%r{^lib/(.*)\.rb}) { |m| "spec/#{m[1]}_spec.rb" }
watch(%|^spec/spec_helper\.rb|) { "spec" } watch('spec/spec_helper.rb') { "spec" }
end end

View File

@ -1,6 +1,6 @@
= Guard = Guard
Guard is a command line tool to easly handle events on files modifications. Guard is a command line tool that easily handle events on files modifications.
== Features == Features
@ -27,33 +27,33 @@ Generate an empty Guardfile with:
guard init guard init
Add guard(s) you need (see available guards below) Add the guards you need (see available guards below)
=== On Mac OS X === On Mac OS X
Install rb-fsevent for {FSEvent}[http://en.wikipedia.org/wiki/FSEvents] support Install rb-fsevent for {FSEvent}[http://en.wikipedia.org/wiki/FSEvents] support:
gem install rb-fsevent gem install rb-fsevent
Install growl for Growl notification support Install growl for Growl notification support:
gem install growl gem install growl
And add it to you Gemfile And add it to you Gemfile:
gem 'growl' gem 'growl'
=== On Linux === On Linux
Install rb-inotify for {inotify}[http://en.wikipedia.org/wiki/Inotify] support Install rb-inotify for {inotify}[http://en.wikipedia.org/wiki/Inotify] support:
gem install rb-inotify gem install rb-inotify
Install libnotify for libonity notification support Install libnotify for libonity notification support:
gem install libnotify gem install libnotify
And add it to you Gemfile And add it to you Gemfile:
gem 'libnotify' gem 'libnotify'
@ -63,6 +63,12 @@ Just launch Guard inside your ruby/rails project with:
guard guard
or if you use Bundler, to run the guard executable specific to your bundle:
bundle exec guard
== Command line options
Shell can be cleared after each change with: Shell can be cleared after each change with:
guard -c guard -c
@ -71,11 +77,13 @@ Options list is available with:
guard help [TASK] guard help [TASK]
== Signal handlers
Signal handlers are used to interact with Guard: Signal handlers are used to interact with Guard:
- Ctrl-C - Quit Guard (call stop guard(s) method before) - Ctrl-C - Quit Guard (call each guard's run_all method, in the same order they are declared in the Guarfile)
- Ctrl-\ - Call run_all guard(s) method - Ctrl-\ - Call each guard's run_all method, in the same order they are declared in the Guarfile
- Ctrl-Z - Call reload guard(s) method - Ctrl-Z - Call each guard's reload method, in the same order they are declared in the Guarfile
== Available Guards == Available Guards
@ -109,6 +117,24 @@ Add guard definition to your Guardfile by running this command:
You are good to go! You are good to go!
== Guardfile DSL
Guardfile DSL consists of just two simple methods: guard & watch. Example:
guard 'rspec', :version => 2 do
# Regexp watch patterns are matched with Regexp#match
watch(%r{^spec/(.*)_spec\.rb})
watch(%r{^lib/(.*)\.rb}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch(%r{^spec/models/.*\.rb}) { ["spec/models", "spec/acceptance"] }
watch(%r{^spec/.*\.rb}) { `say hello` }
# String watch patterns are matched with simple '=='
watch('spec/spec_helper.rb') { "spec" }
end
- "guard" method allow to add a guard with an optional options hash
- "watch" method allow to define which files are supervised per this guard. A optional block can be added to overwrite path sending to run_on_change guard method or launch simple command.
== Create a guard == Create a guard
Create a new guard is very easy, just create a new gem with this basic structure: Create a new guard is very easy, just create a new gem with this basic structure:
@ -173,21 +199,6 @@ lib/guard/guard-name.rb inherit from guard/guard and should overwrite at least o
Looks at available guards code for more concrete example. Looks at available guards code for more concrete example.
== Guardfile DSL
Guardfile DSL consists of just two simple methods: guard & watch. Example:
guard 'rspec', :version => 2 do
watch(%|^spec/(.*)_spec\.rb|)
watch(%|^lib/(.*)\.rb|) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch(%|^spec/spec_helper\.rb|) { "spec" }
watch(%|^spec/models/.*\.rb|) { ["spec/models", "spec/acceptance"] }
watch(%|^spec/spec_helper\.rb|) { `say hello` }
end
- "guard" method allow to add a guard with an optional options hash
- "watch" method allow to define which files are supervised per this guard. A optional block can be added to overwrite path sending to run_on_change guard method or launch simple command.
== TODO == TODO
- Add more specs! Shame on me :) - Add more specs! Shame on me :)

View File

@ -53,8 +53,8 @@ module Guard
end end
end end
# Let a guard execute his task but # Let a guard execute its task but
# fire it if his work lead to 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)
guard.send(task_to_supervise, *args) guard.send(task_to_supervise, *args)
rescue Exception rescue Exception

View File

@ -4,6 +4,17 @@ module Guard
def initialize(pattern, action = nil) def initialize(pattern, action = nil)
@pattern, @action = pattern, action @pattern, @action = pattern, action
@@warning_printed ||= false
# deprecation warning
if @pattern.is_a?(String) && @pattern =~ /(^(\^))|(>?(\\\.)|(\.\*))|(\(.*\))|(\[.*\])|(\$$)/
unless @@warning_printed
UI.info "DEPRECATED!\nYou have strings in your Guardfile's watch patterns that seem to represent regexps.\nGuard matchs String with == and Regexp with Regexp#match.\nYou should either use plain String (without Regexp special characters) or real Regexp.\n"
@@warning_printed = true
end
UI.info "\"#{@pattern}\" has been converted to #{Regexp.new(@pattern).inspect}\n"
@pattern = Regexp.new(@pattern)
end
end end
def self.match_files(guard, files) def self.match_files(guard, files)
@ -31,7 +42,11 @@ module Guard
end end
def match_file?(file) def match_file?(file)
if @pattern.is_a?(Regexp)
file.match(@pattern) file.match(@pattern)
else
file == @pattern
end
end end
def call_action(matches) def call_action(matches)

View File

@ -8,19 +8,32 @@ describe Guard::Watcher do
expect { Guard::Watcher.new }.to raise_error(ArgumentError) expect { Guard::Watcher.new }.to raise_error(ArgumentError)
end end
it "should be set" do it "can be a string" do
Guard::Watcher.new(%|spec_helper\.rb|).pattern.should == %|spec_helper\.rb| Guard::Watcher.new('spec_helper.rb').pattern.should == 'spec_helper.rb'
end
it "can be a regexp" do
Guard::Watcher.new(/spec_helper\.rb/).pattern.should == /spec_helper\.rb/
end
describe "string looking like a regex" do
before(:each) { Guard::UI.should_receive(:info).any_number_of_times }
specify { Guard::Watcher.new('^spec_helper.rb').pattern.should == /^spec_helper.rb/ }
specify { Guard::Watcher.new('spec_helper.rb$').pattern.should == /spec_helper.rb$/ }
specify { Guard::Watcher.new('spec_helper\.rb').pattern.should == /spec_helper\.rb/ }
specify { Guard::Watcher.new('.*_spec.rb').pattern.should == /.*_spec.rb/ }
end end
end end
describe "action" do describe "action" do
it "should set action to nil by default" do it "should set action to nil by default" do
Guard::Watcher.new(%|spec_helper\.rb|).action.should be_nil Guard::Watcher.new(/spec_helper\.rb/).action.should be_nil
end end
it "should set action with a block" do it "should set action with a block" do
action = lambda { |m| "spec/#{m[1]}_spec.rb" } action = lambda { |m| "spec/#{m[1]}_spec.rb" }
Guard::Watcher.new(%|^lib/(.*).rb|, action).action.should == action Guard::Watcher.new(%r{^lib/(.*).rb}, action).action.should == action
end end
end end
@ -28,7 +41,7 @@ describe Guard::Watcher do
before(:all) { @guard = Guard::Guard.new } before(:all) { @guard = Guard::Guard.new }
describe "a watcher's with no action" do describe "a watcher's with no action" do
before(:all) { @guard.watchers = [Guard::Watcher.new(%|.*_spec\.rb|)] } before(:all) { @guard.watchers = [Guard::Watcher.new(/.*_spec\.rb/)] }
it "should return paths as they came" do it "should return paths as they came" do
Guard::Watcher.match_files(@guard, ['guard_rocks_spec.rb']).should == ['guard_rocks_spec.rb'] Guard::Watcher.match_files(@guard, ['guard_rocks_spec.rb']).should == ['guard_rocks_spec.rb']
@ -38,12 +51,12 @@ describe Guard::Watcher do
describe "a watcher's action with an arity equal to 0" do describe "a watcher's action with an arity equal to 0" do
before(:all) do before(:all) do
@guard.watchers = [ @guard.watchers = [
Guard::Watcher.new(%|spec_helper\.rb|, lambda { 'spec' }), Guard::Watcher.new(/spec_helper\.rb/, lambda { 'spec' }),
Guard::Watcher.new(%|addition\.rb|, lambda { 1 + 1 }), Guard::Watcher.new(/addition\.rb/, lambda { 1 + 1 }),
Guard::Watcher.new(%|hash\.rb|, lambda { Hash[:foo, 'bar'] }), Guard::Watcher.new(/hash\.rb/, lambda { Hash[:foo, 'bar'] }),
Guard::Watcher.new(%|array\.rb|, lambda { ['foo', 'bar'] }), Guard::Watcher.new(/array\.rb/, lambda { ['foo', 'bar'] }),
Guard::Watcher.new(%|blank\.rb|, lambda { '' }), Guard::Watcher.new(/blank\.rb/, lambda { '' }),
Guard::Watcher.new(%|uptime\.rb|, lambda { `uptime > /dev/null` }) Guard::Watcher.new(/uptime\.rb/, lambda { `uptime > /dev/null` })
] ]
end end
@ -70,12 +83,12 @@ describe Guard::Watcher do
describe "a watcher's action with an arity equal to 1" do describe "a watcher's action with an arity equal to 1" do
before(:all) do before(:all) do
@guard.watchers = [ @guard.watchers = [
Guard::Watcher.new(%|lib/(.*)\.rb|, lambda { |m| "spec/#{m[1]}_spec.rb" }), Guard::Watcher.new(%r{lib/(.*)\.rb}, lambda { |m| "spec/#{m[1]}_spec.rb" }),
Guard::Watcher.new(%|addition(.*)\.rb|, lambda { |m| 1 + 1 }), Guard::Watcher.new(/addition(.*)\.rb/, lambda { |m| 1 + 1 }),
Guard::Watcher.new(%|hash\.rb|, lambda { Hash[:foo, 'bar'] }), Guard::Watcher.new(/hash\.rb/, lambda { Hash[:foo, 'bar'] }),
Guard::Watcher.new(%|array(.*)\.rb|, lambda { |m| ['foo', 'bar'] }), Guard::Watcher.new(/array(.*)\.rb/, lambda { |m| ['foo', 'bar'] }),
Guard::Watcher.new(%|blank(.*)\.rb|, lambda { |m| '' }), Guard::Watcher.new(/blank(.*)\.rb/, lambda { |m| '' }),
Guard::Watcher.new(%|uptime(.*)\.rb|, lambda { |m| `uptime > /dev/null` }) Guard::Watcher.new(/uptime(.*)\.rb/, lambda { |m| `uptime > /dev/null` })
] ]
end end
@ -111,8 +124,8 @@ describe Guard::Watcher do
describe ".match_files?" do describe ".match_files?" do
before(:all) do before(:all) do
@guard1 = Guard::Guard.new([Guard::Watcher.new(%|.*_spec\.rb|)]) @guard1 = Guard::Guard.new([Guard::Watcher.new(/.*_spec\.rb/)])
@guard2 = Guard::Guard.new([Guard::Watcher.new(%|spec_helper\.rb|, 'spec')]) @guard2 = Guard::Guard.new([Guard::Watcher.new(/spec_helper\.rb/, 'spec')])
@guards = [@guard1, @guard2] @guards = [@guard1, @guard2]
end end
@ -126,10 +139,28 @@ describe Guard::Watcher do
end end
describe "#match_file?" do describe "#match_file?" do
subject { Guard::Watcher.new(%|.*_spec\.rb|) } describe "string pattern" do
describe "normal string" do
subject { Guard::Watcher.new('guard_rocks_spec.rb') }
specify { subject.match_file?('lib/my_wonderful_lib.rb').should be_false } specify { subject.match_file?('lib/my_wonderful_lib.rb').should be_false }
specify { subject.match_file?('guard_rocks_spec.rb').should be_true } specify { subject.match_file?('guard_rocks_spec.rb').should be_true }
end end
describe "string representing a regexp converted (while deprecation is active)" do
subject { Guard::Watcher.new('^guard_rocks_spec\.rb$') }
specify { subject.match_file?('lib/my_wonderful_lib.rb').should be_false }
specify { subject.match_file?('guard_rocks_spec.rb').should be_true }
end
end
describe "regexp pattern" do
subject { Guard::Watcher.new(/.*_spec\.rb/) }
specify { subject.match_file?('lib/my_wonderful_lib.rb').should be_false }
specify { subject.match_file?('guard_rocks_spec.rb').should be_true }
end
end
end end