Skip Menu |

This queue is for tickets about the File-ChangeNotify CPAN distribution.

Report information
The Basics
Id: 114492
Status: resolved
Priority: 0/
Queue: File-ChangeNotify

People
Owner: Nobody in particular
Requestors: HMBRAND [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: 0.24
Fixed in: 0.25



Subject: Allow sub {} in filter and exclude
my $watcher = File::ChangeNotify->instantiate_watcher ( directories => [ "/tmp", "/usr/tmp", "/var/tmp" ], # Only files owned by system-users filter => sub { (stat $_)[4] < 1000 }, # Exclude all files owned by kdm exclude => [ sub { (stat $_)[4] == 202 } ], );
Show quoted text
> # Exclude all files owned by kdm > exclude => [ sub { (stat $_)[4] == 202 } ], > );
A possible implementation for this (also attached): --8<--- diff -purd a/lib/File/ChangeNotify/Watcher.pm b/lib/File/ChangeNotify/Watcher.pm --- a/lib/File/ChangeNotify/Watcher.pm 2013-11-28 16:41:11.000000000 +0100 +++ b/lib/File/ChangeNotify/Watcher.pm 2016-05-19 16:18:37.873495895 +0200 @@ -62,11 +62,12 @@ has sleep_interval => ( default => 2, ); -my $files_or_regexps = subtype as 'ArrayRef[Str|RegexpRef]'; +my $files_or_regexps = subtype as 'ArrayRef[Str|RegexpRef]'; +my $files_or_regexps_or_code = subtype as 'ArrayRef[Str|RegexpRef|CodeRef]'; has exclude => ( is => 'ro', - isa => $files_or_regexps, + isa => $files_or_regexps_or_code, default => sub { [] }, ); @@ -97,8 +98,14 @@ sub _path_is_excluded { foreach my $excluded ( @{ $self->exclude } ) { - if ( ref $excluded && ref $excluded eq 'Regexp' ) { - return 1 if $path =~ /$excluded/; + if ( my $ref = ref $excluded ) { + if ( $ref eq 'Regexp' ) { + return 1 if $path =~ /$excluded/; + } + elsif ( $ref eq "CODE" ) { + local $_ = $path; + return 1 if $excluded->($path); + } } else { return 1 if $path eq $excluded; @@ -140,7 +147,8 @@ version 0.24 File::ChangeNotify->instantiate_watcher ( directories => [ '/my/path', '/my/other' ], filter => qr/\.(?:pm|conf|yml)$/, - exclude => ['t', 'root', qr(/(?!\.)[^/]+$)], + exclude => ['t', 'root', qr(/(?!\.)[^/]+$), + sub { -e && ! -r }], ); if ( my @events = $watcher->new_events() ) { ... } @@ -192,9 +200,13 @@ By default, all files are included. =item * exclude => [...] -An optional list of paths to exclude. This list can contain either plain -strings or regular expressions. If you provide a string it should contain the -complete path to be excluded. +An optional list of paths to exclude. This list can contain plain strings, +regular expressions, or callbacks. If you provide a string it should contain +the complete path to be excluded. + +If you provide a sub, it should return a true value for paths to be excluded +e.g C<< exclude => [ sub { -e && ! -r } ], >>. The path will both be passed +as first argument to the callback as well as localized C<$_>. The paths can be either directories or specific files. If the exclusion matches a directory, all of its files and subdirectories are ignored. diff -purd a/t/excluded-dirs.t b/t/excluded-dirs.t --- a/t/excluded-dirs.t 2013-11-28 16:41:11.000000000 +0100 +++ b/t/excluded-dirs.t 2016-05-19 16:15:02.180460388 +0200 @@ -18,6 +18,7 @@ my $watcher = File::ChangeNotify::Watche f( 'excluded', 'dir' ), qr{(?:\\|/)r[^\\/]+$}, qr{(?:\\|/)\.[^\\/]*$}, + sub { 0; }, ] ); -->8---
Subject: fcw.diff
diff -purd a/lib/File/ChangeNotify/Watcher.pm b/lib/File/ChangeNotify/Watcher.pm --- a/lib/File/ChangeNotify/Watcher.pm 2013-11-28 16:41:11.000000000 +0100 +++ b/lib/File/ChangeNotify/Watcher.pm 2016-05-19 16:18:37.873495895 +0200 @@ -62,11 +62,12 @@ has sleep_interval => ( default => 2, ); -my $files_or_regexps = subtype as 'ArrayRef[Str|RegexpRef]'; +my $files_or_regexps = subtype as 'ArrayRef[Str|RegexpRef]'; +my $files_or_regexps_or_code = subtype as 'ArrayRef[Str|RegexpRef|CodeRef]'; has exclude => ( is => 'ro', - isa => $files_or_regexps, + isa => $files_or_regexps_or_code, default => sub { [] }, ); @@ -97,8 +98,14 @@ sub _path_is_excluded { foreach my $excluded ( @{ $self->exclude } ) { - if ( ref $excluded && ref $excluded eq 'Regexp' ) { - return 1 if $path =~ /$excluded/; + if ( my $ref = ref $excluded ) { + if ( $ref eq 'Regexp' ) { + return 1 if $path =~ /$excluded/; + } + elsif ( $ref eq "CODE" ) { + local $_ = $path; + return 1 if $excluded->($path); + } } else { return 1 if $path eq $excluded; @@ -140,7 +147,8 @@ version 0.24 File::ChangeNotify->instantiate_watcher ( directories => [ '/my/path', '/my/other' ], filter => qr/\.(?:pm|conf|yml)$/, - exclude => ['t', 'root', qr(/(?!\.)[^/]+$)], + exclude => ['t', 'root', qr(/(?!\.)[^/]+$), + sub { -e && ! -r }], ); if ( my @events = $watcher->new_events() ) { ... } @@ -192,9 +200,13 @@ By default, all files are included. =item * exclude => [...] -An optional list of paths to exclude. This list can contain either plain -strings or regular expressions. If you provide a string it should contain the -complete path to be excluded. +An optional list of paths to exclude. This list can contain plain strings, +regular expressions, or callbacks. If you provide a string it should contain +the complete path to be excluded. + +If you provide a sub, it should return a true value for paths to be excluded +e.g C<< exclude => [ sub { -e && ! -r } ], >>. The path will both be passed +as first argument to the callback as well as localized C<$_>. The paths can be either directories or specific files. If the exclusion matches a directory, all of its files and subdirectories are ignored. diff -purd a/t/excluded-dirs.t b/t/excluded-dirs.t --- a/t/excluded-dirs.t 2013-11-28 16:41:11.000000000 +0100 +++ b/t/excluded-dirs.t 2016-05-19 16:15:02.180460388 +0200 @@ -18,6 +18,7 @@ my $watcher = File::ChangeNotify::Watche f( 'excluded', 'dir' ), qr{(?:\\|/)r[^\\/]+$}, qr{(?:\\|/)\.[^\\/]*$}, + sub { 0; }, ] );
Thanks, I included this in 0.25.