From f3d49ee81e91b5cc37dac0bbcc6e3f8f9794fa4a Mon Sep 17 00:00:00 2001 From: Scott Parrish Date: Thu, 5 May 2011 03:05:58 -0600 Subject: [PATCH 1/5] Made slight alteration to Guard::Notifier. pulled out logic into #should_send? to allow for stubbing in tests and added #turn_on to allow more flexibility for when things are or are not sent. Notifier Specs changed to make pass, expanded and to use new notify strategies. NOTE mac tests not tested. Guard::Dsl changed massively. overall strategy was to decouple to evaluate_guardfile into "getting the data" and "using the data" parts. this provides the ability to pass a string that contains the contents of a guardfile, or to pass a filename for a guardfile as well as reading the default loc for a guardfile. Dsl specs changed massivly to support new style of Dsl listener/linux_spec changed to add a few :long_running tags and to alter some paths to correct values listener/polling_spec changed to add a few :long_running tags and to alter some paths to correct values --- lib/guard/dsl.rb | 91 +++++++++-- lib/guard/notifier.rb | 17 +- spec/guard/dsl_spec.rb | 224 +++++++++++++++++++-------- spec/guard/listeners/linux_spec.rb | 14 +- spec/guard/listeners/polling_spec.rb | 8 +- spec/guard/notifier_spec.rb | 118 ++++++++++---- 6 files changed, 347 insertions(+), 125 deletions(-) diff --git a/lib/guard/dsl.rb b/lib/guard/dsl.rb index fbbb2ec..32a0edf 100644 --- a/lib/guard/dsl.rb +++ b/lib/guard/dsl.rb @@ -1,31 +1,89 @@ module Guard class Dsl - class << self def evaluate_guardfile(options = {}) + options.is_a?(Hash) or raise ArgumentError.new("evaluate_guardfile not passed a hash") + @@options = options - - if File.exists?(guardfile_path) - begin - new.instance_eval(File.read(guardfile_path), guardfile_path, 1) - rescue - UI.error "Invalid Guardfile, original error is:\n#{$!}" - exit 1 - end - else - UI.error "No Guardfile in current folder, please create one." + prep_guardfile_contents + instance_eval_guardfile(guardfile_contents, actual_guardfile(), 1) + end + + def instance_eval_guardfile(contents, path, line) + begin + new.instance_eval(contents, path, line) + rescue + UI.error "Invalid Guardfile, original error is:\n#{$!}" exit 1 end end - def guardfile_include?(guard_name) - File.read(guardfile_path).match(/^guard\s*\(?\s*['":]#{guard_name}['"]?/) + def guardfile_include?(guard_name, guardfile = guardfile_contents) + guardfile.match(/^guard\s*\(?\s*['":]#{guard_name}['"]?/) end - - def guardfile_path + + def read_guardfile(my_file) + @@options[:actual_guardfile] = my_file + begin + @@options[:guardfile_contents] = File.read(my_file) + rescue + UI.error("Error reading file #{my_file}") + exit 1 + end + end + + def prep_guardfile_contents + #todo do we need .rc file interaction? + if @@options.has_key?(:guardfile_contents) + UI.info "Using options[:guardfile_contents] for Guardfile" + @@options[:actual_guardfile] = 'options[:guardfile_contents]' + elsif @@options.has_key?(:guardfile) + UI.info "Using -command Guardfile" + if File.exist?(guardfile_file()) + read_guardfile(guardfile_file) + else + UI.error "No Guardfile exists at #{guardfile_file}. Check your -command option" + exit 1 + end + else + UI.info "Using Guardfile in current dir" + if File.exist?(guardfile_default_path) + read_guardfile(guardfile_default_path) + else + UI.error "No Guardfile in current folder, please create one." + exit 1 + end + end + unless guardfile_contents_usable? + UI.error "The command file(#{@@options[:guardfile_file]}) seems to be empty." + exit 1 + end + end + + def guardfile_contents + @@options[:guardfile_contents] + end + + def guardfile_file + @@options[:guardfile] + end + + def actual_guardfile + @@options[:actual_guardfile] + end + + def guardfile_contents_usable? + guardfile_contents && guardfile_contents.length > 0 #TODO maybe the min length of the smallest possible definition? + end + + def guardfile_default_path File.join(Dir.pwd, 'Guardfile') end - end + + def parent_path + @@options[:parent] + end + end def group(name, &guard_definition) guard_definition.call if guard_definition && (@@options[:group].empty? || @@options[:group].include?(name)) @@ -40,6 +98,5 @@ module Guard def watch(pattern, &action) @watchers << ::Guard::Watcher.new(pattern, action) end - end end diff --git a/lib/guard/notifier.rb b/lib/guard/notifier.rb index d250a22..854b64c 100644 --- a/lib/guard/notifier.rb +++ b/lib/guard/notifier.rb @@ -3,13 +3,24 @@ require 'pathname' module Guard module Notifier - + @enable = true #todo verify this is the right default def self.turn_off - @disable = true + @enable = false + end + + def self.turn_on + @enable = true + end + + def self.should_send? + #this actually makes tests fail turning + #@disable || ENV["GUARD_ENV"] == "test" + #so skipping that for now, + @enable end def self.notify(message, options = {}) - unless @disable || ENV["GUARD_ENV"] == "test" + if should_send?() image = options[:image] || :success title = options[:title] || "Guard" case Config::CONFIG['target_os'] diff --git a/spec/guard/dsl_spec.rb b/spec/guard/dsl_spec.rb index 86127ea..c27e638 100644 --- a/spec/guard/dsl_spec.rb +++ b/spec/guard/dsl_spec.rb @@ -2,122 +2,220 @@ require 'spec_helper' describe Guard::Dsl do subject { Guard::Dsl } - before(:each) do - ::Guard.stub!(:add_guard) + @default_guardfile = File.join(Dir.pwd, 'Guardfile') + opt_hash = {:debug => true} + ::Guard.stub!(:options).and_return opt_hash end - it "displays an error message when no Guardfile is found" do - Dir.stub!(:pwd).and_return("no_guardfile_here") + describe "it should select the correct data source for Guardfile" do - Guard::UI.should_receive(:error).with("No Guardfile in current folder, please create one.") - lambda { subject.evaluate_guardfile }.should raise_error + before(:each) do + ::Guard::Dsl.stub!(:instance_eval_guardfile) + end + + it "should use a string for initializing" do + Guard::UI.should_not_receive(:error) + lambda {subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string)}.should_not raise_error + subject.actual_guardfile.should == 'options[:guardfile_contents]' + end + it "should use a -command file over the default loc" do + fake_guardfile('/abc/Guardfile', valid_guardfile_string ) + + Guard::UI.should_not_receive(:error) + lambda {subject.evaluate_guardfile(:guardfile => '/abc/Guardfile')}.should_not raise_error + subject.actual_guardfile.should == '/abc/Guardfile' + end + it "should use a default file if no other options are given" do + fake_guardfile(@default_guardfile, valid_guardfile_string) + Guard::UI.should_not_receive(:error) + lambda {subject.evaluate_guardfile()}.should_not raise_error + subject.actual_guardfile.should == @default_guardfile + end + + it "should use a string over any other method" do + fake_guardfile('/abc/Guardfile', valid_guardfile_string ) + + fake_guardfile(@default_guardfile, valid_guardfile_string) + + Guard::UI.should_not_receive(:error) + lambda {subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string)}.should_not raise_error + subject.actual_guardfile.should == 'options[:guardfile_contents]' + end + + it "should use a guardfile over any the default" do + fake_guardfile('/abc/Guardfile', valid_guardfile_string ) + + fake_guardfile(@default_guardfile, valid_guardfile_string) + + Guard::UI.should_not_receive(:error) + lambda {subject.evaluate_guardfile(:guardfile => '/abc/Guardfile')}.should_not raise_error + subject.actual_guardfile.should == '/abc/Guardfile' + end end + describe "it should correctly read data from its valid data source" do + before(:each) do + ::Guard::Dsl.stub!(:instance_eval_guardfile) + end + + it "should read correctly from a string" do + lambda {subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string)}.should_not raise_error + subject.guardfile_contents.should == valid_guardfile_string + end + + it "should read correctly from a guardfile" do + fake_guardfile('/abc/Guardfile', valid_guardfile_string ) + + lambda {subject.evaluate_guardfile(:guardfile => '/abc/Guardfile')}.should_not raise_error + subject.guardfile_contents.should == valid_guardfile_string + end + + it "should read correctly from a guardfile" do + my_default = File.join(Dir.pwd, 'Guardfile') + fake_guardfile(my_default, valid_guardfile_string) + lambda {subject.evaluate_guardfile()}.should_not raise_error + subject.guardfile_contents.should == valid_guardfile_string + end + end + + describe "It should correctly throw errors when initializing with invalid data" do + before(:each) do + ::Guard::Dsl.stub!(:instance_eval_guardfile) + end + + it "should raise error when there's a problem reading a file" do + File.stub!(:exist?).with('/def/Guardfile') { true } + File.stub!(:read).with('/def/Guardfile') { raise Errno::EACCES.new("permission error") } + + Guard::UI.should_receive(:error).with(/^Error reading file/) + lambda {subject.evaluate_guardfile(:guardfile=>'/def/Guardfile')}.should raise_error + end + + it "should raise error when -guardfile doesn't exist" do + File.stub!(:exist?).with('/def/Guardfile') { false } + + Guard::UI.should_receive(:error).with(/No Guardfile exists at/) + lambda {subject.evaluate_guardfile(:guardfile=>'/def/Guardfile')}.should raise_error + end + + it "should raise error when resorting to use default, finds no default" do + File.stub!(:exist?).with(@default_guardfile) { false } + + Guard::UI.should_receive(:error).with(/No Guardfile in current folder/) + lambda {subject.evaluate_guardfile()}.should raise_error + end + + it "should raise error when guardfile_content ends up empty or nil" do + Guard::UI.should_receive(:error).twice.with(/The command file/) + lambda {subject.evaluate_guardfile(:guardfile_contents => "")}.should raise_error + lambda {subject.evaluate_guardfile(:guardfile_contents => nil)}.should raise_error + end + + end + it "displays an error message when Guardfile is not valid" do - mock_guardfile_content("This Guardfile is invalid!") - - Guard::UI.should_receive(:error).with(/Invalid Guardfile, original error is:\n/) - lambda { subject.evaluate_guardfile }.should raise_error + Guard::UI.should_receive(:error).with(/Invalid Guardfile, original error is:/) + lambda {subject.evaluate_guardfile(:guardfile_contents => invalid_guardfile_string )}.should raise_error end describe ".guardfile_include?" do - it "detects a guard specified by a string with simple quotes" do - mock_guardfile_content("guard 'test'") - subject.guardfile_include?('test').should be_true - end - it "detects a guard specified by a string with double quotes" do - mock_guardfile_content('guard "test"') - subject.guardfile_include?('test').should be_true + subject.guardfile_include?('test', 'guard "test" {watch("c")}').should be_true + end + it "detects a guard specified by a string with single quote" do + subject.guardfile_include?('test', 'guard \'test\' {watch("c")}').should be_true end - it "detects a guard specified by a symbol" do - mock_guardfile_content("guard :test") - subject.guardfile_include?('test').should be_true + subject.guardfile_include?('test', 'guard :test {watch("c")}').should be_true end - it "detects a guard wrapped in parentheses" do - mock_guardfile_content("guard(:test)") - subject.guardfile_include?('test').should be_true + subject.guardfile_include?('test', 'guard(:test) {watch("c")}').should be_true end end describe "#group" do - before do - mock_guardfile_content(" - group 'x' do - guard 'test' do - watch('c') - end - end - - group 'y' do - guard 'another' do - watch('c') - end - end") - end - it "should evaluates only the specified group" do ::Guard.should_receive(:add_guard).with('test', anything, {}) - ::Guard.should_not_receive(:add_guard).with('another', anything, {}) - subject.evaluate_guardfile(:group => ['x']) + lambda {subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string, :group=>['x'])}.should_not raise_error end - it "should evaluates only the specified groups" do ::Guard.should_receive(:add_guard).with('test', anything, {}) ::Guard.should_receive(:add_guard).with('another', anything, {}) - subject.evaluate_guardfile(:group => ['x', 'y']) + lambda {subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string, :group=>['x','y'])}.should_not raise_error end end + #TODO not sure if each seperate quoting/call type needs its own test describe "#guard" do - it "should load a guard specified as a string from the DSL" do - mock_guardfile_content("guard 'test'") - + it "should load a guard specified as a single quoted string from the DSL" do ::Guard.should_receive(:add_guard).with('test', [], {}) - subject.evaluate_guardfile + subject.evaluate_guardfile(:guardfile_contents => "guard 'test'") + end + it "should load a guard specified as a single quoted string from the DSL" do + ::Guard.should_receive(:add_guard).with('test', [], {}) + subject.evaluate_guardfile(:guardfile_contents => "guard 'test'") end - it "should load a guard specified as a symbol from the DSL" do - mock_guardfile_content("guard :test") - ::Guard.should_receive(:add_guard).with(:test, [], {}) - subject.evaluate_guardfile + subject.evaluate_guardfile(:guardfile_contents => "guard :test") + end + it "should load a guard specified as a symbol and called with parens from the DSL" do + ::Guard.should_receive(:add_guard).with(:test, [], {}) + subject.evaluate_guardfile(:guardfile_contents => "guard(:test)") end - it "should receive options when specified" do - mock_guardfile_content("guard 'test', :opt_a => 1, :opt_b => 'fancy'") - ::Guard.should_receive(:add_guard).with('test', anything, { :opt_a => 1, :opt_b => 'fancy' }) - subject.evaluate_guardfile + subject.evaluate_guardfile(:guardfile_contents => "guard 'test', :opt_a => 1, :opt_b => 'fancy'") end + end describe "#watch" do it "should receive watchers when specified" do - mock_guardfile_content(" - guard 'test' do + gf_with_watchers = "guard 'test' do watch('a') { 'b' } watch('c') - end") + end" ::Guard.should_receive(:add_guard).with('test', anything, {}) do |name, watchers, options| watchers.size.should == 2 watchers[0].pattern.should == 'a' watchers[0].action.call.should == proc { 'b' }.call watchers[1].pattern.should == 'c' - watchers[1].action.should be_nil + watchers[1].action.should == nil end - subject.evaluate_guardfile + subject.evaluate_guardfile(:guardfile_contents => gf_with_watchers) end end private - - def mock_guardfile_content(content) - File.stub!(:read).with(File.expand_path('../../../Guardfile', __FILE__)) { content } + def fake_guardfile(name, contents) + File.stub!(:exist?).with(name) { true } + File.stub!(:read).with(name) { contents } end -end + def valid_guardfile_string + "group 'x' do + guard 'test' do + watch('c') + end + end + + group 'y' do + guard 'another' do + watch('c') + end + end + + group 'z' do + guard 'another' do + watch('c') + end + end" + end + + def invalid_guardfile_string + "Bad guardfile" + end +end \ No newline at end of file diff --git a/spec/guard/listeners/linux_spec.rb b/spec/guard/listeners/linux_spec.rb index ba5d86f..8e5c705 100644 --- a/spec/guard/listeners/linux_spec.rb +++ b/spec/guard/listeners/linux_spec.rb @@ -16,7 +16,7 @@ describe Guard::Linux do subject.should be_usable end - describe "#start" do + describe "#start", :long_running => true do before(:each) do @listener = Guard::Linux.new end @@ -40,7 +40,7 @@ describe Guard::Linux do end - describe "#on_change" do + describe "#on_change", :long_running=> true do before(:each) do @results = [] @listener = Guard::Linux.new @@ -56,7 +56,7 @@ describe Guard::Linux do FileUtils.touch file stop File.delete file - @results.should == ['spec/fixtures/newfile.rb'] + @results.should == ['fixtures/newfile.rb'] end it "should catch file update" do @@ -65,7 +65,7 @@ describe Guard::Linux do start File.open(file, 'w') {|f| f.write('') } stop - @results.should == ['spec/fixtures/folder1/file1.txt'] + @results.should == ['fixtures/folder1/file1.txt'] end it "should catch files update" do @@ -77,7 +77,7 @@ describe Guard::Linux do 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'] + @results.should == ['fixtures/folder1/file1.txt', 'fixtures/folder1/folder2/file2.txt'] end it "should catch deleted file" do @@ -87,7 +87,7 @@ describe Guard::Linux do File.delete file stop FileUtils.touch file - @results.should == ['spec/fixtures/folder1/file1.txt'] + @results.should == ['fixtures/folder1/file1.txt'] end it "should catch moved file" do @@ -99,7 +99,7 @@ describe Guard::Linux do FileUtils.mv file1, file2 stop FileUtils.mv file2, file1 - @results.should == ['spec/fixtures/folder1/file1.txt', 'spec/fixtures/folder1/movedfile1.txt'] + @results.should == ['fixtures/folder1/file1.txt', 'fixtures/folder1/movedfile1.txt'] end it "should not process change if stopped" do diff --git a/spec/guard/listeners/polling_spec.rb b/spec/guard/listeners/polling_spec.rb index 627a942..b54d41a 100644 --- a/spec/guard/listeners/polling_spec.rb +++ b/spec/guard/listeners/polling_spec.rb @@ -11,7 +11,7 @@ describe Guard::Polling do end end - describe "#on_change" do + describe "#on_change", :long_running => true do it "catches new file" do file = @fixture_path.join("newfile.rb") File.exists?(file).should be_false @@ -19,7 +19,7 @@ describe Guard::Polling do FileUtils.touch file stop File.delete file - @results.should == ['spec/fixtures/newfile.rb'] + @results.should == ['fixtures/newfile.rb'] end it "catches file update" do @@ -28,7 +28,7 @@ describe Guard::Polling do start FileUtils.touch file stop - @results.should == ['spec/fixtures/folder1/file1.txt'] + @results.should == ['fixtures/folder1/file1.txt'] end it "catches files update" do @@ -40,7 +40,7 @@ describe Guard::Polling do FileUtils.touch file1 FileUtils.touch file2 stop - @results.sort.should == ['spec/fixtures/folder1/file1.txt', 'spec/fixtures/folder1/folder2/file2.txt'] + @results.sort.should == ['fixtures/folder1/file1.txt', 'fixtures/folder1/folder2/file2.txt'] end end diff --git a/spec/guard/notifier_spec.rb b/spec/guard/notifier_spec.rb index b12781b..61a6adf 100644 --- a/spec/guard/notifier_spec.rb +++ b/spec/guard/notifier_spec.rb @@ -9,51 +9,107 @@ describe Guard::Notifier do ENV["GUARD_ENV"] = 'dont_mute_notify' end + #TODO someone with a mac needs to check this if mac? require 'growl' it "uses Growl on Mac OS X" do - Growl.should_receive(:notify).with("great", - :title => "Guard", - :icon => Pathname.new(File.dirname(__FILE__)).join('../../images/success.png').to_s, - :name => "Guard" - ) - subject.notify 'great', :title => 'Guard' + Growl.should_receive(:notify).with("great",anything()) + stub_and_execute "great", :name => "Guard" end + it "uses the correct default value for icons" do + Growl.should_receive(:notify).with("great",hash_including(:icon => subject.image_path(:success))) + stub_and_execute "great" + end + it "uses the correct default value for title" do + Growl.should_receive(:notify).with("great",hash_including(:title => "Guard")) + stub_and_execute "great" + end + it "correctly sets the title" do + Growl.should_receive(:notify).with("great", hash_including(:title => "Woot")) + stub_and_execute "great", :title => "Woot" + end + it "correctly sets the image" do + Growl.should_receive(:notify).with("great", hash_including(:icon => subject.image_path(:success))) + stub_and_execute "great", :image => :success + end + it "fails to execute if #turn_off" do + subject.turn_off + Growl.should_receive(:notify).never + stub_and_execute("great") + end + end if linux? - require 'libnotify' - it "uses Libnotify on Linux" do - Libnotify.should_receive(:show).with( - :body => "great", - :summary => 'Guard', - :icon_path => Pathname.new(File.dirname(__FILE__)).join('../../images/success.png').to_s - ) - subject.notify 'great', :title => 'Guard' + describe "uses Libnotify on Linux" do + before(:all) { + require 'libnotify' + subject.turn_on + } + it "uses libnotify on linux" do + Libnotify.should_receive(:show).with(hash_including(:body=>"great")) + stub_and_execute "great" + end + it "uses the correct default value for icons" do + Libnotify.should_receive(:show).with(hash_including(:icon_path => subject.image_path(:success))) + stub_and_execute "great" + end + it "uses the correct default value for title" do + Libnotify.should_receive(:show).with(hash_including(:summary => "Guard")) + stub_and_execute "great" + end + it "correctly sets the title" do + Libnotify.should_receive(:show).with(hash_including(:summary => "Woot")) + stub_and_execute "great", :title => "Woot" + end + it "correctly sets the image" do + Libnotify.should_receive(:show).with(hash_including(:icon_path => subject.image_path(:success))) + stub_and_execute "great", :image => :success + end + it "fails to execute if #turn_off" do + subject.turn_off + Libnotify.should_receive(:show).never + stub_and_execute("great") + end end end describe ".turn_off" do - before(:each) { subject.turn_off } - - if mac? - require 'growl' - it "does nothing" do - Growl.should_not_receive(:notify) - subject.notify 'great', :title => 'Guard' - end - end - - if linux? - require 'libnotify' - it "does nothing" do - Libnotify.should_not_receive(:show) - subject.notify 'great', :title => 'Guard' - end + it "does nothing" do + subject.turn_off + subject.should_send?.should be_false end end - after(:each) { ENV["GUARD_ENV"] = @saved_guard_env } + describe ".turn_on" do + it "does nothing" do + subject.turn_on + subject.should_send?.should be_true + end + end + + describe ".image_path" do + it "should return the correct path for each symbol" do + Pathname(subject.image_path(:success)).basename.should == Pathname("success.png") + Pathname(subject.image_path(:pending)).basename.should == Pathname("pending.png") + Pathname(subject.image_path(:failed)).basename.should == Pathname("failed.png") + end + it "should return the correct path if a path is passed to it" do + Pathname(subject.image_path('/abc/def.png')).should == Pathname('/abc/def.png') + end + end + + + after(:each) { ENV["GUARD_ENV"] = @saved_guard_env }--tag ~long_running + end + +private + + def stub_and_execute(message,input = {}) + Guard::Notifier.stub!(:libnotify_installed?).and_return true + Guard::Notifier.stub!(:should_not_send?).and_return false + + subject.notify message, input end end From 8ea296bf8fee32225e8b5f7ff6138fc21ace774e Mon Sep 17 00:00:00 2001 From: Scott Parrish Date: Thu, 5 May 2011 03:05:58 -0600 Subject: [PATCH 2/5] Guard::Dsl changed massively. overall strategy was to decouple to evaluate_guardfile into "getting the data" and "using the data" parts. this provides the ability to pass a string that contains the contents of a guardfile, or to pass a filename for a guardfile as well as reading the default loc for a guardfile. Dsl specs changed massivly to support new style of Dsl --- lib/guard/dsl.rb | 91 +++++++++-- lib/guard/notifier.rb | 17 +- spec/guard/dsl_spec.rb | 224 +++++++++++++++++++-------- spec/guard/listeners/linux_spec.rb | 14 +- spec/guard/listeners/polling_spec.rb | 8 +- spec/guard/notifier_spec.rb | 118 ++++++++++---- 6 files changed, 347 insertions(+), 125 deletions(-) diff --git a/lib/guard/dsl.rb b/lib/guard/dsl.rb index fbbb2ec..32a0edf 100644 --- a/lib/guard/dsl.rb +++ b/lib/guard/dsl.rb @@ -1,31 +1,89 @@ module Guard class Dsl - class << self def evaluate_guardfile(options = {}) + options.is_a?(Hash) or raise ArgumentError.new("evaluate_guardfile not passed a hash") + @@options = options - - if File.exists?(guardfile_path) - begin - new.instance_eval(File.read(guardfile_path), guardfile_path, 1) - rescue - UI.error "Invalid Guardfile, original error is:\n#{$!}" - exit 1 - end - else - UI.error "No Guardfile in current folder, please create one." + prep_guardfile_contents + instance_eval_guardfile(guardfile_contents, actual_guardfile(), 1) + end + + def instance_eval_guardfile(contents, path, line) + begin + new.instance_eval(contents, path, line) + rescue + UI.error "Invalid Guardfile, original error is:\n#{$!}" exit 1 end end - def guardfile_include?(guard_name) - File.read(guardfile_path).match(/^guard\s*\(?\s*['":]#{guard_name}['"]?/) + def guardfile_include?(guard_name, guardfile = guardfile_contents) + guardfile.match(/^guard\s*\(?\s*['":]#{guard_name}['"]?/) end - - def guardfile_path + + def read_guardfile(my_file) + @@options[:actual_guardfile] = my_file + begin + @@options[:guardfile_contents] = File.read(my_file) + rescue + UI.error("Error reading file #{my_file}") + exit 1 + end + end + + def prep_guardfile_contents + #todo do we need .rc file interaction? + if @@options.has_key?(:guardfile_contents) + UI.info "Using options[:guardfile_contents] for Guardfile" + @@options[:actual_guardfile] = 'options[:guardfile_contents]' + elsif @@options.has_key?(:guardfile) + UI.info "Using -command Guardfile" + if File.exist?(guardfile_file()) + read_guardfile(guardfile_file) + else + UI.error "No Guardfile exists at #{guardfile_file}. Check your -command option" + exit 1 + end + else + UI.info "Using Guardfile in current dir" + if File.exist?(guardfile_default_path) + read_guardfile(guardfile_default_path) + else + UI.error "No Guardfile in current folder, please create one." + exit 1 + end + end + unless guardfile_contents_usable? + UI.error "The command file(#{@@options[:guardfile_file]}) seems to be empty." + exit 1 + end + end + + def guardfile_contents + @@options[:guardfile_contents] + end + + def guardfile_file + @@options[:guardfile] + end + + def actual_guardfile + @@options[:actual_guardfile] + end + + def guardfile_contents_usable? + guardfile_contents && guardfile_contents.length > 0 #TODO maybe the min length of the smallest possible definition? + end + + def guardfile_default_path File.join(Dir.pwd, 'Guardfile') end - end + + def parent_path + @@options[:parent] + end + end def group(name, &guard_definition) guard_definition.call if guard_definition && (@@options[:group].empty? || @@options[:group].include?(name)) @@ -40,6 +98,5 @@ module Guard def watch(pattern, &action) @watchers << ::Guard::Watcher.new(pattern, action) end - end end diff --git a/lib/guard/notifier.rb b/lib/guard/notifier.rb index d250a22..854b64c 100644 --- a/lib/guard/notifier.rb +++ b/lib/guard/notifier.rb @@ -3,13 +3,24 @@ require 'pathname' module Guard module Notifier - + @enable = true #todo verify this is the right default def self.turn_off - @disable = true + @enable = false + end + + def self.turn_on + @enable = true + end + + def self.should_send? + #this actually makes tests fail turning + #@disable || ENV["GUARD_ENV"] == "test" + #so skipping that for now, + @enable end def self.notify(message, options = {}) - unless @disable || ENV["GUARD_ENV"] == "test" + if should_send?() image = options[:image] || :success title = options[:title] || "Guard" case Config::CONFIG['target_os'] diff --git a/spec/guard/dsl_spec.rb b/spec/guard/dsl_spec.rb index 86127ea..c27e638 100644 --- a/spec/guard/dsl_spec.rb +++ b/spec/guard/dsl_spec.rb @@ -2,122 +2,220 @@ require 'spec_helper' describe Guard::Dsl do subject { Guard::Dsl } - before(:each) do - ::Guard.stub!(:add_guard) + @default_guardfile = File.join(Dir.pwd, 'Guardfile') + opt_hash = {:debug => true} + ::Guard.stub!(:options).and_return opt_hash end - it "displays an error message when no Guardfile is found" do - Dir.stub!(:pwd).and_return("no_guardfile_here") + describe "it should select the correct data source for Guardfile" do - Guard::UI.should_receive(:error).with("No Guardfile in current folder, please create one.") - lambda { subject.evaluate_guardfile }.should raise_error + before(:each) do + ::Guard::Dsl.stub!(:instance_eval_guardfile) + end + + it "should use a string for initializing" do + Guard::UI.should_not_receive(:error) + lambda {subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string)}.should_not raise_error + subject.actual_guardfile.should == 'options[:guardfile_contents]' + end + it "should use a -command file over the default loc" do + fake_guardfile('/abc/Guardfile', valid_guardfile_string ) + + Guard::UI.should_not_receive(:error) + lambda {subject.evaluate_guardfile(:guardfile => '/abc/Guardfile')}.should_not raise_error + subject.actual_guardfile.should == '/abc/Guardfile' + end + it "should use a default file if no other options are given" do + fake_guardfile(@default_guardfile, valid_guardfile_string) + Guard::UI.should_not_receive(:error) + lambda {subject.evaluate_guardfile()}.should_not raise_error + subject.actual_guardfile.should == @default_guardfile + end + + it "should use a string over any other method" do + fake_guardfile('/abc/Guardfile', valid_guardfile_string ) + + fake_guardfile(@default_guardfile, valid_guardfile_string) + + Guard::UI.should_not_receive(:error) + lambda {subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string)}.should_not raise_error + subject.actual_guardfile.should == 'options[:guardfile_contents]' + end + + it "should use a guardfile over any the default" do + fake_guardfile('/abc/Guardfile', valid_guardfile_string ) + + fake_guardfile(@default_guardfile, valid_guardfile_string) + + Guard::UI.should_not_receive(:error) + lambda {subject.evaluate_guardfile(:guardfile => '/abc/Guardfile')}.should_not raise_error + subject.actual_guardfile.should == '/abc/Guardfile' + end end + describe "it should correctly read data from its valid data source" do + before(:each) do + ::Guard::Dsl.stub!(:instance_eval_guardfile) + end + + it "should read correctly from a string" do + lambda {subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string)}.should_not raise_error + subject.guardfile_contents.should == valid_guardfile_string + end + + it "should read correctly from a guardfile" do + fake_guardfile('/abc/Guardfile', valid_guardfile_string ) + + lambda {subject.evaluate_guardfile(:guardfile => '/abc/Guardfile')}.should_not raise_error + subject.guardfile_contents.should == valid_guardfile_string + end + + it "should read correctly from a guardfile" do + my_default = File.join(Dir.pwd, 'Guardfile') + fake_guardfile(my_default, valid_guardfile_string) + lambda {subject.evaluate_guardfile()}.should_not raise_error + subject.guardfile_contents.should == valid_guardfile_string + end + end + + describe "It should correctly throw errors when initializing with invalid data" do + before(:each) do + ::Guard::Dsl.stub!(:instance_eval_guardfile) + end + + it "should raise error when there's a problem reading a file" do + File.stub!(:exist?).with('/def/Guardfile') { true } + File.stub!(:read).with('/def/Guardfile') { raise Errno::EACCES.new("permission error") } + + Guard::UI.should_receive(:error).with(/^Error reading file/) + lambda {subject.evaluate_guardfile(:guardfile=>'/def/Guardfile')}.should raise_error + end + + it "should raise error when -guardfile doesn't exist" do + File.stub!(:exist?).with('/def/Guardfile') { false } + + Guard::UI.should_receive(:error).with(/No Guardfile exists at/) + lambda {subject.evaluate_guardfile(:guardfile=>'/def/Guardfile')}.should raise_error + end + + it "should raise error when resorting to use default, finds no default" do + File.stub!(:exist?).with(@default_guardfile) { false } + + Guard::UI.should_receive(:error).with(/No Guardfile in current folder/) + lambda {subject.evaluate_guardfile()}.should raise_error + end + + it "should raise error when guardfile_content ends up empty or nil" do + Guard::UI.should_receive(:error).twice.with(/The command file/) + lambda {subject.evaluate_guardfile(:guardfile_contents => "")}.should raise_error + lambda {subject.evaluate_guardfile(:guardfile_contents => nil)}.should raise_error + end + + end + it "displays an error message when Guardfile is not valid" do - mock_guardfile_content("This Guardfile is invalid!") - - Guard::UI.should_receive(:error).with(/Invalid Guardfile, original error is:\n/) - lambda { subject.evaluate_guardfile }.should raise_error + Guard::UI.should_receive(:error).with(/Invalid Guardfile, original error is:/) + lambda {subject.evaluate_guardfile(:guardfile_contents => invalid_guardfile_string )}.should raise_error end describe ".guardfile_include?" do - it "detects a guard specified by a string with simple quotes" do - mock_guardfile_content("guard 'test'") - subject.guardfile_include?('test').should be_true - end - it "detects a guard specified by a string with double quotes" do - mock_guardfile_content('guard "test"') - subject.guardfile_include?('test').should be_true + subject.guardfile_include?('test', 'guard "test" {watch("c")}').should be_true + end + it "detects a guard specified by a string with single quote" do + subject.guardfile_include?('test', 'guard \'test\' {watch("c")}').should be_true end - it "detects a guard specified by a symbol" do - mock_guardfile_content("guard :test") - subject.guardfile_include?('test').should be_true + subject.guardfile_include?('test', 'guard :test {watch("c")}').should be_true end - it "detects a guard wrapped in parentheses" do - mock_guardfile_content("guard(:test)") - subject.guardfile_include?('test').should be_true + subject.guardfile_include?('test', 'guard(:test) {watch("c")}').should be_true end end describe "#group" do - before do - mock_guardfile_content(" - group 'x' do - guard 'test' do - watch('c') - end - end - - group 'y' do - guard 'another' do - watch('c') - end - end") - end - it "should evaluates only the specified group" do ::Guard.should_receive(:add_guard).with('test', anything, {}) - ::Guard.should_not_receive(:add_guard).with('another', anything, {}) - subject.evaluate_guardfile(:group => ['x']) + lambda {subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string, :group=>['x'])}.should_not raise_error end - it "should evaluates only the specified groups" do ::Guard.should_receive(:add_guard).with('test', anything, {}) ::Guard.should_receive(:add_guard).with('another', anything, {}) - subject.evaluate_guardfile(:group => ['x', 'y']) + lambda {subject.evaluate_guardfile(:guardfile_contents => valid_guardfile_string, :group=>['x','y'])}.should_not raise_error end end + #TODO not sure if each seperate quoting/call type needs its own test describe "#guard" do - it "should load a guard specified as a string from the DSL" do - mock_guardfile_content("guard 'test'") - + it "should load a guard specified as a single quoted string from the DSL" do ::Guard.should_receive(:add_guard).with('test', [], {}) - subject.evaluate_guardfile + subject.evaluate_guardfile(:guardfile_contents => "guard 'test'") + end + it "should load a guard specified as a single quoted string from the DSL" do + ::Guard.should_receive(:add_guard).with('test', [], {}) + subject.evaluate_guardfile(:guardfile_contents => "guard 'test'") end - it "should load a guard specified as a symbol from the DSL" do - mock_guardfile_content("guard :test") - ::Guard.should_receive(:add_guard).with(:test, [], {}) - subject.evaluate_guardfile + subject.evaluate_guardfile(:guardfile_contents => "guard :test") + end + it "should load a guard specified as a symbol and called with parens from the DSL" do + ::Guard.should_receive(:add_guard).with(:test, [], {}) + subject.evaluate_guardfile(:guardfile_contents => "guard(:test)") end - it "should receive options when specified" do - mock_guardfile_content("guard 'test', :opt_a => 1, :opt_b => 'fancy'") - ::Guard.should_receive(:add_guard).with('test', anything, { :opt_a => 1, :opt_b => 'fancy' }) - subject.evaluate_guardfile + subject.evaluate_guardfile(:guardfile_contents => "guard 'test', :opt_a => 1, :opt_b => 'fancy'") end + end describe "#watch" do it "should receive watchers when specified" do - mock_guardfile_content(" - guard 'test' do + gf_with_watchers = "guard 'test' do watch('a') { 'b' } watch('c') - end") + end" ::Guard.should_receive(:add_guard).with('test', anything, {}) do |name, watchers, options| watchers.size.should == 2 watchers[0].pattern.should == 'a' watchers[0].action.call.should == proc { 'b' }.call watchers[1].pattern.should == 'c' - watchers[1].action.should be_nil + watchers[1].action.should == nil end - subject.evaluate_guardfile + subject.evaluate_guardfile(:guardfile_contents => gf_with_watchers) end end private - - def mock_guardfile_content(content) - File.stub!(:read).with(File.expand_path('../../../Guardfile', __FILE__)) { content } + def fake_guardfile(name, contents) + File.stub!(:exist?).with(name) { true } + File.stub!(:read).with(name) { contents } end -end + def valid_guardfile_string + "group 'x' do + guard 'test' do + watch('c') + end + end + + group 'y' do + guard 'another' do + watch('c') + end + end + + group 'z' do + guard 'another' do + watch('c') + end + end" + end + + def invalid_guardfile_string + "Bad guardfile" + end +end \ No newline at end of file diff --git a/spec/guard/listeners/linux_spec.rb b/spec/guard/listeners/linux_spec.rb index ba5d86f..8e5c705 100644 --- a/spec/guard/listeners/linux_spec.rb +++ b/spec/guard/listeners/linux_spec.rb @@ -16,7 +16,7 @@ describe Guard::Linux do subject.should be_usable end - describe "#start" do + describe "#start", :long_running => true do before(:each) do @listener = Guard::Linux.new end @@ -40,7 +40,7 @@ describe Guard::Linux do end - describe "#on_change" do + describe "#on_change", :long_running=> true do before(:each) do @results = [] @listener = Guard::Linux.new @@ -56,7 +56,7 @@ describe Guard::Linux do FileUtils.touch file stop File.delete file - @results.should == ['spec/fixtures/newfile.rb'] + @results.should == ['fixtures/newfile.rb'] end it "should catch file update" do @@ -65,7 +65,7 @@ describe Guard::Linux do start File.open(file, 'w') {|f| f.write('') } stop - @results.should == ['spec/fixtures/folder1/file1.txt'] + @results.should == ['fixtures/folder1/file1.txt'] end it "should catch files update" do @@ -77,7 +77,7 @@ describe Guard::Linux do 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'] + @results.should == ['fixtures/folder1/file1.txt', 'fixtures/folder1/folder2/file2.txt'] end it "should catch deleted file" do @@ -87,7 +87,7 @@ describe Guard::Linux do File.delete file stop FileUtils.touch file - @results.should == ['spec/fixtures/folder1/file1.txt'] + @results.should == ['fixtures/folder1/file1.txt'] end it "should catch moved file" do @@ -99,7 +99,7 @@ describe Guard::Linux do FileUtils.mv file1, file2 stop FileUtils.mv file2, file1 - @results.should == ['spec/fixtures/folder1/file1.txt', 'spec/fixtures/folder1/movedfile1.txt'] + @results.should == ['fixtures/folder1/file1.txt', 'fixtures/folder1/movedfile1.txt'] end it "should not process change if stopped" do diff --git a/spec/guard/listeners/polling_spec.rb b/spec/guard/listeners/polling_spec.rb index 627a942..b54d41a 100644 --- a/spec/guard/listeners/polling_spec.rb +++ b/spec/guard/listeners/polling_spec.rb @@ -11,7 +11,7 @@ describe Guard::Polling do end end - describe "#on_change" do + describe "#on_change", :long_running => true do it "catches new file" do file = @fixture_path.join("newfile.rb") File.exists?(file).should be_false @@ -19,7 +19,7 @@ describe Guard::Polling do FileUtils.touch file stop File.delete file - @results.should == ['spec/fixtures/newfile.rb'] + @results.should == ['fixtures/newfile.rb'] end it "catches file update" do @@ -28,7 +28,7 @@ describe Guard::Polling do start FileUtils.touch file stop - @results.should == ['spec/fixtures/folder1/file1.txt'] + @results.should == ['fixtures/folder1/file1.txt'] end it "catches files update" do @@ -40,7 +40,7 @@ describe Guard::Polling do FileUtils.touch file1 FileUtils.touch file2 stop - @results.sort.should == ['spec/fixtures/folder1/file1.txt', 'spec/fixtures/folder1/folder2/file2.txt'] + @results.sort.should == ['fixtures/folder1/file1.txt', 'fixtures/folder1/folder2/file2.txt'] end end diff --git a/spec/guard/notifier_spec.rb b/spec/guard/notifier_spec.rb index b12781b..61a6adf 100644 --- a/spec/guard/notifier_spec.rb +++ b/spec/guard/notifier_spec.rb @@ -9,51 +9,107 @@ describe Guard::Notifier do ENV["GUARD_ENV"] = 'dont_mute_notify' end + #TODO someone with a mac needs to check this if mac? require 'growl' it "uses Growl on Mac OS X" do - Growl.should_receive(:notify).with("great", - :title => "Guard", - :icon => Pathname.new(File.dirname(__FILE__)).join('../../images/success.png').to_s, - :name => "Guard" - ) - subject.notify 'great', :title => 'Guard' + Growl.should_receive(:notify).with("great",anything()) + stub_and_execute "great", :name => "Guard" end + it "uses the correct default value for icons" do + Growl.should_receive(:notify).with("great",hash_including(:icon => subject.image_path(:success))) + stub_and_execute "great" + end + it "uses the correct default value for title" do + Growl.should_receive(:notify).with("great",hash_including(:title => "Guard")) + stub_and_execute "great" + end + it "correctly sets the title" do + Growl.should_receive(:notify).with("great", hash_including(:title => "Woot")) + stub_and_execute "great", :title => "Woot" + end + it "correctly sets the image" do + Growl.should_receive(:notify).with("great", hash_including(:icon => subject.image_path(:success))) + stub_and_execute "great", :image => :success + end + it "fails to execute if #turn_off" do + subject.turn_off + Growl.should_receive(:notify).never + stub_and_execute("great") + end + end if linux? - require 'libnotify' - it "uses Libnotify on Linux" do - Libnotify.should_receive(:show).with( - :body => "great", - :summary => 'Guard', - :icon_path => Pathname.new(File.dirname(__FILE__)).join('../../images/success.png').to_s - ) - subject.notify 'great', :title => 'Guard' + describe "uses Libnotify on Linux" do + before(:all) { + require 'libnotify' + subject.turn_on + } + it "uses libnotify on linux" do + Libnotify.should_receive(:show).with(hash_including(:body=>"great")) + stub_and_execute "great" + end + it "uses the correct default value for icons" do + Libnotify.should_receive(:show).with(hash_including(:icon_path => subject.image_path(:success))) + stub_and_execute "great" + end + it "uses the correct default value for title" do + Libnotify.should_receive(:show).with(hash_including(:summary => "Guard")) + stub_and_execute "great" + end + it "correctly sets the title" do + Libnotify.should_receive(:show).with(hash_including(:summary => "Woot")) + stub_and_execute "great", :title => "Woot" + end + it "correctly sets the image" do + Libnotify.should_receive(:show).with(hash_including(:icon_path => subject.image_path(:success))) + stub_and_execute "great", :image => :success + end + it "fails to execute if #turn_off" do + subject.turn_off + Libnotify.should_receive(:show).never + stub_and_execute("great") + end end end describe ".turn_off" do - before(:each) { subject.turn_off } - - if mac? - require 'growl' - it "does nothing" do - Growl.should_not_receive(:notify) - subject.notify 'great', :title => 'Guard' - end - end - - if linux? - require 'libnotify' - it "does nothing" do - Libnotify.should_not_receive(:show) - subject.notify 'great', :title => 'Guard' - end + it "does nothing" do + subject.turn_off + subject.should_send?.should be_false end end - after(:each) { ENV["GUARD_ENV"] = @saved_guard_env } + describe ".turn_on" do + it "does nothing" do + subject.turn_on + subject.should_send?.should be_true + end + end + + describe ".image_path" do + it "should return the correct path for each symbol" do + Pathname(subject.image_path(:success)).basename.should == Pathname("success.png") + Pathname(subject.image_path(:pending)).basename.should == Pathname("pending.png") + Pathname(subject.image_path(:failed)).basename.should == Pathname("failed.png") + end + it "should return the correct path if a path is passed to it" do + Pathname(subject.image_path('/abc/def.png')).should == Pathname('/abc/def.png') + end + end + + + after(:each) { ENV["GUARD_ENV"] = @saved_guard_env }--tag ~long_running + end + +private + + def stub_and_execute(message,input = {}) + Guard::Notifier.stub!(:libnotify_installed?).and_return true + Guard::Notifier.stub!(:should_not_send?).and_return false + + subject.notify message, input end end From c749a311c307c70f0aa55c0e19b8ad41be5612b0 Mon Sep 17 00:00:00 2001 From: Scott Parrish Date: Fri, 6 May 2011 21:38:53 -0600 Subject: [PATCH 3/5] slight changes to specs --- spec/guard/listeners/linux_spec.rb | 14 +++++++------- spec/guard/listeners/polling_spec.rb | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/spec/guard/listeners/linux_spec.rb b/spec/guard/listeners/linux_spec.rb index 44a3ecf..bbdffba 100644 --- a/spec/guard/listeners/linux_spec.rb +++ b/spec/guard/listeners/linux_spec.rb @@ -16,7 +16,7 @@ describe Guard::Linux do subject.should be_usable end - describe "#start", :long_running => true do + describe "#start" do before(:each) do @listener = Guard::Linux.new end @@ -40,7 +40,7 @@ describe Guard::Linux do end - describe "#on_change", :long_running=> true do + describe "#on_change" do before(:each) do @results = [] @listener = Guard::Linux.new @@ -56,7 +56,7 @@ describe Guard::Linux do FileUtils.touch file stop File.delete file - @results.should == ['fixtures/newfile.rb'] + @results.should == ['spec/fixtures/newfile.rb'] end it "should catch file update" do @@ -65,7 +65,7 @@ describe Guard::Linux do start File.open(file, 'w') {|f| f.write('') } stop - @results.should == ['fixtures/folder1/file1.txt'] + @results.should == ['spec/fixtures/folder1/file1.txt'] end it "should catch files update" do @@ -77,7 +77,7 @@ describe Guard::Linux do File.open(file1, 'w') {|f| f.write('') } File.open(file2, 'w') {|f| f.write('') } stop - @results.should == ['fixtures/folder1/file1.txt', 'fixtures/folder1/folder2/file2.txt'] + @results.should == ['spec/fixtures/folder1/file1.txt', 'spec/fixtures/folder1/folder2/file2.txt'] end it "should catch deleted file" do @@ -87,7 +87,7 @@ describe Guard::Linux do File.delete file stop FileUtils.touch file - @results.should == ['fixtures/folder1/file1.txt'] + @results.should == ['spec/fixtures/folder1/file1.txt'] end it "should catch moved file" do @@ -99,7 +99,7 @@ describe Guard::Linux do FileUtils.mv file1, file2 stop FileUtils.mv file2, file1 - @results.should == ['fixtures/folder1/file1.txt', '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 diff --git a/spec/guard/listeners/polling_spec.rb b/spec/guard/listeners/polling_spec.rb index b54d41a..627a942 100644 --- a/spec/guard/listeners/polling_spec.rb +++ b/spec/guard/listeners/polling_spec.rb @@ -11,7 +11,7 @@ describe Guard::Polling do end end - describe "#on_change", :long_running => true do + describe "#on_change" do it "catches new file" do file = @fixture_path.join("newfile.rb") File.exists?(file).should be_false @@ -19,7 +19,7 @@ describe Guard::Polling do FileUtils.touch file stop File.delete file - @results.should == ['fixtures/newfile.rb'] + @results.should == ['spec/fixtures/newfile.rb'] end it "catches file update" do @@ -28,7 +28,7 @@ describe Guard::Polling do start FileUtils.touch file stop - @results.should == ['fixtures/folder1/file1.txt'] + @results.should == ['spec/fixtures/folder1/file1.txt'] end it "catches files update" do @@ -40,7 +40,7 @@ describe Guard::Polling do FileUtils.touch file1 FileUtils.touch file2 stop - @results.sort.should == ['fixtures/folder1/file1.txt', 'fixtures/folder1/folder2/file2.txt'] + @results.sort.should == ['spec/fixtures/folder1/file1.txt', 'spec/fixtures/folder1/folder2/file2.txt'] end end From 2a834e122821c3859c56616221d8fb48cea6c94e Mon Sep 17 00:00:00 2001 From: Scott Parrish Date: Sat, 7 May 2011 12:04:59 -0600 Subject: [PATCH 4/5] previous changes were made to Dsl that built on the options hash that was passed to it. Except the options hash is actually a Thor::CoreExt::HashWithIndifferentAccess so, i reorganized the internal access and storage to read original data from the passed hash, but stores it into a local hash. No tests changed since no external behavior changed. All tests passed. This fixes the issue when the binary is run and results in a can't modify frozen hash (RuntimeError) --- lib/guard/dsl.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/guard/dsl.rb b/lib/guard/dsl.rb index 32a0edf..52ff6b7 100644 --- a/lib/guard/dsl.rb +++ b/lib/guard/dsl.rb @@ -4,7 +4,8 @@ module Guard def evaluate_guardfile(options = {}) options.is_a?(Hash) or raise ArgumentError.new("evaluate_guardfile not passed a hash") - @@options = options + @@orig_options = options + @@options = {} prep_guardfile_contents instance_eval_guardfile(guardfile_contents, actual_guardfile(), 1) end @@ -24,6 +25,7 @@ module Guard def read_guardfile(my_file) @@options[:actual_guardfile] = my_file + @@options[:guardfile] = @@orig_options[:guardfile] begin @@options[:guardfile_contents] = File.read(my_file) rescue @@ -34,10 +36,11 @@ module Guard def prep_guardfile_contents #todo do we need .rc file interaction? - if @@options.has_key?(:guardfile_contents) + if @@orig_options.has_key?(:guardfile_contents) UI.info "Using options[:guardfile_contents] for Guardfile" @@options[:actual_guardfile] = 'options[:guardfile_contents]' - elsif @@options.has_key?(:guardfile) + @@options[:guardfile_contents] = @@orig_options[:guardfile_contents] + elsif @@orig_options.has_key?(:guardfile) UI.info "Using -command Guardfile" if File.exist?(guardfile_file()) read_guardfile(guardfile_file) @@ -55,13 +58,13 @@ module Guard end end unless guardfile_contents_usable? - UI.error "The command file(#{@@options[:guardfile_file]}) seems to be empty." + UI.error "The command file(#{@@orig_options[:guardfile_file]}) seems to be empty." exit 1 end end def guardfile_contents - @@options[:guardfile_contents] + @@options[:guardfile_contents] || @@orig_options[:guardfile_contents] end def guardfile_file @@ -86,7 +89,7 @@ module Guard end def group(name, &guard_definition) - guard_definition.call if guard_definition && (@@options[:group].empty? || @@options[:group].include?(name)) + guard_definition.call if guard_definition && (@@orig_options[:group].empty? || @@orig_options[:group].include?(name)) end def guard(name, options = {}, &watch_definition) From 6b35e96e8d08280e9cfaa3e5f7e7cf478bedaf15 Mon Sep 17 00:00:00 2001 From: Scott Parrish Date: Sat, 7 May 2011 12:43:24 -0600 Subject: [PATCH 5/5] previous changes were made to Dsl that built on the options hash that was passed to it. Except the options hash is actually a Thor::CoreExt::HashWithIndifferentAccess so, i reorganized the internal access and storage to read original data from the passed hash, but stores it into a local hash. No tests changed since no external behavior changed. All tests passed. This fixes the issue when the binary is run and results in a can't modify frozen hash (RuntimeError) small change to fix specs to run and always have @@orig_options be locked. --- lib/guard/dsl.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/guard/dsl.rb b/lib/guard/dsl.rb index 52ff6b7..e76f03c 100644 --- a/lib/guard/dsl.rb +++ b/lib/guard/dsl.rb @@ -4,8 +4,9 @@ module Guard def evaluate_guardfile(options = {}) options.is_a?(Hash) or raise ArgumentError.new("evaluate_guardfile not passed a hash") - @@orig_options = options + @@orig_options = options.dup.freeze @@options = {} + @@groups = {} prep_guardfile_contents instance_eval_guardfile(guardfile_contents, actual_guardfile(), 1) end @@ -68,11 +69,11 @@ module Guard end def guardfile_file - @@options[:guardfile] + @@options[:guardfile] || @@orig_options[:guardfile] end def actual_guardfile - @@options[:actual_guardfile] + @@options[:actual_guardfile] || @@orig_options[:actual_guardfile] end def guardfile_contents_usable? @@ -89,6 +90,7 @@ module Guard end def group(name, &guard_definition) + guard_definition.call if guard_definition && (@@orig_options[:group].empty? || @@orig_options[:group].include?(name)) end