filewatcher 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +47 -13
- data/bin/filewatcher +70 -89
- data/lib/filewatcher.rb +99 -40
- data/test/fixtures/file1.txt +1 -1
- data/test/fixtures/file2.txt +1 -1
- data/test/test_filewatcher.rb +57 -0
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43546a6002f63f8251ab718f13676e812c47a64c
|
4
|
+
data.tar.gz: 734a6f6708d85692d9141644a1f583f5633c1dc3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 240dd96db19430b21f3fd29baedd6d3ad4a7cd3fb1089e76930de90a6d38f5fbc2c6f1d55fa34c6a17ae1192352021cc82395e14344666ff0dc8649ff7e82951
|
7
|
+
data.tar.gz: ef86c4909413021b72f7c93e7a46451f62bc358a8db175c0757c837627ef0d37dd3fabd1441f2fbeced9cd728148527aa8fa2743f5e026d427b5010af3751359
|
data/README.md
CHANGED
@@ -84,12 +84,16 @@ filesystem gets updated:
|
|
84
84
|
|
85
85
|
$ filewatcher "src test" "ruby test/test_suite.rb"
|
86
86
|
|
87
|
-
|
88
|
-
|
87
|
+
Restart long running commands
|
88
|
+
-----------------------------
|
89
|
+
|
90
|
+
The `--restart` option kills the command if it's still running when a filesystem change happens. Can be used to restart locally running webservers on updates, or kill long running tests and restart on updates. This option often makes filewatcher faster in general. To not wait for tests to finish:
|
89
91
|
|
90
|
-
|
92
|
+
$ filewatcher --restart "**/*.rb" "rake test"
|
91
93
|
|
92
|
-
|
94
|
+
The `--dontwait` option starts the command on startup without waiting for filesystem updates. To start a webserver and have it automatically restart when html files are updated:
|
95
|
+
|
96
|
+
$ filewatcher --restart --dontwait "*.html" "python -m SimpleHTTPServer"
|
93
97
|
|
94
98
|
Available enviroment variables
|
95
99
|
------------------------------
|
@@ -105,13 +109,20 @@ The environment variables $FILEPATH, $FILEDIR and $FSEVENT is also available.
|
|
105
109
|
Command line options
|
106
110
|
--------------------
|
107
111
|
|
112
|
+
Useful command line options:
|
113
|
+
|
114
|
+
--list, -l: Print name of files being watched on startup
|
115
|
+
--restart, -r: Kill the command if it's still running
|
116
|
+
--dontwait, -d: Start the command immediately
|
117
|
+
|
118
|
+
Other command line options:
|
119
|
+
|
120
|
+
--version, -v: Print version and exit
|
121
|
+
--help, -h: Show this message
|
108
122
|
--interval, -i <f>: Interval in seconds to scan filesystem. Defaults to 0.5 seconds.
|
109
|
-
--exec, -e: Execute file as a script when file is updated
|
123
|
+
--exec, -e: Execute file as a script when file is updated
|
110
124
|
--include, -n <s>: Include files (default: *)
|
111
125
|
--exclude, -x <s>: Exclude file(s) matching (default: "")
|
112
|
-
--list, -l: Print name of files being watched
|
113
|
-
--version, -v: Print version and exit
|
114
|
-
--help, -h: Show this message
|
115
126
|
|
116
127
|
Ruby API
|
117
128
|
--------
|
@@ -188,18 +199,41 @@ for syntax.
|
|
188
199
|
puts "Updated " + filename
|
189
200
|
end
|
190
201
|
|
191
|
-
|
202
|
+
Start, pause, resume, stop, and finalize a running watch. This is particularly
|
203
|
+
useful when the update block takes a while to process each file (eg. sending
|
204
|
+
over the network)
|
205
|
+
|
206
|
+
filewatcher = FileWatcher.new(["*.rb"])
|
207
|
+
thread = Thread.new(filewatcher){|fw| fw.watch{|f| puts "Updated " + f}}
|
208
|
+
...
|
209
|
+
filewatcher.pause # block stops responding to filesystem changes
|
210
|
+
filewatcher.finalize # Ensure all filesystem changes made prior to
|
211
|
+
# pausing are handled.
|
212
|
+
...
|
213
|
+
filewatcher.resume # block begins responding again, but is not given
|
214
|
+
# changes made between #pause_watch and
|
215
|
+
# #resume_watch
|
216
|
+
...
|
217
|
+
filewatcher.end # block stops responding to filesystem changes
|
218
|
+
# and takes a final snapshot of the filesystem
|
219
|
+
thread.join
|
220
|
+
|
221
|
+
filewatcher.finalize # Ensure all filesystem changes made prior to
|
222
|
+
# ending the watch are handled.
|
223
|
+
|
224
|
+
The filewatcher library is just a single file with 147 LOC (including comments)
|
192
225
|
with no dependencies.
|
193
226
|
|
194
227
|
|
195
228
|
Credits
|
196
229
|
-------
|
197
|
-
This project would not be where it is today without the generous help provided by people reporting issues and these contributors:
|
198
|
-
|
230
|
+
This project would not be where it is today without the generous help provided by people reporting issues and these contributors:
|
199
231
|
|
200
|
-
*
|
232
|
+
* Penn Taylor: Spinner displayed in the terminal and Start, pause, resume, stop, and finalize a running watch.
|
233
|
+
|
234
|
+
* Franco Leonardo Bulgarelli: Support for absolute and globbed paths by https://github.com/flbulgarelli
|
201
235
|
|
202
|
-
*
|
236
|
+
* Kristoffer Roupé https://github.com/kitofr Command line globbing by
|
203
237
|
|
204
238
|
This gem was initially inspired by Tom Lieber's blogg posting: http://alltom.com/pages/detecting-file-changes-with-ruby
|
205
239
|
|
data/bin/filewatcher
CHANGED
@@ -29,10 +29,11 @@ EOS
|
|
29
29
|
opt :exec, "Execute file as a script when file is updated.", :short => 'e', :type => :boolean, :default => false
|
30
30
|
opt :include, "Include files", :type => :string, :default => "*"
|
31
31
|
opt :exclude, "Exclude file(s) matching", :type => :string, :default => ""
|
32
|
-
opt :interval, "Interval to scan filesystem.
|
32
|
+
opt :interval, "Interval to scan filesystem.", :short => 'i', :type => :float, :default => 0.5
|
33
|
+
opt :quiet, "Hide spinner", :short => 'q', :type => :boolean, :default => false
|
33
34
|
end
|
34
35
|
|
35
|
-
Trollop::die
|
36
|
+
Trollop::die Trollop::educate if(ARGV.size == 0)
|
36
37
|
|
37
38
|
files = []
|
38
39
|
ARGV[0...-1].each do |a|
|
@@ -59,37 +60,13 @@ end
|
|
59
60
|
|
60
61
|
files = split_files_void_escaped_whitespace(files)
|
61
62
|
|
62
|
-
def
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
Kernel.sleep 1
|
71
|
-
pipe_write.close
|
72
|
-
child_pid = pipe_read.read.to_i
|
73
|
-
pipe_read.close
|
74
|
-
return child_pid
|
75
|
-
end
|
76
|
-
|
77
|
-
def kill_process(child_pid)
|
78
|
-
still_running = true
|
79
|
-
begin
|
80
|
-
Process.kill(1, child_pid)
|
81
|
-
rescue Errno::ESRCH
|
82
|
-
still_running = false
|
83
|
-
end
|
84
|
-
while still_running do
|
85
|
-
begin
|
86
|
-
Process.getpgid( child_pid)
|
87
|
-
still_running = true
|
88
|
-
rescue Errno::ESRCH
|
89
|
-
still_running = false
|
90
|
-
end
|
91
|
-
Kernel.sleep 0.1
|
92
|
-
end
|
63
|
+
def restart(child_pid, env, cmd)
|
64
|
+
Process.kill(9,child_pid)
|
65
|
+
Process.wait(child_pid)
|
66
|
+
rescue Errno::ESRCH
|
67
|
+
# already killed
|
68
|
+
ensure
|
69
|
+
child_pid = Process.spawn(env, cmd)
|
93
70
|
end
|
94
71
|
|
95
72
|
if(options[:restart])
|
@@ -97,70 +74,74 @@ if(options[:restart])
|
|
97
74
|
child_pid = nil
|
98
75
|
end
|
99
76
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
77
|
+
begin
|
78
|
+
fw = FileWatcher.new(files, options[:list], options[:dontwait], !options[:quiet])
|
79
|
+
fw.watch(options[:interval]) do |filename, event|
|
80
|
+
cmd = nil
|
81
|
+
if(options[:exec] and File.exist?(filename))
|
82
|
+
extension = filename[/(\.[^\.]*)$/,0]
|
83
|
+
runners = {
|
84
|
+
".py" => "python",
|
85
|
+
".js" => "node",
|
86
|
+
".rb" => "ruby",
|
87
|
+
".pl" => "perl",
|
88
|
+
".awk" => "awk",
|
89
|
+
".php" => "php",
|
90
|
+
".phtml" => "php",
|
91
|
+
".php4" => "php",
|
92
|
+
".php3" => "php",
|
93
|
+
".php5" => "php",
|
94
|
+
".phps" => "php"
|
95
|
+
}
|
96
|
+
runner = runners[extension]
|
97
|
+
if(runner)
|
98
|
+
cmd = "env #{runner.to_s} #{filename}"
|
99
|
+
end
|
100
|
+
elsif(ARGV.length > 1)
|
101
|
+
cmd = ARGV[-1]
|
120
102
|
end
|
121
|
-
elsif(ARGV.length > 1)
|
122
|
-
cmd = ARGV[-1]
|
123
|
-
end
|
124
103
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
104
|
+
if(cmd)
|
105
|
+
path = Pathname.new(filename)
|
106
|
+
env = {
|
107
|
+
'FILENAME'=> path.to_s,
|
108
|
+
'FILEDIR' => path.parent.realpath.to_s,
|
109
|
+
'FSEVENT' => event.to_s
|
110
|
+
}
|
111
|
+
if(event != :delete)
|
112
|
+
ENV['FILEPATH'] = path.realpath.to_s
|
113
|
+
end
|
135
114
|
|
136
|
-
|
137
|
-
|
138
|
-
|
115
|
+
if(options[:restart])
|
116
|
+
if(child_pid == nil)
|
117
|
+
child_pid = Process.spawn(env, cmd)
|
118
|
+
else
|
119
|
+
child_id = restart(child_pid, env, cmd)
|
120
|
+
end
|
139
121
|
else
|
140
|
-
|
141
|
-
|
122
|
+
begin
|
123
|
+
pid = Process.spawn(env, cmd)
|
124
|
+
Process.wait()
|
125
|
+
rescue SystemExit, Interrupt
|
126
|
+
exit(0)
|
127
|
+
end
|
142
128
|
end
|
129
|
+
|
143
130
|
else
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
131
|
+
case(event)
|
132
|
+
when :changed
|
133
|
+
print "file updated"
|
134
|
+
when :delete
|
135
|
+
print "file deleted"
|
136
|
+
when :new
|
137
|
+
print "new file"
|
138
|
+
else
|
139
|
+
print event.to_s
|
149
140
|
end
|
141
|
+
puts ": " + filename
|
150
142
|
end
|
151
143
|
|
152
|
-
else
|
153
|
-
case(event)
|
154
|
-
when :changed
|
155
|
-
print "file updated"
|
156
|
-
when :delete
|
157
|
-
print "file deleted"
|
158
|
-
when :new
|
159
|
-
print "new file"
|
160
|
-
else
|
161
|
-
print event.to_s
|
162
|
-
end
|
163
|
-
puts ": " + filename
|
164
144
|
end
|
165
|
-
|
145
|
+
rescue SystemExit, Interrupt
|
146
|
+
fw.finalize
|
166
147
|
end
|
data/lib/filewatcher.rb
CHANGED
@@ -6,76 +6,135 @@ class FileWatcher
|
|
6
6
|
attr_accessor :filenames
|
7
7
|
|
8
8
|
def self.VERSION
|
9
|
-
return '0.
|
9
|
+
return '0.5.0'
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
12
|
+
def update_spinner(label)
|
13
|
+
return nil unless @show_spinner
|
14
|
+
@spinner ||= %w(\\ | / -)
|
15
|
+
print "#{' ' * 30}\r#{label} #{@spinner.rotate!.first}\r"
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(unexpanded_filenames, print_filelist=false, dontwait=false, show_spinner=false)
|
13
19
|
@unexpanded_filenames = unexpanded_filenames
|
14
|
-
@
|
15
|
-
@
|
20
|
+
@filenames = nil
|
21
|
+
@stored_update = nil
|
22
|
+
@keep_watching = false
|
23
|
+
@pausing = false
|
24
|
+
@last_snapshot = mtime_snapshot
|
25
|
+
@end_snapshot = nil
|
16
26
|
@dontwait = dontwait
|
27
|
+
@show_spinner = show_spinner
|
17
28
|
puts 'Watching:' if print_filelist
|
18
29
|
@filenames.each do |filename|
|
19
30
|
raise 'File does not exist' unless File.exist?(filename)
|
20
|
-
@last_mtimes[filename] = File.stat(filename).mtime
|
21
31
|
puts filename if print_filelist
|
22
32
|
end
|
23
33
|
end
|
24
34
|
|
25
|
-
def watch(sleep=
|
35
|
+
def watch(sleep=0.5, &on_update)
|
36
|
+
@sleep = sleep
|
37
|
+
@stored_update = on_update
|
38
|
+
@keep_watching = true
|
26
39
|
if(@dontwait)
|
27
40
|
yield '',''
|
28
41
|
end
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
Kernel.
|
42
|
+
while @keep_watching
|
43
|
+
@end_snapshot = mtime_snapshot if @pausing
|
44
|
+
while @keep_watching && @pausing
|
45
|
+
update_spinner('Pausing')
|
46
|
+
Kernel.sleep sleep
|
34
47
|
end
|
35
|
-
|
48
|
+
while @keep_watching && !filesystem_updated? && !@pausing
|
49
|
+
update_spinner('Scanning')
|
50
|
+
Kernel.sleep sleep
|
51
|
+
end
|
52
|
+
# test and null @updated_file to prevent yielding the last
|
53
|
+
# file twice if @keep_watching has just been set to false
|
54
|
+
yield @updated_file, @event if @updated_file
|
55
|
+
@updated_file = nil
|
36
56
|
end
|
57
|
+
@end_snapshot = mtime_snapshot
|
58
|
+
finalize(&on_update)
|
37
59
|
end
|
38
60
|
|
39
|
-
def
|
40
|
-
|
61
|
+
def pause
|
62
|
+
@pausing = true
|
63
|
+
update_spinner('Initiating pause')
|
64
|
+
Kernel.sleep @sleep # Ensure we wait long enough to enter pause loop
|
65
|
+
# in #watch
|
66
|
+
end
|
41
67
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
@last_mtimes[filename] = File.stat(filename).mtime
|
46
|
-
@updated_file = filename
|
47
|
-
@event = :new
|
48
|
-
return true
|
68
|
+
def resume
|
69
|
+
if !@keep_watching || !@pausing
|
70
|
+
raise "Can't resume unless #watch and #pause were first called"
|
49
71
|
end
|
72
|
+
@last_snapshot = mtime_snapshot # resume with fresh snapshot
|
73
|
+
@pausing = false
|
74
|
+
update_spinner('Resuming')
|
75
|
+
Kernel.sleep @sleep # Wait long enough to exit pause loop in #watch
|
76
|
+
end
|
50
77
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
78
|
+
# Ends the watch, allowing any remaining changes to be finalized.
|
79
|
+
# Used mainly in multi-threaded situations.
|
80
|
+
def stop
|
81
|
+
@keep_watching = false
|
82
|
+
update_spinner('Stopping')
|
83
|
+
return nil
|
84
|
+
end
|
85
|
+
|
86
|
+
# Calls the update block repeatedly until all changes in the
|
87
|
+
# current snapshot are dealt with
|
88
|
+
def finalize(&on_update)
|
89
|
+
on_update = @stored_update if !block_given?
|
90
|
+
snapshot = @end_snapshot ? @end_snapshot : mtime_snapshot
|
91
|
+
while filesystem_updated?(snapshot)
|
92
|
+
update_spinner('Finalizing')
|
93
|
+
on_update.call(@updated_file, @event)
|
58
94
|
end
|
95
|
+
@end_snapshot =nil
|
96
|
+
return nil
|
97
|
+
end
|
59
98
|
|
99
|
+
# Takes a snapshot of the current status of watched files.
|
100
|
+
# (Allows avoidance of potential race condition during #finalize)
|
101
|
+
def mtime_snapshot
|
102
|
+
snapshot = {}
|
103
|
+
@filenames = expand_directories(@unexpanded_filenames)
|
60
104
|
@filenames.each do |filename|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
updated = @last_mtimes[filename] < mtime
|
105
|
+
mtime = File.exist?(filename) ? File.stat(filename).mtime : Time.new(0)
|
106
|
+
snapshot[filename] = mtime
|
107
|
+
end
|
108
|
+
return snapshot
|
109
|
+
end
|
110
|
+
|
111
|
+
def filesystem_updated?(snapshot_to_use = nil)
|
112
|
+
snapshot = snapshot_to_use ? snapshot_to_use : mtime_snapshot
|
70
113
|
|
71
|
-
|
72
|
-
|
73
|
-
|
114
|
+
forward_changes = snapshot.to_a - @last_snapshot.to_a
|
115
|
+
|
116
|
+
forward_changes.each do |file,mtime|
|
117
|
+
@updated_file = file
|
118
|
+
unless @last_snapshot.fetch(@updated_file,false)
|
119
|
+
@last_snapshot[file] = mtime
|
120
|
+
@event = :new
|
121
|
+
return true
|
122
|
+
else
|
123
|
+
@last_snapshot[file] = mtime
|
74
124
|
@event = :changed
|
75
125
|
return true
|
76
126
|
end
|
77
127
|
end
|
78
128
|
|
129
|
+
backward_changes = @last_snapshot.to_a - snapshot.to_a
|
130
|
+
forward_names = forward_changes.map{|change| change.first}
|
131
|
+
backward_changes.reject!{|f,m| forward_names.include?(f)}
|
132
|
+
backward_changes.each do |file,mtime|
|
133
|
+
@updated_file = file
|
134
|
+
@last_snapshot.delete(file)
|
135
|
+
@event = :delete
|
136
|
+
return true
|
137
|
+
end
|
79
138
|
return false
|
80
139
|
end
|
81
140
|
|
data/test/fixtures/file1.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
content1
|
data/test/fixtures/file2.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
content2
|
data/test/test_filewatcher.rb
CHANGED
@@ -98,4 +98,61 @@ describe FileWatcher do
|
|
98
98
|
filewatcher.filesystem_updated?.should.be.true
|
99
99
|
end
|
100
100
|
|
101
|
+
it "should be stoppable" do
|
102
|
+
filewatcher = FileWatcher.new(["test/fixtures"])
|
103
|
+
thread = Thread.new(filewatcher){filewatcher.watch(0.1)}
|
104
|
+
sleep 0.2 # thread needs a chance to start
|
105
|
+
filewatcher.stop
|
106
|
+
thread.join.should.equal thread # Proves thread successfully joined
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should be pauseable/resumable" do
|
110
|
+
filewatcher = FileWatcher.new(["test/fixtures"])
|
111
|
+
filewatcher.filesystem_updated?.should.be.false
|
112
|
+
processed = []
|
113
|
+
thread = Thread.new(filewatcher,processed) do
|
114
|
+
filewatcher.watch(0.1){|f,e| processed << f }
|
115
|
+
end
|
116
|
+
sleep 0.2 # thread needs a chance to start
|
117
|
+
filewatcher.pause
|
118
|
+
(1..4).each do |n|
|
119
|
+
open("test/fixtures/file#{n}.txt","w") { |f| f.puts "content#{n}" }
|
120
|
+
end
|
121
|
+
sleep 0.2 # Give filewatcher time to respond
|
122
|
+
processed.should.equal [] #update block should not have been called
|
123
|
+
filewatcher.resume
|
124
|
+
sleep 0.2 # Give filewatcher time to respond
|
125
|
+
processed.should.equal [] #update block still should not have been called
|
126
|
+
added_files = []
|
127
|
+
(5..7).each do |n|
|
128
|
+
added_files << "test/fixtures/file#{n}.txt"
|
129
|
+
open(added_files.last,"w") { |f| f.puts "content#{n}" }
|
130
|
+
end
|
131
|
+
sleep 0.2 # Give filewatcher time to respond
|
132
|
+
filewatcher.stop
|
133
|
+
processed.should.satisfy &includes_all(added_files)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should process all remaining changes at finalize" do
|
137
|
+
filewatcher = FileWatcher.new(["test/fixtures"])
|
138
|
+
filewatcher.filesystem_updated?.should.be.false
|
139
|
+
processed = []
|
140
|
+
thread = Thread.new(filewatcher,processed) do
|
141
|
+
filewatcher.watch(0.1){|f,e| processed << f }
|
142
|
+
end
|
143
|
+
sleep 0.2 # thread needs a chance to start
|
144
|
+
filewatcher.stop
|
145
|
+
thread.join
|
146
|
+
added_files = []
|
147
|
+
(1..4).each do |n|
|
148
|
+
added_files << "test/fixtures/file#{n}.txt"
|
149
|
+
open(added_files.last,"w") { |f| f.puts "content#{n}" }
|
150
|
+
end
|
151
|
+
filewatcher.finalize
|
152
|
+
puts "What is wrong with finalize:"
|
153
|
+
puts "Expect: #{added_files.inspect}"
|
154
|
+
puts "Actual: #{processed.inspect}"
|
155
|
+
processed.should.satisfy &includes_all(added_files)
|
156
|
+
end
|
157
|
+
|
101
158
|
end
|
metadata
CHANGED
@@ -1,55 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: filewatcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Flemming
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: trollop
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '2.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '10.3'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.3'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bacon
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '1.2'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.2'
|
55
55
|
description: Detect changes in filesystem. Works anywhere.
|
@@ -82,12 +82,12 @@ require_paths:
|
|
82
82
|
- lib
|
83
83
|
required_ruby_version: !ruby/object:Gem::Requirement
|
84
84
|
requirements:
|
85
|
-
- -
|
85
|
+
- - ">="
|
86
86
|
- !ruby/object:Gem::Version
|
87
87
|
version: '0'
|
88
88
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
89
|
requirements:
|
90
|
-
- -
|
90
|
+
- - ">="
|
91
91
|
- !ruby/object:Gem::Version
|
92
92
|
version: '0'
|
93
93
|
requirements: []
|