It turns out the restarter didn't really work on Win32. This checkin
[catagits/Catalyst-Devel.git] / lib / Catalyst / Restarter.pm
CommitLineData
8462f41e 1package Catalyst::Restarter;
2
3use Moose;
4
ffbcd711 5use Cwd qw( abs_path );
a13b99da 6use File::ChangeNotify;
ffbcd711 7use FindBin;
8462f41e 8use namespace::clean -except => 'meta';
9
b8e3feb1 10has start_sub => (
8462f41e 11 is => 'ro',
12 isa => 'CodeRef',
13 required => 1,
14);
15
16has _watcher => (
17 is => 'rw',
a13b99da 18 isa => 'File::ChangeNotify::Watcher',
8462f41e 19);
20
21has _child => (
22 is => 'rw',
23 isa => 'Int',
24);
25
2e9609df 26sub pick_subclass {
27 my $class = shift;
28
29 my $subclass;
30 $subclass =
31 defined $ENV{CATALYST_RESTARTER}
32 ? $ENV{CATALYST_RESTARTER}
33 : $^O eq 'MSWin32'
34 ? 'Win32'
35 : 'Forking';
36
37 $subclass = 'Catalyst::Restarter::' . $subclass;
38
39 eval "use $subclass";
40 die $@ if $@;
41
42 return $subclass;
43}
44
8462f41e 45sub BUILD {
46 my $self = shift;
47 my $p = shift;
48
b8e3feb1 49 delete $p->{start_sub};
8462f41e 50
a13b99da 51 $p->{filter} ||= qr/(?:\/|^)(?!\.\#).+(?:\.yml$|\.yaml$|\.conf|\.pm)$/;
ffbcd711 52 $p->{directories} ||= abs_path( File::Spec->catdir( $FindBin::Bin, '..' ) );
a13b99da 53
8462f41e 54 # We could make this lazily, but this lets us check that we
55 # received valid arguments for the watcher up front.
a13b99da 56 $self->_watcher( File::ChangeNotify->instantiate_watcher( %{$p} ) );
8462f41e 57}
58
59sub run_and_watch {
60 my $self = shift;
61
62 $self->_fork_and_start;
63
64 return unless $self->_child;
65
66 $self->_restart_on_changes;
67}
68
8462f41e 69sub _restart_on_changes {
70 my $self = shift;
71
a13b99da 72 my @events = $self->_watcher->wait_for_events();
73 $self->_handle_events(@events);
7f564068 74}
8462f41e 75
a13b99da 76sub _handle_events {
77 my $self = shift;
78 my @events = @_;
8462f41e 79
7f564068 80 print STDERR "\n";
81 print STDERR "Saw changes to the following files:\n";
a13b99da 82
83 for my $event (@events) {
84 my $path = $event->path();
85 my $type = $event->type();
86
87 print STDERR " - $path ($type)\n";
88 }
89
7f564068 90 print STDERR "\n";
91 print STDERR "Attempting to restart the server\n\n";
8462f41e 92
7f564068 93 $self->_kill_child;
8462f41e 94
7f564068 95 $self->_fork_and_start;
8462f41e 96
7f564068 97 $self->_restart_on_changes;
8462f41e 98}
99
02758cf8 100sub DEMOLISH {
101 my $self = shift;
102
103 $self->_kill_child;
104}
105
8462f41e 106__PACKAGE__->meta->make_immutable;
107
1081;
83d2d4a4 109
110__END__
111
112=head1 NAME
113
b8e3feb1 114Catalyst::Restarter - Uses File::ChangeNotify to check for changed files and restart the server
83d2d4a4 115
116=head1 SYNOPSIS
117
b8e3feb1 118 my $restarter = Catalyst::Restarter->new(
119 directories => '/path/to/MyApp',
120 regex => '\.yml$|\.yaml$|\.conf|\.pm$',
121 start_sub => sub { ... }
83d2d4a4 122 );
123
b8e3feb1 124 $restarter->run_and_watch;
83d2d4a4 125
126=head1 DESCRIPTION
127
b8e3feb1 128This class uses L<File::ChangeNotify> to watch one or more directories
129of files and restart the Catalyst server when any of those files
130changes.
83d2d4a4 131
132=head1 METHODS
133
b8e3feb1 134=head2 new ( start_sub => sub { ... }, ... )
135
136This method creates a new restarter object.
83d2d4a4 137
b8e3feb1 138The "start_sub" argument is required. This is a subroutine reference
139that can be used to start the Catalyst server.
83d2d4a4 140
b8e3feb1 141=head2 run_and_watch
83d2d4a4 142
b8e3feb1 143This method forks, starts the server in a child process, and then
144watched for changed files in the parent. When files change, it kills
145the child, forks again, and starts a new server.
83d2d4a4 146
147=head1 SEE ALSO
148
b8e3feb1 149L<Catalyst>, <File::ChangeNotify>
83d2d4a4 150
151=head1 AUTHORS
152
153Catalyst Contributors, see Catalyst.pm
154
155=head1 COPYRIGHT
156
157This program is free software, you can redistribute it and/or modify
158it under the same terms as Perl itself.
159
160=cut