nite-owl 0.1.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 98012eb7fa0d83d070a5ea27e9a802124506d3f8
4
+ data.tar.gz: 68149cdad3bcb5156e72318ad43b0354be15f63f
5
+ SHA512:
6
+ metadata.gz: cbba57bfcd8f61d35a1bacb5d80c4cb2b520af292688d01e2f6def2a6d10095b4eb3b8b9f41b92abdb5d98760ca09251550190b252a53ad95b1ee4e7a8491414
7
+ data.tar.gz: 1ec829878b577acc16a501a0d75a494223bb1a71c69aa380b5b8a6268e0ad8a26871ab0d8767ab8a3b1177dc3dbc356575faff35b12fae7f671f928e06489d07
@@ -0,0 +1,12 @@
1
+ *.lock
2
+ /.bundle/
3
+ /.yardoc
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.16.1
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in nite-owl.gemspec
6
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 troydm
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/Niteowl ADDED
@@ -0,0 +1,14 @@
1
+ whenever(/.*rb/)
2
+ .changes
3
+ .after(5.seconds)
4
+ .if_not {
5
+ false
6
+ }
7
+ .run do |n,f|
8
+ puts "Hello World"
9
+ cancel
10
+ shell "ls -lh"
11
+ end
12
+ .also.run do |n,f|
13
+ puts "Change detected "+n.to_s+" "+f.to_s
14
+ end
@@ -0,0 +1,29 @@
1
+ # Nite::Owl [![Gem Version](https://badge.fury.io/rb/nite-owl.svg)](https://badge.fury.io/rb/nite-owl) [![Build Status](https://travis-ci.org/troydm/nite-owl.png?branch=master)](https://travis-ci.org/troydm/nite-owl)
2
+
3
+ Nite Owl watches over your files and executes commands if anything happens to them, it's like [guard](https://github.com/guard/guard) on a super diet!
4
+ Supports linux and macos only and depends only on rb-fsevent and rb-inotify.
5
+
6
+ ## Installation
7
+
8
+ To install just run this command:
9
+
10
+ $ gem install nite-owl
11
+
12
+ ## Usage
13
+
14
+ Create Niteowl configuration file inside a directory you want to watch over and the run nite-owl.
15
+ See example Niteowl configuration file.
16
+
17
+ ## Development
18
+
19
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
20
+
21
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
22
+
23
+ ## Contributing
24
+
25
+ Bug reports and pull requests are welcome on GitHub at https://github.com/troydm/nite-owl.
26
+
27
+ ## License
28
+
29
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "nite/owl"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ require "nite/owl"
3
+
4
+ if ARGV.empty?
5
+ Nite::Owl::NiteOwl.instance.watch(Dir.pwd)
6
+ else
7
+ Nite::Owl::NiteOwl.instance.watch(ARGV[0])
8
+ end
9
+
10
+ Nite::Owl::NiteOwl.instance.start
@@ -0,0 +1,2 @@
1
+ require "nite/owl/version"
2
+ require "nite/owl/niteowl"
@@ -0,0 +1,564 @@
1
+ require 'open3'
2
+
3
+ # Nite Owl DSL
4
+ def quote(path)
5
+ if path.include? " "
6
+ "\"#{path}\""
7
+ else
8
+ path
9
+ end
10
+ end
11
+
12
+ def cd(dir)
13
+ Dir.chdir quote(dir)
14
+ puts "cd #{dir}"
15
+ end
16
+
17
+ def pwd
18
+ d = Dir.pwd
19
+ puts "pwd: #{d}"
20
+ d
21
+ end
22
+
23
+ def whenever(files)
24
+ if files.is_a?(String) or files.is_a?(Regexp)
25
+ files = [files]
26
+ end
27
+ Nite::Owl::NiteOwl.instance.whenever(files)
28
+ end
29
+
30
+ def action
31
+ Nite::Owl::NiteOwl.instance.current_action()
32
+ end
33
+
34
+ def delay(time)
35
+ action.delay(time)
36
+ end
37
+
38
+ def cancel
39
+ action.cancel
40
+ end
41
+
42
+ # Run command in shell and redirect it's output to stdout and stderr
43
+ def shell(command,options={:verbose => false,:silent => false,:stdin => nil})
44
+ stdout = ""
45
+ stderr = ""
46
+ verbose = options[:verbose]
47
+ silent = options[:silent]
48
+ stdin = options[:stdin]
49
+ if verbose
50
+ puts "Executing: #{command}"
51
+ end
52
+ Open3.popen3(command) do |i,o,e,t|
53
+ stdin_i = 0
54
+ stdin_open = stdin != nil
55
+ stdout_buffer = ""
56
+ stderr_buffer = ""
57
+ stdout_open = true
58
+ stderr_open = true
59
+ stdout_ch = nil
60
+ stderr_ch = nil
61
+ while stdout_open or stderr_open or stdin_open
62
+ if stdin_open
63
+ begin
64
+ p stdin
65
+ i.write(stdin)
66
+ i.close_write
67
+ stdin_open = false
68
+ #c = i.write_nonblock(stdin[stdin_i])
69
+ #if c > 0
70
+ # stdin_i += 1
71
+ # if stdin_i == stdin.size
72
+ # i.close_write
73
+ # stdin_open = false
74
+ # end
75
+ #end
76
+ rescue IO::WaitWritable
77
+ IO.select([i])
78
+ puts "retry writeable"
79
+ retry
80
+ rescue EOFError
81
+ stdin_open = false
82
+ end
83
+ end
84
+ if stdout_open
85
+ begin
86
+ stdout_ch = o.read_nonblock(1)
87
+ rescue IO::WaitReadable
88
+ IO.select([o])
89
+ retry
90
+ rescue EOFError
91
+ stdout_open = false
92
+ end
93
+ end
94
+ if stderr_open
95
+ begin
96
+ stderr_ch = e.read_nonblock(1)
97
+ rescue IO::WaitReadable
98
+ IO.select([e])
99
+ retry
100
+ rescue EOFError
101
+ stderr_open = false
102
+ end
103
+ end
104
+ if stdout_ch == "\n" then
105
+ stdout += stdout_buffer+"\n"
106
+ unless silent
107
+ puts stdout_buffer
108
+ end
109
+ stdout_buffer = ""
110
+ elsif stdout_ch != nil
111
+ stdout_buffer << stdout_ch
112
+ end
113
+ stdout_ch = nil
114
+ if stderr_ch == "\n" then
115
+ stderr += stderr_buffer+"\n"
116
+ unless silent
117
+ STDERR.puts stderr_buffer
118
+ end
119
+ stderr_buffer = ""
120
+ elsif stderr_ch != nil
121
+ stderr_buffer << stderr_ch
122
+ end
123
+ stderr_ch = nil
124
+ end
125
+ end
126
+ if stderr != ""
127
+ return stdout, stderr
128
+ else
129
+ return stdout
130
+ end
131
+ end
132
+
133
+ # get process pid(s)
134
+ def process(name,full=true)
135
+ if full
136
+ full = '-f '
137
+ else
138
+ full = ''
139
+ end
140
+ out,_ = Open3.capture2("/usr/bin/pgrep #{full}#{name}")
141
+ if out == ''
142
+ nil
143
+ else
144
+ pids = []
145
+ out.lines.each do |pid|
146
+ pids << pid.to_i
147
+ end
148
+ if pids.size == 1
149
+ pids[0]
150
+ else
151
+ pids
152
+ end
153
+ end
154
+ end
155
+
156
+ # kill process
157
+ def kill(pids,signal=15)
158
+ if pids.is_a?(Array)
159
+ pids.each do |pid|
160
+ Process.kill(signal,pid)
161
+ end
162
+ else
163
+ Process.kill(signal,pids)
164
+ end
165
+ end
166
+
167
+ module Nite
168
+ module Owl
169
+ require 'singleton'
170
+ require 'time'
171
+
172
+ class ::Fixnum
173
+ def milliseconds
174
+ self/1000.0
175
+ end
176
+ def seconds
177
+ to_f
178
+ end
179
+ def minutes
180
+ self*60.0
181
+ end
182
+ def hours
183
+ self*3600.0
184
+ end
185
+ end
186
+
187
+ # special exception thrown by cancel method
188
+ class Cancel < Exception
189
+ end
190
+
191
+ # special exception thrown by delay method
192
+ class Delay < Exception
193
+ attr_accessor :time
194
+ def initialize(time)
195
+ @time = time
196
+ end
197
+ end
198
+
199
+ $current_action = nil
200
+ $deferred_actions = {}
201
+
202
+ class Action
203
+ attr_accessor :parent
204
+ def initialize
205
+ @actions = []
206
+ @parent=nil
207
+ @delay=nil
208
+ end
209
+ def current_action
210
+ $current_action
211
+ end
212
+ def cancel
213
+ raise Cancel.new
214
+ end
215
+ def defer(name,flags)
216
+ unless $deferred_actions.has_key?(self)
217
+ $deferred_actions[self] = [name,flags]
218
+ end
219
+ end
220
+ def undefer
221
+ $deferred_actions.delete(self)
222
+ end
223
+ def self.call_all_deferred_actions
224
+ unless $deferred_actions.empty?
225
+ $deferred_actions.dup.each do |a,event|
226
+ a.call(event[0],event[1])
227
+ end
228
+ end
229
+ end
230
+ def root
231
+ r = self
232
+ while r.parent.parent
233
+ r = r.parent
234
+ end
235
+ r
236
+ end
237
+ def also
238
+ root
239
+ end
240
+ def add(a)
241
+ @actions << a
242
+ if a.is_a?(Action)
243
+ a.parent = self
244
+ end
245
+ a
246
+ end
247
+ def contains?(a)
248
+ @actions.find { |b| a == b or (b.is_a?(Action) and b.contains?(a)) }
249
+ end
250
+ def remove(a)
251
+ @actions.delete_if { |b| a == b }
252
+ @actions.each { |b| b.is_a?(Action) and b.remove(a) }
253
+ a
254
+ end
255
+ def run(&block)
256
+ add(block)
257
+ self
258
+ end
259
+ def call(name,flags)
260
+ $current_action = self
261
+ @actions.each do |n|
262
+ begin
263
+ n.call(name,flags)
264
+ rescue Cancel => c
265
+ undefer()
266
+ rescue Delay => d
267
+ handle_delay(d)
268
+ defer(name,flags)
269
+ rescue Exception => e
270
+ STDERR.puts e.message
271
+ STDERR.puts e.backtrace
272
+ end
273
+ end
274
+ end
275
+ def delay(time)
276
+ if @delay
277
+ if Time.now >= @delay
278
+ @delay = nil
279
+ else
280
+ raise Delay.new(0)
281
+ end
282
+ else
283
+ raise Delay.new(time)
284
+ end
285
+ end
286
+ def handle_delay(d)
287
+ unless @delay
288
+ @delay = Time.now + d.time
289
+ end
290
+ end
291
+ def only_once
292
+ run { root.parent.remove(self) }
293
+ end
294
+ def ignore(files)
295
+ add(NameIsNot.new(files))
296
+ end
297
+ def after(delay)
298
+ add(After.new(delay))
299
+ end
300
+ def created
301
+ add(HasFlags.new([:create]))
302
+ end
303
+ def modified
304
+ add(HasFlags.new([:modify]))
305
+ end
306
+ def deleted
307
+ add(HasFlags.new([:delete]))
308
+ end
309
+ def renamed
310
+ add(HasFlags.new([:rename]))
311
+ end
312
+ def changes
313
+ add(HasFlags.new([:create,:delete,:modify,:rename]))
314
+ end
315
+ def only_if(&block)
316
+ add(OnlyIf.new(block))
317
+ end
318
+ def if_not(&block)
319
+ add(IfNot.new(block))
320
+ end
321
+ end
322
+
323
+ class PredicateAction < Action
324
+ def initialize
325
+ super()
326
+ @time = nil
327
+ @expires = nil
328
+ end
329
+ def predicate?(name,flags)
330
+ true
331
+ end
332
+ def expired?
333
+ @expires and @time and (@time+@expires) >= Time.now.to_f
334
+ end
335
+ def expires(delay)
336
+ @expires = delay.to_f
337
+ self
338
+ end
339
+ def call(name,flags)
340
+ $current_action = self
341
+ begin
342
+ unless @time
343
+ @time = Time.now.to_f
344
+ end
345
+ if expired?
346
+ cancel
347
+ elsif predicate?(name,flags)
348
+ super(name,flags)
349
+ cancel
350
+ else
351
+ defer(name,flags)
352
+ end
353
+ rescue Cancel => c
354
+ undefer()
355
+ @time = nil
356
+ rescue Delay => d
357
+ handle_delay(d)
358
+ defer(name,flags)
359
+ rescue Exception => e
360
+ STDERR.puts e.message
361
+ STDERR.puts e.backtrace
362
+ end
363
+ end
364
+ end
365
+
366
+ class After < PredicateAction
367
+ def initialize(delay)
368
+ super()
369
+ @delay = delay.to_f
370
+ @time = nil
371
+ end
372
+ def predicate?(name,flags)
373
+ Time.now.to_f >= @time+@delay
374
+ end
375
+ end
376
+
377
+ class OnlyIf < PredicateAction
378
+ def initialize(block)
379
+ super()
380
+ @predicate = block
381
+ end
382
+ def predicate?(name,flags)
383
+ @predicate.call(name,flags)
384
+ end
385
+ end
386
+
387
+ class IfNot < PredicateAction
388
+ def initialize(block)
389
+ super()
390
+ @predicate = block
391
+ end
392
+ def predicate?(name,flags)
393
+ not @predicate.call(name,flags)
394
+ end
395
+ end
396
+
397
+ class HasFlags < Action
398
+ def initialize(flags)
399
+ super()
400
+ @flags = flags
401
+ end
402
+ def match?(flags)
403
+ @flags.find { |f| flags.include?(f) }
404
+ end
405
+ def call(name,flags)
406
+ match?(flags) && super(name,flags)
407
+ end
408
+ end
409
+
410
+ class FilesAction < Action
411
+ def initialize(files)
412
+ super()
413
+ @files = files
414
+ end
415
+ def match?(file)
416
+ @files.find do |pattern|
417
+ if pattern.is_a?(Regexp)
418
+ pattern.match(file) != nil
419
+ else
420
+ File.fnmatch?(pattern,file)
421
+ end
422
+ end
423
+ end
424
+ end
425
+
426
+ class NameIs < FilesAction
427
+ def call(name,flags)
428
+ match?(name) && super(name,flags)
429
+ end
430
+ end
431
+
432
+ class NameIsNot < FilesAction
433
+ def call(name,flags)
434
+ not match?(name) && super(name,flags)
435
+ end
436
+ end
437
+
438
+ class NiteOwl < Action
439
+ include Singleton
440
+
441
+ def initialize
442
+ super()
443
+ @workers_thread = nil
444
+ @queue = Queue.new
445
+ end
446
+
447
+ def watch(dir)
448
+ Dir.chdir dir
449
+ if File.file?("Niteowl") && File.readable?("Niteowl")
450
+ load "Niteowl"
451
+ else
452
+ puts "No Niteowl file found in: #{dir}"
453
+ end
454
+ if @actions.empty?
455
+ puts "No actions configured"
456
+ end
457
+ end
458
+
459
+ def whenever(files)
460
+ add(NameIs.new(files))
461
+ end
462
+
463
+ def start
464
+ @workers_thread = Thread.new {
465
+ begin
466
+ interval = 0.1
467
+ event_interval = 0.5
468
+ last_event_time = nil
469
+ next_time = Time.now.to_f+interval
470
+ events = {}
471
+ while true
472
+ until @queue.empty?
473
+ event = @queue.pop(true) rescue nil
474
+ if event
475
+ name = event[0]
476
+ flags = event[1]
477
+ if events[name]
478
+ new_flags = events[name] + flags
479
+ if new_flags == [:delete, :create, :modify]
480
+ new_flags = [:modify]
481
+ end
482
+ events[name] = new_flags
483
+ else
484
+ events[name] = flags
485
+ end
486
+ last_event_time = Time.now.to_f
487
+ end
488
+ end
489
+ if last_event_time && Time.now.to_f >= (last_event_time+event_interval)
490
+ events.each do |name,flags|
491
+ begin
492
+ Nite::Owl::NiteOwl.instance.call(name,flags.uniq)
493
+ rescue Exception => e
494
+ puts e.message
495
+ puts e.backtrace
496
+ end
497
+ end
498
+ events.clear
499
+ last_event_time = nil
500
+ end
501
+ Action.call_all_deferred_actions()
502
+ delay = next_time - Time.now.to_f
503
+ if delay > 0
504
+ sleep(delay)
505
+ end
506
+ next_time = Time.now.to_f+interval
507
+ end
508
+ rescue Exception => e
509
+ puts e.message
510
+ puts e.backtrace
511
+ end
512
+ }
513
+ # start platform specific notifier
514
+ pwd = Dir.pwd
515
+ if RUBY_PLATFORM =~ /linux/
516
+ require 'rb-inotify'
517
+ puts "Nite Owl watching: #{pwd}"
518
+ notifier = INotify::Notifier.new
519
+ notifier.watch(pwd, :recursive, :modify, :create, :delete, :move) do |event|
520
+ name = event.absolute_name.slice(pwd.size+1,event.absolute_name.size-pwd.size)
521
+ flags = event.flags do |f|
522
+ if f == :moved_to or f == :moved_from
523
+ :rename
524
+ else
525
+ f
526
+ end
527
+ end
528
+ @queue << [name,flags]
529
+ end
530
+ begin
531
+ notifier.run
532
+ rescue Interrupt => e
533
+ end
534
+ elsif RUBY_PLATFORM =~ /darwin/
535
+ require 'rb-fsevent'
536
+ puts "Nite Owl watching: #{pwd}"
537
+ fsevent = FSEvent.new
538
+ fsevent.watch pwd,{:file_events => true} do |paths, event_meta|
539
+ event_meta['events'].each do |event|
540
+ name = event['path']
541
+ name = name.slice(pwd.size+1,name.size-pwd.size)
542
+ flags = event['flags'].map do |f|
543
+ if f == 'ItemCreated'
544
+ :create
545
+ elsif f == 'ItemModified'
546
+ :modify
547
+ elsif f == 'ItemRemoved'
548
+ :delete
549
+ elsif f == 'ItemRenamed'
550
+ :rename
551
+ end
552
+ end.keep_if {|f| f}
553
+ @queue << [name,flags]
554
+ end
555
+ end
556
+ fsevent.run
557
+ else
558
+ puts "Platform unsupported"
559
+ exit(1)
560
+ end
561
+ end
562
+ end
563
+ end
564
+ end
@@ -0,0 +1,5 @@
1
+ module Nite
2
+ module Owl
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,29 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "nite/owl/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "nite-owl"
8
+ spec.version = Nite::Owl::VERSION
9
+ spec.authors = ["Dmitry Geurkov"]
10
+ spec.email = ["d.geurkov@gmail.com"]
11
+
12
+ spec.summary = %q{Linux/OSX File System Events Watcher.}
13
+ spec.description = %q{Linux/OSX File System Events Watcher.}
14
+ spec.homepage = "https://github.com/troydm/nite-owl"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_dependency "rb-fsevent", "~> 0.10", ">= 0.10.2"
25
+ spec.add_dependency "rb-inotify", "~> 0.9", ">= 0.9.10"
26
+ spec.add_development_dependency "bundler", "~> 1.16"
27
+ spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "rspec", "~> 3.0"
29
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nite-owl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dmitry Geurkov
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-09-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rb-fsevent
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.10'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.10.2
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.10'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.10.2
33
+ - !ruby/object:Gem::Dependency
34
+ name: rb-inotify
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.9'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 0.9.10
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '0.9'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 0.9.10
53
+ - !ruby/object:Gem::Dependency
54
+ name: bundler
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '1.16'
60
+ type: :development
61
+ prerelease: false
62
+ version_requirements: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '1.16'
67
+ - !ruby/object:Gem::Dependency
68
+ name: rake
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "~>"
72
+ - !ruby/object:Gem::Version
73
+ version: '10.0'
74
+ type: :development
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "~>"
79
+ - !ruby/object:Gem::Version
80
+ version: '10.0'
81
+ - !ruby/object:Gem::Dependency
82
+ name: rspec
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '3.0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '3.0'
95
+ description: Linux/OSX File System Events Watcher.
96
+ email:
97
+ - d.geurkov@gmail.com
98
+ executables:
99
+ - nite-owl
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - ".gitignore"
104
+ - ".rspec"
105
+ - ".travis.yml"
106
+ - Gemfile
107
+ - LICENSE.txt
108
+ - Niteowl
109
+ - README.md
110
+ - Rakefile
111
+ - bin/console
112
+ - bin/setup
113
+ - exe/nite-owl
114
+ - lib/nite/owl.rb
115
+ - lib/nite/owl/niteowl.rb
116
+ - lib/nite/owl/version.rb
117
+ - nite-owl.gemspec
118
+ homepage: https://github.com/troydm/nite-owl
119
+ licenses:
120
+ - MIT
121
+ metadata: {}
122
+ post_install_message:
123
+ rdoc_options: []
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ requirements: []
137
+ rubyforge_project:
138
+ rubygems_version: 2.5.2.1
139
+ signing_key:
140
+ specification_version: 4
141
+ summary: Linux/OSX File System Events Watcher.
142
+ test_files: []