rb-fsevent 0.9.8 → 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 33b6645ea468e8ad531d5cc24e3b8ae9794a30a9
4
- data.tar.gz: 2d775b72b9303d0e93068850a7d119315bcad81d
3
+ metadata.gz: 61d076a09964b861d80f4724752654bd1e03d7b1
4
+ data.tar.gz: 549a175bc931f6e247d09e87bc4a0e805a8715b8
5
5
  SHA512:
6
- metadata.gz: 5cbb1ac611ea29a0fa14e72a8f016741e39bf0d9987717244ad9dbe14188a8c94f891687e12d0320f96dea49b47f5a9697deb189eb9751e42dda406b0a680e65
7
- data.tar.gz: 2c87389ccab291b776189be56f12f322e0e26e2ea0ed1d22429f5d932b212788cf3e29e15ce02f762f82849d6a293e01e630955aaa01b7a0db17db69046c1711
6
+ metadata.gz: e124acb15e091aae6d754e00dde77dde57a267c3c209cab827735f527abce5800d4b16066adaeacdbadc4fa8311b1622bda29bf300de8a1a4c3c4d1033e7f1d4
7
+ data.tar.gz: d27912bb5ea1822547af03aeabb819a6aabf39b1cae25289e0132ac768d68d7751f1895ccd97bdbf9026c2c1fe787d8d0612708a725fcef6c9882fa4a91e1082
data/Gemfile CHANGED
@@ -1,6 +1,3 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
-
5
- gem 'rake'
6
-
data/README.md CHANGED
@@ -7,8 +7,8 @@ Very simple & usable Mac OSX FSEvents API
7
7
 
8
8
  * RubyCocoa not required!
9
9
  * Signals are working (really)
10
- * Tested on MRI 2.1, RBX 2.5, JRuby
11
- * Tested on 10.10
10
+ * Tested on MRI 2.4.1, RBX 3.72, JRuby 1.7.26 and 9.1.8.0
11
+ * Tested on 10.8
12
12
 
13
13
  ## HFS+ filename corruption bug
14
14
 
@@ -131,6 +131,23 @@ end
131
131
  fsevent.run
132
132
  ```
133
133
 
134
+ ### Using _full_ event information
135
+
136
+ ```ruby
137
+ require 'rb-fsevent'
138
+ fsevent = FSEvent.new
139
+ fsevent.watch Dir.pwd do |paths, event_meta|
140
+ event_meta.events.each do |event|
141
+ puts "event ID: #{event.id}"
142
+ puts "path: #{event.path}"
143
+ puts "c flags: #{event.cflags}"
144
+ puts "named flags: #{event.flags.join(', ')}"
145
+ # named flags will include strings such as `ItemInodeMetaMod` or `OwnEvent`
146
+ end
147
+ end
148
+ fsevent.run
149
+ ```
150
+
134
151
  ## Options
135
152
 
136
153
  When defining options using a hash or hash-like object, it gets checked for validity and converted to the appropriate fsevent\_watch commandline arguments array when the FSEvent class is instantiated. This is obviously the safest and preferred method of passing in options.
@@ -233,7 +250,7 @@ Pull requests are quite welcome! Please ensure that your commits are in a topic
233
250
 
234
251
  The list of tested targets is currently:
235
252
 
236
- %w[2.2.2 2.3.0-dev rbx-2.5.5 jruby-1.7.9]
253
+ %w[2.4.1 rbx-3.72 jruby-1.7.26 jruby-9.1.8.0]
237
254
 
238
255
  ## Authors
239
256
 
data/Rakefile CHANGED
@@ -9,7 +9,7 @@ task :default => :spec
9
9
  namespace(:spec) do
10
10
  desc "Run all specs on multiple ruby versions"
11
11
  task(:portability) do
12
- versions = %w[2.2.2 2.3.0-dev rbx-2.5.5 jruby-1.7.9]
12
+ versions = %w[2.4.1 rbx-3.72 jruby-1.7.26 jruby-9.1.8.0]
13
13
  versions.each do |version|
14
14
  # system <<-BASH
15
15
  # bash -c 'source ~/.rvm/scripts/rvm;
@@ -24,6 +24,7 @@ namespace(:spec) do
24
24
  [[ ! -a $HOME/.rbenv/versions/#{version} ]] && rbenv install #{version};
25
25
  rbenv shell #{version};
26
26
  rbenv which bundle 2> /dev/null || gem install bundler;
27
+ rm Gemfile.lock;
27
28
  bundle install;
28
29
  rake spec;'
29
30
  BASH
Binary file
@@ -27,7 +27,7 @@ static void default_args (struct cli_info* args_info)
27
27
  args_info->ignore_self_flag = false;
28
28
  args_info->file_events_flag = false;
29
29
  args_info->mark_self_flag = false;
30
- args_info->format_arg = kFSEventWatchOutputFormatClassic;
30
+ args_info->format_arg = kFSEventWatchOutputFormatOTNetstring;
31
31
  }
32
32
 
33
33
  static void cli_parser_release (struct cli_info* args_info)
@@ -199,4 +199,3 @@ int cli_parser (int argc, const char** argv, struct cli_info* args_info)
199
199
 
200
200
  return EXIT_SUCCESS;
201
201
  }
202
-
@@ -1,10 +1,13 @@
1
1
  #include "compat.h"
2
2
 
3
- #if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
3
+
4
+ #if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_6) || \
5
+ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_6_0)
4
6
  FSEventStreamCreateFlags kFSEventStreamCreateFlagIgnoreSelf = 0x00000008;
5
7
  #endif
6
8
 
7
- #if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
9
+ #if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_7) || \
10
+ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_6_0)
8
11
  FSEventStreamCreateFlags kFSEventStreamCreateFlagFileEvents = 0x00000010;
9
12
  FSEventStreamEventFlags kFSEventStreamEventFlagItemCreated = 0x00000100;
10
13
  FSEventStreamEventFlags kFSEventStreamEventFlagItemRemoved = 0x00000200;
@@ -19,7 +22,20 @@ FSEventStreamEventFlags kFSEventStreamEventFlagItemIsDir = 0x00020000
19
22
  FSEventStreamEventFlags kFSEventStreamEventFlagItemIsSymlink = 0x00040000;
20
23
  #endif
21
24
 
22
- #if MAC_OS_X_VERSION_MAX_ALLOWED < 1090
25
+ #if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_9) || \
26
+ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_7_0)
23
27
  FSEventStreamCreateFlags kFSEventStreamCreateFlagMarkSelf = 0x00000020;
24
28
  FSEventStreamEventFlags kFSEventStreamEventFlagOwnEvent = 0x00080000;
25
29
  #endif
30
+
31
+ #if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_10) || \
32
+ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_9_0)
33
+ FSEventStreamEventFlags kFSEventStreamEventFlagItemIsHardlink = 0x00100000;
34
+ FSEventStreamEventFlags kFSEventStreamEventFlagItemIsLastHardlink = 0x00200000;
35
+ #endif
36
+
37
+ #if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_13) || \
38
+ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_11_0)
39
+ FSEventStreamCreateFlags kFSEventStreamCreateFlagUseExtendedData = 0x00000040;
40
+ FSEventStreamEventFlags kFSEventStreamEventFlagItemCloned = 0x00400000;
41
+ #endif
@@ -9,20 +9,57 @@
9
9
  */
10
10
 
11
11
 
12
- #ifndef fsevent_watch_compat_h
13
- #define fsevent_watch_compat_h
12
+ #ifndef listen_fsevents_compat_h
13
+ #define listen_fsevents_compat_h
14
14
 
15
15
  #ifndef __CORESERVICES__
16
16
  #include <CoreServices/CoreServices.h>
17
17
  #endif // __CORESERVICES__
18
18
 
19
- #if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
20
- // ignoring events originating from the current process introduced in 10.6
19
+ #ifndef __AVAILABILITY__
20
+ #include <Availability.h>
21
+ #endif // __AVAILABILITY__
22
+
23
+ #ifndef __MAC_10_6
24
+ #define __MAC_10_6 1060
25
+ #endif
26
+ #ifndef __MAC_10_7
27
+ #define __MAC_10_7 1070
28
+ #endif
29
+ #ifndef __MAC_10_9
30
+ #define __MAC_10_9 1090
31
+ #endif
32
+ #ifndef __MAC_10_10
33
+ #define __MAC_10_10 101000
34
+ #endif
35
+ #ifndef __MAC_10_13
36
+ #define __MAC_10_13 101300
37
+ #endif
38
+ #ifndef __IPHONE_6_0
39
+ #define __IPHONE_6_0 60000
40
+ #endif
41
+ #ifndef __IPHONE_7_0
42
+ #define __IPHONE_7_0 70000
43
+ #endif
44
+ #ifndef __IPHONE_9_0
45
+ #define __IPHONE_9_0 90000
46
+ #endif
47
+ #ifndef __IPHONE_11_0
48
+ #define __IPHONE_11_0 110000
49
+ #endif
50
+
51
+ #ifdef __cplusplus
52
+ extern "C" {
53
+ #endif
54
+
55
+
56
+ #if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_6) || \
57
+ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_6_0)
21
58
  extern FSEventStreamCreateFlags kFSEventStreamCreateFlagIgnoreSelf;
22
59
  #endif
23
60
 
24
- #if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
25
- // file-level events introduced in 10.7
61
+ #if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_7) || \
62
+ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_6_0)
26
63
  extern FSEventStreamCreateFlags kFSEventStreamCreateFlagFileEvents;
27
64
  extern FSEventStreamEventFlags kFSEventStreamEventFlagItemCreated,
28
65
  kFSEventStreamEventFlagItemRemoved,
@@ -37,11 +74,27 @@ extern FSEventStreamEventFlags kFSEventStreamEventFlagItemCreated,
37
74
  kFSEventStreamEventFlagItemIsSymlink;
38
75
  #endif
39
76
 
40
- #if MAC_OS_X_VERSION_MAX_ALLOWED < 1090
41
- // marking, rather than ignoring, events originating from the current process introduced in 10.9
77
+ #if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_9) || \
78
+ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_7_0)
42
79
  extern FSEventStreamCreateFlags kFSEventStreamCreateFlagMarkSelf;
43
80
  extern FSEventStreamEventFlags kFSEventStreamEventFlagOwnEvent;
44
81
  #endif
45
82
 
83
+ #if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_10) || \
84
+ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_9_0)
85
+ extern FSEventStreamEventFlags kFSEventStreamEventFlagItemIsHardlink,
86
+ kFSEventStreamEventFlagItemIsLastHardlink;
87
+ #endif
88
+
89
+ #if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_13) || \
90
+ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_11_0)
91
+ extern FSEventStreamCreateFlags kFSEventStreamCreateFlagUseExtendedData;
92
+ extern FSEventStreamEventFlags kFSEventStreamEventFlagItemCloned;
93
+ #endif
94
+
95
+
96
+ #ifdef __cplusplus
97
+ }
98
+ #endif
46
99
 
47
- #endif // fsevent_watch_compat_h
100
+ #endif // listen_fsevents_compat_h
@@ -24,7 +24,7 @@ static struct {
24
24
  (double) 0.3,
25
25
  (CFOptionFlags) kFSEventStreamCreateFlagNone,
26
26
  NULL,
27
- kFSEventWatchOutputFormatClassic
27
+ kFSEventWatchOutputFormatOTNetstring
28
28
  };
29
29
 
30
30
  // Prototypes
@@ -350,18 +350,54 @@ static void tstring_output_format(size_t numEvents,
350
350
  false);
351
351
  CFDictionarySetValue(event, CFSTR("path"), path);
352
352
 
353
- CFNumberRef flags = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &eventFlags[i]);
354
- CFDictionarySetValue(event, CFSTR("flags"), flags);
355
-
356
353
  CFNumberRef ident = CFNumberCreate(kCFAllocatorDefault, kCFNumberLongLongType, &eventIds[i]);
357
354
  CFDictionarySetValue(event, CFSTR("id"), ident);
358
355
 
356
+ CFNumberRef cflags = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &eventFlags[i]);
357
+ CFDictionarySetValue(event, CFSTR("cflags"), cflags);
358
+
359
+ CFMutableArrayRef flags = CFArrayCreateMutable(kCFAllocatorDefault,
360
+ 0, &kCFTypeArrayCallBacks);
361
+
362
+ #define FLAG_ADD_NAME(flagsnum, flagnum, flagname, flagarray) \
363
+ do { \
364
+ if (FLAG_CHECK(flagsnum, flagnum)) { \
365
+ CFArrayAppendValue(flagarray, CFSTR(flagname)); } } \
366
+ while(0)
367
+
368
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagMustScanSubDirs, "MustScanSubDirs", flags);
369
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagUserDropped, "UserDropped", flags);
370
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagKernelDropped, "KernelDropped", flags);
371
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagEventIdsWrapped, "EventIdsWrapped", flags);
372
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagHistoryDone, "HistoryDone", flags);
373
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagRootChanged, "RootChanged", flags);
374
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagMount, "Mount", flags);
375
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagUnmount, "Unmount", flags);
376
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagItemCreated, "ItemCreated", flags);
377
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagItemRemoved, "ItemRemoved", flags);
378
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagItemInodeMetaMod, "ItemInodeMetaMod", flags);
379
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagItemRenamed, "ItemRenamed", flags);
380
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagItemModified, "ItemModified", flags);
381
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagItemFinderInfoMod, "ItemFinderInfoMod", flags);
382
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagItemChangeOwner, "ItemChangeOwner", flags);
383
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagItemXattrMod, "ItemXattrMod", flags);
384
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagItemIsFile, "ItemIsFile", flags);
385
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagItemIsDir, "ItemIsDir", flags);
386
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagItemIsSymlink, "ItemIsSymlink", flags);
387
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagOwnEvent, "OwnEvent", flags);
388
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagItemIsHardlink, "ItemIsHardLink", flags);
389
+ FLAG_ADD_NAME(eventFlags[i], kFSEventStreamEventFlagItemIsLastHardlink, "ItemIsLastHardLink", flags);
390
+
391
+ CFDictionarySetValue(event, CFSTR("flags"), flags);
392
+
393
+
359
394
  CFArrayAppendValue(events, event);
360
395
 
361
396
  CFRelease(event);
362
397
  CFRelease(path);
363
- CFRelease(flags);
364
398
  CFRelease(ident);
399
+ CFRelease(cflags);
400
+ CFRelease(flags);
365
401
  }
366
402
 
367
403
  CFMutableDictionaryRef meta = CFDictionaryCreateMutable(kCFAllocatorDefault,
@@ -446,7 +482,10 @@ static void callback(__attribute__((unused)) FSEventStreamRef streamRef,
446
482
  " Item is a directory");
447
483
  FLAG_CHECK_STDERR(eventFlags[i], kFSEventStreamEventFlagItemIsSymlink,
448
484
  " Item is a symbolic link");
449
-
485
+ FLAG_CHECK_STDERR(eventFlags[i], kFSEventStreamEventFlagItemIsHardlink,
486
+ " Item is a hard link");
487
+ FLAG_CHECK_STDERR(eventFlags[i], kFSEventStreamEventFlagItemIsLastHardlink,
488
+ " Item is the last hard link");
450
489
  fprintf(stderr, " event path: %s\n", paths[i]);
451
490
  fprintf(stderr, "\n");
452
491
  }
@@ -8,7 +8,7 @@ require 'rake/clean'
8
8
  raise "unable to find xcodebuild" unless system('which', 'xcodebuild')
9
9
 
10
10
 
11
- FSEVENT_WATCH_EXE_VERSION = '0.1.4'
11
+ FSEVENT_WATCH_EXE_VERSION = '0.1.5'
12
12
 
13
13
  $this_dir = Pathname.new(__FILE__).dirname.expand_path
14
14
  $final_exe = $this_dir.parent.join('bin/fsevent_watch')
@@ -148,7 +148,7 @@ file $obj_dir.join('Info.plist').to_s => [$obj_dir.to_s, :setup_env] do
148
148
  key['CFBundleDisplayName']
149
149
  string['FSEvent Watch CLI']
150
150
  key['NSHumanReadableCopyright']
151
- string['Copyright (C) 2011-2015 Travis Tilley']
151
+ string['Copyright (C) 2011-2017 Travis Tilley']
152
152
 
153
153
  key['CFBundleVersion']
154
154
  string["#{FSEVENT_WATCH_EXE_VERSION}"]
@@ -216,8 +216,10 @@ task :codesign => :build do
216
216
  sh "codesign -s '#{$CODE_SIGN_IDENTITY}' #{$obj_dir.join('fsevent_watch')}"
217
217
  end
218
218
 
219
+ directory $this_dir.parent.join('bin')
220
+
219
221
  desc 'replace bundled fsevent_watch binary with build/fsevent_watch'
220
- task :replace_exe => :build do
222
+ task :replace_exe => [$this_dir.parent.join('bin'), :build] do
221
223
  sh "mv #{$obj_dir.join('fsevent_watch')} #{$final_exe}"
222
224
  end
223
225
 
@@ -0,0 +1,85 @@
1
+ # Copyright (c) 2011 Konstantin Haase
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+
22
+ require 'stringio'
23
+
24
+ module OTNetstring
25
+ class Error < StandardError; end
26
+
27
+ class << self
28
+ def parse(io, encoding = 'internal', fallback_encoding = nil)
29
+ fallback_encoding = io.encoding if io.respond_to? :encoding
30
+ io = StringIO.new(io) if io.respond_to? :to_str
31
+ length, byte = "", nil
32
+
33
+ while byte.nil? || byte =~ /\d/
34
+ length << byte if byte
35
+ byte = io.read(1)
36
+ end
37
+
38
+ if length.size > 9
39
+ raise Error, "#{length} is longer than 9 digits"
40
+ elsif length !~ /\d+/
41
+ raise Error, "Expected '#{byte}' to be a digit"
42
+ end
43
+ length = Integer(length)
44
+
45
+ case byte
46
+ when '#' then Integer io.read(length)
47
+ when ',' then with_encoding io.read(length), encoding, fallback_encoding
48
+ when '~' then
49
+ raise Error, "nil has length of 0, #{length} given" unless length == 0
50
+ when '!' then io.read(length) == 'true'
51
+ when '[', '{'
52
+ array = []
53
+ start = io.pos
54
+ array << parse(io, encoding, fallback_encoding) while io.pos - start < length
55
+ raise Error, 'Nested element longer than container' if io.pos - start != length
56
+ byte == "{" ? Hash[*array] : array
57
+ else
58
+ raise Error, "Unknown type '#{byte}'"
59
+ end
60
+ end
61
+
62
+ def encode(obj, string_sep = ',')
63
+ case obj
64
+ when String then with_encoding "#{obj.bytesize}#{string_sep}#{obj}", "binary"
65
+ when Integer then encode(obj.inspect, '#')
66
+ when NilClass then "0~"
67
+ when Array then encode(obj.map { |e| encode(e) }.join, '[')
68
+ when Hash then encode(obj.map { |a,b| encode(a)+encode(b) }.join, '{')
69
+ when FalseClass, TrueClass then encode(obj.inspect, '!')
70
+ else raise Error, 'cannot encode %p' % obj
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ def with_encoding(str, encoding, fallback = nil)
77
+ return str unless str.respond_to? :encode
78
+ encoding = Encoding.find encoding if encoding.respond_to? :to_str
79
+ encoding ||= fallback
80
+ encoding ? str.encode(encoding) : str
81
+ rescue EncodingError
82
+ str.force_encoding(encoding)
83
+ end
84
+ end
85
+ end
@@ -1,5 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
+ require 'otnetstring'
4
+
3
5
  class FSEvent
4
6
  class << self
5
7
  class_eval <<-END
@@ -40,9 +42,41 @@ class FSEvent
40
42
  # please note the use of IO::select() here, as it is used specifically to
41
43
  # preserve correct signal handling behavior in ruby 1.8.
42
44
  while @running && IO::select([@pipe], nil, nil, nil)
43
- if line = @pipe.readline
44
- modified_dir_paths = line.split(':').select { |dir| dir != "\n" }
45
- callback.call(modified_dir_paths)
45
+ # managing the IO ourselves allows us to be careful and never pass an
46
+ # incomplete message to OTNetstring.parse()
47
+ message = ""
48
+ length = ""
49
+ byte = nil
50
+
51
+ reading_length = true
52
+ found_length = false
53
+
54
+ while reading_length
55
+ byte = @pipe.read(1)
56
+ if "#{byte}" =~ /\d/
57
+ length << byte
58
+ found_length = true
59
+ elsif found_length == false
60
+ next
61
+ else
62
+ reading_length = false
63
+ end
64
+ end
65
+ length = Integer(length, 10)
66
+ type = byte
67
+
68
+ message << "#{length}#{type}"
69
+ message << @pipe.read(length)
70
+
71
+ decoded = OTNetstring.parse(message)
72
+ modified_paths = decoded["events"].map {|event| event["path"]}
73
+ # passing the full info as a second block param feels icky, but such is
74
+ # the trap of backward compatibility.
75
+ case callback.arity
76
+ when 1
77
+ callback.call(modified_paths)
78
+ when 2
79
+ callback.call(modified_paths, decoded)
46
80
  end
47
81
  end
48
82
  rescue Interrupt, IOError, Errno::EBADF
@@ -110,7 +144,7 @@ class FSEvent
110
144
  private
111
145
 
112
146
  def parse_options(options={})
113
- opts = []
147
+ opts = ['--format=otnetstring']
114
148
  opts.concat(['--since-when', options[:since_when]]) if options[:since_when]
115
149
  opts.concat(['--latency', options[:latency]]) if options[:latency]
116
150
  opts.push('--no-defer') if options[:no_defer]
@@ -1,5 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
3
  class FSEvent
4
- VERSION = '0.9.8'
4
+ VERSION = '0.10.2'
5
5
  end
@@ -13,10 +13,15 @@ Gem::Specification.new do |s|
13
13
  s.description = 'FSEvents API with Signals catching (without RubyCocoa)'
14
14
  s.license = 'MIT'
15
15
 
16
+ s.metadata = {
17
+ 'source_code_uri' => 'https://github.com/thibaudgg/rb-fsevent'
18
+ }
19
+
16
20
  s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^spec/}) }
17
21
  s.require_path = 'lib'
18
22
 
19
23
  s.add_development_dependency 'bundler', '~> 1.0'
20
- s.add_development_dependency 'rspec', '~> 2.11'
24
+ s.add_development_dependency 'rspec', '~> 3.6'
21
25
  s.add_development_dependency 'guard-rspec', '~> 4.2'
26
+ s.add_development_dependency 'rake', '~> 12.0'
22
27
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rb-fsevent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.8
4
+ version: 0.10.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thibaud Guillaume-Gentil
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-10-24 00:00:00.000000000 Z
12
+ date: 2017-07-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -31,14 +31,14 @@ dependencies:
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '2.11'
34
+ version: '3.6'
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: '2.11'
41
+ version: '3.6'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: guard-rspec
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -53,6 +53,20 @@ dependencies:
53
53
  - - "~>"
54
54
  - !ruby/object:Gem::Version
55
55
  version: '4.2'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rake
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '12.0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '12.0'
56
70
  description: FSEvents API with Signals catching (without RubyCocoa)
57
71
  email:
58
72
  - thibaud@thibaud.gg
@@ -83,6 +97,7 @@ files:
83
97
  - ext/fsevent_watch/signal_handlers.c
84
98
  - ext/fsevent_watch/signal_handlers.h
85
99
  - ext/rakefile.rb
100
+ - lib/otnetstring.rb
86
101
  - lib/rb-fsevent.rb
87
102
  - lib/rb-fsevent/fsevent.rb
88
103
  - lib/rb-fsevent/version.rb
@@ -90,7 +105,8 @@ files:
90
105
  homepage: http://rubygems.org/gems/rb-fsevent
91
106
  licenses:
92
107
  - MIT
93
- metadata: {}
108
+ metadata:
109
+ source_code_uri: https://github.com/thibaudgg/rb-fsevent
94
110
  post_install_message:
95
111
  rdoc_options: []
96
112
  require_paths:
@@ -107,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
123
  version: '0'
108
124
  requirements: []
109
125
  rubyforge_project:
110
- rubygems_version: 2.4.5.1
126
+ rubygems_version: 2.6.11
111
127
  signing_key:
112
128
  specification_version: 4
113
129
  summary: Very simple & usable FSEvents API