| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#!/usr/bin/perl |
|
2
|
|
|
|
|
|
|
## Emacs: -*- tab-width: 4; -*- |
|
3
|
|
|
|
|
|
|
|
|
4
|
1
|
|
|
1
|
|
7687
|
use strict; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
68
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package Module::Reload::Selective; |
|
7
|
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
5
|
use vars qw($VERSION); $VERSION = '1.02'; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
174
|
|
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
=pod |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 NAME |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
Module::Reload::Selective - Reload perl modules during development |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
Instead of: |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
use Foobar::MyModule; |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
Do this: |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
use Module::Reload::Selective; |
|
25
|
|
|
|
|
|
|
&Module::Reload::Selective->reload(qw(Foobar::MyModule)); |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
Or, if you need the "import" semantics of "use", do this: |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
use Foobar::MyModule (@ImportArgs); |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
Do this: |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
use Module::Reload::Selective; |
|
34
|
|
|
|
|
|
|
Module::Reload::Selective->reload(qw(Foobar::MyModule)); |
|
35
|
|
|
|
|
|
|
import Foobar::MyModule (@ImportArgs); |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
... then configure your server or other runtime environment settings |
|
39
|
|
|
|
|
|
|
to trigger Module::Reload::Selective to only kick in when you need. |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
For example: you could have it kick in only when the web server is |
|
42
|
|
|
|
|
|
|
running on a particular port number or particular (development) host. |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=head1 OVERVIEW |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
Utility for module developers to selectively reload needed modules |
|
47
|
|
|
|
|
|
|
and/or conditionally augment @INC with additional, per-developer |
|
48
|
|
|
|
|
|
|
library directories, at development time based on environment |
|
49
|
|
|
|
|
|
|
variables. |
|
50
|
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
Particularly helpful in conjunction with mod_perl applications where |
|
52
|
|
|
|
|
|
|
some or all application logic resides in separate Perl modules that |
|
53
|
|
|
|
|
|
|
would otherwise not get reloaded until the server restarts. |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
Copyright (c) 2002, Chris Thorman. |
|
56
|
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
Released to the public under the terms of the Perl Artistic License. |
|
58
|
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=head1 DETAILS |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
This module defines a "reload" routine that scripts, CGI scripts, |
|
62
|
|
|
|
|
|
|
Embperl scripts, handlers, etc. can use to reload (re-require) a |
|
63
|
|
|
|
|
|
|
module or modules, optionally forcing the modules AND ANY MODULES THEY |
|
64
|
|
|
|
|
|
|
USE, recursively, to reload, even if already previously loaded and |
|
65
|
|
|
|
|
|
|
listed in %INC. |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
The reloading feature is helpful for when you're actively writing and |
|
68
|
|
|
|
|
|
|
debugging modules intended to be used with Apache and mod_perl (either |
|
69
|
|
|
|
|
|
|
used by Apache::Registry or HTML::Embperl script, or handlers, or |
|
70
|
|
|
|
|
|
|
other mechanisms) and want to ensure that your code changes get |
|
71
|
|
|
|
|
|
|
reloaded on every hit, even if the module had previously been loaded |
|
72
|
|
|
|
|
|
|
into the parent or child process. |
|
73
|
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
In addition to the selective reloading feature, this module can also |
|
75
|
|
|
|
|
|
|
(optionally) dynamically prepend some additional paths to @INC to |
|
76
|
|
|
|
|
|
|
allow programmers to work on, test, and debug private development |
|
77
|
|
|
|
|
|
|
copies of modules in a private directory while other modules are |
|
78
|
|
|
|
|
|
|
loaded from a more stable, shared, or public, library directory. |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
The @INC-modifying feature is helpful even if you're only developing |
|
81
|
|
|
|
|
|
|
command-line perl scripts in an environment where there are multiple |
|
82
|
|
|
|
|
|
|
programmers and an individual programmer, for testing purposes, needs |
|
83
|
|
|
|
|
|
|
to optionally load some modules under development from his or her own |
|
84
|
|
|
|
|
|
|
private source directory in preference to the "standard" locations. |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
This is a common need when multiple Perl developers are working on the |
|
87
|
|
|
|
|
|
|
same Unix host. |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
How this module differs from Module::Reload: |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=over 4 |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=item * |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
Module::Reload reloads just files that it sees have changed on disk |
|
96
|
|
|
|
|
|
|
since the last reload, whereas this module conditionally reloads based |
|
97
|
|
|
|
|
|
|
on other conditions at runtime; this module also has other features of |
|
98
|
|
|
|
|
|
|
convenience to develoepers. |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
=back |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
How this module differs from Apache::StatINC: |
|
103
|
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=over 4 |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=item * |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
Reloads requested modules (recursively) regardless of modification |
|
109
|
|
|
|
|
|
|
date. |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=item * |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
Skips reloading any modules that have been previously loaded from |
|
114
|
|
|
|
|
|
|
lib/perl* (or other customizable list of dir name patterns), so you |
|
115
|
|
|
|
|
|
|
can only reload items outside the standard library locations, by |
|
116
|
|
|
|
|
|
|
default. |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=item * |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
Allows dynamic overriding of @INC on a per-USER basis. |
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
=item * |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
This module lacks StatINC's ability to disable symbol-redef warnings, |
|
125
|
|
|
|
|
|
|
so best not to reload modules with const subroutines... (sorry). |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=item * |
|
128
|
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
Works outside of Apache as well as within it (not sure whether this is |
|
130
|
|
|
|
|
|
|
true of Apache::StatINC), so is testable from the command line, and |
|
131
|
|
|
|
|
|
|
even useful in a batch script context, if not for its reloading |
|
132
|
|
|
|
|
|
|
capabilities, then at least for its ability to override the search |
|
133
|
|
|
|
|
|
|
path on a per-USER basis, allowing the development and debugging of a |
|
134
|
|
|
|
|
|
|
private copy of a system-wide module or modules. |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=item * |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
Works fine from within individual pages or scripts; does not |
|
139
|
|
|
|
|
|
|
necessarily need to be loaded at server startup time. |
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=item * |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
Is a no-op (does not reload) unless certain environment variables |
|
144
|
|
|
|
|
|
|
and/or options are set, allowing you to leave calls to it in |
|
145
|
|
|
|
|
|
|
production code with negligible performance hit on non-debugging |
|
146
|
|
|
|
|
|
|
servers. |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
=back |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=head1 DISCUSSION |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
To request that a module Foobar::MyModule, and any modules it calls, |
|
153
|
|
|
|
|
|
|
be reloaded, do this: |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
use Module::Reload::Selective; |
|
156
|
|
|
|
|
|
|
Module::Reload::Selective->reload(qw(Foobar::MyModule)); |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
This reloads the module, executing its BEGIN blocks, syntax-checking |
|
160
|
|
|
|
|
|
|
it, and recompiling any subroutines it has. |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
Then, if you want to import any semantics from the module into the |
|
163
|
|
|
|
|
|
|
current namespace, you should directly "import" the module. |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
import Foobar::MyModule (@ImportArgs); |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
IMPORTANT: Under normal circumstances, reload will load the module |
|
168
|
|
|
|
|
|
|
normally with no difference from the usual behavior of "use" |
|
169
|
|
|
|
|
|
|
... i.e. files won't be reloaded if they already have been, and no |
|
170
|
|
|
|
|
|
|
special modifications to @INC will be applied. |
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
BUT, if certain environment variables (see below) are set to non-false |
|
173
|
|
|
|
|
|
|
values, Module::Reload::Selective will force them and any modules THEY need, to |
|
174
|
|
|
|
|
|
|
be reloaded from their source file every time, also using temporary |
|
175
|
|
|
|
|
|
|
modifications to @INC. |
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
The variables are: |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
$ENV{RLD} ## Useful for command-line testing/debugging |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
prompt> RLD=1 perl index.cgi |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
Just set this environment variable before invoking the script and the |
|
184
|
|
|
|
|
|
|
Reloader will be activated. |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
$ENV{DEBUGGING_SERVER} ## Set this in the server startup |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
At server startup, set the environment variable conditionally, only if |
|
189
|
|
|
|
|
|
|
you're starting up a private debugging server, say, on a different |
|
190
|
|
|
|
|
|
|
port. You could use something like this in a section in your |
|
191
|
|
|
|
|
|
|
httpd.conf, for example: |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
if (($My::HostName =~ /^dev/) && $Port == 8081) |
|
194
|
|
|
|
|
|
|
{ |
|
195
|
|
|
|
|
|
|
$User = 'upload'; |
|
196
|
|
|
|
|
|
|
$Group = 'upload'; |
|
197
|
|
|
|
|
|
|
print STDERR "Starting as user $User/$Group\n" if -t STDERR; |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
push @PerlSetEnv, ['DEBUGGING_SERVER', 1]; |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
## Could also set other Module::Reload::Selective runtime options here. |
|
202
|
|
|
|
|
|
|
} |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=head1 RUNTIME OPTIONS |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
Runtime options are initialized by Module::Reload::Selective when it |
|
209
|
|
|
|
|
|
|
is first "use"d, and may be overridden individually later before |
|
210
|
|
|
|
|
|
|
calling "reload", by setting a few elements of the |
|
211
|
|
|
|
|
|
|
$Module::Reload::Selective::Options hash, like this: |
|
212
|
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
$Module::Reload::Selective::Options->{SearchProgramDir} = 0; |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
The available options, and their initial default values, are: |
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
ReloadOnlyIfEnvVarsSet => 1, |
|
219
|
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
## If 0, always reloads, regardless of environment var settings |
|
221
|
|
|
|
|
|
|
## described above. |
|
222
|
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
SearchProgramDir => 1, |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
## If 1, cur working dir of script, as determined from $0, will be |
|
226
|
|
|
|
|
|
|
## added to the search paths before reloading. |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
## This is very handy for keeping private local copies of modules |
|
229
|
|
|
|
|
|
|
## being tested in the same directory tree as the application that |
|
230
|
|
|
|
|
|
|
## uses them. |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
SearchUserDir => 1, |
|
233
|
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
## If 1, "user dir" as determined by the other "User" options |
|
235
|
|
|
|
|
|
|
## below, will added to the search paths, after ProgramDir. |
|
236
|
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
DontReloadIfPathContains => ['lib/perl'], |
|
238
|
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
## List of strings that, if found in the loaded path of an already |
|
240
|
|
|
|
|
|
|
## loaded module, prevent that module from being re-loaded. By |
|
241
|
|
|
|
|
|
|
## specifying "lib/perl" (on Unix), no library modules installed |
|
242
|
|
|
|
|
|
|
## in the standard perl library locations will ever be reloaded. |
|
243
|
|
|
|
|
|
|
## Force reloading of those, too, by removing that entry, or add |
|
244
|
|
|
|
|
|
|
## additional strings to disable additional subdirectories, |
|
245
|
|
|
|
|
|
|
## perhaps ones of your own. |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
FirstAdditionalPaths => [], |
|
248
|
|
|
|
|
|
|
LastAdditionalPaths => [], |
|
249
|
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
## Lists; if non-empty, these specify additional paths to be |
|
251
|
|
|
|
|
|
|
## searched before or after any of the obove options, but in any |
|
252
|
|
|
|
|
|
|
## case always before any of the other locations normally in @INC. |
|
253
|
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
User => '', |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
## Name of user whose directory will be searched. |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
DefaultUser => $ENV{RELOAD_USER} || $ENV{USER} || $ENV{REMOTE_USER}, |
|
259
|
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
## Name of user whose directory will be searched if no User option |
|
261
|
|
|
|
|
|
|
## is specified to override it. If empty, no user name will be |
|
262
|
|
|
|
|
|
|
## used. |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
UserDirTemplate => '/home/USER/src/lib', |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
## Path to search when looking for source modules in a User's |
|
267
|
|
|
|
|
|
|
## programming directory. If "USER" is in the path, it will be |
|
268
|
|
|
|
|
|
|
## substituted at runtime with the value of User or DefaultUser as |
|
269
|
|
|
|
|
|
|
## appropriate. The resulting directory path is only added to the |
|
270
|
|
|
|
|
|
|
## search paths if it actually exists. |
|
271
|
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
=head1 DEBUGGING & ANALYSIS OF WHAT GOT LOADED |
|
273
|
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
For debugging purposes, Module::Reload::Selective creates these hash |
|
275
|
|
|
|
|
|
|
references, in the same format as %INC, that show what the last |
|
276
|
|
|
|
|
|
|
"reload" command did. You can examine these (e.g. with Data::Dumper) |
|
277
|
|
|
|
|
|
|
after calling reload if you want to be sure that reload did its job. |
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{INCHashBefore} |
|
280
|
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{INCHashAfter} |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{NewlyLoaded} |
|
283
|
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{Reloaded} |
|
284
|
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{NotReloaded} |
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{GotLoaded} |
|
287
|
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
NewlyLoaded -- modules that weren't loaded (from anywhere) prior to |
|
289
|
|
|
|
|
|
|
calling reload. |
|
290
|
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
Reloaded -- modules that previously appeared in %INC but got reloaded. |
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
NotReloaded -- modules that previously appeared in %INC but were not |
|
294
|
|
|
|
|
|
|
reloaded. |
|
295
|
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
GotLoaded -- The union of Reloaded and NewlyLoaded -- i.e. anything |
|
297
|
|
|
|
|
|
|
that got loaded as a result of the "reload" command. |
|
298
|
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
You can examine these by putting something like one of these |
|
300
|
|
|
|
|
|
|
statements in your code: |
|
301
|
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
use Data::Dumper; |
|
303
|
|
|
|
|
|
|
print &Dumper($Module::Reload::Selective::Debug); |
|
304
|
|
|
|
|
|
|
print &Dumper($Module::Reload::Selective::Debug->{GotLoaded}); |
|
305
|
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
For example, if you use HTML::Embperl, you could put the following |
|
307
|
|
|
|
|
|
|
line in your application: |
|
308
|
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
[+ &Dumper($Module::Reload::Selective::Debug); +] |
|
310
|
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
... and comment it out when done: |
|
312
|
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
[# [+ &Dumper($Module::Reload::Selective::Debug); +] #] |
|
314
|
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
Note: if you use "reload" to force a reload of all your modules into a |
|
316
|
|
|
|
|
|
|
virgin child process, the "NewlyLoaded" hash should be empty in a web |
|
317
|
|
|
|
|
|
|
server environment where the Web server has been properly configured |
|
318
|
|
|
|
|
|
|
to pre-load all necessary modules at server startup. You could use |
|
319
|
|
|
|
|
|
|
this side-effect as a way to test your server configuration to see if |
|
320
|
|
|
|
|
|
|
you've remembered to preload everything needed by your application at |
|
321
|
|
|
|
|
|
|
server startup; anything that shows up in NewlyLoaded is something |
|
322
|
|
|
|
|
|
|
you've forgotten to preload and you can fix that. |
|
323
|
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
To see what private version of @INC was used by "reload", have a look |
|
325
|
|
|
|
|
|
|
at this debugging variable: |
|
326
|
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{INCArrayAfterModification} |
|
328
|
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
To see what time the last reload occurred, view this variable: |
|
330
|
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{LastLoadTime} |
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
(This, along with the GotLoaded hash, will also help you reassure |
|
334
|
|
|
|
|
|
|
yourself that the things you wanted to reload really did get reloaded; |
|
335
|
|
|
|
|
|
|
if GotLoaded doesn't list your module, and/or LastLoadTime did not |
|
336
|
|
|
|
|
|
|
change, then something did not reload.) |
|
337
|
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
=head1 WARNINGS |
|
339
|
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
RELOADING IS RECURSIVE |
|
341
|
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
If you reload module A that uses module B, module B will be reloaded, |
|
343
|
|
|
|
|
|
|
too. This allows you to reload all related modules at one time. But |
|
344
|
|
|
|
|
|
|
if you're not working on A, only on B, it is more efficient to just |
|
345
|
|
|
|
|
|
|
reload module B. Don't reload more than you need, in other words. |
|
346
|
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
RELOADING CAN MESS WITH GLOBALS IN APACHE CHILD PROCESSES |
|
349
|
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
Note that the reloaded modules are loaded into the (child) process's |
|
351
|
|
|
|
|
|
|
global namespace and so will affect all applications served by the |
|
352
|
|
|
|
|
|
|
affected process... including any bugs you've introduced or modules |
|
353
|
|
|
|
|
|
|
that failed to compile. |
|
354
|
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
So if using Module::Reload::Selective for Web application development, each |
|
356
|
|
|
|
|
|
|
programmer should be testing with his/her own private Apache server, |
|
357
|
|
|
|
|
|
|
(possibly running on a unique port). |
|
358
|
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
This way when you force the reloading of a buggy version of a module, |
|
360
|
|
|
|
|
|
|
everyone else's runtime environment is not also screwed up. |
|
361
|
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
WARNING: SYMBOL REDEFINITION WARNINGS |
|
364
|
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
If the loaded module, or any module it reloads uses constant |
|
366
|
|
|
|
|
|
|
subroutines, as in constant.pm, you will get warnings every time it |
|
367
|
|
|
|
|
|
|
reloads. I tried to emulate a trick used by Doug MacEachern in |
|
368
|
|
|
|
|
|
|
Apache::StatINC to prevent this from happening, but in this version, I |
|
369
|
|
|
|
|
|
|
haven't been able to get that to work. Suggestions / fixes welcome. |
|
370
|
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
=head1 THANKS |
|
372
|
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
Thanks to Joshua Pritikin for suggestions and the use of the |
|
374
|
|
|
|
|
|
|
Module::Reload namespace. |
|
375
|
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
=head1 INSTALLATION |
|
377
|
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
Using CPAN module: |
|
379
|
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
perl -MCPAN -e 'install Module::Reload::Selective' |
|
381
|
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
Or manually: |
|
383
|
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
tar xzvf Module-Reload-Sel*gz |
|
385
|
|
|
|
|
|
|
cd Module-Reload-Sel*-?.?? |
|
386
|
|
|
|
|
|
|
perl Makefile.PL |
|
387
|
|
|
|
|
|
|
make |
|
388
|
|
|
|
|
|
|
make test |
|
389
|
|
|
|
|
|
|
make install |
|
390
|
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
392
|
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
The Module::Reload::Selective home page: |
|
394
|
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
http://christhorman.com/projects/perl/Module-Reload-Selective/ |
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
Apache(3), mod_perl, http://perl.apache.org/src/contrib, |
|
398
|
|
|
|
|
|
|
Module::Reload, Apache::StatINC. |
|
399
|
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
The implementation in Selective.pm. |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
The perlmod manual page. |
|
403
|
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
=head1 AUTHOR |
|
405
|
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
Chris Thorman |
|
407
|
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
Copyright (c) 1995-2002 Chris Thorman. All rights reserved. |
|
409
|
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify |
|
411
|
|
|
|
|
|
|
it under the same terms as Perl itself. |
|
412
|
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
=cut |
|
414
|
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
{}; ## Get emacs to indent correctly. Sigh. |
|
416
|
|
|
|
|
|
|
|
|
417
|
1
|
|
|
1
|
|
1213
|
use Data::Dumper; |
|
|
1
|
|
|
|
|
14830
|
|
|
|
1
|
|
|
|
|
222
|
|
|
418
|
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
BEGIN |
|
420
|
|
|
|
|
|
|
{ |
|
421
|
1
|
|
50
|
1
|
|
10
|
$Module::Reload::Selective::Debug ||= {}; |
|
422
|
|
|
|
|
|
|
|
|
423
|
1
|
|
50
|
|
|
7
|
$Module::Reload::Selective::Options ||= {}; |
|
424
|
|
|
|
|
|
|
|
|
425
|
1
|
|
50
|
|
|
7
|
$Module::Reload::Selective::Options->{ReloadOnlyIfEnvVarsSet} ||= 1; |
|
426
|
1
|
|
50
|
|
|
16
|
$Module::Reload::Selective::Options->{SearchProgramDir} ||= 1; |
|
427
|
1
|
|
50
|
|
|
6
|
$Module::Reload::Selective::Options->{SearchUserDir} ||= 1; |
|
428
|
|
|
|
|
|
|
|
|
429
|
1
|
|
50
|
|
|
7
|
$Module::Reload::Selective::Options->{DontReloadIfPathContains} ||= ['lib/perl']; |
|
430
|
|
|
|
|
|
|
|
|
431
|
1
|
|
50
|
|
|
7
|
$Module::Reload::Selective::Options->{FirstAdditionalPaths} ||= []; |
|
432
|
1
|
|
50
|
|
|
64
|
$Module::Reload::Selective::Options->{LastAdditionalPaths} ||= []; |
|
433
|
|
|
|
|
|
|
|
|
434
|
1
|
|
50
|
|
|
1603
|
$Module::Reload::Selective::Options->{User} ||= '', |
|
|
|
|
33
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
435
|
|
|
|
|
|
|
$Module::Reload::Selective::Options->{DefaultUser} ||= $ENV{RELOAD_USER} || $ENV{USER} || $ENV{REMOTE_USER}, |
|
436
|
|
|
|
|
|
|
$Module::Reload::Selective::Options->{UserDirTemplate} ||= '/home/USER/src/lib', |
|
437
|
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
} |
|
439
|
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
sub import |
|
441
|
|
|
|
|
|
|
{ |
|
442
|
1
|
|
|
1
|
|
1963
|
my ($Class, @Args) = @_; |
|
443
|
|
|
|
|
|
|
} |
|
444
|
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
### reload |
|
447
|
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
### Can be called either procedurally or as a class method. Knows to |
|
449
|
|
|
|
|
|
|
### not reload the Module::Reload::Selective class itself. |
|
450
|
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
sub reload |
|
452
|
|
|
|
|
|
|
{ |
|
453
|
0
|
|
|
0
|
0
|
|
my (@PackageNames) = @_; |
|
454
|
|
|
|
|
|
|
|
|
455
|
0
|
|
|
|
|
|
my $ReturnVal = undef; |
|
456
|
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
## This module doesn't reload itself. Sorry. Restart |
|
459
|
|
|
|
|
|
|
## your server for that. |
|
460
|
|
|
|
|
|
|
|
|
461
|
0
|
|
|
|
|
|
@PackageNames = (grep {$_ ne __PACKAGE__} @PackageNames); |
|
|
0
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
## Do nothing unless given at least one package name to reload. |
|
464
|
|
|
|
|
|
|
|
|
465
|
0
|
0
|
|
|
|
|
goto done unless @PackageNames; |
|
466
|
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
## Initialize/empty out the debugging info |
|
468
|
|
|
|
|
|
|
|
|
469
|
0
|
|
|
|
|
|
$Module::Reload::Selective::Debug = {}; |
|
470
|
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
## RELOAD MODE... kicks in if either of the two environment |
|
472
|
|
|
|
|
|
|
## variables is set or the ReloadOnlyIfEnvVarsSet option is turned |
|
473
|
|
|
|
|
|
|
## off. |
|
474
|
|
|
|
|
|
|
|
|
475
|
0
|
0
|
0
|
|
|
|
if ( |
|
|
|
|
0
|
|
|
|
|
|
476
|
|
|
|
|
|
|
$ENV{DEBUGGING_SERVER} || |
|
477
|
|
|
|
|
|
|
$ENV{RLD} || |
|
478
|
|
|
|
|
|
|
!$Module::Reload::Selective::Options->{ReloadOnlyIfEnvVarsSet} |
|
479
|
|
|
|
|
|
|
) |
|
480
|
|
|
|
|
|
|
{ |
|
481
|
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
## FIRST MODIFY @INC TO HAVE SOME ADDITIONAL SEARCH DIRS |
|
483
|
|
|
|
|
|
|
## PREPENDED... |
|
484
|
|
|
|
|
|
|
|
|
485
|
0
|
|
|
|
|
|
my $ExtraSearchDirs = []; |
|
486
|
|
|
|
|
|
|
|
|
487
|
0
|
0
|
0
|
|
|
|
if ($Module::Reload::Selective::Options->{FirstAdditionalPaths} && |
|
|
0
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
@{$Module::Reload::Selective::Options->{FirstAdditionalPaths}}) |
|
489
|
|
|
|
|
|
|
{ |
|
490
|
0
|
|
|
|
|
|
push @$ExtraSearchDirs, @{$Module::Reload::Selective::Options->{FirstAdditionalPaths}}; |
|
|
0
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
} |
|
492
|
|
|
|
|
|
|
|
|
493
|
0
|
0
|
|
|
|
|
if ($Module::Reload::Selective::Options->{SearchProgramDir}) |
|
494
|
|
|
|
|
|
|
{ |
|
495
|
0
|
|
|
|
|
|
(my $ProgramDir = $0) =~ s|(.*/).*|$1|; |
|
496
|
0
|
0
|
|
|
|
|
push @$ExtraSearchDirs, $ProgramDir if -d $ProgramDir; |
|
497
|
|
|
|
|
|
|
} |
|
498
|
|
|
|
|
|
|
|
|
499
|
0
|
0
|
|
|
|
|
if ($Module::Reload::Selective::Options->{SearchUserDir}) |
|
500
|
|
|
|
|
|
|
{ |
|
501
|
|
|
|
|
|
|
my $User = ($Module::Reload::Selective::Options->{User } || |
|
502
|
0
|
|
0
|
|
|
|
$Module::Reload::Selective::Options->{DefaultUser}); |
|
503
|
|
|
|
|
|
|
|
|
504
|
0
|
|
|
|
|
|
my $UsersProgrammingDir = $Module::Reload::Selective::Options->{UserDirTemplate}; |
|
505
|
0
|
|
|
|
|
|
$UsersProgrammingDir =~ s/\bUSER\b/$User/g; |
|
506
|
|
|
|
|
|
|
|
|
507
|
0
|
0
|
0
|
|
|
|
push @$ExtraSearchDirs, $UsersProgrammingDir if $User && -d $UsersProgrammingDir; |
|
508
|
|
|
|
|
|
|
} |
|
509
|
|
|
|
|
|
|
|
|
510
|
0
|
0
|
0
|
|
|
|
if ($Module::Reload::Selective::Options->{LastAdditionalPaths} && |
|
|
0
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
@{$Module::Reload::Selective::Options->{LastAdditionalPaths}}) |
|
512
|
|
|
|
|
|
|
{ |
|
513
|
0
|
|
|
|
|
|
push @$ExtraSearchDirs, @{$Module::Reload::Selective::Options->{LastAdditionalPaths}}; |
|
|
0
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
} |
|
515
|
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
## Prepend the ExtraSearchDirs to a local copy of @INC so they |
|
517
|
|
|
|
|
|
|
## will get searched in order before any of the places in |
|
518
|
|
|
|
|
|
|
## @INC. |
|
519
|
|
|
|
|
|
|
|
|
520
|
0
|
|
|
|
|
|
local @INC = @INC; |
|
521
|
0
|
|
|
|
|
|
unshift @INC, @$ExtraSearchDirs; |
|
522
|
|
|
|
|
|
|
|
|
523
|
0
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{INCArrayAfterModification} = [@INC]; |
|
524
|
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
## die &Dumper(\@INC, $ExtraSearchDirs, $Module::Reload::Selective::Options); |
|
526
|
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
## THEN MODIFY %INC TO REMOVE ANY MENTION OF ITEMS THAT MIGHT |
|
528
|
|
|
|
|
|
|
## NEED TO GET RELOADED.... |
|
529
|
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
## Before mucking with %INC, get a list of any installed perl |
|
531
|
|
|
|
|
|
|
## library modules that we don't want to muck with (any items |
|
532
|
|
|
|
|
|
|
## with "lib/perl" in the path).... or any other of a list of |
|
533
|
|
|
|
|
|
|
## path elements that should be disabled... |
|
534
|
|
|
|
|
|
|
|
|
535
|
0
|
|
|
|
|
|
my $DisabledPatterns = $Module::Reload::Selective::Options->{DontReloadIfPathContains}; |
|
536
|
|
|
|
|
|
|
|
|
537
|
0
|
|
|
|
|
|
my $DisabledItems = {}; |
|
538
|
0
|
|
|
|
|
|
foreach my $Pattern (@$DisabledPatterns) |
|
539
|
|
|
|
|
|
|
{ |
|
540
|
0
|
|
|
|
|
|
@$DisabledItems{grep {$INC{$_} =~ m|\Q$Pattern\E|} keys %INC} = undef; |
|
|
0
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
} |
|
542
|
0
|
|
|
|
|
|
@$DisabledItems{keys %$DisabledItems} = @INC{keys %$DisabledItems}; |
|
543
|
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
## die &Dumper($DisabledItems); |
|
545
|
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
## Empty out our private copy of %INC, so "require" doesn't |
|
547
|
|
|
|
|
|
|
## think any modules have yet been loaded. |
|
548
|
|
|
|
|
|
|
|
|
549
|
0
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{INCHashBefore} = {%INC}; |
|
550
|
0
|
|
|
|
|
|
local %INC = (); |
|
551
|
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
## Restore the disabled items in %INC so we don't reload those. |
|
553
|
|
|
|
|
|
|
|
|
554
|
0
|
|
|
|
|
|
@INC{keys %$DisabledItems} = values %$DisabledItems; |
|
555
|
|
|
|
|
|
|
## die &Dumper(\%INC); |
|
556
|
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
## THEN LOAD EACH OF THE REQUESTED MODULES... |
|
559
|
|
|
|
|
|
|
|
|
560
|
0
|
|
|
|
|
|
foreach my $PackageName (@PackageNames) |
|
561
|
|
|
|
|
|
|
{ |
|
562
|
|
|
|
|
|
|
|
|
563
|
0
|
|
|
|
|
|
(my $PackageRelPath = "$PackageName.pm") =~ s|::|/|g; |
|
564
|
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
## Many thanks to Doug MacEachern / Apache::StatINC for |
|
566
|
|
|
|
|
|
|
## this attempt turning of warnings for const subroutine |
|
567
|
|
|
|
|
|
|
## redefinitions, but I can't seem to get it to work, so it's commented out. |
|
568
|
|
|
|
|
|
|
|
|
569
|
|
|
|
|
|
|
## require Apache::Symbol; |
|
570
|
|
|
|
|
|
|
## my $Class = Apache::Symbol::file2class($PackageRelPath); |
|
571
|
|
|
|
|
|
|
## $Class->Apache::Symbol::undef_functions( undef, 1 ); |
|
572
|
|
|
|
|
|
|
|
|
573
|
0
|
|
|
|
|
|
require ($PackageRelPath); |
|
574
|
0
|
|
|
|
|
|
$ReturnVal = import $PackageName; |
|
575
|
|
|
|
|
|
|
} |
|
576
|
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
## TAKE A SNAPSHOT OF THE NEW %INC FOR LATER ANALYSIS... |
|
578
|
|
|
|
|
|
|
|
|
579
|
0
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{INCHashAfter} = {%INC}; |
|
580
|
0
|
|
|
|
|
|
delete @{$Module::Reload::Selective::Debug->{INCHashAfter}}{keys %$DisabledItems}; |
|
|
0
|
|
|
|
|
|
|
|
581
|
0
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{LastLoadTime} = localtime().''; |
|
582
|
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
## %INC and @INC WILL BE RESTORED HERE BY local %INC and local |
|
584
|
|
|
|
|
|
|
## @INC GOING OUT OF SCOPE... |
|
585
|
|
|
|
|
|
|
} |
|
586
|
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
## REGULAR MODE: Do the equivlaent of a "use", except that |
|
588
|
|
|
|
|
|
|
## semantics won't be imported into the caller's namespace. |
|
589
|
|
|
|
|
|
|
|
|
590
|
|
|
|
|
|
|
else |
|
591
|
|
|
|
|
|
|
{ |
|
592
|
0
|
|
|
|
|
|
foreach my $PackageName (@PackageNames) |
|
593
|
|
|
|
|
|
|
{ |
|
594
|
0
|
|
|
|
|
|
(my $PackageRelPath = "$PackageName.pm") =~ s|::|/|g; |
|
595
|
0
|
|
|
|
|
|
require ($PackageRelPath); |
|
596
|
0
|
|
|
|
|
|
$ReturnVal = import $PackageName; |
|
597
|
|
|
|
|
|
|
} |
|
598
|
|
|
|
|
|
|
|
|
599
|
0
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{Reload_Disabled_Because} = "No environment variables were set."; |
|
600
|
|
|
|
|
|
|
} |
|
601
|
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
done: |
|
603
|
|
|
|
|
|
|
|
|
604
|
|
|
|
|
|
|
## if %INC was messed with, we analyze the differences between the |
|
605
|
|
|
|
|
|
|
## before and after and set some derived hashes. |
|
606
|
|
|
|
|
|
|
|
|
607
|
0
|
0
|
0
|
|
|
|
if ($Module::Reload::Selective::Debug->{INCHashBefore} && |
|
608
|
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{INCHashAfter}) |
|
609
|
|
|
|
|
|
|
{ |
|
610
|
0
|
|
|
|
|
|
($Module::Reload::Selective::Debug->{NotReloaded}, |
|
611
|
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{NewlyLoaded}, |
|
612
|
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{Reloaded}) = |
|
613
|
|
|
|
|
|
|
CompareHashKeys($Module::Reload::Selective::Debug->{INCHashBefore}, |
|
614
|
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{INCHashAfter}); |
|
615
|
|
|
|
|
|
|
|
|
616
|
|
|
|
|
|
|
## CompareHashKeys leaves the values undefined; for |
|
617
|
|
|
|
|
|
|
## convenience, we pick up the values from the Before and |
|
618
|
|
|
|
|
|
|
## After hashes. |
|
619
|
|
|
|
|
|
|
|
|
620
|
0
|
|
|
|
|
|
foreach ($Module::Reload::Selective::Debug->{NotReloaded}, |
|
621
|
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{NewlyLoaded}, |
|
622
|
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{Reloaded}) |
|
623
|
|
|
|
|
|
|
{ |
|
624
|
0
|
0
|
|
|
|
|
@{$_}{keys %$_} = (map {($Module::Reload::Selective::Debug->{INCHashAfter }->{$_} || |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{INCHashBefore}->{$_})} keys %$_); |
|
626
|
|
|
|
|
|
|
} |
|
627
|
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
## Finally make another debugging hash of anything that got |
|
629
|
|
|
|
|
|
|
## loaded for any reason, whether newly, or re-loaded. |
|
630
|
|
|
|
|
|
|
|
|
631
|
0
|
|
|
|
|
|
$Module::Reload::Selective::Debug->{GotLoaded} = {}; |
|
632
|
0
|
|
|
|
|
|
@{$Module::Reload::Selective::Debug->{GotLoaded}}{keys %{$Module::Reload::Selective::Debug->{NewlyLoaded}}} = values %{$Module::Reload::Selective::Debug->{NewlyLoaded}}; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
633
|
0
|
|
|
|
|
|
@{$Module::Reload::Selective::Debug->{GotLoaded}}{keys %{$Module::Reload::Selective::Debug->{Reloaded }}} = values %{$Module::Reload::Selective::Debug->{Reloaded }}; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
## Copy entries for the items that changed into the non-local %INC hash. |
|
636
|
0
|
|
|
|
|
|
@INC{keys %{$Module::Reload::Selective::Debug->{GotLoaded}}} = values %{$Module::Reload::Selective::Debug->{GotLoaded}}; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
} |
|
639
|
|
|
|
|
|
|
|
|
640
|
0
|
|
|
|
|
|
return($ReturnVal); |
|
641
|
|
|
|
|
|
|
} |
|
642
|
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
######### Utility routines ########## |
|
646
|
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
sub CompareHashKeys |
|
648
|
|
|
|
|
|
|
{ |
|
649
|
0
|
|
|
0
|
0
|
|
my ($Hash1, $Hash2) = @_; |
|
650
|
|
|
|
|
|
|
|
|
651
|
0
|
|
|
|
|
|
my $In1NotIn2 = {}; @$In1NotIn2{keys %$Hash1 } = undef; delete @$In1NotIn2{keys %$Hash2 }; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
652
|
0
|
|
|
|
|
|
my $In2NotIn1 = {}; @$In2NotIn1{keys %$Hash2 } = undef; delete @$In2NotIn1{keys %$Hash1 }; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
653
|
0
|
|
|
|
|
|
my $Subset = {}; @$Subset {keys %$Hash1, keys %$Hash2} = undef; delete @$Subset {keys %$In1NotIn2, keys %$In2NotIn1}; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
|
|
655
|
0
|
|
|
|
|
|
return($In1NotIn2, $In2NotIn1, $Subset); |
|
656
|
|
|
|
|
|
|
} |
|
657
|
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
1; |