Add built local::lib
[catagits/Gitalist.git] / local-lib5 / lib / perl5 / File / ChangeNotify / Watcher.pm
1 package File::ChangeNotify::Watcher;
2
3 use strict;
4 use warnings;
5
6 our $VERSION = '0.11';
7
8 use File::ChangeNotify::Event;
9 use List::MoreUtils qw(all);
10 use Moose;
11 use Moose::Util::TypeConstraints;
12 use MooseX::Params::Validate qw( pos_validated_list );
13
14 has filter => (
15     is      => 'ro',
16     isa     => 'RegexpRef',
17     default => sub {qr/.*/},
18 );
19
20 my $dir = subtype as 'Str' => where { -d $_ } =>
21     message {"$_ is not a valid directory"};
22
23 my $array_of_dirs = subtype
24     as 'ArrayRef[Str]', => where {
25     map {-d} @{$_};
26     } => message {"@{$_} is not a list of valid directories"};
27
28 coerce $array_of_dirs => from $dir => via { [$_] };
29
30 has directories => (
31     is       => 'rw',
32     writer   => '_set_directories',
33     isa      => $array_of_dirs,
34     required => 1,
35     coerce   => 1,
36 );
37
38 has follow_symlinks => (
39     is      => 'ro',
40     isa     => 'Bool',
41     default => 0,
42 );
43
44 has event_class => (
45     is      => 'ro',
46     isa     => 'ClassName',
47     default => 'File::ChangeNotify::Event',
48 );
49
50 has sleep_interval => (
51     is      => 'ro',
52     isa     => 'Num',
53     default => 2,
54 );
55
56 my $files_or_regexps = subtype as 'ArrayRef[Str|RegexpRef]';
57
58 has exclude => (
59     is      => 'ro',
60     isa     => $files_or_regexps,
61     default => sub { [] },
62     coerce  => 1,
63 );
64
65 sub BUILD {
66     my $self = shift;
67
68     Class::MOP::load_class( $self->event_class() );
69 }
70
71 sub new_events {
72     my $self = shift;
73
74     return $self->_interesting_events();
75 }
76
77 sub _add_directory {
78     my $self = shift;
79     my $dir  = shift;
80
81     return if grep { $_ eq $dir } $self->directories();
82
83     push @{ $self->directories() }, $dir;
84 }
85
86 sub _path_is_excluded {
87     my $self = shift;
88     my $path = shift;
89
90     foreach my $excluded ( @{ $self->exclude } ) {
91
92         if ( ref $excluded && ref $excluded eq 'Regexp' ) {
93             return 1 if $path =~ /$excluded/;
94         }
95         else {
96             return 1 if $path eq $excluded;
97         }
98     }
99
100     return;
101 }
102
103 sub _remove_directory {
104     my $self = shift;
105     my $dir  = shift;
106
107     $self->_set_directories(
108         [ grep { $_ ne $dir } @{ $self->directories() } ] );
109 }
110
111 no Moose;
112 no Moose::Util::TypeConstraints;
113 no MooseX::Params::Validate;
114
115 __PACKAGE__->meta()->make_immutable();
116
117 1;
118
119 __END__
120
121 =head1 NAME
122
123 File::ChangeNotify::Watcher - Base class for all watchers
124
125 =head1 SYNOPSIS
126
127     my $watcher =
128         File::ChangeNotify->instantiate_watcher
129             ( directories => [ '/my/path', '/my/other' ],
130               filter      => qr/\.(?:pm|conf|yml)$/,
131               exclude     => ['t', 'root', qr(/(?!\.)[^/]+$)],
132             );
133
134     if ( my @events = $watcher->new_events() ) { ... }
135
136     # blocking
137     while ( my @events = $watcher->wait_for_events() ) { ... }
138
139 =head1 DESCRIPTION
140
141 A C<File::ChangeNotify::Watcher> class monitors a directory for
142 changes made to any file. You can provide a regular expression to
143 filter out files you are not interested in. It handles the addition of
144 new subdirectories by adding them to the watch list.
145
146 Note that the actual granularity of what each watcher subclass reports
147 may vary across subclasses. Implementations that hook into some sort
148 of kernel event interface (Inotify, for example) have much better
149 knowledge of exactly what changes are happening than one implemented
150 purely in userspace code (like the Default subclass).
151
152 By default, events are returned in the form
153 L<File::ChangeNotify::Event> objects, but this can be overridden by
154 providing an "event_class" attribute to the constructor.
155
156 The watcher can operate in a blocking/callback style, or you can
157 simply ask it for a list of new events as needed.
158
159 =head1 METHODS
160
161 =head2 File::ChangeNotify::Watcher::Subclass->new(...)
162
163 This method creates a new watcher. It accepts the following arguments:
164
165 =over 4
166
167 =item * directories => $path
168
169 =item * directories => \@paths
170
171 This argument is required. It can be either one or many paths which
172 should be watched for changes.
173
174 =item * filter => qr/.../
175
176 This is an optional regular expression that will be used to check if a
177 file is of interest. This filter is only applied to files.
178
179 By default, all files are included.
180
181 =item * exclude => [...]
182
183 An optional list of paths to exclude. This list can contain either plain
184 strings or regular expressions. If you provide a string it should contain the
185 complete path to be excluded.
186
187 The paths can be either directories or specific files. If the exclusion
188 matches a directory, all of its files and subdirectories are ignored.
189
190 =item * follow_symlinks => $bool
191
192 By default, symlinks are ignored. Set this to true to follow them.
193
194 If this symlinks are being followed, symlinks to files and directories
195 will be followed. Directories will be watched, and changes for
196 directories and files reported.
197
198 =item * sleep_interval => $number
199
200 For watchers which call C<sleep> to implement the C<<
201 $watcher->wait_for_events() >> method, this argument controls how long
202 it sleeps for. The value is a number in seconds.
203
204 The default is 2 seconds.
205
206 =item * event_class => $class
207
208 This can be used to change the class used to report events. By
209 default, this is L<File::ChangeNotify::Event>.
210
211 =back
212
213 =head2 $watcher->wait_for_events()
214
215 This method causes the watcher to block until it sees interesting
216 events, and then return them as a list.
217
218 Some watcher subclasses may implement blocking as a sleep loop, while
219 others may actually block.
220
221 =head2 $watcher->new_events()
222
223 This method returns a list of any interesting events seen since the
224 last time the watcher checked.
225
226 =head2 $watcher->sees_all_events()
227
228 If this is true, the watcher will report on all events.
229
230 Some watchers, like the Default subclass, are not smart enough to
231 track things like a file being created and then immediately deleted,
232 and can only detect changes between snapshots of the file system.
233
234 Other watchers, like the Inotify subclass, see all events that happen
235 and report on them.
236
237 =head1 AUTHOR
238
239 Dave Rolsky, E<lt>autarch@urth.orgE<gt>
240
241 =head1 COPYRIGHT & LICENSE
242
243 Copyright 2009 Dave Rolsky, All Rights Reserved.
244
245 This program is free software; you can redistribute it and/or modify
246 it under the same terms as Perl itself.
247
248 =cut