fssm 0.2.5 → 0.2.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +42 -40
- data/Rakefile +5 -5
- data/example.rb +3 -3
- data/fssm.gemspec +14 -14
- data/lib/fssm.rb +2 -1
- data/lib/fssm/backends/inotify.rb +1 -1
- data/lib/fssm/backends/rbfsevent.rb +23 -7
- data/lib/fssm/monitor.rb +6 -0
- data/lib/fssm/path.rb +1 -0
- data/lib/fssm/support.rb +10 -3
- data/lib/fssm/version.rb +1 -1
- data/profile/prof-cache.rb +3 -3
- data/profile/prof-pathname-rubinius.rb +3 -3
- data/profile/prof-pathname.rb +7 -7
- data/spec/count_down_latch.rb +10 -10
- data/spec/monitor_spec.rb +34 -34
- data/spec/path_spec.rb +15 -15
- data/spec/spec_helper.rb +5 -6
- metadata +84 -75
data/README.markdown
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# FSSM ![project status](http://stillmaintained.com/ttilley/fssm.png) #
|
2
|
+
|
1
3
|
Monitor API
|
2
4
|
===========
|
3
5
|
|
@@ -12,70 +14,70 @@ Monitor with path
|
|
12
14
|
|
13
15
|
This form watches one path, and enters the run loop automatically. The first parameter is the path to watch, and the second parameter is an optional glob pattern or array of glob patterns that a file must match in order to trigger a callback. The default glob, if ommitted, is `'**/*'`.
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
FSSM.monitor('/some/directory/', '**/*') do
|
18
|
+
update {|base, relative|}
|
19
|
+
delete {|base, relative|}
|
20
|
+
create {|base, relative|}
|
21
|
+
end
|
20
22
|
|
21
23
|
Monitor with block
|
22
24
|
------------------
|
23
25
|
|
24
26
|
This form watches one or more paths, and enters the run loop automatically. The glob configuration call can be ommitted, and defaults to `'**/*'`.
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
28
|
+
FSSM.monitor do
|
29
|
+
path '/some/directory/' do
|
30
|
+
glob '**/*.yml'
|
31
|
+
|
32
|
+
update {|base, relative|}
|
33
|
+
delete {|base, relative|}
|
34
|
+
create {|base, relative|}
|
35
|
+
end
|
36
|
+
|
37
|
+
path '/some/other/directory/' do
|
38
|
+
update {|base, relative|}
|
39
|
+
delete {|base, relative|}
|
40
|
+
create {|base, relative|}
|
41
|
+
end
|
42
|
+
end
|
41
43
|
|
42
44
|
Monitor object
|
43
45
|
--------------
|
44
46
|
|
45
47
|
This form doesn't enter the run loop automatically.
|
46
48
|
|
47
|
-
|
49
|
+
monitor = FSSM::Monitor.new
|
48
50
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
monitor.path '/some/directory/' do
|
52
|
+
update {|base, relative|}
|
53
|
+
delete {|base, relative|}
|
54
|
+
create {|base, relative|}
|
55
|
+
end
|
54
56
|
|
55
|
-
|
57
|
+
monitor.run
|
56
58
|
|
57
59
|
Monitoring directories
|
58
60
|
----------------------
|
59
61
|
|
60
|
-
By default, FSSM monitors changes in files only. To enable monitoring of files and directories, pass option `directories => true` in a hash to the monitor. For example:
|
62
|
+
By default, FSSM monitors changes in files only. To enable monitoring of files and directories, pass option `directories => true` in a hash to the monitor. Please note that this may not work as expected in all backends. For example:
|
61
63
|
|
62
|
-
|
63
|
-
|
64
|
+
FSSM::Monitor.new(:directories => true)
|
65
|
+
FSSM.monitor(dir, file_glob, :directories => true)
|
64
66
|
|
65
67
|
When directories are monitored, there's an additional third argument to the callbacks. Instead of
|
66
68
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
69
|
+
FSSM.monitor('/some/directory/', '**/*') do
|
70
|
+
update {|base, relative|}
|
71
|
+
delete {|base, relative|}
|
72
|
+
create {|base, relative|}
|
73
|
+
end
|
72
74
|
|
73
75
|
you get this:
|
74
76
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
77
|
+
FSSM.monitor('/some/directory/', '**/*', :directories => true) do
|
78
|
+
update {|base, relative, type|}
|
79
|
+
delete {|base, relative, type|}
|
80
|
+
create {|base, relative, type|}
|
81
|
+
end
|
80
82
|
|
81
83
|
The value of `type` argument is either `:file` or `:directory`.
|
data/Rakefile
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
+
require 'rubygems'
|
1
2
|
require 'bundler'
|
2
3
|
Bundler::GemHelper.install_tasks
|
3
4
|
|
4
|
-
require '
|
5
|
-
|
6
|
-
spec.
|
7
|
-
spec.
|
8
|
-
spec.spec_opts = ['--format', 'specdoc']
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
7
|
+
spec.rspec_opts = ["--color", "--backtrace", "--format", "documentation"]
|
8
|
+
spec.verbose = true
|
9
9
|
end
|
10
10
|
|
11
11
|
task :default => :spec
|
data/example.rb
CHANGED
@@ -6,7 +6,7 @@ require 'rubygems'
|
|
6
6
|
require 'fssm'
|
7
7
|
|
8
8
|
FSSM.monitor('.', '**/*') do
|
9
|
-
update {|b, r| puts "Update in #{b} to #{r}"}
|
10
|
-
delete {|b, r| puts "Delete in #{b} to #{r}"}
|
11
|
-
create {|b, r| puts "Create in #{b} to #{r}"}
|
9
|
+
update { |b, r| puts "Update in #{b} to #{r}" }
|
10
|
+
delete { |b, r| puts "Delete in #{b} to #{r}" }
|
11
|
+
create { |b, r| puts "Create in #{b} to #{r}" }
|
12
12
|
end
|
data/fssm.gemspec
CHANGED
@@ -3,22 +3,22 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
require "fssm/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
|
-
s.name
|
7
|
-
s.version
|
8
|
-
s.platform
|
9
|
-
s.authors
|
10
|
-
|
11
|
-
s.email
|
12
|
-
s.homepage
|
13
|
-
s.summary
|
14
|
-
s.description
|
6
|
+
s.name = "fssm"
|
7
|
+
s.version = FSSM::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Travis Tilley", "Nathan Weizenbaum", "Chris Eppstein",
|
10
|
+
"Jonathan Castello", "Tuomas Kareinen"]
|
11
|
+
s.email = ["ttilley@gmail.com"]
|
12
|
+
s.homepage = "https://github.com/ttilley/fssm"
|
13
|
+
s.summary = %q{File System State Monitor}
|
14
|
+
s.description = %q{The File System State Monitor keeps track of the state of any number of paths and will fire events when said state changes (create/update/delete). FSSM supports using FSEvents on MacOS, Inotify on GNU/Linux, and polling anywhere else.}
|
15
15
|
|
16
16
|
s.rubyforge_project = "fssm"
|
17
17
|
|
18
|
-
s.files
|
19
|
-
s.test_files
|
20
|
-
s.executables
|
21
|
-
s.require_paths
|
18
|
+
s.files = `git ls-files`.split("\n")
|
19
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
20
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
21
|
+
s.require_paths = ["lib"]
|
22
22
|
|
23
|
-
s.add_development_dependency "rspec", "
|
23
|
+
s.add_development_dependency "rspec", ">= 2.4.0"
|
24
24
|
end
|
data/lib/fssm.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
dir = File.dirname(__FILE__)
|
2
2
|
$LOAD_PATH.unshift dir unless $LOAD_PATH.include?(dir)
|
3
3
|
|
4
|
+
#noinspection ALL
|
4
5
|
module FSSM
|
5
6
|
FileNotFoundError = Class.new(StandardError)
|
6
7
|
FileNotRealError = Class.new(StandardError)
|
@@ -8,7 +9,7 @@ module FSSM
|
|
8
9
|
|
9
10
|
class << self
|
10
11
|
def dbg(msg=nil)
|
11
|
-
STDERR.puts(msg)
|
12
|
+
STDERR.puts("FSSM -> #{msg}")
|
12
13
|
end
|
13
14
|
|
14
15
|
def monitor(*args, &block)
|
@@ -5,7 +5,7 @@ module FSSM::Backends
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def add_handler(handler, preload=true)
|
8
|
-
@notifier.watch(handler.path.to_s, :recursive, :attrib, :
|
8
|
+
@notifier.watch(handler.path.to_s, :recursive, :attrib, :close_write, :create,
|
9
9
|
:delete, :delete_self, :moved_from, :moved_to, :move_self) do |event|
|
10
10
|
path = FSSM::Pathname.for(event.absolute_name)
|
11
11
|
path = path.dirname unless event.name == "" # Event on root directory
|
@@ -1,26 +1,42 @@
|
|
1
1
|
module FSSM::Backends
|
2
2
|
class RBFSEvent
|
3
3
|
def initialize
|
4
|
-
@
|
4
|
+
@handlers = []
|
5
5
|
end
|
6
6
|
|
7
7
|
def add_handler(handler, preload=true)
|
8
|
-
@
|
9
|
-
paths.each do |path|
|
10
|
-
handler.refresh(path)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
8
|
+
@handlers << handler
|
14
9
|
handler.refresh(nil, true) if preload
|
15
10
|
end
|
16
11
|
|
17
12
|
def run
|
18
13
|
begin
|
14
|
+
@fsevent = FSEvent.new
|
15
|
+
@fsevent.watch(temporary_multipath_hack) do |paths|
|
16
|
+
paths.each do |path|
|
17
|
+
temporary_multipath_handler(path)
|
18
|
+
end
|
19
|
+
end
|
19
20
|
@fsevent.run
|
20
21
|
rescue Interrupt
|
21
22
|
@fsevent.stop
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
26
|
+
def temporary_multipath_handler(path)
|
27
|
+
@handlers.each do |handler|
|
28
|
+
handler_path = File.join(handler.path.to_s, "")
|
29
|
+
if handler_path.start_with?(path)
|
30
|
+
handler.refresh(path)
|
31
|
+
break
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def temporary_multipath_hack
|
37
|
+
@handlers = @handlers.sort {|x,y| y.path.to_pathname.segments.length <=> x.path.to_pathname.segments.length}
|
38
|
+
return @handlers.map {|handler| handler.path.to_s}
|
39
|
+
end
|
40
|
+
|
25
41
|
end
|
26
42
|
end
|
data/lib/fssm/monitor.rb
CHANGED
@@ -8,12 +8,18 @@ class FSSM::Monitor
|
|
8
8
|
path = create_path(path, glob, &block)
|
9
9
|
@backend.add_handler(FSSM::State::Directory.new(path, @options))
|
10
10
|
path
|
11
|
+
rescue FSSM::FileNotRealError => e
|
12
|
+
FSSM.dbg("#{e}")
|
13
|
+
nil
|
11
14
|
end
|
12
15
|
|
13
16
|
def file(path=nil, glob=nil, &block)
|
14
17
|
path = create_path(path, glob, &block)
|
15
18
|
@backend.add_handler(FSSM::State::File.new(path))
|
16
19
|
path
|
20
|
+
rescue FSSM::FileNotRealError => e
|
21
|
+
FSSM.dbg("#{e}")
|
22
|
+
nil
|
17
23
|
end
|
18
24
|
|
19
25
|
def run
|
data/lib/fssm/path.rb
CHANGED
@@ -85,6 +85,7 @@ class FSSM::Path
|
|
85
85
|
@path = FSSM::Pathname.for(path).expand_path
|
86
86
|
raise FSSM::FileNotFoundError, "No such file or directory - #{@path}" unless @path.exist?
|
87
87
|
raise FSSM::FileNotRealError, "Path is virtual - #{@path}" if @path.is_virtual?
|
88
|
+
@path = @path.realpath
|
88
89
|
end
|
89
90
|
|
90
91
|
def set_glob(glob)
|
data/lib/fssm/support.rb
CHANGED
@@ -4,7 +4,7 @@ module FSSM::Support
|
|
4
4
|
class << self
|
5
5
|
def usable_backend
|
6
6
|
choice = case
|
7
|
-
when mac? && !jruby? && carbon_core?
|
7
|
+
when mac? && !lion? && !jruby? && carbon_core?
|
8
8
|
'FSEvents'
|
9
9
|
when mac? && rb_fsevent?
|
10
10
|
'RBFSEvent'
|
@@ -21,8 +21,8 @@ module FSSM::Support
|
|
21
21
|
when linux?
|
22
22
|
'rb-inotify'
|
23
23
|
end
|
24
|
-
|
25
|
-
|
24
|
+
FSSM.dbg("An optimized backend is available for this platform!")
|
25
|
+
FSSM.dbg(" gem install #{optimal}")
|
26
26
|
end
|
27
27
|
|
28
28
|
choice
|
@@ -40,6 +40,10 @@ module FSSM::Support
|
|
40
40
|
Config::CONFIG['target_os'] =~ /darwin/i
|
41
41
|
end
|
42
42
|
|
43
|
+
def lion?
|
44
|
+
Config::CONFIG['target_os'] =~ /darwin11/i
|
45
|
+
end
|
46
|
+
|
43
47
|
def linux?
|
44
48
|
Config::CONFIG['target_os'] =~ /linux/i
|
45
49
|
end
|
@@ -57,6 +61,9 @@ module FSSM::Support
|
|
57
61
|
def rb_fsevent?
|
58
62
|
begin
|
59
63
|
require 'rb-fsevent'
|
64
|
+
if defined?(FSEvent::VERSION)
|
65
|
+
FSEvent::VERSION.to_f >= 0.4
|
66
|
+
end
|
60
67
|
true
|
61
68
|
rescue LoadError
|
62
69
|
false
|
data/lib/fssm/version.rb
CHANGED
data/profile/prof-cache.rb
CHANGED
@@ -5,7 +5,7 @@ require 'fssm'
|
|
5
5
|
require 'rubygems'
|
6
6
|
require 'ruby-prof'
|
7
7
|
|
8
|
-
$test_path
|
8
|
+
$test_path = FSSM::Pathname.new('..').expand_path
|
9
9
|
$test_files = FSSM::Pathname.glob(File.join($test_path, '**', '*'))
|
10
10
|
|
11
11
|
RubyProf.start
|
@@ -33,8 +33,8 @@ cache = FSSM::Tree::Cache.new
|
|
33
33
|
print "\n\n"
|
34
34
|
end
|
35
35
|
|
36
|
-
result
|
37
|
-
output
|
36
|
+
result = RubyProf.stop
|
37
|
+
output = File.new('prof.html', 'w+')
|
38
38
|
|
39
39
|
printer = RubyProf::GraphHtmlPrinter.new(result)
|
40
40
|
printer.print(output, :min_percent => 1)
|
@@ -2,7 +2,7 @@ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
2
2
|
|
3
3
|
require 'pathname'
|
4
4
|
|
5
|
-
$test_path
|
5
|
+
$test_path = "#{Pathname.new('..').expand_path}"
|
6
6
|
$iterations = 900000
|
7
7
|
|
8
8
|
if ARGV.first == 'native'
|
@@ -20,7 +20,7 @@ if ARGV.first == 'native'
|
|
20
20
|
end
|
21
21
|
|
22
22
|
$iterations.times do |num|
|
23
|
-
p
|
23
|
+
p = ::Pathname.new($test_path)
|
24
24
|
segments = p.segments
|
25
25
|
end
|
26
26
|
else
|
@@ -29,7 +29,7 @@ else
|
|
29
29
|
require 'fssm'
|
30
30
|
|
31
31
|
$iterations.times do |num|
|
32
|
-
p
|
32
|
+
p = FSSM::Pathname.new($test_path)
|
33
33
|
segments = p.segments
|
34
34
|
end
|
35
35
|
end
|
data/profile/prof-pathname.rb
CHANGED
@@ -6,7 +6,7 @@ require 'pathname'
|
|
6
6
|
require 'rubygems'
|
7
7
|
require 'ruby-prof'
|
8
8
|
|
9
|
-
$test_path
|
9
|
+
$test_path = "#{Pathname.new('..').expand_path}"
|
10
10
|
$iterations = 90000
|
11
11
|
|
12
12
|
class Pathname
|
@@ -32,15 +32,15 @@ $iterations.times do |num|
|
|
32
32
|
puts "FSSM::Pathname iteration #{iteration}"
|
33
33
|
|
34
34
|
RubyProf.resume
|
35
|
-
p
|
35
|
+
p = FSSM::Pathname.new($test_path)
|
36
36
|
segments = p.segments
|
37
37
|
RubyProf.pause
|
38
38
|
end
|
39
39
|
|
40
40
|
puts "\nFSSM Pathname profile finished\n\n"
|
41
41
|
|
42
|
-
result
|
43
|
-
output
|
42
|
+
result = RubyProf.stop
|
43
|
+
output = File.new('prof-fssm-pathname.html', 'w+')
|
44
44
|
|
45
45
|
printer = RubyProf::GraphHtmlPrinter.new(result)
|
46
46
|
printer.print(output, :min_percent => 1)
|
@@ -54,15 +54,15 @@ $iterations.times do |num|
|
|
54
54
|
puts "::Pathname iteration #{iteration}"
|
55
55
|
|
56
56
|
RubyProf.resume
|
57
|
-
p
|
57
|
+
p = ::Pathname.new($test_path)
|
58
58
|
segments = p.segments
|
59
59
|
RubyProf.pause
|
60
60
|
end
|
61
61
|
|
62
62
|
puts "\nruby Pathname profile finished\n\n"
|
63
63
|
|
64
|
-
result
|
65
|
-
output
|
64
|
+
result = RubyProf.stop
|
65
|
+
output = File.new('prof-plain-pathname.html', 'w+')
|
66
66
|
|
67
67
|
printer = RubyProf::GraphHtmlPrinter.new(result)
|
68
68
|
printer.print(output, :min_percent => 1)
|
data/spec/count_down_latch.rb
CHANGED
@@ -9,7 +9,7 @@ class CountDownLatch
|
|
9
9
|
def initialize(to)
|
10
10
|
@count = to.to_i
|
11
11
|
raise ArgumentError, "cannot count down from negative integer" unless @count >= 0
|
12
|
-
@lock
|
12
|
+
@lock = Mutex.new
|
13
13
|
@condition = ConditionVariable.new
|
14
14
|
end
|
15
15
|
|
@@ -37,7 +37,7 @@ if $0 == __FILE__
|
|
37
37
|
|
38
38
|
def test_basic_latch_usage
|
39
39
|
latch = CountDownLatch.new(1)
|
40
|
-
name
|
40
|
+
name = "foo"
|
41
41
|
Thread.new do
|
42
42
|
name = "bar"
|
43
43
|
latch.count_down
|
@@ -49,7 +49,7 @@ if $0 == __FILE__
|
|
49
49
|
|
50
50
|
def test_basic_latch_usage_inverted
|
51
51
|
latch = CountDownLatch.new(1)
|
52
|
-
name
|
52
|
+
name = "foo"
|
53
53
|
Thread.new do
|
54
54
|
latch.wait
|
55
55
|
assert_equal(0, latch.count)
|
@@ -67,7 +67,7 @@ if $0 == __FILE__
|
|
67
67
|
|
68
68
|
def test_count_down_twice_with_thread
|
69
69
|
latch = CountDownLatch.new(2)
|
70
|
-
name
|
70
|
+
name = "foo"
|
71
71
|
Thread.new do
|
72
72
|
latch.count_down
|
73
73
|
name = "bar"
|
@@ -80,7 +80,7 @@ if $0 == __FILE__
|
|
80
80
|
|
81
81
|
def test_count_down_twice_with_two_parallel_threads
|
82
82
|
latch = CountDownLatch.new(2)
|
83
|
-
name
|
83
|
+
name = "foo"
|
84
84
|
Thread.new { latch.count_down }
|
85
85
|
Thread.new do
|
86
86
|
name = "bar"
|
@@ -93,7 +93,7 @@ if $0 == __FILE__
|
|
93
93
|
|
94
94
|
def test_count_down_twice_with_two_chained_threads
|
95
95
|
latch = CountDownLatch.new(2)
|
96
|
-
name
|
96
|
+
name = "foo"
|
97
97
|
Thread.new do
|
98
98
|
latch.count_down
|
99
99
|
Thread.new do
|
@@ -108,8 +108,8 @@ if $0 == __FILE__
|
|
108
108
|
|
109
109
|
def test_count_down_with_multiple_waiters
|
110
110
|
proceed_latch = CountDownLatch.new(2)
|
111
|
-
check_latch
|
112
|
-
results
|
111
|
+
check_latch = CountDownLatch.new(2)
|
112
|
+
results = {}
|
113
113
|
Thread.new do
|
114
114
|
proceed_latch.wait
|
115
115
|
results[:first] = 1
|
@@ -131,9 +131,9 @@ if $0 == __FILE__
|
|
131
131
|
|
132
132
|
def test_interleaved_latches
|
133
133
|
change_1_latch = CountDownLatch.new(1)
|
134
|
-
check_latch
|
134
|
+
check_latch = CountDownLatch.new(1)
|
135
135
|
change_2_latch = CountDownLatch.new(1)
|
136
|
-
name
|
136
|
+
name = "foo"
|
137
137
|
Thread.new do
|
138
138
|
name = "bar"
|
139
139
|
change_1_latch.count_down
|
data/spec/monitor_spec.rb
CHANGED
@@ -25,9 +25,9 @@ module FSSM::MonitorSpecHelpers
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def run_monitor(num_events_to_expect=0, options={})
|
28
|
-
event_latch
|
29
|
-
@handler_results = Hash.new {|hash, key| hash[key] = []}
|
30
|
-
thread
|
28
|
+
event_latch = CountDownLatch.new(num_events_to_expect)
|
29
|
+
@handler_results = Hash.new { |hash, key| hash[key] = [] }
|
30
|
+
thread = Thread.new do
|
31
31
|
monitor = FSSM::Monitor.new(options)
|
32
32
|
monitor.path(@tmp_dir) do |p|
|
33
33
|
p.create(&create_handler(:create, event_latch))
|
@@ -36,7 +36,7 @@ module FSSM::MonitorSpecHelpers
|
|
36
36
|
end
|
37
37
|
monitor.run
|
38
38
|
end
|
39
|
-
sleep 1
|
39
|
+
sleep 1 # give time for monitor to start up
|
40
40
|
yield if block_given?
|
41
41
|
event_latch.wait
|
42
42
|
thread.kill
|
@@ -126,18 +126,18 @@ describe "The File System State Monitor" do
|
|
126
126
|
run_monitor(3, :directories => true) do
|
127
127
|
FileUtils.mv @tmp_dir + "/root/yawn", @tmp_dir + "/root/old_yawn"
|
128
128
|
end
|
129
|
-
@handler_results[:create].should include([@tmp_dir, 'root/old_yawn',
|
130
|
-
@handler_results[:delete].should include([@tmp_dir, 'root/yawn',
|
131
|
-
@handler_results[:update].should include([@tmp_dir, 'root',
|
129
|
+
@handler_results[:create].should include([@tmp_dir, 'root/old_yawn', :directory])
|
130
|
+
@handler_results[:delete].should include([@tmp_dir, 'root/yawn', :directory])
|
131
|
+
@handler_results[:update].should include([@tmp_dir, 'root', :directory])
|
132
132
|
end
|
133
133
|
|
134
134
|
it "should call create, update, and delete callbacks upon directory moving to another directory" do
|
135
135
|
run_monitor(3, :directories => true) do
|
136
136
|
FileUtils.mv @tmp_dir + "/root/yawn", @tmp_dir + "/old_yawn"
|
137
137
|
end
|
138
|
-
@handler_results[:create].should include([@tmp_dir, 'old_yawn',
|
139
|
-
@handler_results[:delete].should include([@tmp_dir, 'root/yawn',
|
140
|
-
@handler_results[:update].should include([@tmp_dir, 'root',
|
138
|
+
@handler_results[:create].should include([@tmp_dir, 'old_yawn', :directory])
|
139
|
+
@handler_results[:delete].should include([@tmp_dir, 'root/yawn', :directory])
|
140
|
+
@handler_results[:update].should include([@tmp_dir, 'root', :directory])
|
141
141
|
end
|
142
142
|
|
143
143
|
it "should call create, update, and delete callbacks upon file renaming in the same directory" do
|
@@ -145,55 +145,55 @@ describe "The File System State Monitor" do
|
|
145
145
|
FileUtils.mv @tmp_dir + "/root/file.rb", @tmp_dir + "/root/old_file.rb"
|
146
146
|
end
|
147
147
|
@handler_results[:create].should include([@tmp_dir, 'root/old_file.rb', :file])
|
148
|
-
@handler_results[:delete].should include([@tmp_dir, 'root/file.rb',
|
149
|
-
@handler_results[:update].should include([@tmp_dir, 'root',
|
148
|
+
@handler_results[:delete].should include([@tmp_dir, 'root/file.rb', :file])
|
149
|
+
@handler_results[:update].should include([@tmp_dir, 'root', :directory])
|
150
150
|
end
|
151
151
|
|
152
152
|
it "should call create, update, and delete callbacks upon file moving to another directory" do
|
153
153
|
run_monitor(3, :directories => true) do
|
154
154
|
FileUtils.mv @tmp_dir + "/root/file.rb", @tmp_dir + "/old_file.rb"
|
155
155
|
end
|
156
|
-
@handler_results[:create].should include([@tmp_dir, 'old_file.rb',
|
156
|
+
@handler_results[:create].should include([@tmp_dir, 'old_file.rb', :file])
|
157
157
|
@handler_results[:delete].should include([@tmp_dir, 'root/file.rb', :file])
|
158
|
-
@handler_results[:update].should include([@tmp_dir, 'root',
|
158
|
+
@handler_results[:update].should include([@tmp_dir, 'root', :directory])
|
159
159
|
end
|
160
160
|
|
161
161
|
it "should call delete callbacks upon directory structure deletion, in reverse order" do
|
162
162
|
expected_delete_events = [
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
163
|
+
['root/yawn', :directory],
|
164
|
+
['root/moo/cow.txt', :file],
|
165
|
+
['root/moo', :directory],
|
166
|
+
['root/file.yml', :file],
|
167
|
+
['root/file.rb', :file],
|
168
|
+
['root/file.css', :file],
|
169
|
+
['root/duck/quack.txt', :file],
|
170
|
+
['root/duck', :directory],
|
171
|
+
['root', :directory]
|
172
172
|
]
|
173
173
|
run_monitor(expected_delete_events.size, :directories => true) do
|
174
174
|
FileUtils.rm_rf @tmp_dir + '/.'
|
175
175
|
end
|
176
176
|
@handler_results[:create].should == []
|
177
|
-
@handler_results[:delete].should == expected_delete_events.map {|(file, type)| [@tmp_dir, file, type]}
|
177
|
+
@handler_results[:delete].should == expected_delete_events.map { |(file, type)| [@tmp_dir, file, type] }
|
178
178
|
@handler_results[:update].should == []
|
179
179
|
end
|
180
180
|
|
181
181
|
it "should call create callbacks upon directory structure creation, in order" do
|
182
182
|
expected_create_events = [
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
183
|
+
['new_root', :directory],
|
184
|
+
['new_root/duck', :directory],
|
185
|
+
['new_root/duck/quack.txt', :file],
|
186
|
+
['new_root/file.css', :file],
|
187
|
+
['new_root/file.rb', :file],
|
188
|
+
['new_root/file.yml', :file],
|
189
|
+
['new_root/moo', :directory],
|
190
|
+
['new_root/moo/cow.txt', :file],
|
191
|
+
['new_root/yawn', :directory]
|
192
192
|
]
|
193
193
|
run_monitor(expected_create_events.size, :directories => true) do
|
194
194
|
FileUtils.cp_r @tmp_dir + '/root/.', @tmp_dir + '/new_root'
|
195
195
|
end
|
196
|
-
@handler_results[:create].should == expected_create_events.map {|(file, type)| [@tmp_dir, file, type]}
|
196
|
+
@handler_results[:create].should == expected_create_events.map { |(file, type)| [@tmp_dir, file, type] }
|
197
197
|
@handler_results[:delete].should == []
|
198
198
|
@handler_results[:update].should == []
|
199
199
|
end
|
data/spec/path_spec.rb
CHANGED
@@ -3,11 +3,11 @@ require "spec_helper"
|
|
3
3
|
describe "The File System State Monitor" do
|
4
4
|
describe "paths" do
|
5
5
|
it "should accept a valid filesystem directory" do
|
6
|
-
lambda {FSSM::Path.new("#{@watch_root}")}.should_not raise_error
|
6
|
+
lambda { FSSM::Path.new("#{@watch_root}") }.should_not raise_error
|
7
7
|
end
|
8
8
|
|
9
9
|
it "should not accept an invalid filesystem directory" do
|
10
|
-
lambda {FSSM::Path.new('/does/not/exist/kthxbye')}.should raise_error
|
10
|
+
lambda { FSSM::Path.new('/does/not/exist/kthxbye') }.should raise_error
|
11
11
|
end
|
12
12
|
|
13
13
|
it "should default the path to the current directory" do
|
@@ -28,7 +28,7 @@ describe "The File System State Monitor" do
|
|
28
28
|
end
|
29
29
|
|
30
30
|
it "should accept an optional option parameter" do
|
31
|
-
lambda {FSSM::Path.new('.', '**/*.yml', :foo => :bar)}.should_not raise_error
|
31
|
+
lambda { FSSM::Path.new('.', '**/*.yml', :foo => :bar) }.should_not raise_error
|
32
32
|
end
|
33
33
|
|
34
34
|
it "should default the glob to ['**/*']" do
|
@@ -37,22 +37,22 @@ describe "The File System State Monitor" do
|
|
37
37
|
end
|
38
38
|
|
39
39
|
it "should accept a callback for update events" do
|
40
|
-
path
|
41
|
-
callback = lambda {|base, relative| return true}
|
40
|
+
path = FSSM::Path.new
|
41
|
+
callback = lambda { |base, relative| return true }
|
42
42
|
path.update(&callback)
|
43
43
|
(path.update).should == callback
|
44
44
|
end
|
45
45
|
|
46
46
|
it "should accept a callback for delete events" do
|
47
|
-
path
|
48
|
-
callback = lambda {|base, relative| return true}
|
47
|
+
path = FSSM::Path.new
|
48
|
+
callback = lambda { |base, relative| return true }
|
49
49
|
path.delete(&callback)
|
50
50
|
(path.delete).should == callback
|
51
51
|
end
|
52
52
|
|
53
53
|
it "should accept a callback for create events" do
|
54
|
-
path
|
55
|
-
callback = lambda {|base, relative| return true}
|
54
|
+
path = FSSM::Path.new
|
55
|
+
callback = lambda { |base, relative| return true }
|
56
56
|
path.create(&callback)
|
57
57
|
(path.create).should == callback
|
58
58
|
end
|
@@ -60,9 +60,9 @@ describe "The File System State Monitor" do
|
|
60
60
|
it "should accept a configuration block" do
|
61
61
|
path = FSSM::Path.new "#{@watch_root}" do
|
62
62
|
glob '**/*.yml'
|
63
|
-
update {|base, relative| 'success'}
|
64
|
-
delete {|base, relative| 'success'}
|
65
|
-
create {|base, relative| 'success'}
|
63
|
+
update { |base, relative| 'success' }
|
64
|
+
delete { |base, relative| 'success' }
|
65
|
+
create { |base, relative| 'success' }
|
66
66
|
end
|
67
67
|
|
68
68
|
"#{path}".should == "#{@watch_root}"
|
@@ -78,9 +78,9 @@ describe "The File System State Monitor" do
|
|
78
78
|
it "should pass file type to callbacks as the third argument if :directories option is used" do
|
79
79
|
path = FSSM::Path.new "#{@watch_root}", nil, :directories => true do
|
80
80
|
glob '**/*.yml'
|
81
|
-
update {|base, relative, type| [base, relative, type]}
|
82
|
-
delete {|base, relative, type| [base, relative, type]}
|
83
|
-
create {|base, relative, type| [base, relative, type]}
|
81
|
+
update { |base, relative, type| [base, relative, type] }
|
82
|
+
delete { |base, relative, type| [base, relative, type] }
|
83
|
+
create { |base, relative, type| [base, relative, type] }
|
84
84
|
end
|
85
85
|
|
86
86
|
"#{path}".should == "#{@watch_root}"
|
data/spec/spec_helper.rb
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
-
$LOAD_PATH.unshift(File.
|
2
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', File.dirname(__FILE__)))
|
3
3
|
|
4
|
-
require 'pathname'
|
5
4
|
require 'rubygems'
|
5
|
+
require 'bundler/setup'
|
6
6
|
require 'fssm'
|
7
7
|
|
8
|
-
require '
|
9
|
-
require 'spec/autorun'
|
8
|
+
require 'rspec'
|
10
9
|
|
11
|
-
|
10
|
+
RSpec.configure do |config|
|
12
11
|
config.before :all do
|
13
|
-
@watch_root = Pathname.new(__FILE__).dirname.join('root').expand_path
|
12
|
+
@watch_root = FSSM::Pathname.new(__FILE__).dirname.join('root').expand_path
|
14
13
|
end
|
15
14
|
end
|
metadata
CHANGED
@@ -1,36 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fssm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 6
|
9
|
+
version: 0.2.6
|
6
10
|
platform: ruby
|
7
11
|
authors:
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
- Travis Tilley
|
13
|
+
- Nathan Weizenbaum
|
14
|
+
- Chris Eppstein
|
15
|
+
- Jonathan Castello
|
16
|
+
- Tuomas Kareinen
|
13
17
|
autorequire:
|
14
18
|
bindir: bin
|
15
19
|
cert_chain: []
|
16
20
|
|
17
|
-
date: 2011-
|
21
|
+
date: 2011-03-21 00:00:00 -04:00
|
18
22
|
default_executable:
|
19
23
|
dependencies:
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: rspec
|
26
|
+
prerelease: false
|
27
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
segments:
|
32
|
+
- 2
|
33
|
+
- 4
|
34
|
+
- 0
|
35
|
+
version: 2.4.0
|
36
|
+
type: :development
|
37
|
+
version_requirements: *id001
|
31
38
|
description: The File System State Monitor keeps track of the state of any number of paths and will fire events when said state changes (create/update/delete). FSSM supports using FSEvents on MacOS, Inotify on GNU/Linux, and polling anywhere else.
|
32
39
|
email:
|
33
|
-
|
40
|
+
- ttilley@gmail.com
|
34
41
|
executables: []
|
35
42
|
|
36
43
|
extensions: []
|
@@ -38,42 +45,42 @@ extensions: []
|
|
38
45
|
extra_rdoc_files: []
|
39
46
|
|
40
47
|
files:
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
48
|
+
- .gitignore
|
49
|
+
- Gemfile
|
50
|
+
- LICENSE
|
51
|
+
- README.markdown
|
52
|
+
- Rakefile
|
53
|
+
- example.rb
|
54
|
+
- fssm.gemspec
|
55
|
+
- lib/fssm.rb
|
56
|
+
- lib/fssm/backends/fsevents.rb
|
57
|
+
- lib/fssm/backends/inotify.rb
|
58
|
+
- lib/fssm/backends/polling.rb
|
59
|
+
- lib/fssm/backends/rbfsevent.rb
|
60
|
+
- lib/fssm/backends/rubycocoa/fsevents.rb
|
61
|
+
- lib/fssm/monitor.rb
|
62
|
+
- lib/fssm/path.rb
|
63
|
+
- lib/fssm/pathname.rb
|
64
|
+
- lib/fssm/state/directory.rb
|
65
|
+
- lib/fssm/state/file.rb
|
66
|
+
- lib/fssm/support.rb
|
67
|
+
- lib/fssm/tree.rb
|
68
|
+
- lib/fssm/version.rb
|
69
|
+
- profile/prof-cache.rb
|
70
|
+
- profile/prof-fssm-pathname.html
|
71
|
+
- profile/prof-pathname-rubinius.rb
|
72
|
+
- profile/prof-pathname.rb
|
73
|
+
- profile/prof-plain-pathname.html
|
74
|
+
- profile/prof.html
|
75
|
+
- spec/count_down_latch.rb
|
76
|
+
- spec/monitor_spec.rb
|
77
|
+
- spec/path_spec.rb
|
78
|
+
- spec/root/duck/quack.txt
|
79
|
+
- spec/root/file.css
|
80
|
+
- spec/root/file.rb
|
81
|
+
- spec/root/file.yml
|
82
|
+
- spec/root/moo/cow.txt
|
83
|
+
- spec/spec_helper.rb
|
77
84
|
has_rdoc: true
|
78
85
|
homepage: https://github.com/ttilley/fssm
|
79
86
|
licenses: []
|
@@ -82,33 +89,35 @@ post_install_message:
|
|
82
89
|
rdoc_options: []
|
83
90
|
|
84
91
|
require_paths:
|
85
|
-
|
92
|
+
- lib
|
86
93
|
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
-
none: false
|
88
94
|
requirements:
|
89
|
-
|
90
|
-
|
91
|
-
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
segments:
|
98
|
+
- 0
|
99
|
+
version: "0"
|
92
100
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
-
none: false
|
94
101
|
requirements:
|
95
|
-
|
96
|
-
|
97
|
-
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
segments:
|
105
|
+
- 0
|
106
|
+
version: "0"
|
98
107
|
requirements: []
|
99
108
|
|
100
109
|
rubyforge_project: fssm
|
101
|
-
rubygems_version: 1.
|
110
|
+
rubygems_version: 1.3.6
|
102
111
|
signing_key:
|
103
112
|
specification_version: 3
|
104
113
|
summary: File System State Monitor
|
105
114
|
test_files:
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
+
- spec/count_down_latch.rb
|
116
|
+
- spec/monitor_spec.rb
|
117
|
+
- spec/path_spec.rb
|
118
|
+
- spec/root/duck/quack.txt
|
119
|
+
- spec/root/file.css
|
120
|
+
- spec/root/file.rb
|
121
|
+
- spec/root/file.yml
|
122
|
+
- spec/root/moo/cow.txt
|
123
|
+
- spec/spec_helper.rb
|