AnyEvent-Filesys-Watcher

 view release on metacpan or  search on metacpan

lib/AnyEvent/Filesys/Watcher/FSEvents.pm  view on Meta::CPAN

	# kFSEventStreamEventFlagItemCreated, we can safely ignore it.
	kFSEventStreamEventFlagItemCloned => IGNORE,
);

sub new {
	my ($class, %args) = @_;

	$args{interval} = 0.1 if !exists $args{interval};

	my $self = $class->SUPER::_new(%args);

	delete $args{directories};
	delete $args{callback};
	delete $args{filter};
	my $fs_monitor = Mac::FSEvents->new({
		path => $self->directories,
		latency => $args{interval},
		file_events => $has_file_events,
		%args,
	});

	# Create an AnyEvent->io watcher for each fs_monitor
	my $alter_ego = $self;
	$self->{__mac_fh} = $fs_monitor->watch;

	my $watcher = AE::io $self->{__mac_fh}, 0, sub {
		if (my @raw_events = $fs_monitor->read_events) {
			$alter_ego->_processEvents(@raw_events);
		}
	};
	weaken $alter_ego;

	$self->_watcher($watcher);

	return $self;
}

if ($has_file_events) {
	sub _parseEvents {
		my ($self, $filter, @raw_events) = @_;

		my @events;
		foreach my $raw_event (@raw_events) {
			my $cooked = eval { $self->__parseEvent($raw_event) };
			if ($@) {
				if ("rescan\n" eq $@) {
					push @events, $self->rescan;
					return @events;
				}
			}
			push @events, $cooked if $filter->($cooked);
		}

		return @events;
	}
}

sub __parseEvent {
	my ($self, $raw_event) = @_;

	# Count trailing zero bits. Taken from Chess::Plisco::Macro.
	my $ctzb = sub {
		my ($bb) = @_;

		my $B = $bb & -$bb;
		my $A = $B - 1 - ((($B - 1) >> 1) & $FIVES);
		my $C = ($A & $THREES) + (($A >> 2) & $THREES);
		my $n = $C + ($C >> 32);
		$n = ($n & 0x0f0f0f0f) + (($n >> 4) & 0x0f0f0f0f);
		$n = ($n & 0xffff) + ($n >> 16);
		$n = ($n & 0xff) + ($n >> 8);
	};

	my $flags = $raw_event->flags || return;

	my $path = $self->_makeAbsolute($raw_event->path);
	my ($type, $is_directory);
	my $old_fs = $self->_oldFilesystem;
	while ($flags) {
		my $bit = $ctzb->($flags);
		$flags &= $flags - 1;
		my $flag = $flags[$bit + 1];

		if ('FSEventStreamEventFlagItemIsDir' eq $flag) {
			$is_directory = 1;
		} elsif (CREATED eq $flag_type{$flag}) {
			$type = 'created' if $type ne 'deleted';
		} elsif (MODIFIED eq $flag_type{$flag}) {
			$type = 'modified' if $type ne 'deleted',
		} elsif (DELETED eq $flag_type{$flag}) {
			$type = 'deleted';
		} elsif (IGNORE eq $flag_type{$flag}) {
			next;
		} elsif (RENAMED eq $flag_type{$flag}) {
			if (-e $path) {
				if ($old_fs->{$path}) {
					$type = 'modified';
				} else {
					$type = 'created';
				}
			} else {
				$type = 'deleted';
			}
		} elsif (RESCAN eq $flag_type{$flag}) {
			die "must rescan\n";
		}
	}

	if ('deleted' eq $type) {
		delete $old_fs->{$path};
	} elsif ('modified' eq $type || 'created' eq $type) {
		$old_fs->{path} = $self->_stat($path);
	} else {
		# Issue a warning?
		return;
	}

	return AnyEvent::Filesys::Watcher::Event->new(
		path => $path,
		type => $type,
		is_directory => $is_directory,



( run in 0.619 second using v1.01-cache-2.11-cpan-2398b32b56e )