tidings 0.2.0 → 0.2.1

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.
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: {}