AnyEvent-Filesys-Watcher
view release on metacpan or search on metacpan
lib/AnyEvent/Filesys/Watcher/Inotify2.pm view on Meta::CPAN
package AnyEvent::Filesys::Watcher::Inotify2;
use strict;
our $VERSION = 'v0.1.1'; # VERSION
use Locale::TextDomain ('AnyEvent-Filesys-Watcher');
use AnyEvent;
use Linux::Inotify2;
use Carp;
use Path::Iterator::Rule;
use Scalar::Util qw(weaken);
use base qw(AnyEvent::Filesys::Watcher);
sub new {
my ($class, %args) = @_;
my $self = $class->SUPER::_new(%args);
my $inotify = Linux::Inotify2->new
or croak "Unable to create new Linux::INotify2 object: $!";
# Need to add all the subdirs to the watch list, this will catch
# modifications to files too.
my $old_fs = $self->_oldFilesystem;
my @dirs = grep { $old_fs->{$_}->{is_directory} } keys %$old_fs;
my $alter_ego = $self;
for my $dir (@dirs) {
$inotify->watch(
$dir,
IN_MODIFY | IN_CREATE | IN_DELETE | IN_DELETE_SELF |
IN_MOVE | IN_MOVE_SELF | IN_ATTRIB,
sub { my $e = shift; $alter_ego->_processEvents($e); }
);
}
weaken $alter_ego;
$self->_filesystemMonitor($inotify);
$self->_watcher([AnyEvent->io(
fh => $inotify->fileno,
poll => 'r',
cb => sub {
$inotify->poll;
}
)]);
bless $self, $class;
}
# Parse the events returned by Inotify2 instead of rescanning the files.
# There are small changes in behaviour compared to the previous releases
# without parse_events:
#
# 1. `touch test` causes an additional "modified" event after the "created"
# 2. `mv test2 test` if test exists before, event for test would be "modified"
# in parent code, but is "created" here
#
# Because of these differences, we default to the original behavior unless the
# parse_events flag is true.
sub _parseEvents {
my ($self, $filter_cb, @raw_events) = @_;
my @events =
map { $filter_cb->($_) }
grep { defined }
map { $self->__makeEvent($_) } @raw_events;
# New directories are not automatically watched by inotify.
$self->__addEventsToWatch(@events);
# Any entities that were created in new dirs (before the call to
# _add_events_to_watch) will have been missed. So we walk the filesystem
# now.
push @events,
map { $self->__addEntitiesInSubdir($filter_cb, $_) }
grep { $_->isDirectory && $_->isCreated }
@events;
return @events;
}
sub __addEntitiesInSubdir {
my ($self, $filter_cb, $e) = @_;
my @events;
my $rule = Path::Iterator::Rule->new;
my $next = $rule->iter($e->path);
while (my $file = $next->()) {
next if $file eq $e->path; # $e->path will have already been added
my $new_event = AnyEvent::Filesys::Watcher::Event->new(
path => $file,
type => 'created',
isDirectory => -d $file,
);
( run in 0.485 second using v1.01-cache-2.11-cpan-39bf76dae61 )