Ditch Carp::Clan for our own thing
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Optional / Dependencies.pm
CommitLineData
8057ed01 1package DBIx::Class::Optional::Dependencies;
2
3use warnings;
4use strict;
5
9c1700e3 6use Carp ();
fb39747c 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
9c1700e3 414 Carp::croak "req_list_for() expects a requirement group name"
fb39747c 415 unless $group;
416
f6b26571 417 my $deps = $reqs->{$group}{req}
9c1700e3 418 or Carp::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
9c1700e3 428 Carp::croak "req_ok_for() expects a requirement group name"
fb39747c 429 unless $group;
430
d8799bab 431 return $class->_check_deps($group)->{status};
fb39747c 432}
433
434sub req_missing_for {
435 my ($class, $group) = @_;
436
9c1700e3 437 Carp::croak "req_missing_for() expects a requirement group name"
fb39747c 438 unless $group;
439
d8799bab 440 return $class->_check_deps($group)->{missing};
fb39747c 441}
442
443sub req_errorlist_for {
444 my ($class, $group) = @_;
445
9c1700e3 446 Carp::croak "req_errorlist_for() expects a requirement group name"
fb39747c 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};
70c28808 476 $missing .= "\n";
d8799bab 477 $res = {
478 status => 0,
479 errorlist => \%errors,
480 missing => $missing,
481 };
fb39747c 482 }
483 else {
d8799bab 484 $res = {
485 status => 1,
486 errorlist => {},
487 missing => '',
488 };
fb39747c 489 }
490
d8799bab 491 $res;
492 };
fb39747c 493}
494
e3fc11e1 495sub req_group_list {
496 return { map { $_ => { %{ $reqs->{$_}{req} || {} } } } (keys %$reqs) };
497}
498
499# This is to be called by the author only (automatically in Makefile.PL)
f6b26571 500sub _gen_pod {
ccebe1f1 501 my ($class, $distver) = @_;
31fa1764 502
af4ac504 503 my $modfn = __PACKAGE__ . '.pm';
504 $modfn =~ s/\:\:/\//g;
f6b26571 505
31fa1764 506 my $podfn = __FILE__;
507 $podfn =~ s/\.pm$/\.pod/;
508
ccebe1f1 509 $distver ||=
31fa1764 510 eval { require DBIx::Class; DBIx::Class->VERSION; }
511 ||
ccebe1f1 512 die
31fa1764 513"\n\n---------------------------------------------------------------------\n" .
514'Unable to load core DBIx::Class module to determine current version, '.
515'possibly due to missing dependencies. Author-mode autodocumentation ' .
516"halted\n\n" . $@ .
517"\n\n---------------------------------------------------------------------\n"
31fa1764 518 ;
519
e3fc11e1 520 my $sqltver = $class->req_list_for ('deploy')->{'SQL::Translator'}
521 or die "Hrmm? No sqlt dep?";
7e3dc46f 522
f6b26571 523 my @chunks = (
d8799bab 524 <<'EOC',
af4ac504 525#########################################################################
526##################### A U T O G E N E R A T E D ########################
527#########################################################################
528#
529# The contents of this POD file are auto-generated. Any changes you make
530# will be lost. If you need to change the generated text edit _gen_pod()
531# at the end of $modfn
532#
533EOC
f6b26571 534 '=head1 NAME',
7e3dc46f 535 "$class - Optional module dependency specifications (for module authors)",
e3fc11e1 536 '=head1 SYNOPSIS',
d8799bab 537 <<"EOS",
7e3dc46f 538Somewhere in your build-file (e.g. L<Module::Install>'s Makefile.PL):
539
540 ...
541
542 configure_requires 'DBIx::Class' => '$distver';
543
544 require $class;
545
be68095d 546 my \$deploy_deps = $class->req_list_for('deploy');
7e3dc46f 547
548 for (keys %\$deploy_deps) {
549 requires \$_ => \$deploy_deps->{\$_};
550 }
551
552 ...
553
554Note that there are some caveats regarding C<configure_requires()>, more info
555can be found at L<Module::Install/configure_requires>
556EOS
f6b26571 557 '=head1 DESCRIPTION',
558 <<'EOD',
559Some of the less-frequently used features of L<DBIx::Class> have external
560module dependencies on their own. In order not to burden the average user
561with modules he will never use, these optional dependencies are not included
562in the base Makefile.PL. Instead an exception with a descriptive message is
563thrown when a specific feature is missing one or several modules required for
564its operation. This module is the central holding place for the current list
7e3dc46f 565of such dependencies, for DBIx::Class core authors, and DBIx::Class extension
566authors alike.
f6b26571 567EOD
568 '=head1 CURRENT REQUIREMENT GROUPS',
569 <<'EOD',
570Dependencies are organized in C<groups> and each group can list one or more
571required modules, with an optional minimum version (or 0 for any version).
ecb68746 572The group name can be used in the
f6b26571 573EOD
574 );
575
576 for my $group (sort keys %$reqs) {
577 my $p = $reqs->{$group}{pod}
578 or next;
579
580 my $modlist = $reqs->{$group}{req}
581 or next;
582
583 next unless keys %$modlist;
584
585 push @chunks, (
586 "=head2 $p->{title}",
587 "$p->{desc}",
588 '=over',
589 ( map { "=item * $_" . ($modlist->{$_} ? " >= $modlist->{$_}" : '') } (sort keys %$modlist) ),
590 '=back',
591 "Requirement group: B<$group>",
592 );
593 }
594
595 push @chunks, (
596 '=head1 METHODS',
e3fc11e1 597 '=head2 req_group_list',
598 '=over',
d8799bab 599 '=item Arguments: none',
e3fc11e1 600 '=item Returns: \%list_of_requirement_groups',
601 '=back',
d8799bab 602 <<'EOD',
e3fc11e1 603This method should be used by DBIx::Class packagers, to get a hashref of all
604dependencies keyed by dependency group. Each key (group name) can be supplied
605to one of the group-specific methods below.
606EOD
607
f6b26571 608 '=head2 req_list_for',
609 '=over',
610 '=item Arguments: $group_name',
611 '=item Returns: \%list_of_module_version_pairs',
612 '=back',
d8799bab 613 <<'EOD',
f6b26571 614This method should be used by DBIx::Class extension authors, to determine the
7e3dc46f 615version of modules a specific feature requires in the B<current> version of
e3fc11e1 616DBIx::Class. See the L</SYNOPSIS> for a real-world
7e3dc46f 617example.
f6b26571 618EOD
619
620 '=head2 req_ok_for',
621 '=over',
622 '=item Arguments: $group_name',
623 '=item Returns: 1|0',
624 '=back',
d8799bab 625 <<'EOD',
626Returns true or false depending on whether all modules required by
627C<$group_name> are present on the system and loadable.
628EOD
f6b26571 629
630 '=head2 req_missing_for',
631 '=over',
632 '=item Arguments: $group_name',
633 '=item Returns: $error_message_string',
634 '=back',
d8799bab 635 <<"EOD",
f6b26571 636Returns a single line string suitable for inclusion in larger error messages.
637This method would normally be used by DBIx::Class core-module author, to
638indicate to the user that he needs to install specific modules before he will
639be able to use a specific feature.
640
e3fc11e1 641For example if some of the requirements for C<deploy> are not available,
642the returned string could look like:
f6b26571 643
e3fc11e1 644 SQL::Translator >= $sqltver (see $class for details)
f6b26571 645
646The author is expected to prepend the necessary text to this message before
647returning the actual error seen by the user.
648EOD
649
650 '=head2 req_errorlist_for',
651 '=over',
652 '=item Arguments: $group_name',
653 '=item Returns: \%list_of_loaderrors_per_module',
654 '=back',
655 <<'EOD',
656Returns a hashref containing the actual errors that occured while attempting
657to load each module in the requirement group.
658EOD
fb8ae353 659 '=head1 AUTHOR',
660 'See L<DBIx::Class/CONTRIBUTORS>.',
661 '=head1 LICENSE',
662 'You may distribute this code under the same terms as Perl itself',
f6b26571 663 );
664
9c1700e3 665 open (my $fh, '>', $podfn) or Carp::croak "Unable to write to $podfn: $!";
f6b26571 666 print $fh join ("\n\n", @chunks);
667 close ($fh);
668}
669
8057ed01 6701;