File Coverage

blib/lib/Module/Refresh.pm
Criterion Covered Total %
statement 22 22 100.0
branch 5 6 83.3
condition n/a
subroutine 7 7 100.0
pod n/a
total 34 35 97.1


line stmt bran cond sub pod time code
1             package Module::Refresh;
2              
3 4     4   61956 use strict;
  4         12  
  4         113  
4 4     4   21 use vars qw( $VERSION %CACHE );
  4         6  
  4         268  
5              
6             $VERSION = "0.18";
7              
8             BEGIN {
9              
10             # Turn on the debugger's symbol source tracing
11 4     4   16 $^P |= 0x10;
12              
13             # Work around bug in pre-5.8.7 perl where turning on $^P
14             # causes caller() to be confused about eval {}'s in the stack.
15             # (See http://rt.perl.org/rt3/Ticket/Display.html?id=35059 for more info.)
16 4 50       2229 eval 'sub DB::sub' if $] < 5.008007;
17             }
18              
19             =head1 NAME
20              
21             Module::Refresh - Refresh %INC files when updated on disk
22              
23             =head1 SYNOPSIS
24              
25             # During each request, call this once to refresh changed modules:
26              
27             Module::Refresh->refresh;
28              
29             # Each night at midnight, you automatically download the latest
30             # Acme::Current from CPAN. Use this snippet to make your running
31             # program pick it up off disk:
32              
33             $refresher->refresh_module('Acme/Current.pm');
34              
35             =head1 DESCRIPTION
36              
37             This module is a generalization of the functionality provided by
38             L and L. It's designed to make it
39             easy to do simple iterative development when working in a persistent
40             environment.
41              
42             It does not require mod_perl.
43              
44             =cut
45              
46             =head2 new
47              
48             Initialize the module refresher.
49              
50             =cut
51              
52             sub new {
53             my $proto = shift;
54             my $self = ref($proto) || $proto;
55             $self->update_cache($_) for keys %INC;
56             return ($self);
57             }
58              
59             =head2 refresh
60              
61             Refresh all modules that have mtimes on disk newer than the newest ones we've got.
62             Calls C to initialize the cache if it had not yet been called.
63              
64             Specifically, it will renew any module that was loaded before the previous call
65             to C (or C) and has changed on disk since then. If a module was
66             both loaded for the first time B changed on disk between the previous call
67             and this one, it will B be reloaded by this call (or any future one); you
68             will need to update the modification time again (by using the Unix C command or
69             making a change to it) in order for it to be reloaded.
70              
71             =cut
72              
73             sub refresh {
74             my $self = shift;
75              
76             return $self->new if !%CACHE;
77              
78             foreach my $mod ( sort keys %INC ) {
79             $self->refresh_module_if_modified($mod);
80             }
81             return ($self);
82             }
83              
84             =head2 refresh_module_if_modified $module
85              
86             If $module has been modified on disk, refresh it. Otherwise, do nothing
87              
88              
89             =cut
90              
91             sub refresh_module_if_modified {
92             my $self = shift;
93             return $self->new if !%CACHE;
94             my $mod = shift;
95              
96             if (!$INC{$mod}) {
97             return;
98             } elsif ( !$CACHE{$mod} ) {
99             $self->update_cache($mod);
100             } elsif ( $self->mtime( $INC{$mod} ) ne $CACHE{$mod} ) {
101             $self->refresh_module($mod);
102             }
103              
104             }
105              
106             =head2 refresh_module $module
107              
108             Refresh a module. It doesn't matter if it's already up to date. Just do it.
109              
110             Note that it only accepts module names like C, not C.
111              
112             =cut
113              
114             sub refresh_module {
115             my $self = shift;
116             my $mod = shift;
117              
118             $self->unload_module($mod);
119              
120             local $@;
121             eval { require $mod; 1 } or warn $@;
122              
123             $self->update_cache($mod);
124              
125             return ($self);
126             }
127              
128             =head2 unload_module $module
129              
130             Remove a module from C<%INC>, and remove all subroutines defined in it.
131              
132             =cut
133              
134             sub unload_module {
135             my $self = shift;
136             my $mod = shift;
137             my $file = $INC{$mod};
138              
139             delete $INC{$mod};
140             delete $CACHE{$mod};
141             $self->unload_subs($file);
142              
143             return ($self);
144             }
145              
146             =head2 mtime $file
147              
148             Get the last modified time of $file in seconds since the epoch;
149              
150             =cut
151              
152             sub mtime {
153             return join ' ', ( stat( $_[1] ) )[ 1, 7, 9 ];
154             }
155              
156             =head2 update_cache $file
157              
158             Updates the cached "last modified" time for $file.
159              
160             =cut
161              
162             sub update_cache {
163             my $self = shift;
164             my $module_pm = shift;
165              
166             # In case the module was not loaded successfully.
167             return unless defined $INC{$module_pm};
168              
169             $CACHE{$module_pm} = $self->mtime( $INC{$module_pm} );
170             }
171              
172             =head2 unload_subs $file
173              
174             Wipe out subs defined in $file.
175              
176             =cut
177              
178             sub unload_subs {
179             my $self = shift;
180             my $file = shift;
181              
182             foreach my $sym ( grep { index( $DB::sub{$_}, "$file:" ) == 0 }
183             keys %DB::sub )
184             {
185              
186             warn "Deleting $sym from $file" if ( $sym =~ /freeze/ );
187             eval { undef &$sym };
188             warn "$sym: $@" if $@;
189             delete $DB::sub{$sym};
190 4     4   24 { no strict 'refs';
  4         6  
  4         544  
191             if ($sym =~ /^(.*::)(.*?)$/) {
192             delete *{$1}->{$2};
193             }
194             }
195             }
196              
197             return $self;
198             }
199              
200             # "Anonymize" all our subroutines into unnamed closures; so we can safely
201             # refresh this very package.
202             BEGIN {
203 4     4   23 no strict 'refs';
  4         5  
  4         476  
204 4     4   12 foreach my $sym ( sort keys %{ __PACKAGE__ . '::' } ) {
  4         34  
205             next
206 48 100       85 if $sym eq
207             'VERSION'; # Skip the version sub, inherited from UNIVERSAL
208 44 100       140 my $code = __PACKAGE__->can($sym) or next;
209 32         39 delete ${ __PACKAGE__ . '::' }{$sym};
  32         98  
210 32     1422   274 *$sym = sub { goto &$code };
  1422         2007467  
211             }
212              
213             }
214              
215             1;
216              
217             =head1 BUGS
218              
219             When we walk the symbol table to whack reloaded subroutines, we don't
220             have a good way to invalidate the symbol table properly, so we mess up
221             on things like global variables that were previously set.
222              
223             =head1 SEE ALSO
224              
225             L, L
226              
227             =head1 COPYRIGHT
228              
229             Copyright 2004,2011 by Jesse Vincent Ejesse@bestpractical.comE,
230             Audrey Tang Eaudreyt@audreyt.orgE
231              
232             This program is free software; you can redistribute it and/or
233             modify it under the same terms as Perl itself.
234              
235             See L
236              
237             =cut
238