watchr 0.5.7 → 0.5.8
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Manifest +1 -1
- data/Rakefile +32 -27
- data/bin/watchr +3 -21
- data/lib/watchr.rb +1 -1
- data/lib/watchr/controller.rb +6 -2
- data/lib/watchr/event_handlers/portable.rb +17 -11
- data/lib/watchr/event_handlers/unix.rb +4 -0
- data/lib/watchr/script.rb +70 -26
- data/specs.watchr +5 -5
- data/test/event_handlers/test_portable.rb +91 -7
- data/test/test_controller.rb +10 -0
- data/test/test_helper.rb +1 -4
- data/test/test_script.rb +55 -15
- data/watchr.gemspec +16 -51
- metadata +5 -11
data/.gitignore
CHANGED
data/Manifest
CHANGED
data/Rakefile
CHANGED
@@ -1,40 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
end
|
6
|
-
|
7
|
-
desc "Generate rdoc documentation."
|
8
|
-
Rake::RDocTask.new(:rdoc => 'rdoc', :clobber_rdoc => 'rdoc:clean', :rerdoc => 'rdoc:force') { |rdoc|
|
9
|
-
rdoc.rdoc_dir = 'doc/rdoc'
|
10
|
-
rdoc.title = "Watchr"
|
11
|
-
rdoc.options << '--line-numbers' << '--inline-source'
|
12
|
-
rdoc.options << '--charset' << 'utf-8'
|
13
|
-
rdoc.main = 'README.rdoc'
|
14
|
-
rdoc.rdoc_files.include('README.rdoc')
|
15
|
-
rdoc.rdoc_files.include('TODO.txt')
|
16
|
-
rdoc.rdoc_files.include('LICENSE')
|
17
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
18
|
-
}
|
19
|
-
|
20
|
-
if defined? YARD
|
21
|
-
YARD::Rake::YardocTask.new do |t|
|
22
|
-
t.files = %w( lib/**/*.rb )
|
23
|
-
t.options = %w( -o doc/yard --readme README.rdoc --files LICENSE,TODO.txt )
|
24
|
-
end
|
25
|
-
end
|
1
|
+
# --------------------------------------------------
|
2
|
+
# Tests
|
3
|
+
# --------------------------------------------------
|
4
|
+
task(:default => "test:all")
|
26
5
|
|
27
6
|
namespace(:test) do
|
28
7
|
|
29
8
|
desc "Run all tests"
|
30
9
|
task(:all) do
|
31
10
|
tests = Dir['test/**/test_*.rb'] - ['test/test_helper.rb']
|
32
|
-
cmd = "ruby -rubygems -
|
11
|
+
cmd = "ruby -rubygems -I.:lib -e'%w( #{tests.join(' ')} ).each {|file| require file }'"
|
33
12
|
puts cmd if ENV['VERBOSE']
|
34
13
|
system cmd
|
35
14
|
end
|
36
15
|
|
37
|
-
desc "Run all tests on multiple ruby versions (requires rvm
|
16
|
+
desc "Run all tests on multiple ruby versions (requires rvm)"
|
38
17
|
task(:portability) do
|
39
18
|
versions = %w( 1.8.6 1.8.7 )
|
40
19
|
versions.each do |version|
|
@@ -47,3 +26,29 @@ namespace(:test) do
|
|
47
26
|
end
|
48
27
|
end
|
49
28
|
end
|
29
|
+
|
30
|
+
# --------------------------------------------------
|
31
|
+
# Docs
|
32
|
+
# --------------------------------------------------
|
33
|
+
require 'rake/rdoctask'
|
34
|
+
desc "Generate rdoc documentation."
|
35
|
+
Rake::RDocTask.new(:rdoc => 'rdoc', :clobber_rdoc => 'rdoc:clean', :rerdoc => 'rdoc:force') do |rdoc|
|
36
|
+
rdoc.rdoc_dir = 'doc/rdoc'
|
37
|
+
rdoc.title = "Watchr"
|
38
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
39
|
+
rdoc.options << '--charset' << 'utf-8'
|
40
|
+
rdoc.main = 'README.rdoc'
|
41
|
+
rdoc.rdoc_files.include('README.rdoc')
|
42
|
+
rdoc.rdoc_files.include('TODO.txt')
|
43
|
+
rdoc.rdoc_files.include('LICENSE')
|
44
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
45
|
+
end
|
46
|
+
|
47
|
+
desc "Generate YARD Documentation"
|
48
|
+
task(:yardoc) do
|
49
|
+
require 'yard'
|
50
|
+
files = %w( lib/**/*.rb )
|
51
|
+
options = %w( -o doc/yard --readme README.rdoc --files LICENSE )
|
52
|
+
YARD::CLI::Yardoc.run *(options + files)
|
53
|
+
end
|
54
|
+
|
data/bin/watchr
CHANGED
@@ -26,30 +26,12 @@ module Watchr
|
|
26
26
|
# ===== Returns
|
27
27
|
# <Pathname>::
|
28
28
|
# absolute path of first occurence of partial path in load path, or nil if not found
|
29
|
-
|
29
|
+
#--
|
30
|
+
# Adds '.' for ruby1.9.2
|
30
31
|
def find_in_load_path(path)
|
31
|
-
dir =
|
32
|
-
$LOAD_PATH.detect {|p| Pathname(p).join(path).exist? }
|
33
|
-
end
|
32
|
+
dir = (['.'] + $LOAD_PATH).uniq.detect {|p| Pathname(p).join(path).exist? }
|
34
33
|
dir ? path.expand_path(dir) : nil
|
35
34
|
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
# If the block returns nil, requires gem <tt>name</tt> and tries running the
|
40
|
-
# block again. If all fails, returns nil
|
41
|
-
#
|
42
|
-
# ===== Params
|
43
|
-
# name<Pathname,String>:: name of gem to require
|
44
|
-
#
|
45
|
-
# ===== Returns
|
46
|
-
# block's value or nil if gem <tt>name</tt> doesn't exist
|
47
|
-
#
|
48
|
-
def potentially_with_gem(name)
|
49
|
-
yield || (require(name) && yield)
|
50
|
-
rescue LoadError
|
51
|
-
nil
|
52
|
-
end
|
53
35
|
end
|
54
36
|
end
|
55
37
|
|
data/lib/watchr.rb
CHANGED
data/lib/watchr/controller.rb
CHANGED
@@ -21,10 +21,12 @@ module Watchr
|
|
21
21
|
#
|
22
22
|
# ===== Parameters
|
23
23
|
# script<Script>:: The script object
|
24
|
+
# handler<EventHanlder::Base>:: The filesystem event handler
|
24
25
|
#
|
25
26
|
def initialize(script, handler)
|
26
27
|
@script = script
|
27
28
|
@handler = handler
|
29
|
+
|
28
30
|
@handler.add_observer(self)
|
29
31
|
|
30
32
|
Watchr.debug "using %s handler" % handler.class.name
|
@@ -35,18 +37,20 @@ module Watchr
|
|
35
37
|
# Will block control flow until application is explicitly stopped/killed.
|
36
38
|
#
|
37
39
|
def run
|
40
|
+
@script.parse!
|
38
41
|
@handler.listen(monitored_paths)
|
42
|
+
rescue Interrupt
|
39
43
|
end
|
40
44
|
|
41
45
|
# Callback for file events.
|
42
46
|
#
|
43
|
-
# Called while control flow
|
47
|
+
# Called while control flow is in listening loop. It will execute the
|
44
48
|
# file's corresponding action as defined in the script. If the file is the
|
45
49
|
# script itself, it will refresh its state to account for potential changes.
|
46
50
|
#
|
47
51
|
# ===== Parameters
|
48
52
|
# path<Pathname, String>:: path that triggered event
|
49
|
-
#
|
53
|
+
# event_type<Symbol>:: event type
|
50
54
|
#
|
51
55
|
def update(path, event_type = nil)
|
52
56
|
path = Pathname(path).expand_path
|
@@ -3,11 +3,8 @@ module Watchr
|
|
3
3
|
class Portable
|
4
4
|
include Base
|
5
5
|
|
6
|
-
attr_accessor :monitored_paths
|
7
|
-
attr_accessor :reference_mtime
|
8
|
-
|
9
6
|
def initialize
|
10
|
-
@reference_mtime = Time.now
|
7
|
+
@reference_mtime = @reference_atime = @reference_ctime = Time.now
|
11
8
|
end
|
12
9
|
|
13
10
|
# Enters listening loop.
|
@@ -40,15 +37,24 @@ module Watchr
|
|
40
37
|
# ===== Returns
|
41
38
|
# path and type of event if event occured, nil otherwise
|
42
39
|
#
|
40
|
+
#--
|
41
|
+
# OPTIMIZE, REFACTOR
|
42
|
+
# TODO fix/figure out ENOENT error
|
43
43
|
def detect_event
|
44
|
-
|
45
|
-
|
46
|
-
if path.mtime > @reference_mtime
|
47
|
-
@reference_mtime = path.mtime
|
48
|
-
[path, :modified]
|
49
|
-
else
|
50
|
-
nil
|
44
|
+
@monitored_paths.each do |path|
|
45
|
+
return [path, :deleted] unless path.exist?
|
51
46
|
end
|
47
|
+
|
48
|
+
mtime_path = @monitored_paths.max {|a,b| a.mtime <=> b.mtime }
|
49
|
+
atime_path = @monitored_paths.max {|a,b| a.atime <=> b.atime }
|
50
|
+
ctime_path = @monitored_paths.max {|a,b| a.ctime <=> b.ctime }
|
51
|
+
|
52
|
+
if mtime_path.mtime > @reference_mtime then @reference_mtime = mtime_path.mtime; [mtime_path, :modified]
|
53
|
+
elsif atime_path.atime > @reference_atime then @reference_atime = atime_path.atime; [atime_path, :accessed]
|
54
|
+
elsif ctime_path.ctime > @reference_ctime then @reference_ctime = ctime_path.ctime; [ctime_path, :changed ]
|
55
|
+
else; nil; end
|
56
|
+
rescue Errno::ENOENT
|
57
|
+
retry
|
52
58
|
end
|
53
59
|
end
|
54
60
|
end
|
@@ -31,10 +31,14 @@ module Watchr
|
|
31
31
|
|
32
32
|
private
|
33
33
|
|
34
|
+
#--
|
35
|
+
# TODO fix/figure out ENOENT error
|
34
36
|
def update_reference_times
|
35
37
|
@reference_atime = pathname.atime
|
36
38
|
@reference_mtime = pathname.mtime
|
37
39
|
@reference_ctime = pathname.ctime
|
40
|
+
rescue Errno::ENOENT
|
41
|
+
retry
|
38
42
|
end
|
39
43
|
|
40
44
|
# Type of latest event.
|
data/lib/watchr/script.rb
CHANGED
@@ -20,23 +20,65 @@ module Watchr
|
|
20
20
|
#
|
21
21
|
Rule = Struct.new(:pattern, :event_type, :action)
|
22
22
|
|
23
|
-
#
|
24
|
-
|
23
|
+
# Script file evaluation context
|
24
|
+
#
|
25
|
+
# Script files are evaluated in the context of an instance of this class so
|
26
|
+
# that they get a clearly defined set of methods to work with. In other
|
27
|
+
# words, it is the user script's API.
|
28
|
+
#
|
29
|
+
class EvalContext #:nodoc:
|
30
|
+
|
31
|
+
def initialize(script)
|
32
|
+
@__script = script
|
33
|
+
end
|
34
|
+
|
35
|
+
# Delegated to Script
|
36
|
+
def default_action(&action)
|
37
|
+
@__script.default_action(&action)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Delegated to Script
|
41
|
+
def watch(*args, &block)
|
42
|
+
@__script.watch(*args, &block)
|
43
|
+
end
|
44
|
+
|
45
|
+
def reload
|
46
|
+
@__script.parse!
|
47
|
+
end
|
25
48
|
end
|
26
49
|
|
27
|
-
#
|
50
|
+
# EvalContext instance
|
51
|
+
#
|
52
|
+
# ===== Examples
|
53
|
+
# script.ec.watch('pattern') { }
|
54
|
+
# script.ec.rules
|
55
|
+
#
|
56
|
+
attr_reader :ec
|
57
|
+
|
58
|
+
# Defined rules
|
59
|
+
#
|
60
|
+
# ===== Returns
|
61
|
+
# Array[Rule]:: rules defined with #watch calls
|
62
|
+
#
|
63
|
+
attr_reader :rules
|
64
|
+
|
65
|
+
# Default action
|
28
66
|
#
|
29
|
-
#
|
30
|
-
#
|
67
|
+
# ===== Returns
|
68
|
+
# Proc:: action defined with #default_action call
|
69
|
+
#
|
70
|
+
attr_reader :default_action
|
71
|
+
|
72
|
+
# Create a script object for <tt>path</tt>.
|
31
73
|
#
|
32
74
|
# ===== Parameters
|
33
75
|
# path<Pathname>:: the path to the script
|
34
76
|
#
|
35
|
-
def initialize(path)
|
36
|
-
@path
|
77
|
+
def initialize(path = nil)
|
78
|
+
@path = path
|
37
79
|
@rules = []
|
38
80
|
@default_action = lambda {}
|
39
|
-
|
81
|
+
@ec = EvalContext.new(self)
|
40
82
|
end
|
41
83
|
|
42
84
|
# Main script API method. Builds a new rule, binding a pattern to an action.
|
@@ -106,24 +148,32 @@ module Watchr
|
|
106
148
|
# watch( 'TODO.txt' ) { system('rake --silent rdoc') }
|
107
149
|
# watch( 'LICENSE' ) { system('rake --silent rdoc') }
|
108
150
|
#
|
151
|
+
# ===== Returns
|
152
|
+
# Proc:: default action
|
153
|
+
#
|
109
154
|
def default_action(&action)
|
110
|
-
@default_action = action
|
155
|
+
@default_action = action if action
|
156
|
+
@default_action
|
157
|
+
end
|
158
|
+
|
159
|
+
# Reset script state
|
160
|
+
def reset
|
161
|
+
@rules = []
|
162
|
+
@default_action = lambda {}
|
111
163
|
end
|
112
164
|
|
113
165
|
# Eval content of script file.
|
114
166
|
#--
|
115
|
-
# TODO fix
|
167
|
+
# TODO fix/figure out ENOENT error
|
116
168
|
def parse!
|
117
|
-
|
118
|
-
|
169
|
+
return unless @path
|
119
170
|
reset
|
120
|
-
instance_eval(@path.read)
|
121
|
-
|
171
|
+
@ec.instance_eval(@path.read, @path.to_s)
|
122
172
|
rescue Errno::ENOENT
|
123
|
-
# TODO figure out why this is happening. still can't reproduce
|
124
|
-
Watchr.debug('script file "not found". wth')
|
125
173
|
sleep(0.3) #enough?
|
126
|
-
|
174
|
+
retry
|
175
|
+
ensure
|
176
|
+
Watchr.debug('loaded script file %s' % @path.to_s.inspect)
|
127
177
|
end
|
128
178
|
|
129
179
|
# Find an action corresponding to a path and event type. The returned
|
@@ -131,7 +181,7 @@ module Watchr
|
|
131
181
|
# match_data prepopulated.
|
132
182
|
#
|
133
183
|
# ===== Params
|
134
|
-
# path<Pathnane,String>:: Find action that
|
184
|
+
# path<Pathnane,String>:: Find action that corresponds to this path.
|
135
185
|
# event_type<Symbol>:: Find action only if rule's event if of this type.
|
136
186
|
#
|
137
187
|
# ===== Examples
|
@@ -163,10 +213,10 @@ module Watchr
|
|
163
213
|
# Path to the script file
|
164
214
|
#
|
165
215
|
# ===== Returns
|
166
|
-
# path<Pathname>:: path to script file
|
216
|
+
# path<Pathname>:: absolute path to script file
|
167
217
|
#
|
168
218
|
def path
|
169
|
-
Pathname(@path.respond_to?(:to_path) ? @path.to_path : @path.to_s).expand_path
|
219
|
+
@path && Pathname(@path.respond_to?(:to_path) ? @path.to_path : @path.to_s).expand_path
|
170
220
|
end
|
171
221
|
|
172
222
|
private
|
@@ -195,11 +245,5 @@ module Watchr
|
|
195
245
|
def rel_path(path)
|
196
246
|
Pathname(path).expand_path.relative_path_from(Pathname(Dir.pwd))
|
197
247
|
end
|
198
|
-
|
199
|
-
# Reset script state
|
200
|
-
def reset
|
201
|
-
@default_action = lambda {}
|
202
|
-
@rules.clear
|
203
|
-
end
|
204
248
|
end
|
205
249
|
end
|
data/specs.watchr
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# $ watchr specs.watchr
|
4
4
|
|
5
5
|
# --------------------------------------------------
|
6
|
-
#
|
6
|
+
# Helpers
|
7
7
|
# --------------------------------------------------
|
8
8
|
def run(cmd)
|
9
9
|
puts(cmd)
|
@@ -18,10 +18,10 @@ end
|
|
18
18
|
# --------------------------------------------------
|
19
19
|
# Watchr Rules
|
20
20
|
# --------------------------------------------------
|
21
|
-
watch( '^test.*/test_.*\.rb' ) { |m| run( "ruby -rubygems %s" % m[0] ) }
|
22
|
-
watch( '^lib/(.*)\.rb' ) { |m| run( "ruby -rubygems test/test_%s.rb" % m[1] ) }
|
23
|
-
watch( '^lib/watchr/(.*)\.rb' ) { |m| run( "ruby -rubygems test/test_%s.rb" % m[1] ) }
|
24
|
-
watch( '^lib/watchr/event_handlers/(.*)\.rb' ) { |m| run( "ruby -rubygems test/event_handlers/test_%s.rb" % m[1] ) }
|
21
|
+
watch( '^test.*/test_.*\.rb' ) { |m| run( "ruby -rubygems -I.:lib %s" % m[0] ) }
|
22
|
+
watch( '^lib/(.*)\.rb' ) { |m| run( "ruby -rubygems -I.:lib test/test_%s.rb" % m[1] ) }
|
23
|
+
watch( '^lib/watchr/(.*)\.rb' ) { |m| run( "ruby -rubygems -I.:lib test/test_%s.rb" % m[1] ) }
|
24
|
+
watch( '^lib/watchr/event_handlers/(.*)\.rb' ) { |m| run( "ruby -rubygems -I.:lib test/event_handlers/test_%s.rb" % m[1] ) }
|
25
25
|
watch( '^test/test_helper\.rb' ) { run_all_tests }
|
26
26
|
|
27
27
|
# --------------------------------------------------
|
@@ -1,5 +1,9 @@
|
|
1
1
|
require 'test/test_helper'
|
2
2
|
|
3
|
+
class Watchr::EventHandler::Portable
|
4
|
+
attr_accessor :monitored_paths
|
5
|
+
end
|
6
|
+
|
3
7
|
class PortableEventHandlerTest < Test::Unit::TestCase
|
4
8
|
include Watchr
|
5
9
|
|
@@ -12,10 +16,13 @@ class PortableEventHandlerTest < Test::Unit::TestCase
|
|
12
16
|
@baz = Pathname('baz').expand_path
|
13
17
|
@bax = Pathname('bax').expand_path
|
14
18
|
|
15
|
-
@
|
16
|
-
@bar.
|
17
|
-
|
18
|
-
|
19
|
+
@now = Time.now
|
20
|
+
[@foo, @bar, @baz, @bax].each do |path|
|
21
|
+
path.stubs(:mtime ).returns(@now - 100)
|
22
|
+
path.stubs(:atime ).returns(@now - 100)
|
23
|
+
path.stubs(:ctime ).returns(@now - 100)
|
24
|
+
path.stubs(:exist?).returns(true)
|
25
|
+
end
|
19
26
|
end
|
20
27
|
|
21
28
|
test "triggers listening state" do
|
@@ -31,15 +38,80 @@ class PortableEventHandlerTest < Test::Unit::TestCase
|
|
31
38
|
@handler.monitored_paths.should include(@bar)
|
32
39
|
end
|
33
40
|
|
34
|
-
test "
|
35
|
-
|
41
|
+
test "doesn't trigger on start" do
|
42
|
+
end
|
43
|
+
|
44
|
+
## event types
|
45
|
+
|
46
|
+
test "deleted file event" do
|
47
|
+
@foo.stubs(:exist?).returns(false)
|
48
|
+
|
49
|
+
@handler.listen [ @foo, @bar ]
|
50
|
+
@handler.expects(:notify).with(@foo, :deleted)
|
51
|
+
@handler.trigger
|
52
|
+
end
|
53
|
+
|
54
|
+
test "modified file event" do
|
55
|
+
@foo.stubs(:mtime).returns(@now + 100)
|
36
56
|
|
37
57
|
@handler.listen [ @foo, @bar ]
|
38
58
|
@handler.expects(:notify).with(@foo, :modified)
|
39
59
|
@handler.trigger
|
40
60
|
end
|
41
61
|
|
42
|
-
test "
|
62
|
+
test "accessed file event" do
|
63
|
+
@foo.stubs(:atime).returns(@now + 100)
|
64
|
+
|
65
|
+
@handler.listen [ @foo, @bar ]
|
66
|
+
@handler.expects(:notify).with(@foo, :accessed)
|
67
|
+
@handler.trigger
|
68
|
+
end
|
69
|
+
|
70
|
+
test "changed file event" do
|
71
|
+
@foo.stubs(:ctime).returns(@now + 100)
|
72
|
+
|
73
|
+
@handler.listen [ @foo, @bar ]
|
74
|
+
@handler.expects(:notify).with(@foo, :changed)
|
75
|
+
@handler.trigger
|
76
|
+
end
|
77
|
+
|
78
|
+
## event type priorities
|
79
|
+
|
80
|
+
test "mtime > atime" do
|
81
|
+
@foo.stubs(:mtime).returns(@now + 100)
|
82
|
+
@foo.stubs(:atime).returns(@now + 100)
|
83
|
+
@foo.stubs(:ctime).returns(@now + 100)
|
84
|
+
|
85
|
+
@handler.listen [ @foo, @bar ]
|
86
|
+
@handler.expects(:notify).with(@foo, :modified)
|
87
|
+
@handler.trigger
|
88
|
+
end
|
89
|
+
|
90
|
+
test "mtime > ctime" do
|
91
|
+
@foo.stubs(:mtime).returns(@now + 100)
|
92
|
+
@foo.stubs(:ctime).returns(@now + 100)
|
93
|
+
|
94
|
+
@handler.listen [ @foo, @bar ]
|
95
|
+
@handler.expects(:notify).with(@foo, :modified)
|
96
|
+
@handler.trigger
|
97
|
+
end
|
98
|
+
|
99
|
+
test "atime > ctime" do
|
100
|
+
@foo.stubs(:atime).returns(@now + 100)
|
101
|
+
@foo.stubs(:ctime).returns(@now + 100)
|
102
|
+
|
103
|
+
@handler.listen [ @foo, @bar ]
|
104
|
+
@handler.expects(:notify).with(@foo, :accessed)
|
105
|
+
@handler.trigger
|
106
|
+
end
|
107
|
+
|
108
|
+
test "deleted > mtime" do
|
109
|
+
@foo.stubs(:exist?).returns(false)
|
110
|
+
@foo.stubs(:mtime ).returns(@now + 100)
|
111
|
+
|
112
|
+
@handler.listen [ @foo, @bar ]
|
113
|
+
@handler.expects(:notify).with(@foo, :deleted)
|
114
|
+
@handler.trigger
|
43
115
|
end
|
44
116
|
|
45
117
|
## on the fly updates of monitored files list
|
@@ -55,4 +127,16 @@ class PortableEventHandlerTest < Test::Unit::TestCase
|
|
55
127
|
@handler.monitored_paths.should exclude(@foo)
|
56
128
|
@handler.monitored_paths.should exclude(@bar)
|
57
129
|
end
|
130
|
+
|
131
|
+
test "retries on ENOENT errors" do
|
132
|
+
@oops = Pathname('oops').expand_path
|
133
|
+
@oops.stubs(:exist?).returns(true)
|
134
|
+
@oops.stubs(:mtime).raises(Errno::ENOENT).
|
135
|
+
then.returns(Time.now + 100)
|
136
|
+
|
137
|
+
@handler.listen [ @oops ]
|
138
|
+
|
139
|
+
@handler.expects(:notify).with(@oops, :modified)
|
140
|
+
@handler.trigger
|
141
|
+
end
|
58
142
|
end
|
data/test/test_controller.rb
CHANGED
@@ -27,6 +27,11 @@ class TestController < Test::Unit::TestCase
|
|
27
27
|
@controller.run
|
28
28
|
end
|
29
29
|
|
30
|
+
test "parses the script on #run" do
|
31
|
+
@script.expects(:parse!)
|
32
|
+
@controller.run
|
33
|
+
end
|
34
|
+
|
30
35
|
test "adds itself as handler observer" do
|
31
36
|
@handler.count_observers.should be(1)
|
32
37
|
@handler.delete_observer(@controller)
|
@@ -99,5 +104,10 @@ class TestController < Test::Unit::TestCase
|
|
99
104
|
@handler.expects(:refresh).with %w( foo bar )
|
100
105
|
@controller.update(path)
|
101
106
|
end
|
107
|
+
|
108
|
+
test "exits gracefully when Interrupted" do
|
109
|
+
@handler.stubs(:listen).raises(Interrupt)
|
110
|
+
@controller.run
|
111
|
+
end
|
102
112
|
end
|
103
113
|
|
data/test/test_helper.rb
CHANGED
data/test/test_script.rb
CHANGED
@@ -4,20 +4,33 @@ class TestScript < Test::Unit::TestCase
|
|
4
4
|
include Watchr
|
5
5
|
|
6
6
|
def setup
|
7
|
-
|
8
|
-
@script = Script.new( Pathname.new( tmpfile.path ) )
|
7
|
+
@script = Script.new
|
9
8
|
end
|
10
9
|
|
11
10
|
## external api
|
12
11
|
|
13
12
|
test "watch" do
|
14
|
-
@script.watch('pattern')
|
15
|
-
@script.watch('pattern', :event_type)
|
16
|
-
@script.watch('pattern') { nil }
|
13
|
+
@script.ec.watch('pattern')
|
14
|
+
@script.ec.watch('pattern', :event_type)
|
15
|
+
@script.ec.watch('pattern') { nil }
|
17
16
|
end
|
18
17
|
|
19
18
|
test "default action" do
|
20
|
-
@script.default_action { nil }
|
19
|
+
@script.ec.default_action { nil }
|
20
|
+
end
|
21
|
+
|
22
|
+
test "reload" do
|
23
|
+
@script.ec.reload
|
24
|
+
end
|
25
|
+
|
26
|
+
test "eval context delegates methods to script" do
|
27
|
+
@script.ec.watch('pattern')
|
28
|
+
@script.ec.watch('pattern', :event_type)
|
29
|
+
@script.ec.watch('pattern') { nil }
|
30
|
+
@script.ec.default_action { :foo }
|
31
|
+
|
32
|
+
@script.rules.size.should be(3)
|
33
|
+
@script.default_action.call.should be(:foo)
|
21
34
|
end
|
22
35
|
|
23
36
|
## functionality
|
@@ -65,26 +78,48 @@ class TestScript < Test::Unit::TestCase
|
|
65
78
|
end
|
66
79
|
|
67
80
|
test "parses script file" do
|
68
|
-
|
69
|
-
|
81
|
+
path = Pathname( Tempfile.open('bar').path )
|
82
|
+
path.open('w') {|f| f.write <<-STR }
|
70
83
|
watch( 'abc' ) { :x }
|
71
84
|
STR
|
72
|
-
script = Script.new(
|
85
|
+
script = Script.new(path)
|
86
|
+
script.parse!
|
73
87
|
script.action_for('abc').call.should be(:x)
|
74
88
|
end
|
75
89
|
|
90
|
+
test "__FILE__ is set properly in script file" do
|
91
|
+
path = Pathname( Tempfile.open('bar').path )
|
92
|
+
path.open('w') {|f| f.write <<-STR }
|
93
|
+
throw __FILE__.to_sym
|
94
|
+
STR
|
95
|
+
script = Script.new(path)
|
96
|
+
lambda { script.parse! }.should throw_symbol(path.to_s.to_sym)
|
97
|
+
end
|
98
|
+
|
99
|
+
test "reloads script file" do
|
100
|
+
@script.expects(:parse!)
|
101
|
+
@script.ec.reload
|
102
|
+
end
|
103
|
+
|
104
|
+
test "skips parsing on nil script file" do
|
105
|
+
script = Script.new
|
106
|
+
script.ec.stubs(:instance_eval).raises(Exception) #negative expectation hack
|
107
|
+
script.parse!
|
108
|
+
end
|
109
|
+
|
76
110
|
test "resets state" do
|
77
111
|
@script.default_action { 'x' }
|
78
112
|
@script.watch('foo') { 'bar' }
|
79
|
-
@script.
|
80
|
-
@script.
|
81
|
-
@script.
|
113
|
+
@script.reset
|
114
|
+
@script.default_action.call.should be(nil)
|
115
|
+
@script.rules.should be([])
|
82
116
|
end
|
83
117
|
|
84
118
|
test "resets state on parse" do
|
85
|
-
|
86
|
-
|
87
|
-
|
119
|
+
script = Script.new( Pathname( Tempfile.new('foo').path ) )
|
120
|
+
script.stubs(:instance_eval)
|
121
|
+
script.expects(:reset)
|
122
|
+
script.parse!
|
88
123
|
end
|
89
124
|
|
90
125
|
test "actions receive a MatchData object" do
|
@@ -108,6 +143,11 @@ class TestScript < Test::Unit::TestCase
|
|
108
143
|
script.path.should be(path)
|
109
144
|
end
|
110
145
|
|
146
|
+
test "nil file path" do
|
147
|
+
script = Script.new
|
148
|
+
script.path.should be(nil)
|
149
|
+
end
|
150
|
+
|
111
151
|
test "later rules take precedence" do
|
112
152
|
@script.watch('a/(.*)\.x') { :x }
|
113
153
|
@script.watch('a/b/(.*)\.x') { :y }
|
data/watchr.gemspec
CHANGED
@@ -1,56 +1,21 @@
|
|
1
|
+
require 'lib/watchr'
|
1
2
|
|
2
3
|
Gem::Specification.new do |s|
|
3
|
-
s.name
|
4
|
-
s.
|
5
|
-
s.
|
6
|
-
s.
|
7
|
-
s.
|
8
|
-
s.
|
9
|
-
s.
|
10
|
-
s.has_rdoc
|
11
|
-
s.rdoc_options
|
12
|
-
s.extra_rdoc_files
|
13
|
-
s.require_path
|
14
|
-
s.bindir
|
15
|
-
s.executables
|
16
|
-
s.
|
17
|
-
|
18
|
-
History.txt
|
19
|
-
LICENSE
|
20
|
-
Manifest
|
21
|
-
README.rdoc
|
22
|
-
Rakefile
|
23
|
-
TODO.txt
|
24
|
-
bin/watchr
|
25
|
-
docs.watchr
|
26
|
-
gem.watchr
|
27
|
-
lib/watchr.rb
|
28
|
-
lib/watchr/controller.rb
|
29
|
-
lib/watchr/event_handlers/base.rb
|
30
|
-
lib/watchr/event_handlers/portable.rb
|
31
|
-
lib/watchr/event_handlers/unix.rb
|
32
|
-
lib/watchr/script.rb
|
33
|
-
manifest.watchr
|
34
|
-
specs.watchr
|
35
|
-
test/README
|
36
|
-
test/event_handlers/test_base.rb
|
37
|
-
test/event_handlers/test_portable.rb
|
38
|
-
test/event_handlers/test_unix.rb
|
39
|
-
test/test_controller.rb
|
40
|
-
test/test_helper.rb
|
41
|
-
test/test_script.rb
|
42
|
-
test/test_watchr.rb
|
43
|
-
watchr.gemspec
|
44
|
-
]
|
45
|
-
s.test_files = %w[
|
46
|
-
test/test_helper.rb
|
47
|
-
test/test_watchr.rb
|
48
|
-
test/test_script.rb
|
49
|
-
test/test_controller.rb
|
50
|
-
test/event_handlers/test_base.rb
|
51
|
-
test/event_handlers/test_unix.rb
|
52
|
-
test/event_handlers/test_portable.rb
|
53
|
-
]
|
4
|
+
s.name = "watchr"
|
5
|
+
s.summary = "Modern continious testing (flexible alternative to autotest)"
|
6
|
+
s.description = "Modern continious testing (flexible alternative to autotest)."
|
7
|
+
s.author = "mynyml"
|
8
|
+
s.email = "mynyml@gmail.com"
|
9
|
+
s.homepage = "http://mynyml.com/ruby/flexible-continuous-testing"
|
10
|
+
s.rubyforge_project = "watchr"
|
11
|
+
s.has_rdoc = true
|
12
|
+
s.rdoc_options = %w( --main README.rdoc )
|
13
|
+
s.extra_rdoc_files = %w( README.rdoc )
|
14
|
+
s.require_path = "lib"
|
15
|
+
s.bindir = "bin"
|
16
|
+
s.executables = "watchr"
|
17
|
+
s.version = Watchr::VERSION
|
18
|
+
s.files = File.read("Manifest").strip.split("\n")
|
54
19
|
|
55
20
|
s.add_development_dependency 'mocha'
|
56
21
|
s.add_development_dependency 'jeremymcanally-matchy'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: watchr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mynyml
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-11-12 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -122,16 +122,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
122
|
version:
|
123
123
|
requirements: []
|
124
124
|
|
125
|
-
rubyforge_project:
|
125
|
+
rubyforge_project: watchr
|
126
126
|
rubygems_version: 1.3.5
|
127
127
|
signing_key:
|
128
128
|
specification_version: 3
|
129
129
|
summary: Modern continious testing (flexible alternative to autotest)
|
130
|
-
test_files:
|
131
|
-
|
132
|
-
- test/test_watchr.rb
|
133
|
-
- test/test_script.rb
|
134
|
-
- test/test_controller.rb
|
135
|
-
- test/event_handlers/test_base.rb
|
136
|
-
- test/event_handlers/test_unix.rb
|
137
|
-
- test/event_handlers/test_portable.rb
|
130
|
+
test_files: []
|
131
|
+
|