Make sure the component_class autoloader works across module reloads
[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
2a2a7b23 14my $json_any = {
15 'JSON::Any' => '1.22',
16};
17
2b48ebff 18my $moose_basic = {
68de9438 19 'Moose' => '0.98',
20 'MooseX::Types' => '0.21',
21};
22
23my $replicated = {
24 %$moose_basic,
2b48ebff 25};
26
ebcd0e4f 27my $admin_basic = {
28 %$moose_basic,
2a2a7b23 29 %$json_any,
68de9438 30 'MooseX::Types::Path::Class' => '0.05',
31 'MooseX::Types::JSON' => '0.02',
68de9438 32 'namespace::autoclean' => '0.09',
33};
34
35my $datetime_basic = {
36 'DateTime' => '0.55',
37 'DateTime::Format::Strptime' => '1.2',
ebcd0e4f 38};
39
c7d50a7d 40my $id_shortener = {
41 'Math::BigInt' => '1.89',
42 'Math::Base36' => '0.07',
43};
44
be68095d 45my $rdbms_sqlite = {
46 'DBD::SQLite' => '0',
47};
48my $rdbms_pg = {
49 'DBD::Pg' => '0',
50};
51my $rdbms_mssql_odbc = {
52 'DBD::ODBC' => '0',
53};
54my $rdbms_mssql_sybase = {
55 'DBD::Sybase' => '0',
56};
56dca25f 57my $rdbms_mssql_ado = {
58 'DBD::ADO' => '0',
59};
be68095d 60my $rdbms_mysql = {
61 'DBD::mysql' => '0',
62};
63my $rdbms_oracle = {
64 'DBD::Oracle' => '0',
65 %$id_shortener,
66};
67my $rdbms_ase = {
68 'DBD::Sybase' => '0',
69};
70my $rdbms_db2 = {
71 'DBD::DB2' => '0',
72};
e02b39b4 73my $rdbms_firebird_odbc = {
74 'DBD::ODBC' => '0',
75};
be68095d 76
8057ed01 77my $reqs = {
78 dist => {
79 #'Module::Install::Pod::Inherit' => '0.01',
80 },
81
82 replicated => {
68de9438 83 req => $replicated,
f6b26571 84 pod => {
85 title => 'Storage::Replicated',
86 desc => 'Modules required for L<DBIx::Class::Storage::DBI::Replicated>',
87 },
8057ed01 88 },
89
68de9438 90 test_replicated => {
91 req => {
92 %$replicated,
93 'Test::Moose' => '0',
94 },
95 },
96
97
8057ed01 98 admin => {
2b48ebff 99 req => {
ebcd0e4f 100 %$admin_basic,
101 },
102 pod => {
103 title => 'DBIx::Class::Admin',
104 desc => 'Modules required for the DBIx::Class administrative library',
105 },
106 },
107
a4a02f15 108 admin_script => {
ebcd0e4f 109 req => {
2b48ebff 110 %$moose_basic,
ebcd0e4f 111 %$admin_basic,
2b48ebff 112 'Getopt::Long::Descriptive' => '0.081',
2b48ebff 113 'Text::CSV' => '1.16',
114 },
e144415f 115 pod => {
116 title => 'dbicadmin',
117 desc => 'Modules required for the CLI DBIx::Class interface dbicadmin',
118 },
8057ed01 119 },
120
121 deploy => {
f6b26571 122 req => {
9e34d554 123 'SQL::Translator' => '0.11006',
f6b26571 124 },
125 pod => {
126 title => 'Storage::DBI::deploy()',
c7d50a7d 127 desc => 'Modules required for L<DBIx::Class::Storage::DBI/deploy> and L<DBIx::Class::Storage::DBI/deployment_statements>',
f6b26571 128 },
8057ed01 129 },
130
c7d50a7d 131 id_shortener => {
132 req => $id_shortener,
133 },
134
0d374214 135 test_component_accessor => {
136 req => {
137 'Class::Unload' => '0.07',
138 },
139 },
140
a109c954 141 test_pod => {
f6b26571 142 req => {
14d17d71 143 'Test::Pod' => '1.41',
a109c954 144 },
145 },
146
147 test_podcoverage => {
148 req => {
f6b26571 149 'Test::Pod::Coverage' => '1.08',
150 'Pod::Coverage' => '0.20',
a109c954 151 },
152 },
153
154 test_notabs => {
155 req => {
d146b340 156 'Test::NoTabs' => '0.9',
a109c954 157 },
158 },
159
160 test_eol => {
161 req => {
d146b340 162 'Test::EOL' => '0.6',
f6b26571 163 },
8057ed01 164 },
165
2a2a7b23 166 test_prettydebug => {
167 req => $json_any,
168 },
169
226d1c35 170 test_leaks => {
f6b26571 171 req => {
f6b26571 172 'Test::Memory::Cycle' => '0',
173 'Devel::Cycle' => '1.10',
a109c954 174 },
175 },
f6b26571 176
68de9438 177 test_dt => {
178 req => $datetime_basic,
179 },
180
181 test_dt_sqlite => {
a109c954 182 req => {
68de9438 183 %$datetime_basic,
f6b26571 184 # t/36datetime.t
185 # t/60core.t
186 'DateTime::Format::SQLite' => '0',
68de9438 187 },
188 },
f6b26571 189
68de9438 190 test_dt_mysql => {
191 req => {
192 %$datetime_basic,
9c92bb1c 193 # t/inflate/datetime_mysql.t
194 # (doesn't need Mysql itself)
68de9438 195 'DateTime::Format::MySQL' => '0',
196 },
197 },
9c92bb1c 198
68de9438 199 test_dt_pg => {
200 req => {
201 %$datetime_basic,
9c92bb1c 202 # t/inflate/datetime_pg.t
203 # (doesn't need PG itself)
ab35aeab 204 'DateTime::Format::Pg' => '0.16004',
f6b26571 205 },
8057ed01 206 },
207
68de9438 208 test_cdbicompat => {
f6b26571 209 req => {
210 'DBIx::ContextualFetch' => '0',
211 'Class::DBI::Plugin::DeepAbstractSearch' => '0',
212 'Class::Trigger' => '0',
213 'Time::Piece::MySQL' => '0',
214 'Clone' => '0',
215 'Date::Simple' => '3.03',
216 },
8057ed01 217 },
218
be68095d 219 # this is just for completeness as SQLite
220 # is a core dep of DBIC for testing
221 rdbms_sqlite => {
222 req => {
223 %$rdbms_sqlite,
224 },
225 pod => {
226 title => 'SQLite support',
227 desc => 'Modules required to connect to SQLite',
228 },
229 },
230
231 rdbms_pg => {
232 req => {
233 %$rdbms_pg,
234 },
235 pod => {
236 title => 'PostgreSQL support',
237 desc => 'Modules required to connect to PostgreSQL',
238 },
239 },
240
241 rdbms_mssql_odbc => {
242 req => {
243 %$rdbms_mssql_odbc,
244 },
245 pod => {
246 title => 'MSSQL support via DBD::ODBC',
247 desc => 'Modules required to connect to MSSQL via DBD::ODBC',
248 },
249 },
250
251 rdbms_mssql_sybase => {
252 req => {
253 %$rdbms_mssql_sybase,
254 },
255 pod => {
256 title => 'MSSQL support via DBD::Sybase',
56dca25f 257 desc => 'Modules required to connect to MSSQL via DBD::Sybase',
258 },
259 },
260
261 rdbms_mssql_ado => {
262 req => {
263 %$rdbms_mssql_ado,
264 },
265 pod => {
266 title => 'MSSQL support via DBD::ADO (Windows only)',
267 desc => 'Modules required to connect to MSSQL via DBD::ADO. This particular DBD is available on Windows only',
be68095d 268 },
269 },
270
271 rdbms_mysql => {
272 req => {
273 %$rdbms_mysql,
274 },
275 pod => {
276 title => 'MySQL support',
277 desc => 'Modules required to connect to MySQL',
278 },
279 },
280
281 rdbms_oracle => {
282 req => {
283 %$rdbms_oracle,
284 },
285 pod => {
286 title => 'Oracle support',
287 desc => 'Modules required to connect to Oracle',
288 },
289 },
290
291 rdbms_ase => {
292 req => {
293 %$rdbms_ase,
294 },
295 pod => {
296 title => 'Sybase ASE support',
297 desc => 'Modules required to connect to Sybase ASE',
298 },
299 },
300
301 rdbms_db2 => {
302 req => {
303 %$rdbms_db2,
304 },
305 pod => {
306 title => 'DB2 support',
307 desc => 'Modules required to connect to DB2',
308 },
309 },
310
311# the order does matter because the rdbms support group might require
312# a different version that the test group
68de9438 313 test_rdbms_pg => {
f6b26571 314 req => {
315 $ENV{DBICTEST_PG_DSN}
316 ? (
be68095d 317 %$rdbms_pg,
f6b26571 318 'Sys::SigAction' => '0',
319 'DBD::Pg' => '2.009002',
f6b26571 320 ) : ()
321 },
8057ed01 322 },
323
afae8507 324 test_rdbms_mssql_odbc => {
325 req => {
326 $ENV{DBICTEST_MSSQL_ODBC_DSN}
327 ? (
be68095d 328 %$rdbms_mssql_odbc,
afae8507 329 ) : ()
330 },
331 },
332
56dca25f 333 test_rdbms_mssql_ado => {
334 req => {
335 $ENV{DBICTEST_MSSQL_ADO_DSN}
336 ? (
337 %$rdbms_mssql_ado,
338 ) : ()
339 },
340 },
341
afae8507 342 test_rdbms_mssql_sybase => {
343 req => {
344 $ENV{DBICTEST_MSSQL_DSN}
345 ? (
be68095d 346 %$rdbms_mssql_sybase,
afae8507 347 ) : ()
348 },
349 },
350
68de9438 351 test_rdbms_mysql => {
f6b26571 352 req => {
353 $ENV{DBICTEST_MYSQL_DSN}
354 ? (
be68095d 355 %$rdbms_mysql,
f6b26571 356 ) : ()
357 },
8057ed01 358 },
359
68de9438 360 test_rdbms_oracle => {
f6b26571 361 req => {
362 $ENV{DBICTEST_ORA_DSN}
363 ? (
be68095d 364 %$rdbms_oracle,
f6b26571 365 'DateTime::Format::Oracle' => '0',
e1b7e9b4 366 'DBD::Oracle' => '1.24',
f6b26571 367 ) : ()
368 },
8057ed01 369 },
370
68de9438 371 test_rdbms_ase => {
f6b26571 372 req => {
373 $ENV{DBICTEST_SYBASE_DSN}
374 ? (
be68095d 375 %$rdbms_ase,
376 'DateTime::Format::Sybase' => '0',
f6b26571 377 ) : ()
378 },
8057ed01 379 },
380
68de9438 381 test_rdbms_db2 => {
f58a165c 382 req => {
383 $ENV{DBICTEST_DB2_DSN}
384 ? (
be68095d 385 %$rdbms_db2,
f58a165c 386 ) : ()
387 },
388 },
389
e02b39b4 390 test_rdbms_firebird_odbc => {
391 req => {
392 $ENV{DBICTEST_FIREBIRD_ODBC_DSN}
393 ? (
394 %$rdbms_firebird_odbc,
395 ) : ()
396 },
397 },
398
42168332 399 test_memcached => {
400 req => {
401 $ENV{DBICTEST_MEMCACHED}
402 ? (
403 'Cache::Memcached' => 0,
404 ) : ()
405 },
406 },
407
8057ed01 408};
409
f6b26571 410
fb39747c 411sub req_list_for {
412 my ($class, $group) = @_;
413
f6b26571 414 croak "req_list_for() expects a requirement group name"
fb39747c 415 unless $group;
416
f6b26571 417 my $deps = $reqs->{$group}{req}
418 or croak "Requirement group '$group' does not exist";
fb39747c 419
420 return { %$deps };
421}
422
423
424our %req_availability_cache;
425sub req_ok_for {
426 my ($class, $group) = @_;
427
428 croak "req_ok_for() expects a requirement group name"
429 unless $group;
430
d8799bab 431 return $class->_check_deps($group)->{status};
fb39747c 432}
433
434sub req_missing_for {
435 my ($class, $group) = @_;
436
437 croak "req_missing_for() expects a requirement group name"
438 unless $group;
439
d8799bab 440 return $class->_check_deps($group)->{missing};
fb39747c 441}
442
443sub req_errorlist_for {
444 my ($class, $group) = @_;
445
446 croak "req_errorlist_for() expects a requirement group name"
447 unless $group;
448
d8799bab 449 return $class->_check_deps($group)->{errorlist};
fb39747c 450}
451
452sub _check_deps {
453 my ($class, $group) = @_;
454
d8799bab 455 return $req_availability_cache{$group} ||= do {
456
457 my $deps = $class->req_list_for ($group);
458
459 my %errors;
460 for my $mod (keys %$deps) {
461 my $req_line = "require $mod;";
462 if (my $ver = $deps->{$mod}) {
463 $req_line .= "$mod->VERSION($ver);";
464 }
465
466 eval $req_line;
467
468 $errors{$mod} = $@ if $@;
469 }
470
471 my $res;
fb39747c 472
d8799bab 473 if (keys %errors) {
474 my $missing = join (', ', map { $deps->{$_} ? "$_ >= $deps->{$_}" : $_ } (sort keys %errors) );
475 $missing .= " (see $class for details)" if $reqs->{$group}{pod};
476 $res = {
477 status => 0,
478 errorlist => \%errors,
479 missing => $missing,
480 };
fb39747c 481 }
482 else {
d8799bab 483 $res = {
484 status => 1,
485 errorlist => {},
486 missing => '',
487 };
fb39747c 488 }
489
d8799bab 490 $res;
491 };
fb39747c 492}
493
e3fc11e1 494sub req_group_list {
495 return { map { $_ => { %{ $reqs->{$_}{req} || {} } } } (keys %$reqs) };
496}
497
498# This is to be called by the author only (automatically in Makefile.PL)
f6b26571 499sub _gen_pod {
ccebe1f1 500 my ($class, $distver) = @_;
31fa1764 501
af4ac504 502 my $modfn = __PACKAGE__ . '.pm';
503 $modfn =~ s/\:\:/\//g;
f6b26571 504
31fa1764 505 my $podfn = __FILE__;
506 $podfn =~ s/\.pm$/\.pod/;
507
ccebe1f1 508 $distver ||=
31fa1764 509 eval { require DBIx::Class; DBIx::Class->VERSION; }
510 ||
ccebe1f1 511 die
31fa1764 512"\n\n---------------------------------------------------------------------\n" .
513'Unable to load core DBIx::Class module to determine current version, '.
514'possibly due to missing dependencies. Author-mode autodocumentation ' .
515"halted\n\n" . $@ .
516"\n\n---------------------------------------------------------------------\n"
31fa1764 517 ;
518
e3fc11e1 519 my $sqltver = $class->req_list_for ('deploy')->{'SQL::Translator'}
520 or die "Hrmm? No sqlt dep?";
7e3dc46f 521
f6b26571 522 my @chunks = (
d8799bab 523 <<'EOC',
af4ac504 524#########################################################################
525##################### A U T O G E N E R A T E D ########################
526#########################################################################
527#
528# The contents of this POD file are auto-generated. Any changes you make
529# will be lost. If you need to change the generated text edit _gen_pod()
530# at the end of $modfn
531#
532EOC
f6b26571 533 '=head1 NAME',
7e3dc46f 534 "$class - Optional module dependency specifications (for module authors)",
e3fc11e1 535 '=head1 SYNOPSIS',
d8799bab 536 <<"EOS",
7e3dc46f 537Somewhere in your build-file (e.g. L<Module::Install>'s Makefile.PL):
538
539 ...
540
541 configure_requires 'DBIx::Class' => '$distver';
542
543 require $class;
544
be68095d 545 my \$deploy_deps = $class->req_list_for('deploy');
7e3dc46f 546
547 for (keys %\$deploy_deps) {
548 requires \$_ => \$deploy_deps->{\$_};
549 }
550
551 ...
552
553Note that there are some caveats regarding C<configure_requires()>, more info
554can be found at L<Module::Install/configure_requires>
555EOS
f6b26571 556 '=head1 DESCRIPTION',
557 <<'EOD',
558Some of the less-frequently used features of L<DBIx::Class> have external
559module dependencies on their own. In order not to burden the average user
560with modules he will never use, these optional dependencies are not included
561in the base Makefile.PL. Instead an exception with a descriptive message is
562thrown when a specific feature is missing one or several modules required for
563its operation. This module is the central holding place for the current list
7e3dc46f 564of such dependencies, for DBIx::Class core authors, and DBIx::Class extension
565authors alike.
f6b26571 566EOD
567 '=head1 CURRENT REQUIREMENT GROUPS',
568 <<'EOD',
569Dependencies are organized in C<groups> and each group can list one or more
570required modules, with an optional minimum version (or 0 for any version).
ecb68746 571The group name can be used in the
f6b26571 572EOD
573 );
574
575 for my $group (sort keys %$reqs) {
576 my $p = $reqs->{$group}{pod}
577 or next;
578
579 my $modlist = $reqs->{$group}{req}
580 or next;
581
582 next unless keys %$modlist;
583
584 push @chunks, (
585 "=head2 $p->{title}",
586 "$p->{desc}",
587 '=over',
588 ( map { "=item * $_" . ($modlist->{$_} ? " >= $modlist->{$_}" : '') } (sort keys %$modlist) ),
589 '=back',
590 "Requirement group: B<$group>",
591 );
592 }
593
594 push @chunks, (
595 '=head1 METHODS',
e3fc11e1 596 '=head2 req_group_list',
597 '=over',
d8799bab 598 '=item Arguments: none',
e3fc11e1 599 '=item Returns: \%list_of_requirement_groups',
600 '=back',
d8799bab 601 <<'EOD',
e3fc11e1 602This method should be used by DBIx::Class packagers, to get a hashref of all
603dependencies keyed by dependency group. Each key (group name) can be supplied
604to one of the group-specific methods below.
605EOD
606
f6b26571 607 '=head2 req_list_for',
608 '=over',
609 '=item Arguments: $group_name',
610 '=item Returns: \%list_of_module_version_pairs',
611 '=back',
d8799bab 612 <<'EOD',
f6b26571 613This method should be used by DBIx::Class extension authors, to determine the
7e3dc46f 614version of modules a specific feature requires in the B<current> version of
e3fc11e1 615DBIx::Class. See the L</SYNOPSIS> for a real-world
7e3dc46f 616example.
f6b26571 617EOD
618
619 '=head2 req_ok_for',
620 '=over',
621 '=item Arguments: $group_name',
622 '=item Returns: 1|0',
623 '=back',
d8799bab 624 <<'EOD',
625Returns true or false depending on whether all modules required by
626C<$group_name> are present on the system and loadable.
627EOD
f6b26571 628
629 '=head2 req_missing_for',
630 '=over',
631 '=item Arguments: $group_name',
632 '=item Returns: $error_message_string',
633 '=back',
d8799bab 634 <<"EOD",
f6b26571 635Returns a single line string suitable for inclusion in larger error messages.
636This method would normally be used by DBIx::Class core-module author, to
637indicate to the user that he needs to install specific modules before he will
638be able to use a specific feature.
639
e3fc11e1 640For example if some of the requirements for C<deploy> are not available,
641the returned string could look like:
f6b26571 642
e3fc11e1 643 SQL::Translator >= $sqltver (see $class for details)
f6b26571 644
645The author is expected to prepend the necessary text to this message before
646returning the actual error seen by the user.
647EOD
648
649 '=head2 req_errorlist_for',
650 '=over',
651 '=item Arguments: $group_name',
652 '=item Returns: \%list_of_loaderrors_per_module',
653 '=back',
654 <<'EOD',
655Returns a hashref containing the actual errors that occured while attempting
656to load each module in the requirement group.
657EOD
fb8ae353 658 '=head1 AUTHOR',
659 'See L<DBIx::Class/CONTRIBUTORS>.',
660 '=head1 LICENSE',
661 'You may distribute this code under the same terms as Perl itself',
f6b26571 662 );
663
31fa1764 664 open (my $fh, '>', $podfn) or croak "Unable to write to $podfn: $!";
f6b26571 665 print $fh join ("\n\n", @chunks);
666 close ($fh);
667}
668
8057ed01 6691;