tidings 0.2.0 → 0.2.1

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: cbe1831ad74b02894406f9969fca0ceb6240ca90
4
- data.tar.gz: 025784c85abf46654519579b0b70075c25ad6994
3
+ metadata.gz: acdbaca8aecfaa40103a8b5b9dbf7932322cccc0
4
+ data.tar.gz: 3906c9fff15182a42c9d472a69bb0190fb2b6ccf
5
5
  SHA512:
6
- metadata.gz: 34d4541a3abf171a7cafee93930dd477a3341e033b1289cf51cba6500f2d1ac0c511a9c0df48788f8ce9d5ecaecf6cda613ab2aaf63743fd0495096c41fe2d67
7
- data.tar.gz: df256ad3c8678154cc39a057d397740a45f9ac86283d27f454d0533d38cce2081fb40fede9ea85d543bcde4e6a33cb5de62d89357f71b1cc5975b8f9bf82819a
6
+ metadata.gz: 752e52830262e1f14e2fe360621ad0e7fd34fa00e31e597a3bf822559c8650b043c5d702b71a4cc080754ccdb853f3db95b1467acbe4cddc207f7fca2c3b8d72
7
+ data.tar.gz: 1d445b0ad98e8b663a4b96d637f66bcafad891ec1a55cbc61f723f62f08451f6dcebb491de7ed57c0c4b2191dc6dc9b0f767441c64baba0ea93608a7274db85e
data/ext/extconf.rb CHANGED
@@ -3,8 +3,8 @@ require 'mkmf'
3
3
  case RUBY_PLATFORM
4
4
  when /darwin/
5
5
  with_ldflags("-framework CoreServices") do
6
- create_makefile("fs_event/fs_event", "fs_event")
6
+ create_makefile("fs_event", "fs_event")
7
7
  end
8
8
  when /linux/
9
- create_makefile("inotify/inotify", "inotify")
9
+ create_makefile("inotify", "inotify")
10
10
  end
@@ -0,0 +1,104 @@
1
+ #include <stdio.h>
2
+ #include <ruby.h>
3
+
4
+ #include <CoreFoundation/CoreFoundation.h>
5
+ #include <CoreServices/CoreServices.h>
6
+
7
+ static VALUE processor;
8
+
9
+ VALUE fs_event_event_flags(const FSEventStreamEventFlags eventFlags)
10
+ {
11
+ VALUE event_flags = rb_ary_new();
12
+
13
+ if (eventFlags & kFSEventStreamEventFlagMustScanSubDirs)
14
+ rb_ary_push(event_flags, ID2SYM(rb_intern("must_scan")));
15
+ if (eventFlags & kFSEventStreamEventFlagItemCreated)
16
+ rb_ary_push(event_flags, ID2SYM(rb_intern("created")));
17
+ if (eventFlags & kFSEventStreamEventFlagItemRemoved)
18
+ rb_ary_push(event_flags, ID2SYM(rb_intern("removed")));
19
+ if (eventFlags & kFSEventStreamEventFlagItemRenamed)
20
+ rb_ary_push(event_flags, ID2SYM(rb_intern("renamed")));
21
+ if (eventFlags & kFSEventStreamEventFlagItemModified)
22
+ rb_ary_push(event_flags, ID2SYM(rb_intern("modified")));
23
+ if (eventFlags & kFSEventStreamEventFlagItemIsFile)
24
+ rb_ary_push(event_flags, ID2SYM(rb_intern("file")));
25
+ if (eventFlags & kFSEventStreamEventFlagItemIsDir)
26
+ rb_ary_push(event_flags, ID2SYM(rb_intern("dir")));
27
+
28
+ return event_flags;
29
+ }
30
+
31
+ void fs_event_callback(
32
+ ConstFSEventStreamRef streamRef,
33
+ void *userData,
34
+ size_t numberOfEvents,
35
+ void *eventPaths,
36
+ const FSEventStreamEventFlags eventFlags[],
37
+ const FSEventStreamEventId eventIds[]
38
+ )
39
+ {
40
+ char **paths = eventPaths;
41
+ size_t index;
42
+
43
+ for(index=0; index < numberOfEvents; index++) {
44
+ rb_funcall(processor, rb_intern("call"), 2,
45
+ rb_str_new2(paths[index]),
46
+ fs_event_event_flags(eventFlags[index])
47
+ );
48
+ }
49
+ }
50
+
51
+ /*
52
+ * call-seq:
53
+ * fs_event_watch(path, processor)
54
+ *
55
+ * Calls the block with the changed paths when something changes in the
56
+ * specified path. This method blocks the thread forever.
57
+ *
58
+ * FSEvent.watch('/tmp', Proc.new { |files| p files })
59
+ */
60
+ static VALUE fs_event_watch(VALUE self, VALUE path, VALUE proc)
61
+ {
62
+ processor = proc;
63
+
64
+ CFStringRef cfPaths[1];
65
+ cfPaths[0] = CFStringCreateWithCString(
66
+ kCFAllocatorSystemDefault,
67
+ RSTRING_PTR(path),
68
+ kCFStringEncodingUTF8
69
+ );
70
+ CFArrayRef paths = CFArrayCreate(kCFAllocatorSystemDefault, (const void **)cfPaths, 1, NULL);
71
+
72
+ FSEventStreamRef streamRef = FSEventStreamCreate(
73
+ NULL,
74
+ &fs_event_callback,
75
+ NULL,
76
+ paths,
77
+ kFSEventStreamEventIdSinceNow,
78
+ (CFTimeInterval)0.5,
79
+ kFSEventStreamCreateFlagWatchRoot | kFSEventStreamCreateFlagFileEvents
80
+ );
81
+
82
+ #ifdef DEBUG
83
+ FSEventStreamShow(streamRef);
84
+ #endif
85
+
86
+ FSEventStreamScheduleWithRunLoop(streamRef, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
87
+ FSEventStreamStart(streamRef);
88
+
89
+ CFRunLoopRun();
90
+
91
+ FSEventStreamFlushSync(streamRef);
92
+ FSEventStreamStop(streamRef);
93
+
94
+ return Qnil;
95
+ }
96
+
97
+ void Init_fs_event()
98
+ {
99
+ VALUE mFSEvent;
100
+
101
+ mFSEvent = rb_define_module("FSEvent");
102
+
103
+ rb_define_module_function(mFSEvent, "watch", fs_event_watch, 2);
104
+ }
@@ -0,0 +1,103 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <errno.h>
4
+ #include <sys/types.h>
5
+ #include <sys/inotify.h>
6
+ #include <unistd.h>
7
+ #include <ruby.h>
8
+
9
+ #define EVENT_SIZE ( sizeof (struct inotify_event) )
10
+ #define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
11
+
12
+ VALUE inotify_event_flags(uint32_t mask)
13
+ {
14
+ VALUE event_flags = rb_ary_new();
15
+
16
+ if (mask & IN_ACCESS)
17
+ rb_ary_push(event_flags, ID2SYM(rb_intern("accessed")));
18
+ if (mask & IN_CREATE)
19
+ rb_ary_push(event_flags, ID2SYM(rb_intern("created")));
20
+ if (mask & IN_DELETE)
21
+ rb_ary_push(event_flags, ID2SYM(rb_intern("removed")));
22
+ if (mask & IN_MODIFY)
23
+ rb_ary_push(event_flags, ID2SYM(rb_intern("modified")));
24
+ if (mask & IN_ISDIR)
25
+ rb_ary_push(event_flags, ID2SYM(rb_intern("dir")));
26
+ else
27
+ rb_ary_push(event_flags, ID2SYM(rb_intern("file")));
28
+
29
+ return event_flags;
30
+ }
31
+
32
+ /*
33
+ * call-seq:
34
+ * inotify_watch(path, processor)
35
+ *
36
+ * Calls the block with the changed paths when something changes in the
37
+ * specified path. This method blocks the thread forever.
38
+ *
39
+ * Inotify.watch('/tmp', Proc.new { |files| p files })
40
+ */
41
+ static VALUE inotify_watch(VALUE self, VALUE path, VALUE processor)
42
+ {
43
+ int length, i;
44
+ int notify;
45
+ int watch;
46
+ char buffer[BUF_LEN];
47
+ VALUE mFile = rb_const_get(rb_cObject, rb_intern("File"));
48
+
49
+ fd_set rfds;
50
+ struct timeval tv;
51
+ int retval;
52
+
53
+ notify = inotify_init();
54
+
55
+ if (notify < 0) perror("inotify_init");
56
+
57
+ watch = inotify_add_watch(notify, RSTRING_PTR(path), IN_MODIFY | IN_CREATE | IN_DELETE );
58
+
59
+ for (;;)
60
+ {
61
+ FD_ZERO(&rfds);
62
+ FD_SET(notify, &rfds);
63
+
64
+ tv.tv_sec = 0;
65
+ tv.tv_usec = 500;
66
+
67
+ retval = select(notify + 1, &rfds, NULL, NULL, &tv);
68
+
69
+ if (retval < 0) {
70
+ perror("select()");
71
+ return Qfalse;
72
+ } else if (FD_ISSET(notify, &rfds)) {
73
+ length = read(notify, buffer, BUF_LEN);
74
+ if (length < 0) perror("read");
75
+
76
+ i = 0;
77
+ while(i < length) {
78
+ struct inotify_event *event = (struct inotify_event *)&buffer[i];
79
+ if (event->len) {
80
+ rb_funcall(processor, rb_intern("call"), 2,
81
+ rb_funcall(mFile, rb_intern("join"), 2, path, rb_str_new2(event->name)),
82
+ inotify_event_flags(event->mask)
83
+ );
84
+ }
85
+ i += EVENT_SIZE + event->len;
86
+ }
87
+ }
88
+ }
89
+
90
+ inotify_rm_watch(notify, watch);
91
+ close(notify);
92
+
93
+ return Qnil;
94
+ }
95
+
96
+ void Init_inotify()
97
+ {
98
+ VALUE mInotify;
99
+
100
+ mInotify = rb_define_module("Inotify");
101
+
102
+ rb_define_module_function(mInotify, "watch", inotify_watch, 2);
103
+ }
@@ -0,0 +1,3 @@
1
+ module Tidings
2
+ VERSION = '0.2.1'
3
+ end
@@ -0,0 +1,29 @@
1
+ module Tidings
2
+ class Watcher
3
+ def initialize(path, processor)
4
+ @path, @processor, @pid = path, processor, nil
5
+ end
6
+
7
+ def start
8
+ Signal.trap("SIGINT") { stop }
9
+ @pid = fork { watch }
10
+ Tidings.log("Tidings running on PID: #{@pid}")
11
+ Process.wait
12
+ Tidings.log("Tidings stopped running")
13
+ end
14
+
15
+ def stop
16
+ Process.kill("KILL", @pid)
17
+ end
18
+
19
+ if const_defined?(:FSEvent)
20
+ def watch
21
+ FSEvent.watch(@path, @processor)
22
+ end
23
+ elsif const_defined?(:Inotify)
24
+ def watch
25
+ Inotify.watch(@path, @processor)
26
+ end
27
+ end
28
+ end
29
+ end
data/lib/tidings.rb ADDED
@@ -0,0 +1,23 @@
1
+ case RUBY_PLATFORM
2
+ when /darwin/
3
+ require 'fs_event'
4
+ when /linux/
5
+ require 'inotify'
6
+ else
7
+ raise RuntimeError, "Your platform is currently not supported (#{RUBY_PLATFORM})"
8
+ end
9
+
10
+ module Tidings
11
+ autoload :VERSION, 'tidings/version'
12
+ autoload :Watcher, 'tidings/watcher'
13
+
14
+ def self.log(message)
15
+ $stderr.puts('Tidings: ' + message.to_s) if $DEBUG
16
+ end
17
+
18
+ def self.watch(path, processor=nil, &block)
19
+ watcher = Tidings::Watcher.new(path, processor || block)
20
+ watcher.start
21
+ watcher
22
+ end
23
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tidings
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manfred Stienstra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-01 00:00:00.000000000 Z
11
+ date: 2013-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: peck
@@ -48,9 +48,14 @@ extra_rdoc_files:
48
48
  - README.rdoc
49
49
  - COPYING
50
50
  files:
51
+ - lib/tidings/version.rb
52
+ - lib/tidings/watcher.rb
53
+ - lib/tidings.rb
54
+ - ext/extconf.rb
55
+ - ext/fs_event/fs_event.c
56
+ - ext/inotify/inotify.c
51
57
  - README.rdoc
52
58
  - COPYING
53
- - ext/extconf.rb
54
59
  homepage: http://github.com/Manfred/tidings
55
60
  licenses: []
56
61
  metadata: {}