rb-inotify 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ /.yardoc
2
+ /doc
data/.yardopts ADDED
@@ -0,0 +1,4 @@
1
+ --readme README.md
2
+ --markup markdown
3
+ --markup-provider maruku
4
+ --no-private
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Nathan Weizenbaum
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,59 @@
1
+ # rb-inotify
2
+
3
+ This is a simple wrapper over the [inotify](http://en.wikipedia.org/wiki/Inotify) Linux kernel subsystem
4
+ for monitoring changes to files and directories.
5
+ It uses the [FFI](http://wiki.github.com/ffi/ffi) gem to avoid having to compile a C extension.
6
+
7
+ ## Basic Usage
8
+
9
+ The API is similar to the inotify C API, but with a more Rubyish feel.
10
+ First, create a notifier:
11
+
12
+ notifier = INotify::Notifier.new
13
+
14
+ Then, tell it to watch the paths you're interested in
15
+ for the events you care about:
16
+
17
+ notifier.watch("path/to/foo.txt", :modify) {puts "foo.txt was modified!"}
18
+ notifier.watch("path/to/bar", :moved_to, :create) do |event|
19
+ puts "#{event.name} is now in path/to/bar!"
20
+ end
21
+
22
+ Inotify can watch directories or individual files.
23
+ It can pay attention to all sorts of events;
24
+ for a full list, see [the inotify man page](http://www.tin.org/bin/man.cgi?section=7&topic=inotify).
25
+
26
+ Finally, you get at the events themselves:
27
+
28
+ notifier.run
29
+
30
+ This will loop infinitely, calling the appropriate callbacks when the files are changed.
31
+ If you don't want infinite looping,
32
+ you can also block until there are available events,
33
+ process them all at once,
34
+ and then continue on your merry way:
35
+
36
+ notifier.process
37
+
38
+ ## Advanced Usage
39
+
40
+ Sometimes it's necessary to have finer control over the underlying IO operations
41
+ than is provided by the simple callback API.
42
+ The trick to this is that the notifier is a fully-functional IO object,
43
+ with a file descriptor and everything.
44
+ This means, for example, that it can be passed to `IO#select`:
45
+
46
+ # Wait 10 seconds for an event then give up
47
+ if IO.select([notifier], [], [], 10)
48
+ notifier.process
49
+ end
50
+
51
+ It can even be used with EventMachine:
52
+
53
+ require 'eventmachine'
54
+
55
+ EM.run do
56
+ EM.watch notifier do
57
+ notifier.process
58
+ end
59
+ end
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "rb-inotify"
8
+ gem.summary = "A Ruby wrapper for Linux's inotify, using FFI"
9
+ gem.description = gem.summary
10
+ gem.email = "nex342@gmail.com"
11
+ gem.homepage = "http://github.com/nex3/rb-notify"
12
+ gem.authors = ["Nathan Weizenbaum"]
13
+ gem.add_development_dependency "yard"
14
+ end
15
+ Jeweler::GemcutterTasks.new
16
+ rescue LoadError
17
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
18
+ end
19
+
20
+ begin
21
+ require 'yard'
22
+ YARD::Rake::YardocTask.new
23
+ rescue LoadError
24
+ task :yardoc do
25
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
26
+ end
27
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/rb-inotify.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'rb-inotify/native'
2
+ require 'rb-inotify/native/flags'
3
+ require 'rb-inotify/notifier'
4
+ require 'rb-inotify/watcher'
5
+ require 'rb-inotify/event'
6
+
7
+ # The root module of the library, which is laid out as so:
8
+ #
9
+ # * {Notifier} -- The main class, where the notifications are set up
10
+ # * {Watcher} -- A watcher for a single file or directory
11
+ # * {Event} -- An filesystem event notification
12
+ module INotify; end
@@ -0,0 +1,107 @@
1
+ module INotify
2
+ # An event caused by a change on the filesystem.
3
+ # Each {Watcher} can fire many events,
4
+ # which are passed to that watcher's callback.
5
+ class Event
6
+ # An integer specifying that this event is related to some other event,
7
+ # which will have the same cookie.
8
+ #
9
+ # Currently, this is only used for files that are moved within the same directory.
10
+ # Both the `:moved_from` and the `:moved_to` events will have the same cookie.
11
+ #
12
+ # @return [Fixnum]
13
+ attr_reader :cookie
14
+
15
+ # The name of the file that the event occurred on.
16
+ # This is only set for events that occur on files in directories;
17
+ # otherwise, it's `""`.
18
+ #
19
+ # @return [String]
20
+ attr_reader :name
21
+
22
+ # The {Notifier} that fired this event.
23
+ #
24
+ # @return [Notifier]
25
+ attr_reader :notifier
26
+
27
+ # The {Watcher#id id} of the {Watcher} that fired this event.
28
+ #
29
+ # @private
30
+ # @return [Fixnum]
31
+ attr_reader :watcher_id
32
+
33
+ # Returns the {Watcher} that fired this event.
34
+ #
35
+ # @return [Watcher]
36
+ def watcher
37
+ @watcher ||= @notifier.watchers[@watcher_id]
38
+ end
39
+
40
+ # Returns the flags that describe this event.
41
+ # This is generally similar to the input to {Notifier#watch},
42
+ # except that it won't contain options flags nor `:all_events`,
43
+ # and it may contain one or more of the following flags:
44
+ #
45
+ # `:unmount`
46
+ # : The filesystem containing the watched file or directory was unmounted.
47
+ #
48
+ # `:ignored`
49
+ # : The \{#watcher watcher} was closed, or the watched file or directory was deleted.
50
+ #
51
+ # `:isdir`
52
+ # : The subject of this event is a directory.
53
+ #
54
+ # @return [Array<Symbol>]
55
+ def flags
56
+ @flags ||= Native::Flags.from_mask(@native[:mask])
57
+ end
58
+
59
+ # Constructs an {Event} object from a string of binary data,
60
+ # and destructively modifies the string to get rid of the initial segment
61
+ # used to construct the Event.
62
+ #
63
+ # @private
64
+ # @param data [String] The string to be modified
65
+ # @param notifier [Notifier] The {Notifier} that fired the event
66
+ # @return [Event, nil] The event, or `nil` if the string is empty
67
+ def self.consume(data, notifier)
68
+ return nil if data.empty?
69
+ ev = new(data, notifier)
70
+ data.replace data[ev.size..-1]
71
+ ev
72
+ end
73
+
74
+ # Creates an event from a string of binary data.
75
+ # Differs from {Event.consume} in that it doesn't modify the string.
76
+ #
77
+ # @private
78
+ # @param data [String] The data string
79
+ # @param notifier [Notifier] The {Notifier} that fired the event
80
+ def initialize(data, notifier)
81
+ ptr = FFI::MemoryPointer.from_string(data)
82
+ @native = Native::Event.new(ptr)
83
+ @cookie = @native[:cookie]
84
+ @name = data[@native.size, @native[:len]].gsub(/\0+$/, '')
85
+ @notifier = notifier
86
+ @watcher_id = @native[:wd]
87
+
88
+ raise Exception.new("inotify event queue has overflowed.") if @native[:mask] & Native::Flags::IN_Q_OVERFLOW != 0
89
+ end
90
+
91
+ # Calls the callback of the watcher that fired this event,
92
+ # passing in the event itself.
93
+ #
94
+ # @private
95
+ def callback!
96
+ watcher.callback!(self)
97
+ end
98
+
99
+ # Returns the size of this event object in bytes,
100
+ # including the \{#name} string.
101
+ #
102
+ # @return [Fixnum]
103
+ def size
104
+ @native.size + @native[:len]
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,27 @@
1
+ require 'ffi'
2
+
3
+ module INotify
4
+ # This module contains the low-level foreign-function interface code
5
+ # for dealing with the inotify C APIs.
6
+ # It's an implementation detail, and not meant for users to deal with.
7
+ #
8
+ # @private
9
+ module Native
10
+ extend FFI::Library
11
+
12
+ # The C struct describing an inotify event.
13
+ #
14
+ # @private
15
+ class Event < FFI::Struct
16
+ layout(
17
+ :wd, :int,
18
+ :mask, :uint32,
19
+ :cookie, :uint32,
20
+ :len, :uint32)
21
+ end
22
+
23
+ attach_function :inotify_init, [], :int
24
+ attach_function :inotify_add_watch, [:int, :string, :int], :int
25
+ attach_function :inotify_rm_watch, [:int, :int], :int
26
+ end
27
+ end
@@ -0,0 +1,89 @@
1
+ module INotify
2
+ module Native
3
+ # A module containing all the inotify flags
4
+ # to be passed to {Notifier#watch}.
5
+ #
6
+ # @private
7
+ module Flags
8
+ # File was accessed.
9
+ IN_ACCESS = 0x00000001
10
+ # Metadata changed.
11
+ IN_ATTRIB = 0x00000004
12
+ # Writtable file was closed.
13
+ IN_CLOSE_WRITE = 0x00000008
14
+ # File was modified.
15
+ IN_MODIFY = 0x00000002
16
+ # Unwrittable file closed.
17
+ IN_CLOSE_NOWRITE = 0x00000010
18
+ # File was opened.
19
+ IN_OPEN = 0x00000020
20
+ # File was moved from X.
21
+ IN_MOVED_FROM = 0x00000040
22
+ # File was moved to Y.
23
+ IN_MOVED_TO = 0x00000080
24
+ # Subfile was created.
25
+ IN_CREATE = 0x00000100
26
+ # Subfile was deleted.
27
+ IN_DELETE = 0x00000200
28
+ # Self was deleted.
29
+ IN_DELETE_SELF = 0x00000400
30
+ # Self was moved.
31
+ IN_MOVE_SELF = 0x00000800
32
+
33
+ ## Helper events.
34
+
35
+ # Close.
36
+ IN_CLOSE = (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE)
37
+ # Moves.
38
+ IN_MOVE = (IN_MOVED_FROM | IN_MOVED_TO)
39
+ # All events which a program can wait on.
40
+ IN_ALL_EVENTS = (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE |
41
+ IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | IN_MOVED_TO | IN_CREATE |
42
+ IN_DELETE | IN_DELETE_SELF | IN_MOVE_SELF)
43
+
44
+
45
+ ## Special flags.
46
+
47
+ # Only watch the path if it is a directory.
48
+ IN_ONLYDIR = 0x01000000
49
+ # Do not follow a sym link.
50
+ IN_DONT_FOLLOW = 0x02000000
51
+ # Add to the mask of an already existing watch.
52
+ IN_MASK_ADD = 0x20000000
53
+ # Only send event once.
54
+ IN_ONESHOT = 0x80000000
55
+
56
+
57
+ ## Events sent by the kernel.
58
+
59
+ # Backing fs was unmounted.
60
+ IN_UNMOUNT = 0x00002000
61
+ # Event queued overflowed.
62
+ IN_Q_OVERFLOW = 0x00004000
63
+ # File was ignored.
64
+ IN_IGNORED = 0x00008000
65
+ # Event occurred against dir.
66
+ IN_ISDIR = 0x40000000
67
+
68
+ # Converts a list of flags to the bitmask that the C API expects.
69
+ #
70
+ # @param flags [Array<Symbol>]
71
+ # @return Fixnum
72
+ def self.to_mask(flags)
73
+ flags.map {|flag| const_get("IN_#{flag.to_s.upcase}")}.
74
+ inject(0) {|mask, flag| mask | flag}
75
+ end
76
+
77
+ # Converts a bitmask from the C API into a list of flags.
78
+ #
79
+ # @return mask [Fixnum]
80
+ # @return [Array<Symbol>]
81
+ def self.from_mask(mask)
82
+ constants.select do |c|
83
+ next false unless c =~ /^IN_/
84
+ const_get(c) & mask != 0
85
+ end.map {|c| c.sub("IN_", "").downcase.to_sym} - [:all_events]
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,195 @@
1
+ module INotify
2
+ # Notifier wraps a single instance of inotify.
3
+ # It's possible to have more than one instance,
4
+ # but usually unnecessary.
5
+ #
6
+ # @example
7
+ # # Create the notifier
8
+ # notifier = INotify::Notifier.new
9
+ #
10
+ # # Run this callback whenever the file path/to/foo.txt is read
11
+ # notifier.watch("path/to/foo.txt", :access) do
12
+ # puts "Foo.txt was accessed!"
13
+ # end
14
+ #
15
+ # # Watch for any file in the directory being deleted
16
+ # # or moved out of the directory.
17
+ # notifier.watch("path/to/directory", :delete, :moved_from) do |event|
18
+ # # The #name field of the event object contains the name of the affected file
19
+ # puts "#{event.name} is no longer in the directory!"
20
+ # end
21
+ #
22
+ # # Nothing happens until you run the notifier!
23
+ # notifier.run
24
+ #
25
+ # Notifier is a subclass of IO with a fully-functional file descriptor,
26
+ # so it can be passed to functions like `#select`.
27
+ class Notifier < IO
28
+ # A hash from {Watcher} ids to the instances themselves.
29
+ #
30
+ # @private
31
+ # @return [{Fixnum => Watcher}]
32
+ attr_reader :watchers
33
+
34
+ # The underlying file descriptor for this notifier.
35
+ # This is a valid OS file descriptor, and can be used as such.
36
+ #
37
+ # @return [Fixnum]
38
+ attr_reader :fd
39
+
40
+ # Creates a new {Notifier}.
41
+ #
42
+ # @return [Notifier]
43
+ # @raise [SystemCallError] if inotify failed to initialize for some reason
44
+ def initialize
45
+ @fd = Native.inotify_init
46
+ @watchers = {}
47
+ return super(@fd) unless @fd < 0
48
+
49
+ raise SystemCallError.new(
50
+ "Failed to initialize inotify" +
51
+ case FFI.errno
52
+ when Errno::EMFILE::Errno; ": the user limit on the total number of inotify instances has been reached."
53
+ when Errno::ENFILE::Errno; ": the system limit on the total number of file descriptors has been reached."
54
+ when Errno::ENOMEM::Errno; ": insufficient kernel memory is available."
55
+ else; ""
56
+ end,
57
+ FFI.errno)
58
+ end
59
+
60
+ # Watches a file or directory for changes,
61
+ # calling the callback when there are.
62
+ # This is only activated once \{#process} or \{#run} is called.
63
+ #
64
+ # ## Flags
65
+ #
66
+ # `:access`
67
+ # : A file is accessed (that is, read).
68
+ #
69
+ # `:attrib`
70
+ # : A file's metadata is changed (e.g. permissions, timestamps, etc).
71
+ #
72
+ # `:close_write`
73
+ # : A file that was opened for writing is closed.
74
+ #
75
+ # `:close_nowrite`
76
+ # : A file that was not opened for writing is closed.
77
+ #
78
+ # `:modify`
79
+ # : A file is modified.
80
+ #
81
+ # `:open`
82
+ # : A file is opened.
83
+ #
84
+ # ### Directory-Specific Flags
85
+ #
86
+ # These flags only apply when a directory is being watched.
87
+ #
88
+ # `:moved_from`
89
+ # : A file is moved out of the watched directory.
90
+ #
91
+ # `:moved_to`
92
+ # : A file is moved into the watched directory.
93
+ #
94
+ # `:create`
95
+ # : A file is created in the watched directory.
96
+ #
97
+ # `:delete`
98
+ # : A file is deleted in the watched directory.
99
+ #
100
+ # `:delete_self`
101
+ # : The watched file or directory itself is deleted.
102
+ #
103
+ # `:move_self`
104
+ # : The watched file or directory itself is moved.
105
+ #
106
+ # ### Helper Flags
107
+ #
108
+ # These flags are just combinations of the flags above.
109
+ #
110
+ # `:close`
111
+ # : Either `:close_write` or `:close_nowrite` is activated.
112
+ #
113
+ # `:move`
114
+ # : Either `:moved_from` or `:moved_to` is activated.
115
+ #
116
+ # `:all_events`
117
+ # : Any event above is activated.
118
+ #
119
+ # ### Options Flags
120
+ #
121
+ # These flags don't actually specify events.
122
+ # Instead, they specify options for the watcher.
123
+ #
124
+ # `:onlydir`
125
+ # : Only watch the path if it's a directory.
126
+ #
127
+ # `:dont_follow`
128
+ # : Don't follow symlinks.
129
+ #
130
+ # `:mask_add`
131
+ # : Add these flags to the pre-existing flags for this path.
132
+ #
133
+ # `:oneshot`
134
+ # : Only send the event once, then shut down the watcher.
135
+ #
136
+ # @param path [String] The path to the file or directory
137
+ # @param flags [Array<Symbol>] Which events to watch for
138
+ # @yield [event] A block that will be called
139
+ # whenever one of the specified events occur
140
+ # @yieldparam event [Event] The Event object containing information
141
+ # about the event that occured
142
+ # @return [Watcher] A Watcher set up to watch this path for these events
143
+ # @raise [SystemCallError] if the file or directory can't be watched,
144
+ # e.g. if the file isn't found, read access is denied,
145
+ # or the flags don't contain any events
146
+ def watch(path, *flags, &callback)
147
+ Watcher.new(self, path, *flags, &callback)
148
+ end
149
+
150
+ # Starts the notifier watching for filesystem events.
151
+ # Blocks forever and never returns.
152
+ #
153
+ # @see #process
154
+ def run
155
+ loop {process}
156
+ end
157
+
158
+ # Blocks until there are one or more filesystem events
159
+ # that this notifier has watchers registered for.
160
+ # Once there are events, the appropriate callbacks are called
161
+ # and this function returns.
162
+ #
163
+ # @see #run
164
+ def process
165
+ read_events.each {|event| event.callback!}
166
+ end
167
+
168
+ # Blocks until there are one or more filesystem events
169
+ # that this notifier has watchers registered for.
170
+ # Once there are events, returns their {Event} objects.
171
+ #
172
+ # @private
173
+ def read_events
174
+ size = 64 * Native::Event.size
175
+ tries = 1
176
+
177
+ begin
178
+ data = readpartial(size)
179
+ rescue SystemCallError => er
180
+ # EINVAL means that there's more data to be read
181
+ # than will fit in the buffer size
182
+ raise er unless er.errno == EINVAL || tries == 5
183
+ size *= 2
184
+ tries += 1
185
+ retry
186
+ end
187
+
188
+ events = []
189
+ while ev = Event.consume(data, self)
190
+ events << ev
191
+ end
192
+ events
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,83 @@
1
+ module INotify
2
+ # Watchers monitor a single path for changes,
3
+ # specified by {INotify::Notifier#watch event flags}.
4
+ # A watcher is usually created via \{Notifier#watch}.
5
+ #
6
+ # One {Notifier} may have many {Watcher}s.
7
+ # The Notifier actually takes care of the checking for events,
8
+ # via \{Notifier#run #run} or \{Notifier#process #process}.
9
+ # The main purpose of having Watcher objects
10
+ # is to be able to disable them using \{#close}.
11
+ class Watcher
12
+ # The {Notifier} that this Watcher belongs to.
13
+ #
14
+ # @return [Notifier]
15
+ attr_reader :notifier
16
+
17
+ # The path that this Watcher is watching.
18
+ #
19
+ # @return [String]
20
+ attr_reader :path
21
+
22
+ # The {INotify::Notifier#watch flags}
23
+ # specifying the events that this Watcher is watching for,
24
+ # and potentially some options as well.
25
+ #
26
+ # @return [Array<Symbol>]
27
+ attr_reader :flags
28
+
29
+ # The id for this Watcher.
30
+ # Used to retrieve this Watcher from {Notifier#watchers}.
31
+ #
32
+ # @private
33
+ # @return [Fixnum]
34
+ attr_reader :id
35
+
36
+ # Calls this Watcher's callback with the given {Event}.
37
+ #
38
+ # @private
39
+ # @param event [Event]
40
+ def callback!(event)
41
+ @callback[event]
42
+ end
43
+
44
+ # Disables this Watcher, so that it doesn't fire any more events.
45
+ #
46
+ # @raise [SystemCallError] if the watch fails to be disabled for some reason
47
+ def close
48
+ return if Native.inotify_rm_watch(@notifier.fd, @id) == 0
49
+ raise SystemCallError.new("Failed to stop watching #{path.inspect}", FFI.errno)
50
+ end
51
+
52
+ # Creates a new {Watcher}.
53
+ #
54
+ # @private
55
+ # @see Notifier#watch
56
+ def initialize(notifier, path, *flags, &callback)
57
+ @notifier = notifier
58
+ @callback = callback || proc {}
59
+ @path = path
60
+ @flags = flags.freeze
61
+ @id = Native.inotify_add_watch(@notifier.fd, path,
62
+ Native::Flags.to_mask(flags))
63
+
64
+ unless @id < 0
65
+ @notifier.watchers[@id] = self
66
+ return
67
+ end
68
+
69
+ raise SystemCallError.new(
70
+ "Failed to watch #{path.inspect}" +
71
+ case FFI.errno
72
+ when Errno::EACCES::Errno; ": read access to the given file is not permitted."
73
+ when Errno::EBADF::Errno; ": the given file descriptor is not valid."
74
+ when Errno::EFAULT::Errno; ": path points outside of the process's accessible address space."
75
+ when Errno::EINVAL::Errno; ": the given event mask contains no legal events; or fd is not an inotify file descriptor."
76
+ when Errno::ENOMEM::Errno; ": insufficient kernel memory was available."
77
+ when Errno::ENOSPC::Errno; ": The user limit on the total number of inotify watches was reached or the kernel failed to allocate a needed resource."
78
+ else; ""
79
+ end,
80
+ FFI.errno)
81
+ end
82
+ end
83
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rb-inotify
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nathan Weizenbaum
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-29 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: yard
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: A Ruby wrapper for Linux's inotify, using FFI
26
+ email: nex342@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.md
33
+ files:
34
+ - .gitignore
35
+ - .yardopts
36
+ - MIT-LICENSE
37
+ - README.md
38
+ - Rakefile
39
+ - VERSION
40
+ - lib/rb-inotify.rb
41
+ - lib/rb-inotify/event.rb
42
+ - lib/rb-inotify/native.rb
43
+ - lib/rb-inotify/native/flags.rb
44
+ - lib/rb-inotify/notifier.rb
45
+ - lib/rb-inotify/watcher.rb
46
+ has_rdoc: true
47
+ homepage: http://github.com/nex3/rb-notify
48
+ licenses: []
49
+
50
+ post_install_message:
51
+ rdoc_options:
52
+ - --charset=UTF-8
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ requirements: []
68
+
69
+ rubyforge_project:
70
+ rubygems_version: 1.3.5
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: A Ruby wrapper for Linux's inotify, using FFI
74
+ test_files: []
75
+