add namespace::clean as regular dep
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Optional / Dependencies.pm
CommitLineData
8057ed01 1package DBIx::Class::Optional::Dependencies;
2
3use warnings;
4use strict;
5
fb39747c 6use Carp;
7
8# NO EXTERNAL NON-5.8.1 CORE DEPENDENCIES EVER (e.g. C::A::G)
8057ed01 9# This module is to be loaded by Makefile.PM on a pristine system
10
f6b26571 11# POD is generated automatically by calling _gen_pod from the
12# Makefile.PL in $AUTHOR mode
13
2b48ebff 14my $moose_basic = {
15 'Moose' => '0.98',
16 'MooseX::Types' => '0.21',
17};
18
ebcd0e4f 19my $admin_basic = {
20 %$moose_basic,
21 'MooseX::Types::Path::Class' => '0.05',
22 'MooseX::Types::JSON' => '0.02',
cba24c70 23 'JSON::Any' => '1.22',
ebcd0e4f 24 'namespace::autoclean' => '0.09',
ebcd0e4f 25};
26
8057ed01 27my $reqs = {
28 dist => {
29 #'Module::Install::Pod::Inherit' => '0.01',
30 },
31
32 replicated => {
f6b26571 33 req => {
2b48ebff 34 %$moose_basic,
e666c5fd 35 'Hash::Merge' => '0.12',
f6b26571 36 },
37 pod => {
38 title => 'Storage::Replicated',
39 desc => 'Modules required for L<DBIx::Class::Storage::DBI::Replicated>',
40 },
8057ed01 41 },
42
43 admin => {
2b48ebff 44 req => {
ebcd0e4f 45 %$admin_basic,
46 },
47 pod => {
48 title => 'DBIx::Class::Admin',
49 desc => 'Modules required for the DBIx::Class administrative library',
50 },
51 },
52
a4a02f15 53 admin_script => {
ebcd0e4f 54 req => {
2b48ebff 55 %$moose_basic,
ebcd0e4f 56 %$admin_basic,
2b48ebff 57 'Getopt::Long::Descriptive' => '0.081',
2b48ebff 58 'Text::CSV' => '1.16',
59 },
e144415f 60 pod => {
61 title => 'dbicadmin',
62 desc => 'Modules required for the CLI DBIx::Class interface dbicadmin',
63 },
8057ed01 64 },
65
66 deploy => {
f6b26571 67 req => {
270edb2b 68 'SQL::Translator' => '0.11005',
f6b26571 69 },
70 pod => {
71 title => 'Storage::DBI::deploy()',
72 desc => 'Modules required for L<DBIx::Class::Storage::DBI/deploy> and L<DBIx::Class::Storage::DBI/deploymen_statements>',
73 },
8057ed01 74 },
75
a109c954 76
77 test_pod => {
f6b26571 78 req => {
14d17d71 79 'Test::Pod' => '1.41',
a109c954 80 },
81 },
82
83 test_podcoverage => {
84 req => {
f6b26571 85 'Test::Pod::Coverage' => '1.08',
86 'Pod::Coverage' => '0.20',
a109c954 87 },
88 },
89
90 test_notabs => {
91 req => {
d146b340 92 'Test::NoTabs' => '0.9',
a109c954 93 },
94 },
95
96 test_eol => {
97 req => {
d146b340 98 'Test::EOL' => '0.6',
f6b26571 99 },
8057ed01 100 },
101
a109c954 102 test_cycle => {
f6b26571 103 req => {
f6b26571 104 'Test::Memory::Cycle' => '0',
105 'Devel::Cycle' => '1.10',
a109c954 106 },
107 },
f6b26571 108
a109c954 109 test_dtrelated => {
110 req => {
f6b26571 111 # t/36datetime.t
112 # t/60core.t
113 'DateTime::Format::SQLite' => '0',
114
115 # t/96_is_deteministic_value.t
116 'DateTime::Format::Strptime'=> '0',
9c92bb1c 117
118 # t/inflate/datetime_mysql.t
119 # (doesn't need Mysql itself)
120 'DateTime::Format::MySQL' => '0',
121
122 # t/inflate/datetime_pg.t
123 # (doesn't need PG itself)
124 'DateTime::Format::Pg' => '0',
f6b26571 125 },
8057ed01 126 },
127
128 cdbicompat => {
f6b26571 129 req => {
130 'DBIx::ContextualFetch' => '0',
131 'Class::DBI::Plugin::DeepAbstractSearch' => '0',
132 'Class::Trigger' => '0',
133 'Time::Piece::MySQL' => '0',
134 'Clone' => '0',
135 'Date::Simple' => '3.03',
136 },
8057ed01 137 },
138
139 rdbms_pg => {
f6b26571 140 req => {
141 $ENV{DBICTEST_PG_DSN}
142 ? (
143 'Sys::SigAction' => '0',
144 'DBD::Pg' => '2.009002',
f6b26571 145 ) : ()
146 },
8057ed01 147 },
148
149 rdbms_mysql => {
f6b26571 150 req => {
151 $ENV{DBICTEST_MYSQL_DSN}
152 ? (
f6b26571 153 'DBD::mysql' => '0',
154 ) : ()
155 },
8057ed01 156 },
157
158 rdbms_oracle => {
f6b26571 159 req => {
160 $ENV{DBICTEST_ORA_DSN}
161 ? (
162 'DateTime::Format::Oracle' => '0',
163 ) : ()
164 },
8057ed01 165 },
166
167 rdbms_ase => {
f6b26571 168 req => {
169 $ENV{DBICTEST_SYBASE_DSN}
170 ? (
171 'DateTime::Format::Sybase' => 0,
172 ) : ()
173 },
8057ed01 174 },
175
176 rdbms_asa => {
f6b26571 177 req => {
bf9ee8dc 178 (scalar grep { $ENV{$_} } (qw/DBICTEST_SYBASE_ASA_DSN DBICTEST_SYBASE_ASA_ODBC_DSN/) )
f6b26571 179 ? (
180 'DateTime::Format::Strptime' => 0,
181 ) : ()
182 },
8057ed01 183 },
f58a165c 184
185 rdbms_db2 => {
186 req => {
187 $ENV{DBICTEST_DB2_DSN}
188 ? (
189 'DBD::DB2' => 0,
190 ) : ()
191 },
192 },
193
8057ed01 194};
195
f6b26571 196
fb39747c 197sub req_list_for {
198 my ($class, $group) = @_;
199
f6b26571 200 croak "req_list_for() expects a requirement group name"
fb39747c 201 unless $group;
202
f6b26571 203 my $deps = $reqs->{$group}{req}
204 or croak "Requirement group '$group' does not exist";
fb39747c 205
206 return { %$deps };
207}
208
209
210our %req_availability_cache;
211sub req_ok_for {
212 my ($class, $group) = @_;
213
214 croak "req_ok_for() expects a requirement group name"
215 unless $group;
216
217 $class->_check_deps ($group) unless $req_availability_cache{$group};
218
219 return $req_availability_cache{$group}{status};
220}
221
222sub req_missing_for {
223 my ($class, $group) = @_;
224
225 croak "req_missing_for() expects a requirement group name"
226 unless $group;
227
228 $class->_check_deps ($group) unless $req_availability_cache{$group};
229
230 return $req_availability_cache{$group}{missing};
231}
232
233sub req_errorlist_for {
234 my ($class, $group) = @_;
235
236 croak "req_errorlist_for() expects a requirement group name"
237 unless $group;
238
239 $class->_check_deps ($group) unless $req_availability_cache{$group};
240
241 return $req_availability_cache{$group}{errorlist};
242}
243
244sub _check_deps {
245 my ($class, $group) = @_;
246
f6b26571 247 my $deps = $class->req_list_for ($group);
fb39747c 248
249 my %errors;
250 for my $mod (keys %$deps) {
251 if (my $ver = $deps->{$mod}) {
252 eval "use $mod $ver ()";
253 }
254 else {
255 eval "require $mod";
256 }
257
258 $errors{$mod} = $@ if $@;
259 }
260
261 if (keys %errors) {
f6b26571 262 my $missing = join (', ', map { $deps->{$_} ? "$_ >= $deps->{$_}" : $_ } (sort keys %errors) );
263 $missing .= " (see $class for details)" if $reqs->{$group}{pod};
fb39747c 264 $req_availability_cache{$group} = {
265 status => 0,
266 errorlist => { %errors },
f6b26571 267 missing => $missing,
fb39747c 268 };
269 }
270 else {
271 $req_availability_cache{$group} = {
272 status => 1,
273 errorlist => {},
274 missing => '',
275 };
276 }
277}
278
e3fc11e1 279sub req_group_list {
280 return { map { $_ => { %{ $reqs->{$_}{req} || {} } } } (keys %$reqs) };
281}
282
283# This is to be called by the author only (automatically in Makefile.PL)
f6b26571 284sub _gen_pod {
31fa1764 285
f6b26571 286 my $class = shift;
af4ac504 287 my $modfn = __PACKAGE__ . '.pm';
288 $modfn =~ s/\:\:/\//g;
f6b26571 289
31fa1764 290 my $podfn = __FILE__;
291 $podfn =~ s/\.pm$/\.pod/;
292
293 my $distver =
294 eval { require DBIx::Class; DBIx::Class->VERSION; }
295 ||
296 do {
297 warn
298"\n\n---------------------------------------------------------------------\n" .
299'Unable to load core DBIx::Class module to determine current version, '.
300'possibly due to missing dependencies. Author-mode autodocumentation ' .
301"halted\n\n" . $@ .
302"\n\n---------------------------------------------------------------------\n"
303 ;
304 '*UNKNOWN*'; # rv
305 }
306 ;
307
e3fc11e1 308 my $sqltver = $class->req_list_for ('deploy')->{'SQL::Translator'}
309 or die "Hrmm? No sqlt dep?";
7e3dc46f 310
f6b26571 311 my @chunks = (
af4ac504 312 <<"EOC",
313#########################################################################
314##################### A U T O G E N E R A T E D ########################
315#########################################################################
316#
317# The contents of this POD file are auto-generated. Any changes you make
318# will be lost. If you need to change the generated text edit _gen_pod()
319# at the end of $modfn
320#
321EOC
f6b26571 322 '=head1 NAME',
7e3dc46f 323 "$class - Optional module dependency specifications (for module authors)",
e3fc11e1 324 '=head1 SYNOPSIS',
7e3dc46f 325 <<EOS,
7e3dc46f 326Somewhere in your build-file (e.g. L<Module::Install>'s Makefile.PL):
327
328 ...
329
330 configure_requires 'DBIx::Class' => '$distver';
331
332 require $class;
333
334 my \$deploy_deps = $class->req_list_for ('deploy');
335
336 for (keys %\$deploy_deps) {
337 requires \$_ => \$deploy_deps->{\$_};
338 }
339
340 ...
341
342Note that there are some caveats regarding C<configure_requires()>, more info
343can be found at L<Module::Install/configure_requires>
344EOS
f6b26571 345 '=head1 DESCRIPTION',
346 <<'EOD',
347Some of the less-frequently used features of L<DBIx::Class> have external
348module dependencies on their own. In order not to burden the average user
349with modules he will never use, these optional dependencies are not included
350in the base Makefile.PL. Instead an exception with a descriptive message is
351thrown when a specific feature is missing one or several modules required for
352its operation. This module is the central holding place for the current list
7e3dc46f 353of such dependencies, for DBIx::Class core authors, and DBIx::Class extension
354authors alike.
f6b26571 355EOD
356 '=head1 CURRENT REQUIREMENT GROUPS',
357 <<'EOD',
358Dependencies are organized in C<groups> and each group can list one or more
359required modules, with an optional minimum version (or 0 for any version).
ecb68746 360The group name can be used in the
f6b26571 361EOD
362 );
363
364 for my $group (sort keys %$reqs) {
365 my $p = $reqs->{$group}{pod}
366 or next;
367
368 my $modlist = $reqs->{$group}{req}
369 or next;
370
371 next unless keys %$modlist;
372
373 push @chunks, (
374 "=head2 $p->{title}",
375 "$p->{desc}",
376 '=over',
377 ( map { "=item * $_" . ($modlist->{$_} ? " >= $modlist->{$_}" : '') } (sort keys %$modlist) ),
378 '=back',
379 "Requirement group: B<$group>",
380 );
381 }
382
383 push @chunks, (
384 '=head1 METHODS',
e3fc11e1 385 '=head2 req_group_list',
386 '=over',
387 '=item Arguments: $none',
388 '=item Returns: \%list_of_requirement_groups',
389 '=back',
390 <<EOD,
391This method should be used by DBIx::Class packagers, to get a hashref of all
392dependencies keyed by dependency group. Each key (group name) can be supplied
393to one of the group-specific methods below.
394EOD
395
f6b26571 396 '=head2 req_list_for',
397 '=over',
398 '=item Arguments: $group_name',
399 '=item Returns: \%list_of_module_version_pairs',
400 '=back',
401 <<EOD,
402This method should be used by DBIx::Class extension authors, to determine the
7e3dc46f 403version of modules a specific feature requires in the B<current> version of
e3fc11e1 404DBIx::Class. See the L</SYNOPSIS> for a real-world
7e3dc46f 405example.
f6b26571 406EOD
407
408 '=head2 req_ok_for',
409 '=over',
410 '=item Arguments: $group_name',
411 '=item Returns: 1|0',
412 '=back',
af4ac504 413 'Returns true or false depending on whether all modules required by C<$group_name> are present on the system and loadable',
f6b26571 414
415 '=head2 req_missing_for',
416 '=over',
417 '=item Arguments: $group_name',
418 '=item Returns: $error_message_string',
419 '=back',
420 <<EOD,
421Returns a single line string suitable for inclusion in larger error messages.
422This method would normally be used by DBIx::Class core-module author, to
423indicate to the user that he needs to install specific modules before he will
424be able to use a specific feature.
425
e3fc11e1 426For example if some of the requirements for C<deploy> are not available,
427the returned string could look like:
f6b26571 428
e3fc11e1 429 SQL::Translator >= $sqltver (see $class for details)
f6b26571 430
431The author is expected to prepend the necessary text to this message before
432returning the actual error seen by the user.
433EOD
434
435 '=head2 req_errorlist_for',
436 '=over',
437 '=item Arguments: $group_name',
438 '=item Returns: \%list_of_loaderrors_per_module',
439 '=back',
440 <<'EOD',
441Returns a hashref containing the actual errors that occured while attempting
442to load each module in the requirement group.
443EOD
fb8ae353 444 '=head1 AUTHOR',
445 'See L<DBIx::Class/CONTRIBUTORS>.',
446 '=head1 LICENSE',
447 'You may distribute this code under the same terms as Perl itself',
f6b26571 448 );
449
31fa1764 450 open (my $fh, '>', $podfn) or croak "Unable to write to $podfn: $!";
f6b26571 451 print $fh join ("\n\n", @chunks);
452 close ($fh);
453}
454
8057ed01 4551;