rb-fsevent 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }
@@ -1,9 +1,8 @@
1
1
  class FSEvent
2
- attr_reader :path, :latency, :callback, :pipe
2
+ attr_reader :path, :callback, :pipe
3
3
 
4
- def watch(path, options = {}, &callback)
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("KILL", pipe.pid) if pipe
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}/rb-fsevent #{path} #{latency}")
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
@@ -1,3 +1,3 @@
1
1
  module RbFSEvent
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
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: 21
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 2
9
- - 1
10
- version: 0.2.1
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-16 00:00:00 +02:00
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: &id002 !ruby/object:Gem::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: *id002
36
+ version_requirements: *id001
53
37
  - !ruby/object:Gem::Dependency
54
38
  name: rspec
55
39
  prerelease: false
56
- requirement: &id003 !ruby/object:Gem::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: *id003
52
+ version_requirements: *id002
69
53
  - !ruby/object:Gem::Dependency
70
54
  name: guard-rspec
71
55
  prerelease: false
72
- requirement: &id004 !ruby/object:Gem::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: *id004
85
- description: FSEvents API using FFI (without RubyCocoa)
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