nestor 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/.document +5 -0
  2. data/.gitignore +5 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +34 -0
  5. data/Rakefile +76 -0
  6. data/VERSION +1 -0
  7. data/bin/nestor +3 -0
  8. data/doc/.gitignore +3 -0
  9. data/doc/state-diagram.graffle +3870 -0
  10. data/doc/state-diagram.png +0 -0
  11. data/lib/nestor/cli.rb +52 -0
  12. data/lib/nestor/machine.rb +161 -0
  13. data/lib/nestor/strategies/test/unit.rb +116 -0
  14. data/lib/nestor/strategies.rb +18 -0
  15. data/lib/nestor/watchers/rails.rb +56 -0
  16. data/lib/nestor/watchers/rails_script.rb +83 -0
  17. data/lib/nestor/watchers.rb +1 -0
  18. data/lib/nestor.rb +11 -0
  19. data/spec/machine_spec.rb +56 -0
  20. data/spec/spec_helper.rb +9 -0
  21. data/vendor/watchr-0.5.7/.gitignore +5 -0
  22. data/vendor/watchr-0.5.7/History.txt +32 -0
  23. data/vendor/watchr-0.5.7/LICENSE +19 -0
  24. data/vendor/watchr-0.5.7/Manifest +27 -0
  25. data/vendor/watchr-0.5.7/README.rdoc +108 -0
  26. data/vendor/watchr-0.5.7/Rakefile +49 -0
  27. data/vendor/watchr-0.5.7/TODO.txt +40 -0
  28. data/vendor/watchr-0.5.7/bin/watchr +77 -0
  29. data/vendor/watchr-0.5.7/docs.watchr +26 -0
  30. data/vendor/watchr-0.5.7/gem.watchr +32 -0
  31. data/vendor/watchr-0.5.7/lib/watchr/controller.rb +81 -0
  32. data/vendor/watchr-0.5.7/lib/watchr/event_handlers/base.rb +48 -0
  33. data/vendor/watchr-0.5.7/lib/watchr/event_handlers/portable.rb +55 -0
  34. data/vendor/watchr-0.5.7/lib/watchr/event_handlers/unix.rb +97 -0
  35. data/vendor/watchr-0.5.7/lib/watchr/script.rb +203 -0
  36. data/vendor/watchr-0.5.7/lib/watchr.rb +113 -0
  37. data/vendor/watchr-0.5.7/manifest.watchr +70 -0
  38. data/vendor/watchr-0.5.7/specs.watchr +38 -0
  39. data/vendor/watchr-0.5.7/test/README +11 -0
  40. data/vendor/watchr-0.5.7/test/event_handlers/test_base.rb +24 -0
  41. data/vendor/watchr-0.5.7/test/event_handlers/test_portable.rb +58 -0
  42. data/vendor/watchr-0.5.7/test/event_handlers/test_unix.rb +162 -0
  43. data/vendor/watchr-0.5.7/test/test_controller.rb +103 -0
  44. data/vendor/watchr-0.5.7/test/test_helper.rb +52 -0
  45. data/vendor/watchr-0.5.7/test/test_script.rb +123 -0
  46. data/vendor/watchr-0.5.7/test/test_watchr.rb +60 -0
  47. data/vendor/watchr-0.5.7/watchr.gemspec +60 -0
  48. metadata +152 -0
Binary file
data/lib/nestor/cli.rb ADDED
@@ -0,0 +1,52 @@
1
+ require "nestor"
2
+ require "thor"
3
+
4
+ module Nestor
5
+ class Cli < Thor # :nodoc:
6
+ desc("start", <<-EODESC.gsub(/^\s{6}/, ""))
7
+ Starts a continuous test server.
8
+ EODESC
9
+ method_options :strategy => "test/unit", :watcher => "rails", :script => nil, :debug => false, :include => []
10
+ def start
11
+ puts "Using #{options[:strategy].inspect} strategy"
12
+ begin
13
+ # Try the internal version
14
+ require "nestor/strategies/#{options[:strategy]}"
15
+ rescue LoadError
16
+ # Else fallback to something I'm not aware of right now
17
+ require options[:strategy]
18
+ end
19
+
20
+ puts "Using #{options[:watcher].inspect} watcher"
21
+ begin
22
+ require "nestor/watchers/#{options[:watcher]}"
23
+ rescue LoadError
24
+ # Fallback to something external again
25
+ require options[:watcher]
26
+ end
27
+
28
+ Watchr.options.debug = options[:debug]
29
+
30
+ if options[:script] then
31
+ puts "Launching with custom script #{options[:script].inspect}"
32
+ else
33
+ puts "Launching..."
34
+ end
35
+ Nestor::Watchers::Rails.run(:script => Pathname.new(options[:script]))
36
+ end
37
+
38
+ desc("customize PATH", <<-EODESC.gsub(/^\s{6}/, ""))
39
+ Copies the named script file to PATH to allow customizing.
40
+ EODESC
41
+ method_options :strategy => "test/unit", :watcher => "rails"
42
+ def customize(path)
43
+ puts "Using #{options[:watcher].inspect} watcher"
44
+ require "nestor/watchers/#{options[:watcher]}"
45
+
46
+ raise "Destination #{path.inspect} already exists: will not overwrite" if File.file?(path)
47
+ FileUtils.cp(Nestor::Watchers::Rails.path_to_script, path)
48
+
49
+ puts "Wrote #{options[:watcher]} script to #{path.inspect}"
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,161 @@
1
+ require "state_machine"
2
+
3
+ module Nestor
4
+ # Implements the state machine that is at the heart of Nestor.
5
+ #
6
+ # == Usage
7
+ #
8
+ # In the Watchr script, use +@strategy+ to access an instance of this class.
9
+ #
10
+ # The available events you may call are:
11
+ #
12
+ # <tt>ready!</tt>:: Machine instances start in the +booting+ state. Once the boot is complete,
13
+ # call +ready+ to indicate you are ready to process events. The default
14
+ # rails template calls #ready when +test/test_helper.rb+ is loaded.
15
+ #
16
+ # <tt>changed!</tt>:: Tells the Machine a file changed. The Watchr script and Strategy are
17
+ # responsible for assigning meaning to the file. The default Watchr
18
+ # script knows how to map model, controller and view files to given
19
+ # tests, and the script thus only tells the Machine about test files.
20
+ # Nothing prevents another implementation from providing the actual
21
+ # implementation files and letting the Strategy decide later what to
22
+ # do about those.
23
+ #
24
+ # <tt>run_successful!</tt>:: Tells the Machine that the last build was successful. This
25
+ # does not necessarily indicate a a completely green build: only
26
+ # that the last run was successful, given the focused files.
27
+ #
28
+ # <tt>run_failed!</tt>:: Tells the Machine there were one or more test failures or errors.
29
+ # Again, this doesn't mean the whole build failed: only the last couple
30
+ # of files had something that caused a failure.
31
+ #
32
+ # <tt>run!</tt>:: Tells the machine to tell the +#strategy+ to run the tests, given the current
33
+ # state of affairs. This might be running all tests, or a subset if the Machine
34
+ # is currently focusing on some items. A separate event is required by the
35
+ # Machine to allow coalescing multiple change events together.
36
+ #
37
+ class Machine
38
+ # The Machine actually delegates running the tests to another object, and this is it's reference.
39
+ attr_reader :strategy # :nodoc:
40
+
41
+ # The list of files we are focusing on, as received by #changed!
42
+ attr_reader :focused_files # :nodoc:
43
+
44
+ # The last changed file. Set by #changed!
45
+ attr_reader :changed_file # :nodoc:
46
+
47
+ # The list of failing tests or examples being focused on right now
48
+ attr_reader :focuses # :nodoc:
49
+
50
+ # +strategy+ is required, and must implement a couple of methods. See Nestor::Strategies for the required calls.
51
+ def initialize(strategy)
52
+ super() # Have to specify no-args, or else it'll raise an ArgumentError
53
+
54
+ @strategy = strategy
55
+ @focused_files, @focuses = [], []
56
+
57
+ log_state_change
58
+ end
59
+
60
+ state_machine :initial => :booting do
61
+ event :ready do
62
+ transition any => :running_all
63
+ end
64
+
65
+ event :failed do
66
+ transition [:running_all, :running_multi, :running_focused] => :run_focused
67
+ end
68
+
69
+ event :successful do
70
+ transition :running_focused => :running_multi
71
+ transition :running_multi => :running_all
72
+ transition :running_all => :green
73
+ end
74
+
75
+ event :file_changed do
76
+ transition [:run_focused, :run_focused_pending] => :run_focused_pending, :if => :changed_file_in_focused_files?
77
+ transition [:run_focused_pending, :run_multi_pending, :run_focused] => :run_multi_pending
78
+ transition :green => :run_multi_pending
79
+ end
80
+
81
+ event :run do
82
+ transition :run_focused_pending => :running_focused
83
+ transition :run_multi_pending => :running_multi
84
+ end
85
+
86
+ after_transition any => any, :do => :log_state_change
87
+ after_transition :to => :running_all, :do => :run_all_tests
88
+ after_transition :to => :running_focused, :do => :run_focused_tests
89
+ after_transition :to => :running_multi, :do => :run_multi_tests
90
+ before_transition :to => :run_focused, :do => :log_focus
91
+ before_transition :to => [:run_focused_pending, :run_multi_pending],
92
+ :do => :log_pending_run
93
+ after_transition :on => :file_changed, :do => :add_changed_file_to_focused_files
94
+ end
95
+
96
+ # Indicates the run was succesful: a green build. This does not indicate that the
97
+ # whole build was successful: only that the files that ran last were successful.
98
+ def run_successful!(files, tests)
99
+ successful!
100
+ end
101
+
102
+ # Indicates there were one or more failures. +files+ lists the actual files
103
+ # that failed, while +tests+ indicates the test names or examples that failed.
104
+ def run_failed!(files, tests)
105
+ @focused_files, @focuses = files, tests
106
+ failed!
107
+ end
108
+
109
+ # Notifies the Machine that a file changed. This might trigger a state change and schedule a build.
110
+ def changed!(file)
111
+ @changed_file = file
112
+ file_changed!
113
+ end
114
+
115
+ private
116
+
117
+ def run_all_tests
118
+ reset_focused_files
119
+ reset_focuses
120
+ @strategy.run_all
121
+ end
122
+
123
+ def run_multi_tests
124
+ reset_focuses
125
+ @strategy.run(focused_files)
126
+ end
127
+
128
+ def run_focused_tests
129
+ @strategy.run(focused_files, focuses)
130
+ end
131
+
132
+ def reset_focused_files
133
+ @focused_files.clear
134
+ end
135
+
136
+ def add_changed_file_to_focused_files
137
+ @focused_files << @changed_file unless @focused_files.include?(@changed_file)
138
+ end
139
+
140
+ def changed_file_in_focused_files?
141
+ @strategy.log("changed_file #{changed_file}, in focused_files? #{focused_files.inspect}")
142
+ focused_files.include?(changed_file)
143
+ end
144
+
145
+ def reset_focuses
146
+ focuses.clear
147
+ end
148
+
149
+ def log_state_change
150
+ @strategy.log("Machine entering state: #{state.inspect}")
151
+ end
152
+
153
+ def log_focus
154
+ @strategy.log("Focusing on #{focuses.inspect}")
155
+ end
156
+
157
+ def log_pending_run
158
+ @strategy.log("Run pending... Waiting for go ahead")
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,116 @@
1
+ require "yaml"
2
+ require "pathname"
3
+ require "test/unit/ui/console/testrunner"
4
+
5
+ module Nestor
6
+ module Strategies
7
+ module Test
8
+ class Unit
9
+ def initialize(root)
10
+ @root = Pathname.new(root).realpath
11
+ end
12
+
13
+ # Logs a message to STDOUT. This implementation forks, so the #log method also
14
+ # provides the PID of the logger.
15
+ def log(message)
16
+ STDOUT.printf "[%d] %s - %s\n", Process.pid, Time.now.strftime("%H:%M:%S"), message
17
+ STDOUT.flush
18
+ end
19
+
20
+ # Runs absolutely all tests as found by walking test/.
21
+ def run_all
22
+ fork do
23
+ log "Run all tests"
24
+ test_files = Dir["test/**/*_test.rb"]
25
+ test_files.each {|f| log(f); load f}
26
+
27
+ ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
28
+ test_runner = ::Nestor::Strategies::Test::TestRunner.new(nil)
29
+ result = ::Test::Unit::AutoRunner.run(false, nil, []) do |autorunner|
30
+ autorunner.runner = lambda { test_runner }
31
+ end
32
+
33
+ report(test_runner, test_files)
34
+ end
35
+ end
36
+
37
+ # Runs only the named files, and optionally focuses on only a couple of tests
38
+ # within the loaded test cases.
39
+ def run(test_files, focuses=[])
40
+ fork do
41
+ log "Running #{focuses.length} focused tests"
42
+ test_files.each {|f| log(f); load f}
43
+
44
+ ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
45
+ test_runner = ::Nestor::Strategies::Test::TestRunner.new(nil)
46
+ result = ::Test::Unit::AutoRunner.run(false, nil, []) do |autorunner|
47
+ autorunner.runner = lambda { test_runner }
48
+ autorunner.filters << proc{|t| focuses.include?(t.method_name)} unless focuses.empty?
49
+ end
50
+
51
+ report(test_runner, test_files)
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ # Since we forked, we can't call into the Machine from the child process. Upstream
58
+ # communications is implemented by writing new files to the filesystem and letting
59
+ # the parent process catch the changes.
60
+ def report(test_runner, test_files)
61
+ info = {"status" => test_runner.passed? ? "successful" : "failed", "failures" => {}}
62
+ failures = info["failures"]
63
+ test_runner.faults.each do |failure|
64
+ filename = if failure.respond_to?(:location) then
65
+ failure.location.detect do |loc|
66
+ filename = loc.split(":", 2).first
67
+ test_files.detect {|tf| filename.include?(tf)}
68
+ end
69
+ elsif failure.respond_to?(:exception) then
70
+ failure.exception.backtrace.detect do |loc|
71
+ filename = loc.split(":", 2).first
72
+ test_files.detect {|tf| filename.include?(tf)}
73
+ end
74
+ else
75
+ raise "Unknown object type received as failure: #{failure.inspect} doesn't have #exception or #location methods."
76
+ end
77
+
78
+ test_name = failure.test_name.split("(", 2).first.strip
79
+ if filename.nil? then
80
+ log("Could not map #{failure.test_name.inspect} to a specific test file: mapping to #{test_files.length}")
81
+ test_files.each do |tf|
82
+ failures[test_name] = tf
83
+ end
84
+ else
85
+ log("Failed #{failure.test_name.inspect} in #{filename.inspect}")
86
+ failures[test_name] = filename
87
+ end
88
+ end
89
+
90
+ File.open("tmp/nestor-results.yml", "w") {|io| io.write(info.to_yaml) }
91
+ log "Wrote #{failures.length} failure(s) to tmp/nestor-results.yml"
92
+ end
93
+ end
94
+
95
+ # A helper class that allows me to get more information from the build.
96
+ #
97
+ # This is something that definitely will change when Nestor is tested on Ruby 1.9.
98
+ class TestRunner < ::Test::Unit::UI::Console::TestRunner #:nodoc:
99
+ attr_reader :faults
100
+
101
+ # This is a duck-typing method. Test::Unit's design requiers a #run method,
102
+ # but it is implemented as a class method. I fake it here to allow me to
103
+ # pass an instance and have the actual TestRunner instance available afterwards.
104
+ def run(suite, output_level=NORMAL)
105
+ @suite = suite.respond_to?(:suite) ? suite.suite : suite
106
+ start
107
+ end
108
+
109
+ # Returns pass/fail status.
110
+ def passed?
111
+ @faults.empty?
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,18 @@
1
+ module Nestor
2
+ # Nestor::Cli will require a file named +nestor/strategies/#{strategy_name}+. If you want
3
+ # to provide custom strategies, make it available to Nestor using the correct path.
4
+ #
5
+ # Strategies are simple objects that implement the following protocol:
6
+ #
7
+ # <tt>log(message)</tt>:: Logs a simple message, either to the console or a logfile.
8
+ # The Machine will use the +log+ method to notify about it's
9
+ # state transitions.
10
+ #
11
+ # <tt>run_all</tt>:: Runs all the tests, no matter what. In the Rails &
12
+ # +Test::Unit+ case, this means <tt>Dir["test/**/*_test.rb"]</tt>.
13
+ #
14
+ # <tt>run(tests_files, focused_cases=[])</tt>:: Runs only a subset of the tests, maybe
15
+ # focusing on only a couple of tests / examples.
16
+ module Strategies
17
+ end
18
+ end
@@ -0,0 +1,56 @@
1
+ require "watchr"
2
+ require "pathname"
3
+
4
+ module Nestor
5
+ module Watchers
6
+ # Knows how to map file change events from Rails conventions to the corresponding test case.
7
+ module Rails
8
+ # Launches a Watchr::Controller to and never returns. The Controller will
9
+ # listen for file change events and trigger appropriate events on the Machine.
10
+ #
11
+ # By default, the Rails watcher will use the +Test::Unit+ strategy.
12
+ #
13
+ # @option options :strategy [Nestor::Strategies] The strategy to use. Must be an instance of a class that implements the protocol defined in Nestor::Strategies.
14
+ # @option options :script The path to the Watchr script.
15
+ #
16
+ # @return Never...
17
+ def self.run(options={})
18
+ strategy = options[:strategy] || Nestor::Strategies::Test::Unit.new(Dir.pwd)
19
+ script = instantiate_script(options[:script])
20
+
21
+ strategy.log "Instantiating machine"
22
+ script.nestor_strategy = strategy
23
+ script.nestor_machine = Nestor::Machine.new(strategy)
24
+ Watchr::Controller.new(script, Watchr.handler.new).run
25
+ end
26
+
27
+ def self.path_to_script
28
+ default_script_path
29
+ end
30
+
31
+ private
32
+
33
+ def self.default_script_path
34
+ Pathname.new(File.dirname(__FILE__) + "/rails_script.rb")
35
+ end
36
+
37
+ def self.instantiate_script(path) #:nodoc:
38
+ # Use the default if none provided
39
+ path = default_script_path if path.nil?
40
+
41
+ script = Watchr::Script.new(path)
42
+ class << script
43
+ def nestor_machine=(m)
44
+ @machine = m
45
+ end
46
+
47
+ def nestor_strategy=(s)
48
+ @strategy = s
49
+ end
50
+ end
51
+
52
+ script
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,83 @@
1
+ def log(message) #:nodoc:
2
+ @strategy.log(message)
3
+ end
4
+
5
+ RAILS_ENV = "test" unless defined?(RAILS_ENV)
6
+ log "Entering #{RAILS_ENV.inspect} environment"
7
+
8
+ log "Creating tmp/ if it doesn't exist"
9
+ Dir.mkdir("tmp") unless File.directory?("tmp")
10
+
11
+ log "Preloading test/test_helper.rb"
12
+ start_load_at = Time.now
13
+ $LOAD_PATH.unshift "test" unless $LOAD_PATH.include?("test")
14
+ require "test_helper"
15
+
16
+ end_load_at = Time.now
17
+ log "Waiting for changes (saving #{end_load_at - start_load_at} seconds per run)..."
18
+
19
+ def sendoff(timeout=0.8, path="tmp/nestor-sendoff") #:nodoc:
20
+ Thread.start(timeout, path) do |timeout, path|
21
+ log "Sendoff pending #{timeout}..."
22
+ sleep timeout
23
+ File.open(path, "w") {|io| io.write(rand.to_s)}
24
+ log "Sendoff fired on #{path}"
25
+ end
26
+ end
27
+
28
+ def changed!(filename) #:nodoc:
29
+ @machine.changed! filename
30
+ sendoff
31
+ end
32
+
33
+ watch 'app/models/(.+)\.rb' do |md|
34
+ test_file = "test/unit/#{md[1]}_test.rb"
35
+ log "#{md[0].inspect} => #{test_file.inspect}"
36
+ changed! test_file if File.file?(test_file)
37
+ end
38
+
39
+ watch 'app/controllers/(.+)\.rb' do |md|
40
+ test_file = "test/functional/#{md[1]}_test.rb"
41
+ log "#{md[0].inspect} => #{test_file.inspect}"
42
+ changed! test_file if File.file?(test_file)
43
+ end
44
+
45
+ # It might be possible to run focused tests with the view name
46
+ watch 'app/views/(.+)' do |md|
47
+ segments = md[1].split("/")
48
+ path = segments[0..-2]
49
+ test_file = "test/functional/#{path.join("/")}_controller_test.rb"
50
+ log "#{md[0].inspect} => #{test_file.inspect}"
51
+ changed! test_file if File.file?(test_file)
52
+ end
53
+
54
+ watch 'config/' do |md|
55
+ @machine.reset!
56
+ end
57
+
58
+ watch 'test/test_helper\.rb' do |md|
59
+ @machine.reset!
60
+ end
61
+
62
+ watch 'test/(?:unit|functional|integration|performance)/.*' do |md|
63
+ log "#{md[0].inspect} => #{md[0].inspect}"
64
+ changed! md[0]
65
+ end
66
+
67
+ watch 'tmp/nestor-results.yml' do |md|
68
+ # Since we received the results, we must receive our child process' status, or
69
+ # else we'll have zombie processes lying around
70
+ Thread.start { Process.wait }
71
+
72
+ info = YAML.load_file(md[0])
73
+ log "New results in: #{info.inspect}"
74
+ failures = info["failures"]
75
+ @machine.send("run_#{info["status"]}!", failures.values.uniq, failures.keys)
76
+ end
77
+
78
+ watch 'tmp/nestor-sendoff' do |_|
79
+ log "Sendoff"
80
+ @machine.run!
81
+ end
82
+
83
+ @machine.ready!
@@ -0,0 +1 @@
1
+ require "nestor/watchers/rails"
data/lib/nestor.rb ADDED
@@ -0,0 +1,11 @@
1
+ require "watchr"
2
+ require "nestor/machine"
3
+
4
+ begin
5
+ require "ruby-debug"
6
+ rescue LoadError
7
+ # Ignore: development dependency
8
+ end
9
+
10
+ module Nestor # :nodoc:
11
+ end
@@ -0,0 +1,56 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Nestor::Machine do
4
+ it "should accept a strategy on instantiation" do
5
+ strategy = mock.as_null_object
6
+ machine = Nestor::Machine.new(strategy)
7
+ machine.strategy.should be_equal(strategy)
8
+ end
9
+ end
10
+
11
+ describe Nestor::Machine do
12
+ before(:each) do
13
+ @strategy = mock
14
+ @strategy.stub(:run_all)
15
+ end
16
+
17
+ it "should start in the :running_all state" do
18
+ @machine = Nestor::Machine.new(@strategy)
19
+ machine.should be_running_all
20
+ end
21
+
22
+ it "should tell the strategy to run all tests" do
23
+ strategy = mock
24
+ strategy.should_receive(:run_all).with().once
25
+ Nestor::Machine.new(strategy)
26
+ end
27
+
28
+ it "should transition to :green when calling #successful" do
29
+ machine.successful
30
+ machine.should be_green
31
+ end
32
+
33
+ it "should transition to :run_focused when calling #failed" do
34
+ machine.failed
35
+ machine.should be_run_focused
36
+ end
37
+
38
+ def machine
39
+ @machine ||= Nestor::Machine.new(@strategy)
40
+ end
41
+ end
42
+
43
+ describe Nestor::Machine, "when in the run_focused state" do
44
+ before(:each) do
45
+ @strategy = mock
46
+ @strategy.stub(:run_all)
47
+ @machine = Nestor::Machine.new(@strategy)
48
+ @machine.failed
49
+ end
50
+
51
+ it "should transition to :running_focused when calling #changed!(filename)" do
52
+ @strategy.should_receive(:run).with(["spec/machine_spec.rb"])
53
+ @machine.changed!("spec/machine_spec.rb")
54
+ @machine.should be_running_focused
55
+ end
56
+ end
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'nestor'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
@@ -0,0 +1,5 @@
1
+ doc/
2
+ pkg/
3
+ bk/
4
+ .wiki
5
+ .yardoc
@@ -0,0 +1,32 @@
1
+
2
+ === v0.5.7
3
+
4
+ * Added manifest.watchr script
5
+ * Unix handler supports :deleted event type
6
+ * Unix handler supports :accessed (atime), :modified (mtime) and :changed
7
+ (ctime) event types (thanks gzuki[http://github.com/gzuki] for initial work)
8
+
9
+
10
+ === v0.5.6
11
+
12
+ * Rev gem optional in development (thanks TwP[http://github.com/TwP])
13
+ * Allow gems to bundle .watchr scripts (thanks foca[http://github.com/foca])
14
+
15
+ gemname/lib/gemname.watchr
16
+
17
+ is now automatically picked up with
18
+
19
+ $ watchr gemname.watchr
20
+
21
+ * Look for script in path
22
+ * debug msg when rev not found on *nix
23
+ * rake task for cross interpreter testing
24
+
25
+
26
+ === v0.5.5
27
+
28
+ * Rev gem is optional. Fixes issue #1
29
+ Install Rev to automatically get evented handler on *nix
30
+
31
+ gem install rev
32
+
@@ -0,0 +1,19 @@
1
+ Copyright © 2009 Martin Aumont (mynyml)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,27 @@
1
+ .gitignore
2
+ History.txt
3
+ LICENSE
4
+ Manifest
5
+ README.rdoc
6
+ Rakefile
7
+ TODO.txt
8
+ bin/watchr
9
+ docs.watchr
10
+ gem.watchr
11
+ lib/watchr.rb
12
+ lib/watchr/controller.rb
13
+ lib/watchr/event_handlers/base.rb
14
+ lib/watchr/event_handlers/portable.rb
15
+ lib/watchr/event_handlers/unix.rb
16
+ lib/watchr/script.rb
17
+ manifest.watchr
18
+ specs.watchr
19
+ test/README
20
+ test/event_handlers/test_base.rb
21
+ test/event_handlers/test_portable.rb
22
+ test/event_handlers/test_unix.rb
23
+ test/test_controller.rb
24
+ test/test_helper.rb
25
+ test/test_script.rb
26
+ test/test_watchr.rb
27
+ watchr.gemspec