1 package Catalyst::Engine::HTTP::Restarter::Watcher;
7 use Time::HiRes qw/sleep/;
9 has delay => (is => 'rw');
10 has regex => (is => 'rw');
11 has modified => (is => 'rw');
12 has directory => (is => 'rw');
13 has watch_list => (is => 'rw');
14 has follow_simlinks => (is => 'rw');
17 my ( $class, %args ) = @_;
31 my $watch_list = $self->_index_directory;
32 $self->watch_list($watch_list);
37 files => [ keys %{$watch_list} ],
48 my $delay = ( defined $self->delay ) ? $self->delay : 1;
50 sleep $delay if $delay > 0;
52 eval { @changes = $self->modified->changed };
55 # File::Modified will die if a file is deleted.
56 my ($deleted_file) = $@ =~ /stat '(.+)'/;
57 push @changed_files, $deleted_file || 'unknown file';
62 # update all mtime information
63 $self->modified->update;
65 # check if any files were changed
66 @changed_files = grep { -f $_ } @changes;
68 # Check if only directories were changed. This means
69 # a new file was created.
70 unless (@changed_files) {
72 # re-index to find new files
73 my $new_watch = $self->_index_directory;
75 # look through the new list for new files
76 my $old_watch = $self->watch_list;
77 @changed_files = grep { !defined $old_watch->{$_} }
80 return unless @changed_files;
84 for my $file (@changed_files) {
85 next unless $file =~ /\.pm$/;
86 if ( my $error = $self->_test($file) ) {
87 print STDERR qq/File "$file" modified, not restarting\n\n/;
88 print STDERR '*' x 80, "\n";
90 print STDERR '*' x 80, "\n";
96 return @changed_files;
99 sub _index_directory {
102 my $dir = $self->directory;
103 die "No directory specified" if !$dir or ref($dir) && !@{$dir};
105 my $regex = $self->regex || '\.pm$';
111 my $file = File::Spec->rel2abs($File::Find::name);
112 return unless $file =~ /$regex/;
113 return unless -f $file;
114 $file =~ s{/script/..}{};
117 # also watch the directory for changes
118 my $cur_dir = File::Spec->rel2abs($File::Find::dir);
119 $cur_dir =~ s{/script/..}{};
122 follow_fast => $self->follow_symlinks ? 1 : 0,
125 ref $dir eq 'ARRAY' ? @{$dir} : $dir
131 my ( $self, $file ) = @_;
134 local $SIG{__WARN__} = sub { };
136 open my $olderr, '>&STDERR';
137 open STDERR, '>', File::Spec->devnull;
138 eval "require '$file'";
139 open STDERR, '>&', $olderr;
141 return ($@) ? $@ : 0;
149 Catalyst::Engine::HTTP::Restarter::Watcher - Watch for changed application
154 my $watcher = Catalyst::Engine::HTTP::Restarter::Watcher->new(
155 directory => '/path/to/MyApp',
156 regex => '\.yml$|\.yaml$|\.pm$',
161 my @changed_files = $watcher->watch();
166 This class monitors a directory of files for changes made to any file
167 matching a regular expression. It correctly handles new files added to the
168 application as well as files that are deleted.
172 =head2 new ( directory => $path [, regex => $regex, delay => $delay ] )
174 Creates a new Watcher object.
178 Returns a list of files that have been added, deleted, or changed since the
179 last time watch was called.
183 L<Catalyst>, L<Catalyst::Engine::HTTP::Restarter>, L<File::Modified>
187 Sebastian Riedel, <sri@cpan.org>
189 Andy Grundman, <andy@hybridized.org>
193 Many parts are ripped out of C<HTTP::Server::Simple> by Jesse Vincent.
197 This program is free software, you can redistribute it and/or modify it under
198 the same terms as Perl itself.