147 lines
4.7 KiB
Ruby
147 lines
4.7 KiB
Ruby
module INotify
|
|
# An event caused by a change on the filesystem.
|
|
# Each {Watcher} can fire many events,
|
|
# which are passed to that watcher's callback.
|
|
class Event
|
|
# A list of other events that are related to this one.
|
|
# Currently, this is only used for files that are moved within the same directory:
|
|
# the `:moved_from` and the `:moved_to` events will be related.
|
|
#
|
|
# @return [Array<Event>]
|
|
attr_reader :related
|
|
|
|
# The name of the file that the event occurred on.
|
|
# This is only set for events that occur on files in directories;
|
|
# otherwise, it's `""`.
|
|
# Similarly, if the event is being fired for the directory itself
|
|
# the name will be `""`
|
|
#
|
|
# This pathname is relative to the enclosing directory.
|
|
# For the absolute pathname, use \{#absolute\_name}.
|
|
# Note that when the `:recursive` flag is passed to {Notifier#watch},
|
|
# events in nested subdirectories will still have a `#name` field
|
|
# relative to their immediately enclosing directory.
|
|
# For example, an event on the file `"foo/bar/baz"`
|
|
# will have name `"baz"`.
|
|
#
|
|
# @return [String]
|
|
attr_reader :name
|
|
|
|
# The {Notifier} that fired this event.
|
|
#
|
|
# @return [Notifier]
|
|
attr_reader :notifier
|
|
|
|
# An integer specifying that this event is related to some other event,
|
|
# which will have the same cookie.
|
|
#
|
|
# Currently, this is only used for files that are moved within the same directory.
|
|
# Both the `:moved_from` and the `:moved_to` events will have the same cookie.
|
|
#
|
|
# @private
|
|
# @return [Fixnum]
|
|
attr_reader :cookie
|
|
|
|
# The {Watcher#id id} of the {Watcher} that fired this event.
|
|
#
|
|
# @private
|
|
# @return [Fixnum]
|
|
attr_reader :watcher_id
|
|
|
|
# Returns the {Watcher} that fired this event.
|
|
#
|
|
# @return [Watcher]
|
|
def watcher
|
|
@watcher ||= @notifier.watchers[@watcher_id]
|
|
end
|
|
|
|
# The absolute path of the file that the event occurred on.
|
|
#
|
|
# This is actually only as absolute as the path passed to the {Watcher}
|
|
# that created this event.
|
|
# However, it is relative to the working directory,
|
|
# assuming that hasn't changed since the watcher started.
|
|
#
|
|
# @return [String]
|
|
def absolute_name
|
|
return watcher.path if name.empty?
|
|
return File.join(watcher.path, name)
|
|
end
|
|
|
|
# Returns the flags that describe this event.
|
|
# This is generally similar to the input to {Notifier#watch},
|
|
# except that it won't contain options flags nor `:all_events`,
|
|
# and it may contain one or more of the following flags:
|
|
#
|
|
# `:unmount`
|
|
# : The filesystem containing the watched file or directory was unmounted.
|
|
#
|
|
# `:ignored`
|
|
# : The \{#watcher watcher} was closed, or the watched file or directory was deleted.
|
|
#
|
|
# `:isdir`
|
|
# : The subject of this event is a directory.
|
|
#
|
|
# @return [Array<Symbol>]
|
|
def flags
|
|
@flags ||= Native::Flags.from_mask(@native[:mask])
|
|
end
|
|
|
|
# Constructs an {Event} object from a string of binary data,
|
|
# and destructively modifies the string to get rid of the initial segment
|
|
# used to construct the Event.
|
|
#
|
|
# @private
|
|
# @param data [String] The string to be modified
|
|
# @param notifier [Notifier] The {Notifier} that fired the event
|
|
# @return [Event, nil] The event, or `nil` if the string is empty
|
|
def self.consume(data, notifier)
|
|
return nil if data.empty?
|
|
ev = new(data, notifier)
|
|
data.replace data[ev.size..-1]
|
|
ev
|
|
end
|
|
|
|
# Creates an event from a string of binary data.
|
|
# Differs from {Event.consume} in that it doesn't modify the string.
|
|
#
|
|
# @private
|
|
# @param data [String] The data string
|
|
# @param notifier [Notifier] The {Notifier} that fired the event
|
|
def initialize(data, notifier)
|
|
ptr = FFI::MemoryPointer.from_string(data)
|
|
@native = Native::Event.new(ptr)
|
|
@related = []
|
|
@cookie = @native[:cookie]
|
|
@name = fix_encoding(data[@native.size, @native[:len]].gsub(/\0+$/, ''))
|
|
@notifier = notifier
|
|
@watcher_id = @native[:wd]
|
|
|
|
raise QueueOverflowError.new("inotify event queue has overflowed.") if @native[:mask] & Native::Flags::IN_Q_OVERFLOW != 0
|
|
end
|
|
|
|
# Calls the callback of the watcher that fired this event,
|
|
# passing in the event itself.
|
|
#
|
|
# @private
|
|
def callback!
|
|
watcher && watcher.callback!(self)
|
|
end
|
|
|
|
# Returns the size of this event object in bytes,
|
|
# including the \{#name} string.
|
|
#
|
|
# @return [Fixnum]
|
|
def size
|
|
@native.size + @native[:len]
|
|
end
|
|
|
|
private
|
|
|
|
def fix_encoding(name)
|
|
name.force_encoding('filesystem') if name.respond_to?(:force_encoding)
|
|
name
|
|
end
|
|
end
|
|
end
|