rb-fsevent 0.2.1 → 0.3.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.
- data/README.rdoc +4 -1
- data/ext/extconf.rb +19 -0
- data/ext/fsevent/fsevent_watch.c +44 -0
- data/lib/rb-fsevent/fsevent.rb +7 -6
- data/lib/rb-fsevent/version.rb +1 -1
- metadata +16 -31
- data/bin/rb-fsevent +0 -72
data/README.rdoc
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
Very simple & usable Mac OSX FSEvents API
|
4
4
|
|
5
|
-
- No compilation needed (FFI)
|
6
5
|
- RubyCocoa not required!
|
7
6
|
- Signals are working
|
8
7
|
- Tested on Ruby 1.8.7 & 1.9.2
|
@@ -21,6 +20,10 @@ Very simple & usable Mac OSX FSEvents API
|
|
21
20
|
end
|
22
21
|
fsevent.run
|
23
22
|
|
23
|
+
== Not about FFI
|
24
|
+
|
25
|
+
rb-fsevent doesn't use {ruby-ffi}[http://github.com/ffi/ffi] anymore because it sadly doesn't allow to catch Signals, you can see the code in {ffi branch}[http://github.com/thibaudgg/rb-fsevent/tree/ffi].
|
26
|
+
|
24
27
|
== Development
|
25
28
|
|
26
29
|
- Source hosted at {GitHub}[http://github.com/thibaudgg/rb-fsevent]
|
data/ext/extconf.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# Workaround to make Rubygems believe it builds a native gem
|
2
|
+
require 'mkmf'
|
3
|
+
create_makefile('none')
|
4
|
+
|
5
|
+
raise "Only Darwin (Mac OS X) systems are supported" unless `uname -s`.chomp == 'Darwin'
|
6
|
+
|
7
|
+
gem_root = File.expand_path(File.join('..'))
|
8
|
+
darwin_verion = `uname -r`.to_i
|
9
|
+
sdk_verion = { 9 => '10.5', 10 => '10.6', 11 => '10.7' }[darwin_verion]
|
10
|
+
|
11
|
+
raise "Only Darwin systems greather than 8 (Mac OS X 10.5+) are supported" unless sdk_verion
|
12
|
+
|
13
|
+
# Compile the actual fsevent_watch binary
|
14
|
+
system "mkdir -p #{File.join(gem_root, 'bin')}"
|
15
|
+
system "CFLAGS='-isysroot /Developer/SDKs/MacOSX#{sdk_verion}.sdk -mmacosx-version-min=#{sdk_verion}' /usr/bin/gcc -framework CoreServices -o '#{gem_root}/bin/fsevent_watch' fsevent/fsevent_watch.c"
|
16
|
+
|
17
|
+
unless File.executable?("#{gem_root}/bin/fsevent_watch")
|
18
|
+
raise "Compilation of fsevent_watch failed (see README)"
|
19
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#include <CoreServices/CoreServices.h>
|
2
|
+
|
3
|
+
void callback(ConstFSEventStreamRef streamRef,
|
4
|
+
void *clientCallBackInfo,
|
5
|
+
size_t numEvents,
|
6
|
+
void *eventPaths,
|
7
|
+
const FSEventStreamEventFlags eventFlags[],
|
8
|
+
const FSEventStreamEventId eventIds[]
|
9
|
+
) {
|
10
|
+
// Print modified dirs
|
11
|
+
int i;
|
12
|
+
char **paths = eventPaths;
|
13
|
+
for (i = 0; i < numEvents; i++) {
|
14
|
+
printf("%s", paths[i]);
|
15
|
+
printf(":");
|
16
|
+
}
|
17
|
+
printf("\n");
|
18
|
+
fflush(stdout);
|
19
|
+
}
|
20
|
+
|
21
|
+
int main (int argc, const char * argv[]) {
|
22
|
+
// Create event stream
|
23
|
+
CFStringRef pathToWatch = CFStringCreateWithCString(kCFAllocatorDefault, argv[1], kCFStringEncodingUTF8);
|
24
|
+
CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)&pathToWatch, 1, NULL);
|
25
|
+
void *callbackInfo = NULL;
|
26
|
+
FSEventStreamRef stream;
|
27
|
+
CFAbsoluteTime latency = 0.5;
|
28
|
+
stream = FSEventStreamCreate(
|
29
|
+
kCFAllocatorDefault,
|
30
|
+
callback,
|
31
|
+
callbackInfo,
|
32
|
+
pathsToWatch,
|
33
|
+
kFSEventStreamEventIdSinceNow,
|
34
|
+
latency,
|
35
|
+
kFSEventStreamCreateFlagNone
|
36
|
+
);
|
37
|
+
|
38
|
+
// Add stream to run loop
|
39
|
+
FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
40
|
+
FSEventStreamStart(stream);
|
41
|
+
CFRunLoopRun();
|
42
|
+
|
43
|
+
return 2;
|
44
|
+
}
|
data/lib/rb-fsevent/fsevent.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
class FSEvent
|
2
|
-
attr_reader :path, :
|
2
|
+
attr_reader :path, :callback, :pipe
|
3
3
|
|
4
|
-
def watch(path,
|
4
|
+
def watch(path, &callback)
|
5
5
|
@path = path
|
6
|
-
@latency = options[:latency] || 0.5
|
7
6
|
@callback = callback
|
8
7
|
end
|
9
8
|
|
@@ -13,7 +12,7 @@ class FSEvent
|
|
13
12
|
end
|
14
13
|
|
15
14
|
def stop
|
16
|
-
Process.kill("
|
15
|
+
Process.kill("HUP", pipe.pid) if pipe
|
17
16
|
end
|
18
17
|
|
19
18
|
private
|
@@ -23,16 +22,18 @@ private
|
|
23
22
|
end
|
24
23
|
|
25
24
|
def launch_bin
|
26
|
-
@pipe = IO.popen("#{bin_path}/
|
25
|
+
@pipe = IO.popen("#{bin_path}/fsevent_watch #{path}")
|
27
26
|
end
|
28
27
|
|
29
28
|
def listen
|
30
29
|
while !pipe.eof?
|
31
30
|
if line = pipe.readline
|
32
|
-
modified_dir_paths = line.split(" "
|
31
|
+
modified_dir_paths = line.split(":").select { |dir| dir != "\n" }
|
33
32
|
callback.call(modified_dir_paths)
|
34
33
|
end
|
35
34
|
end
|
35
|
+
rescue Interrupt
|
36
|
+
stop
|
36
37
|
end
|
37
38
|
|
38
39
|
end
|
data/lib/rb-fsevent/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rb-fsevent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 0.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Thibaud Guillaume-Gentil
|
@@ -15,29 +15,13 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-10-
|
18
|
+
date: 2010-10-17 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
22
|
-
name: ffi
|
23
|
-
prerelease: false
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ~>
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
hash: 1
|
30
|
-
segments:
|
31
|
-
- 0
|
32
|
-
- 6
|
33
|
-
- 3
|
34
|
-
version: 0.6.3
|
35
|
-
type: :runtime
|
36
|
-
version_requirements: *id001
|
37
21
|
- !ruby/object:Gem::Dependency
|
38
22
|
name: bundler
|
39
23
|
prerelease: false
|
40
|
-
requirement: &
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
41
25
|
none: false
|
42
26
|
requirements:
|
43
27
|
- - ~>
|
@@ -49,11 +33,11 @@ dependencies:
|
|
49
33
|
- 2
|
50
34
|
version: 1.0.2
|
51
35
|
type: :development
|
52
|
-
version_requirements: *
|
36
|
+
version_requirements: *id001
|
53
37
|
- !ruby/object:Gem::Dependency
|
54
38
|
name: rspec
|
55
39
|
prerelease: false
|
56
|
-
requirement: &
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
57
41
|
none: false
|
58
42
|
requirements:
|
59
43
|
- - ~>
|
@@ -65,11 +49,11 @@ dependencies:
|
|
65
49
|
- 0
|
66
50
|
version: 2.0.0
|
67
51
|
type: :development
|
68
|
-
version_requirements: *
|
52
|
+
version_requirements: *id002
|
69
53
|
- !ruby/object:Gem::Dependency
|
70
54
|
name: guard-rspec
|
71
55
|
prerelease: false
|
72
|
-
requirement: &
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
73
57
|
none: false
|
74
58
|
requirements:
|
75
59
|
- - ~>
|
@@ -81,21 +65,22 @@ dependencies:
|
|
81
65
|
- 3
|
82
66
|
version: 0.1.3
|
83
67
|
type: :development
|
84
|
-
version_requirements: *
|
85
|
-
description: FSEvents API
|
68
|
+
version_requirements: *id003
|
69
|
+
description: FSEvents API with Signals catching (without RubyCocoa)
|
86
70
|
email:
|
87
71
|
- thibaud@thibaud.me
|
88
72
|
executables: []
|
89
73
|
|
90
|
-
extensions:
|
91
|
-
|
74
|
+
extensions:
|
75
|
+
- ext/extconf.rb
|
92
76
|
extra_rdoc_files: []
|
93
77
|
|
94
78
|
files:
|
95
|
-
- bin/rb-fsevent
|
96
79
|
- lib/rb-fsevent/fsevent.rb
|
97
80
|
- lib/rb-fsevent/version.rb
|
98
81
|
- lib/rb-fsevent.rb
|
82
|
+
- ext/extconf.rb
|
83
|
+
- ext/fsevent/fsevent_watch.c
|
99
84
|
- LICENSE
|
100
85
|
- README.rdoc
|
101
86
|
has_rdoc: true
|
data/bin/rb-fsevent
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'rubygems'
|
3
|
-
require 'ffi'
|
4
|
-
|
5
|
-
paths, latency = ARGV[0].split(','), ARGV[1].to_f
|
6
|
-
|
7
|
-
module CarbonCore
|
8
|
-
extend FFI::Library
|
9
|
-
ffi_lib '/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Versions/Current/CarbonCore'
|
10
|
-
|
11
|
-
attach_function :CFStringCreateWithCString, [:pointer, :string, :int], :pointer
|
12
|
-
KCFStringEncodingUTF8 = 0x08000100
|
13
|
-
attach_function :CFStringGetLength, [:pointer, :pointer, :int, :pointer, :pointer, :pointer], :int
|
14
|
-
|
15
|
-
attach_function :CFArrayCreate, [:pointer, :pointer, :int, :pointer], :pointer
|
16
|
-
|
17
|
-
attach_function :CFRunLoopRun, :CFRunLoopRun, [], :void
|
18
|
-
attach_function :CFRunLoopGetCurrent, [], :pointer
|
19
|
-
attach_variable :kCFRunLoopDefaultMode, :pointer
|
20
|
-
|
21
|
-
callback :FSEventStreamCallback, [:pointer, :pointer, :int, :pointer, :pointer, :pointer], :void
|
22
|
-
|
23
|
-
KFSEventStreamEventIdSinceNow = -1
|
24
|
-
attach_function :FSEventStreamCreate, [:pointer, :FSEventStreamCallback, :pointer, :pointer, :long, :double, :int], :pointer
|
25
|
-
attach_function :FSEventStreamScheduleWithRunLoop, [:pointer, :pointer, :pointer], :void
|
26
|
-
attach_function :FSEventStreamStart, [:pointer], :void
|
27
|
-
attach_function :FSEventStreamStop, [:pointer], :void
|
28
|
-
end
|
29
|
-
|
30
|
-
class FSEventStream
|
31
|
-
KFSEventStreamEventFlagMustScanSubDirs = 0x1
|
32
|
-
|
33
|
-
class StreamError < StandardError;
|
34
|
-
end
|
35
|
-
|
36
|
-
attr_accessor :stream
|
37
|
-
|
38
|
-
def initialize(paths, latency)
|
39
|
-
# Create array of paths to observe
|
40
|
-
paths_ptr = FFI::MemoryPointer.new(:pointer)
|
41
|
-
paths.each do |path|
|
42
|
-
path_cfstring = CarbonCore.CFStringCreateWithCString(nil, path, CarbonCore::KCFStringEncodingUTF8)
|
43
|
-
paths_ptr.write_pointer(path_cfstring)
|
44
|
-
end
|
45
|
-
paths_cfarray = CarbonCore.CFArrayCreate nil, paths_ptr, 1, nil
|
46
|
-
|
47
|
-
# Create callback
|
48
|
-
callback = lambda do |stream, client_callback_info, number_of_events, event_paths, event_flags, event_ids|
|
49
|
-
if number_of_events > 0
|
50
|
-
paths = event_paths.get_array_of_string(0, number_of_events)
|
51
|
-
$stdout.puts paths.join(" ")
|
52
|
-
$stdout.flush
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
@stream = CarbonCore.FSEventStreamCreate(nil, callback, nil, paths_cfarray, CarbonCore::KFSEventStreamEventIdSinceNow, latency, 0)
|
57
|
-
|
58
|
-
CarbonCore.FSEventStreamScheduleWithRunLoop(stream, CarbonCore.CFRunLoopGetCurrent, CarbonCore.kCFRunLoopDefaultMode)
|
59
|
-
CarbonCore.FSEventStreamStart(stream)
|
60
|
-
end
|
61
|
-
|
62
|
-
def run_loop
|
63
|
-
CarbonCore.CFRunLoopRun
|
64
|
-
end
|
65
|
-
|
66
|
-
def stop
|
67
|
-
CarbonCore.FSEventStreamStop(stream)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
stream = FSEventStream.new(paths, latency)
|
72
|
-
stream.run_loop
|