rerun 0.7.0.pre3 → 0.7.0.pre4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/rerun/watcher.rb +19 -128
- data/rerun.gemspec +1 -1
- metadata +2 -2
data/lib/rerun/watcher.rb
CHANGED
@@ -5,14 +5,13 @@ Thread.abort_on_exception = true
|
|
5
5
|
# This class will watch a directory and alert you of
|
6
6
|
# new files, modified files, deleted files.
|
7
7
|
#
|
8
|
-
#
|
8
|
+
# Now uses the Listen gem, but spawns its own thread on top.
|
9
|
+
# We should probably be accessing the Listen thread directly.
|
10
|
+
#
|
9
11
|
# Author: Alex Chaffee
|
12
|
+
#
|
10
13
|
module Rerun
|
11
14
|
class Watcher
|
12
|
-
CREATED = 0
|
13
|
-
MODIFIED = 1
|
14
|
-
DELETED = 2
|
15
|
-
|
16
15
|
attr_reader :directory, :pattern, :priority
|
17
16
|
|
18
17
|
# Create a file system watcher. Start it by calling #start.
|
@@ -32,47 +31,33 @@ module Rerun
|
|
32
31
|
|
33
32
|
@pattern = options[:pattern]
|
34
33
|
@directory = options[:directory]
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
raise InvalidDirectoryError, "Dir '#{directory}' either doesnt exist or isnt readable"
|
34
|
+
@directory.chomp!("/")
|
35
|
+
unless FileTest.exists?(@directory) && FileTest.readable?(@directory)
|
36
|
+
raise InvalidDirectoryError, "Directory '#{@directory}' either doesnt exist or isnt readable"
|
39
37
|
end
|
40
38
|
@priority = options[:priority]
|
41
|
-
|
42
|
-
@found = nil
|
43
|
-
@first_time = true
|
44
39
|
@thread = nil
|
45
40
|
end
|
46
41
|
|
47
|
-
def prime
|
48
|
-
@first_time = true
|
49
|
-
@found = {}
|
50
|
-
examine
|
51
|
-
@first_time = false
|
52
|
-
end
|
53
|
-
|
54
42
|
def start
|
55
43
|
if @thread then
|
56
44
|
raise RuntimeError, "already started"
|
57
45
|
end
|
58
46
|
|
59
|
-
prime
|
60
|
-
|
61
47
|
@thread = Thread.new do
|
62
48
|
# todo: multiple dirs
|
63
49
|
|
64
50
|
regexp = Glob.new(@pattern).to_regexp
|
65
|
-
@listener = Listen::Listener.new(@directory
|
66
|
-
|
67
|
-
#d { added }
|
68
|
-
#d { removed }
|
69
|
-
examine
|
51
|
+
@listener = Listen::Listener.new(@directory, :filter => regexp) do |modified, added, removed|
|
52
|
+
@client_callback.call(:modified => modified, :added => added, :removed => removed)
|
70
53
|
end
|
71
54
|
@listener.start
|
72
55
|
end
|
73
56
|
|
74
57
|
@thread.priority = @priority
|
75
58
|
|
59
|
+
sleep 0.1 until @listener
|
60
|
+
|
76
61
|
at_exit { stop } # try really hard to clean up after ourselves
|
77
62
|
end
|
78
63
|
|
@@ -83,116 +68,22 @@ module Rerun
|
|
83
68
|
end
|
84
69
|
end
|
85
70
|
|
86
|
-
# kill the
|
71
|
+
# kill the file watcher thread
|
87
72
|
def stop
|
73
|
+
@thread.wakeup rescue ThreadError
|
88
74
|
begin
|
89
|
-
@
|
90
|
-
rescue
|
91
|
-
#
|
92
|
-
end
|
93
|
-
begin
|
94
|
-
@thread.kill
|
95
|
-
rescue ThreadError => e
|
96
|
-
# ignore
|
75
|
+
@listener.stop
|
76
|
+
rescue Exception => e
|
77
|
+
puts "#{e.class}: #{e.message} stopping listener"
|
97
78
|
end
|
79
|
+
@thread.kill rescue ThreadError
|
98
80
|
end
|
99
81
|
|
100
|
-
# wait for the
|
82
|
+
# wait for the file watcher to finish
|
101
83
|
def join
|
102
|
-
@thread.join
|
84
|
+
@thread.join if @thread
|
103
85
|
rescue Interrupt => e
|
104
86
|
# don't care
|
105
87
|
end
|
106
|
-
|
107
|
-
private
|
108
|
-
|
109
|
-
def examine
|
110
|
-
|
111
|
-
already_examined = Hash.new()
|
112
|
-
|
113
|
-
examine_files(@directory.files, already_examined)
|
114
|
-
|
115
|
-
# now diff the found files and the examined files to see if
|
116
|
-
# something has been deleted
|
117
|
-
all_found_files = @found.keys()
|
118
|
-
all_examined_files = already_examined.keys()
|
119
|
-
intersection = all_found_files - all_examined_files
|
120
|
-
|
121
|
-
intersection.each do |file_name|
|
122
|
-
@client_callback.call(DELETED, file_name)
|
123
|
-
@found.delete(file_name)
|
124
|
-
end
|
125
|
-
|
126
|
-
end
|
127
|
-
|
128
|
-
# loops over the file list check for new or modified files
|
129
|
-
def examine_files(files, already_examined)
|
130
|
-
files.each do |file_name|
|
131
|
-
# expand the file name to the fully qual path
|
132
|
-
full_file_name = File.expand_path(file_name)
|
133
|
-
|
134
|
-
# we cant do much if the file isnt readable anyway
|
135
|
-
if File.readable?(full_file_name) then
|
136
|
-
already_examined[full_file_name] = true
|
137
|
-
stat = File.stat(full_file_name)
|
138
|
-
mod_time = stat.mtime
|
139
|
-
size = stat.size
|
140
|
-
|
141
|
-
# on the first iteration just load all of the files into the foundList
|
142
|
-
if @first_time then
|
143
|
-
@found[full_file_name] = FoundFile.new(full_file_name, mod_time, size)
|
144
|
-
else
|
145
|
-
# see if we have found this file already
|
146
|
-
found_file = @found[full_file_name]
|
147
|
-
@found[full_file_name] = FoundFile.new(full_file_name, mod_time, size)
|
148
|
-
|
149
|
-
if found_file
|
150
|
-
if mod_time > found_file.mod_time || size != found_file.size then
|
151
|
-
@client_callback.call(MODIFIED, full_file_name)
|
152
|
-
end
|
153
|
-
else
|
154
|
-
@client_callback.call(CREATED, full_file_name)
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
class Directory
|
162
|
-
attr_reader :dir, :expression
|
163
|
-
|
164
|
-
def initialize(dir, expression)
|
165
|
-
@dir, @expression = dir, expression
|
166
|
-
@dir.chop! if @dir =~ %r{/$}
|
167
|
-
end
|
168
|
-
|
169
|
-
def files
|
170
|
-
return Dir["#{@dir}/#{@expression}"]
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
class FoundFile
|
175
|
-
attr_reader :status, :file_name, :mod_time, :size
|
176
|
-
|
177
|
-
def initialize(file_name, mod_time, size)
|
178
|
-
@file_name, @mod_time, @size = file_name, mod_time, size
|
179
|
-
end
|
180
|
-
|
181
|
-
def modified(mod_time)
|
182
|
-
@mod_time = mod_time
|
183
|
-
end
|
184
|
-
|
185
|
-
def to_s
|
186
|
-
"FoundFile[file_name=#{file_name}, mod_time=#{mod_time.to_i}, size=#{size}]"
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
# if the directory you want to watch doesnt exist or isn't readable this is thrown
|
191
|
-
class InvalidDirectoryError < StandardError;
|
192
|
-
end
|
193
|
-
|
194
|
-
# if the file you want to watch doesnt exist or isn't readable this is thrown
|
195
|
-
class InvalidFileError < StandardError;
|
196
|
-
end
|
197
88
|
end
|
198
89
|
end
|
data/rerun.gemspec
CHANGED
@@ -3,7 +3,7 @@ $spec = Gem::Specification.new do |s|
|
|
3
3
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
4
|
|
5
5
|
s.name = 'rerun'
|
6
|
-
s.version = '0.7.0.
|
6
|
+
s.version = '0.7.0.pre4'
|
7
7
|
|
8
8
|
s.description = "Restarts your app when a file changes"
|
9
9
|
s.summary = "Launches an app, and restarts it whenever the filesystem changes."
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rerun
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.0.
|
4
|
+
version: 0.7.0.pre4
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -61,7 +61,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
61
61
|
version: '0'
|
62
62
|
segments:
|
63
63
|
- 0
|
64
|
-
hash:
|
64
|
+
hash: -2239978270420892770
|
65
65
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
66
|
none: false
|
67
67
|
requirements:
|