App-watchdo
view release on metacpan or search on metacpan
lib/App/watchdo.pm view on Meta::CPAN
package App::watchdo;
# Created on: 2015-03-07 08:21:28
# Create by: Ivan Wills
# $Id$
# $Revision$, $HeadURL$, $Date$
# $Revision$, $Source$, $Date$
use Moo;
use warnings;
use version;
use Carp;
use List::MoreUtils qw/uniq/;
use Data::Dumper qw/Dumper/;
use English qw/ -no_match_vars /;
use AnyEvent;
use AnyEvent::Loop;
use AnyEvent::Filesys::Notify;
use Path::Tiny;
our $VERSION = version->new('0.1.1');
has [qw/git run done/] => ( is => 'rw' );
has [qw/dirs files exclude changed/] => (
is => 'rw',
default => sub {[]},
);
has wait => (
is => 'rw',
default => 1,
);
has vcs => (
is => 'rw',
lazy => 1,
default => sub {
require VCS::Which;
return VCS::Which->new;
},
);
sub watch {
my ($self) = @_;
my $notify = AnyEvent::Filesys::Notify->new(
dirs => [ $self->get_dirs ],
cb => sub {
my @changed = @_;
$self->changed([ @{ $self->changed }, @changed ]);
if ( ! $self->done ) {
$self->done( AE::timer $self->wait, 0, sub { $self->doit() } );
}
},
parse_events => 1,
);
return AnyEvent::Loop::run();
}
sub doit {
my ($self) = @_;
my %files = map { $_ => 1 } $self->get_files();
my %dirs = map { $_ => 1 } @{ $self->dirs() };
my %seen;
my @monitored;
for my $changed (@{ $self->changed() }) {
my $path = $changed->path;
push @monitored, $changed if (
!$seen{$path}++
|| $files{$path}
|| $dirs{$path}
) && (
! @{ $self->exclude }
|| ! grep { $path =~ /$_/ } @{ $self->exclude }
);
}
$self->run()->(@monitored) if @monitored;
$self->done(undef);
$self->changed([]);
}
sub get_dirs {
my ($self) = @_;
return uniq sort +(
@{ $self->dirs || [] },
map {path($_)->parent . ''}
$self->get_files,
);
}
sub get_files {
my ($self) = @_;
return ( $self->_files_from_fs, $self->_files_from_git );
}
sub _files_from_fs {
my ($self) = @_;
return map { -d $_ ? _recurse($_) : $_ }
@{ $self->files };
}
sub _files_from_git {
my ($self) = @_;
return if !$self->git;
( run in 0.635 second using v1.01-cache-2.11-cpan-6aa56a78535 )