Skip to content

Commit 3a222c1

Browse files
committed
change Watcher.new to take an options hash; improve functional tests; glob understands ** and **/
1 parent e3725ed commit 3a222c1

File tree

9 files changed

+99
-45
lines changed

9 files changed

+99
-45
lines changed

.rspec

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
--color
2+
--format=documentation

Rakefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ desc "Run all specs"
1010
RSpec::Core::RakeTask.new('spec') do |t|
1111
ENV['ENV'] = "test"
1212
t.pattern = 'spec/**/*_spec.rb'
13-
t.ruby_opts = ['-rubygems'] if defined? Gem
13+
t.rspec_opts = ['--color']
1414
end
1515

1616
$rubyforge_project = 'pivotalrb'

lib/rerun/glob.rb

+20
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ def initialize glob_string
1212

1313
def to_regexp_string
1414
chars = @glob_string.split('')
15+
16+
chars = smoosh(chars)
17+
1518
curlies = 0;
1619
escaping = false;
1720
chars.map do |char|
@@ -20,6 +23,8 @@ def to_regexp_string
2023
char
2124
else
2225
case char
26+
when '**'
27+
"([^/]+/)*"
2328
when '*'
2429
".*"
2530
when "?"
@@ -58,5 +63,20 @@ def to_regexp_string
5863
def to_regexp
5964
Regexp.new(to_regexp_string)
6065
end
66+
67+
def smoosh chars
68+
out = []
69+
until chars.empty?
70+
char = chars.shift
71+
if char == "*" and chars.first == "*"
72+
chars.shift
73+
chars.shift if chars.first == "/"
74+
out.push("**")
75+
else
76+
out.push(char)
77+
end
78+
end
79+
out
80+
end
6181
end
6282
end

lib/rerun/runner.rb

+1-3
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,10 @@ def start
144144

145145
unless @watcher
146146

147-
watcher = Watcher.new do
147+
watcher = Watcher.new(:directory => dir, :pattern => pattern) do
148148
restart unless @restarting
149149
end
150150
say "Watching #{dir}/#{pattern}"
151-
watcher.add_directory(dir, pattern)
152-
watcher.sleep_time = 1
153151
watcher.start
154152
@watcher = watcher
155153
end

lib/rerun/watcher.rb

+27-23
Original file line numberDiff line numberDiff line change
@@ -13,38 +13,40 @@ class Watcher
1313
MODIFIED = 1
1414
DELETED = 2
1515

16-
attr_accessor :sleep_time, :priority
17-
attr_reader :directory
18-
19-
def initialize(&client_callback)
16+
attr_reader :directory, :pattern, :priority
17+
18+
# Create a file system watcher. Start it by calling #start.
19+
#
20+
# @param options[:directory] the directory to watch (default ".")
21+
# @param options[:pattern] the glob pattern to search under the watched directory (default "**/*")
22+
# @param options[:priority] the priority of the watcher thread (default 0)
23+
#
24+
def initialize(options = {}, &client_callback)
2025
@client_callback = client_callback
2126

22-
@sleep_time = 1
23-
@priority = 0
27+
options = {
28+
:directory => ".",
29+
:pattern => "**/*",
30+
:priority => 0,
31+
}.merge(options)
2432

25-
@directory = nil
26-
@files = []
33+
@pattern = options[:pattern]
34+
@directory = options[:directory]
35+
if FileTest.exists?(directory) && FileTest.readable?(directory) then
36+
@directory = Directory.new(directory, @pattern)
37+
else
38+
raise InvalidDirectoryError, "Dir '#{directory}' either doesnt exist or isnt readable"
39+
end
40+
@priority = options[:priority]
2741

2842
@found = nil
2943
@first_time = true
3044
@thread = nil
31-
32-
end
33-
34-
# add a directory to be watched
35-
# @param dir the directory to watch
36-
# @param expression the glob pattern to search under the watched directory
37-
def add_directory(dir, expression="**/*")
38-
if FileTest.exists?(dir) && FileTest.readable?(dir) then
39-
@directory = Directory.new(dir, expression)
40-
else
41-
raise InvalidDirectoryError, "Dir '#{dir}' either doesnt exist or isnt readable"
42-
end
4345
end
4446

4547
def prime
4648
@first_time = true
47-
@found = Hash.new()
49+
@found = {}
4850
examine
4951
@first_time = false
5052
end
@@ -58,13 +60,15 @@ def start
5860

5961
@thread = Thread.new do
6062
# todo: multiple dirs
63+
6164
# todo: convert each dir's pattern to a regex and get Listen to do the file scan for us
62-
@listener = Listen::Listener.new(@directory.dir) do |modified, added, removed|
65+
regexp = Glob.new(@pattern).to_regexp
66+
puts "regexp is #{regexp.inspect}"
67+
@listener = Listen::Listener.new(@directory.dir, :filter => regexp) do |modified, added, removed|
6368
#d { modified }
6469
#d { added }
6570
#d { removed }
6671
examine
67-
sleep(@sleep_time)
6872
end
6973
@listener.start
7074
end

spec/functional_spec.rb

+15-9
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
require "#{here}/spec_helper.rb"
33
require 'tmpdir'
44

5-
describe "Rerun functionally" do
5+
describe "the rerun command" do
66
before do
77
@dir = Dir.tmpdir + "/#{Time.now.to_i}"
88
FileUtils.mkdir_p(@dir)
@@ -15,15 +15,16 @@
1515

1616
after do
1717
# puts "Killing #{@pid}"
18-
Process.kill("KILL", @pid) && Process.wait(@pid)
18+
Process.kill("KILL", @pid) && Process.wait(@pid) rescue Errno::ESRCH
1919
end
2020

2121
def launch_inc
2222
@pid = fork do
2323
root = File.dirname(__FILE__) + "/.."
2424
exec("#{root}/bin/rerun -d '#{@dir}' ruby #{root}/inc.rb #{@file}")
2525
end
26-
sleep 4
26+
sleep 0.5 until File.exist?(@file)
27+
sleep 2 # let inc get going
2728
end
2829

2930
def read
@@ -51,14 +52,14 @@ def type char
5152
# todo: send a character to stdin of the rerun process
5253
end
5354

54-
it "counts up" do
55+
it "increments a test file once per second" do
5556
x = current_count
5657
sleep 1
5758
y = current_count
5859
y.should be > x
5960
end
6061

61-
it "restarts when an app file is modified" do
62+
it "restarts its target when an app file is modified" do
6263
first_launched_at, count = read
6364
touch @app_file
6465
sleep 4
@@ -67,7 +68,7 @@ def type char
6768
second_launched_at.should be > first_launched_at
6869
end
6970

70-
it "restarts when an app file is created" do
71+
it "restarts its target when an app file is created" do
7172
first_launched_at, count = read
7273
touch @app_file2
7374
sleep 4
@@ -76,9 +77,14 @@ def type char
7677
second_launched_at.should be > first_launched_at
7778
end
7879

79-
it "sends its child process a SIGINT when restarting"
80+
#it "sends its child process a SIGINT to restart"
8081

81-
it "dies when sent a control-C (SIGINT)"
82+
it "dies when sent a control-C (SIGINT)" do
83+
Process.kill("INT", @pid)
84+
timeout(6) {
85+
Process.wait(@pid) rescue Errno::ESRCH
86+
}
87+
end
8288

83-
it "accepts a key press"
89+
#it "accepts a key press"
8490
end

spec/glob_spec.rb

+31-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ module Rerun
2626
"\\*" => "\\*",
2727
"\\\\" => "\\\\",
2828

29-
#"**/*.txt" => "([^/]*/)*.*\\.txt"
29+
"**/*.txt" => "([^/]+/)*.*\\.txt",
3030

3131
}.each_pair do |glob_string, regexp_string|
3232
specify glob_string do
@@ -42,6 +42,36 @@ module Rerun
4242
end
4343
end
4444

45+
describe "#smoosh" do
46+
47+
def check_smoosh string, array
48+
glob = Glob.new("")
49+
glob.smoosh(string.split('')).should == array
50+
end
51+
52+
it "ignores non-stars" do
53+
check_smoosh "", []
54+
check_smoosh "abc", ["a", "b", "c"]
55+
end
56+
57+
it "passes solitary stars" do
58+
check_smoosh "*", ["*"]
59+
check_smoosh "a*b", ["a", "*", "b"]
60+
end
61+
62+
it "smooshes two stars in a row into a single '**' string" do
63+
check_smoosh "**", ["**"]
64+
check_smoosh "a**b", ["a", "**", "b"]
65+
check_smoosh "**b", ["**", "b"]
66+
check_smoosh "a**", ["a", "**"]
67+
end
68+
69+
it "treats **/ like **" do
70+
check_smoosh "**/", ["**"]
71+
check_smoosh "a**/b", ["a", "**", "b"]
72+
end
73+
end
74+
4575
end
4676
end
4777

spec/spec_helper.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
require "rspec"
33
#require "rspec/autorun"
44

5-
require "wrong"
5+
require "wrong/adapters/rspec"
66
include Wrong::D
77

88
here = File.expand_path(File.dirname(__FILE__))

spec/watcher_spec.rb

+1-7
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,14 @@
66
module Rerun
77
describe Watcher do
88

9-
def create_watcher(&block)
10-
Watcher.new(&block)
11-
end
12-
139
before do
1410
@dir = Dir.tmpdir + "/#{Time.now.to_i}"
1511
FileUtils.mkdir_p(@dir)
1612

1713
@log = []
18-
@watcher = create_watcher do |status, file|
14+
@watcher = Watcher.new(:directory => @dir, :pattern => "*.txt") do |status, file|
1915
@log << [status, file]
2016
end
21-
@watcher.add_directory(@dir, "*.txt")
22-
@watcher.sleep_time = 0.1
2317
@watcher.start
2418

2519
@test_file = "#{@dir}/test.txt"

0 commit comments

Comments
 (0)