Move the SQLite test dependency specification to optdeps
[dbsrgits/DBIx-Class-Historic.git] / lib / DBIx / Class / Optional / Dependencies.pm
CommitLineData
8057ed01 1package DBIx::Class::Optional::Dependencies;
2
cb551b07 3### This may look crazy, but it in fact tangibly ( by 50(!)% ) shortens
4# the skip-test time when everything requested is unavailable
5use if $ENV{RELEASE_TESTING} => 'warnings';
6use if $ENV{RELEASE_TESTING} => 'strict';
7
8sub croak {
9 require Carp;
10 Carp::croak(@_);
11};
12###
fb39747c 13
14# NO EXTERNAL NON-5.8.1 CORE DEPENDENCIES EVER (e.g. C::A::G)
8057ed01 15# This module is to be loaded by Makefile.PM on a pristine system
16
f6b26571 17# POD is generated automatically by calling _gen_pod from the
18# Makefile.PL in $AUTHOR mode
19
3ade80ee 20# NOTE: the rationale for 2 JSON::Any versions is that
21# we need the newer only to work around JSON::XS, which
22# itself is an optional dep
23my $min_json_any = {
be855469 24 'JSON::Any' => '1.23',
2a2a7b23 25};
3ade80ee 26my $test_and_dist_json_any = {
27 'JSON::Any' => '1.31',
28};
2a2a7b23 29
2b48ebff 30my $moose_basic = {
68de9438 31 'Moose' => '0.98',
32 'MooseX::Types' => '0.21',
d401ab6b 33 'MooseX::Types::LoadableClass' => '0.011',
68de9438 34};
35
31c31b8d 36my $dbic_reqs = {
8057ed01 37 replicated => {
e163f484 38 req => $moose_basic,
f6b26571 39 pod => {
40 title => 'Storage::Replicated',
41 desc => 'Modules required for L<DBIx::Class::Storage::DBI::Replicated>',
42 },
8057ed01 43 },
44
68de9438 45 test_replicated => {
e163f484 46 include => 'replicated',
68de9438 47 req => {
e163f484 48 'Test::Moose' => '0',
68de9438 49 },
50 },
51
8057ed01 52 admin => {
2b48ebff 53 req => {
e163f484 54 %$moose_basic,
55 %$min_json_any,
56 'MooseX::Types::Path::Class' => '0.05',
57 'MooseX::Types::JSON' => '0.02',
ebcd0e4f 58 },
59 pod => {
60 title => 'DBIx::Class::Admin',
61 desc => 'Modules required for the DBIx::Class administrative library',
62 },
63 },
64
a4a02f15 65 admin_script => {
e163f484 66 include => 'admin',
ebcd0e4f 67 req => {
e163f484 68 'Getopt::Long::Descriptive' => '0.081',
69 'Text::CSV' => '1.16',
2b48ebff 70 },
e144415f 71 pod => {
72 title => 'dbicadmin',
73 desc => 'Modules required for the CLI DBIx::Class interface dbicadmin',
74 },
8057ed01 75 },
76
77 deploy => {
f6b26571 78 req => {
08ac7648 79 'SQL::Translator' => '0.11018',
f6b26571 80 },
81 pod => {
82 title => 'Storage::DBI::deploy()',
5529838f 83 desc => 'Modules required for L<DBIx::Class::Storage::DBI/deployment_statements> and L<DBIx::Class::Schema/deploy>',
f6b26571 84 },
8057ed01 85 },
86
c7d50a7d 87 id_shortener => {
e163f484 88 req => {
89 'Math::BigInt' => '1.80',
90 'Math::Base36' => '0.07',
91 },
c7d50a7d 92 },
93
0d374214 94 test_component_accessor => {
95 req => {
96 'Class::Unload' => '0.07',
97 },
98 },
99
a109c954 100 test_pod => {
f6b26571 101 req => {
cbb19edf 102 'Test::Pod' => '1.42',
a109c954 103 },
cb551b07 104 release_testing_mandatory => 1,
a109c954 105 },
106
107 test_podcoverage => {
108 req => {
f6b26571 109 'Test::Pod::Coverage' => '1.08',
110 'Pod::Coverage' => '0.20',
a109c954 111 },
cb551b07 112 release_testing_mandatory => 1,
a109c954 113 },
114
ffce4b65 115 test_whitespace => {
a109c954 116 req => {
8273e845 117 'Test::EOL' => '1.0',
ffce4b65 118 'Test::NoTabs' => '0.9',
f6b26571 119 },
cb551b07 120 release_testing_mandatory => 1,
8057ed01 121 },
122
4a233f30 123 test_strictures => {
124 req => {
b2c1212f 125 'Test::Strict' => '0.20',
4a233f30 126 },
cb551b07 127 release_testing_mandatory => 1,
4a233f30 128 },
129
2a2a7b23 130 test_prettydebug => {
3ade80ee 131 req => $min_json_any,
2a2a7b23 132 },
133
99503754 134 test_admin_script => {
e163f484 135 include => 'admin_script',
99503754 136 req => {
3ade80ee 137 %$test_and_dist_json_any,
99503754 138 'JSON' => 0,
be855469 139 'JSON::PP' => 0,
140 'Cpanel::JSON::XS' => 0,
99503754 141 'JSON::XS' => 0,
142 $^O eq 'MSWin32'
143 # for t/admin/10script.t
144 ? ('Win32::ShellQuote' => 0)
145 # DWIW does not compile (./configure even) on win32
146 : ('JSON::DWIW' => 0 )
147 ,
148 }
149 },
150
556c4fe6 151 test_leaks_heavy => {
f6b26571 152 req => {
556c4fe6 153 'Class::MethodCache' => '0.02',
154 'PadWalker' => '1.06',
a109c954 155 },
156 },
f6b26571 157
68de9438 158 test_dt => {
e163f484 159 req => {
160 'DateTime' => '0.55',
161 'DateTime::Format::Strptime' => '1.2',
162 },
68de9438 163 },
164
165 test_dt_sqlite => {
e163f484 166 include => 'test_dt',
a109c954 167 req => {
f6b26571 168 # t/36datetime.t
169 # t/60core.t
170 'DateTime::Format::SQLite' => '0',
68de9438 171 },
172 },
f6b26571 173
68de9438 174 test_dt_mysql => {
e163f484 175 include => 'test_dt',
68de9438 176 req => {
9c92bb1c 177 # t/inflate/datetime_mysql.t
178 # (doesn't need Mysql itself)
68de9438 179 'DateTime::Format::MySQL' => '0',
180 },
181 },
9c92bb1c 182
68de9438 183 test_dt_pg => {
e163f484 184 include => 'test_dt',
68de9438 185 req => {
9c92bb1c 186 # t/inflate/datetime_pg.t
187 # (doesn't need PG itself)
ab35aeab 188 'DateTime::Format::Pg' => '0.16004',
f6b26571 189 },
8057ed01 190 },
191
68de9438 192 test_cdbicompat => {
e163f484 193 include => 'test_dt',
f6b26571 194 req => {
f6b26571 195 'Class::DBI::Plugin::DeepAbstractSearch' => '0',
f6b26571 196 'Time::Piece::MySQL' => '0',
f6b26571 197 'Date::Simple' => '3.03',
198 },
8057ed01 199 },
200
e163f484 201 rdbms_generic_odbc => {
202 req => {
203 'DBD::ODBC' => 0,
204 }
205 },
206
207 rdbms_generic_ado => {
208 req => {
209 'DBD::ADO' => 0,
210 }
211 },
212
be68095d 213 # this is just for completeness as SQLite
214 # is a core dep of DBIC for testing
215 rdbms_sqlite => {
216 req => {
e163f484 217 'DBD::SQLite' => 0,
be68095d 218 },
219 pod => {
220 title => 'SQLite support',
221 desc => 'Modules required to connect to SQLite',
222 },
223 },
224
225 rdbms_pg => {
226 req => {
a4fc1239 227 # when changing this list make sure to adjust xt/optional_deps.t
e163f484 228 'DBD::Pg' => 0,
be68095d 229 },
230 pod => {
231 title => 'PostgreSQL support',
232 desc => 'Modules required to connect to PostgreSQL',
233 },
234 },
235
236 rdbms_mssql_odbc => {
e163f484 237 include => 'rdbms_generic_odbc',
be68095d 238 pod => {
239 title => 'MSSQL support via DBD::ODBC',
240 desc => 'Modules required to connect to MSSQL via DBD::ODBC',
241 },
242 },
243
244 rdbms_mssql_sybase => {
245 req => {
e163f484 246 'DBD::Sybase' => 0,
be68095d 247 },
248 pod => {
249 title => 'MSSQL support via DBD::Sybase',
56dca25f 250 desc => 'Modules required to connect to MSSQL via DBD::Sybase',
251 },
252 },
253
254 rdbms_mssql_ado => {
e163f484 255 include => 'rdbms_generic_ado',
56dca25f 256 pod => {
257 title => 'MSSQL support via DBD::ADO (Windows only)',
258 desc => 'Modules required to connect to MSSQL via DBD::ADO. This particular DBD is available on Windows only',
be68095d 259 },
260 },
261
726c8f65 262 rdbms_msaccess_odbc => {
e163f484 263 include => 'rdbms_generic_odbc',
726c8f65 264 pod => {
265 title => 'MS Access support via DBD::ODBC',
266 desc => 'Modules required to connect to MS Access via DBD::ODBC',
267 },
268 },
269
270 rdbms_msaccess_ado => {
e163f484 271 include => 'rdbms_generic_ado',
726c8f65 272 pod => {
273 title => 'MS Access support via DBD::ADO (Windows only)',
274 desc => 'Modules required to connect to MS Access via DBD::ADO. This particular DBD is available on Windows only',
275 },
276 },
277
be68095d 278 rdbms_mysql => {
279 req => {
e163f484 280 'DBD::mysql' => 0,
be68095d 281 },
282 pod => {
283 title => 'MySQL support',
284 desc => 'Modules required to connect to MySQL',
285 },
286 },
287
288 rdbms_oracle => {
e163f484 289 include => 'id_shortener',
be68095d 290 req => {
e163f484 291 'DBD::Oracle' => 0,
be68095d 292 },
293 pod => {
294 title => 'Oracle support',
295 desc => 'Modules required to connect to Oracle',
296 },
297 },
298
299 rdbms_ase => {
300 req => {
e163f484 301 'DBD::Sybase' => 0,
be68095d 302 },
303 pod => {
304 title => 'Sybase ASE support',
305 desc => 'Modules required to connect to Sybase ASE',
306 },
307 },
308
309 rdbms_db2 => {
310 req => {
e163f484 311 'DBD::DB2' => 0,
be68095d 312 },
313 pod => {
314 title => 'DB2 support',
315 desc => 'Modules required to connect to DB2',
316 },
317 },
318
199fbc45 319 rdbms_db2_400 => {
e163f484 320 include => 'rdbms_generic_odbc',
199fbc45 321 pod => {
322 title => 'DB2 on AS/400 support',
323 desc => 'Modules required to connect to DB2 on AS/400',
324 },
325 },
326
327 rdbms_informix => {
328 req => {
e163f484 329 'DBD::Informix' => 0,
199fbc45 330 },
331 pod => {
332 title => 'Informix support',
333 desc => 'Modules required to connect to Informix',
334 },
8273e845 335 },
199fbc45 336
337 rdbms_sqlanywhere => {
338 req => {
e163f484 339 'DBD::SQLAnywhere' => 0,
199fbc45 340 },
341 pod => {
342 title => 'SQLAnywhere support',
343 desc => 'Modules required to connect to SQLAnywhere',
344 },
8273e845 345 },
199fbc45 346
347 rdbms_sqlanywhere_odbc => {
e163f484 348 include => 'rdbms_generic_odbc',
199fbc45 349 pod => {
350 title => 'SQLAnywhere support via DBD::ODBC',
351 desc => 'Modules required to connect to SQLAnywhere via DBD::ODBC',
352 },
8273e845 353 },
199fbc45 354
355 rdbms_firebird => {
356 req => {
e163f484 357 'DBD::Firebird' => 0,
199fbc45 358 },
359 pod => {
360 title => 'Firebird support',
361 desc => 'Modules required to connect to Firebird',
362 },
8273e845 363 },
199fbc45 364
365 rdbms_firebird_interbase => {
366 req => {
e163f484 367 'DBD::InterBase' => 0,
199fbc45 368 },
369 pod => {
370 title => 'Firebird support via DBD::InterBase',
371 desc => 'Modules required to connect to Firebird via DBD::InterBase',
372 },
8273e845 373 },
199fbc45 374
375 rdbms_firebird_odbc => {
e163f484 376 include => 'rdbms_generic_odbc',
199fbc45 377 pod => {
378 title => 'Firebird support via DBD::ODBC',
379 desc => 'Modules required to connect to Firebird via DBD::ODBC',
380 },
8273e845 381 },
199fbc45 382
7975645b 383 test_rdbms_sqlite => {
384 include => 'rdbms_sqlite',
385 req => {
386 ###
387 ### IMPORTANT - do not raise this dependency
388 ### even though many bugfixes are present in newer versions, the general DBIC
389 ### rule is to bend over backwards for available DBDs (given upgrading them is
390 ### often *not* easy or even possible)
391 ###
392 'DBD::SQLite' => '1.29',
393 },
394 },
395
68de9438 396 test_rdbms_pg => {
e163f484 397 include => 'rdbms_pg',
e3a7746c 398 env => [
399 DBICTEST_PG_DSN => 1,
400 DBICTEST_PG_USER => 0,
401 DBICTEST_PG_PASS => 0,
402 ],
f6b26571 403 req => {
e3a7746c 404 # the order does matter because the rdbms support group might require
405 # a different version that the test group
406 #
407 # when changing this list make sure to adjust xt/optional_deps.t
e3a7746c 408 'DBD::Pg' => '2.009002', # specific version to test bytea
f6b26571 409 },
8057ed01 410 },
411
afae8507 412 test_rdbms_mssql_odbc => {
e163f484 413 include => 'rdbms_mssql_odbc',
e3a7746c 414 env => [
415 DBICTEST_MSSQL_ODBC_DSN => 1,
416 DBICTEST_MSSQL_ODBC_USER => 0,
417 DBICTEST_MSSQL_ODBC_PASS => 0,
418 ],
afae8507 419 },
420
56dca25f 421 test_rdbms_mssql_ado => {
e163f484 422 include => 'rdbms_mssql_ado',
e3a7746c 423 env => [
424 DBICTEST_MSSQL_ADO_DSN => 1,
425 DBICTEST_MSSQL_ADO_USER => 0,
426 DBICTEST_MSSQL_ADO_PASS => 0,
427 ],
56dca25f 428 },
429
afae8507 430 test_rdbms_mssql_sybase => {
e163f484 431 include => 'rdbms_mssql_sybase',
e3a7746c 432 env => [
433 DBICTEST_MSSQL_DSN => 1,
434 DBICTEST_MSSQL_USER => 0,
435 DBICTEST_MSSQL_PASS => 0,
436 ],
afae8507 437 },
438
726c8f65 439 test_rdbms_msaccess_odbc => {
4b9c54b5 440 include => 'rdbms_msaccess_odbc',
e3a7746c 441 env => [
442 DBICTEST_MSACCESS_ODBC_DSN => 1,
443 DBICTEST_MSACCESS_ODBC_USER => 0,
444 DBICTEST_MSACCESS_ODBC_PASS => 0,
445 ],
726c8f65 446 req => {
e3a7746c 447 'Data::GUID' => '0',
726c8f65 448 },
449 },
450
451 test_rdbms_msaccess_ado => {
4b9c54b5 452 include => 'rdbms_msaccess_ado',
e3a7746c 453 env => [
454 DBICTEST_MSACCESS_ADO_DSN => 1,
455 DBICTEST_MSACCESS_ADO_USER => 0,
456 DBICTEST_MSACCESS_ADO_PASS => 0,
457 ],
726c8f65 458 req => {
e3a7746c 459 'Data::GUID' => 0,
726c8f65 460 },
461 },
462
68de9438 463 test_rdbms_mysql => {
e163f484 464 include => 'rdbms_mysql',
e3a7746c 465 env => [
466 DBICTEST_MYSQL_DSN => 1,
467 DBICTEST_MYSQL_USER => 0,
468 DBICTEST_MYSQL_PASS => 0,
469 ],
8057ed01 470 },
471
68de9438 472 test_rdbms_oracle => {
e163f484 473 include => 'rdbms_oracle',
e3a7746c 474 env => [
475 DBICTEST_ORA_DSN => 1,
476 DBICTEST_ORA_USER => 0,
477 DBICTEST_ORA_PASS => 0,
478 ],
f6b26571 479 req => {
e3a7746c 480 'DateTime::Format::Oracle' => '0',
481 'DBD::Oracle' => '1.24',
f6b26571 482 },
8057ed01 483 },
484
68de9438 485 test_rdbms_ase => {
e163f484 486 include => 'rdbms_ase',
e3a7746c 487 env => [
488 DBICTEST_SYBASE_DSN => 1,
489 DBICTEST_SYBASE_USER => 0,
490 DBICTEST_SYBASE_PASS => 0,
491 ],
8057ed01 492 },
493
68de9438 494 test_rdbms_db2 => {
e163f484 495 include => 'rdbms_db2',
e3a7746c 496 env => [
497 DBICTEST_DB2_DSN => 1,
498 DBICTEST_DB2_USER => 0,
499 DBICTEST_DB2_PASS => 0,
500 ],
f58a165c 501 },
502
199fbc45 503 test_rdbms_db2_400 => {
e163f484 504 include => 'rdbms_db2_400',
e3a7746c 505 env => [
506 DBICTEST_DB2_400_DSN => 1,
507 DBICTEST_DB2_400_USER => 0,
508 DBICTEST_DB2_400_PASS => 0,
509 ],
199fbc45 510 },
511
512 test_rdbms_informix => {
e163f484 513 include => 'rdbms_informix',
e3a7746c 514 env => [
515 DBICTEST_INFORMIX_DSN => 1,
516 DBICTEST_INFORMIX_USER => 0,
517 DBICTEST_INFORMIX_PASS => 0,
518 ],
199fbc45 519 },
520
521 test_rdbms_sqlanywhere => {
e163f484 522 include => 'rdbms_sqlanywhere',
e3a7746c 523 env => [
524 DBICTEST_SQLANYWHERE_DSN => 1,
525 DBICTEST_SQLANYWHERE_USER => 0,
526 DBICTEST_SQLANYWHERE_PASS => 0,
527 ],
199fbc45 528 },
529
530 test_rdbms_sqlanywhere_odbc => {
e163f484 531 include => 'rdbms_sqlanywhere_odbc',
e3a7746c 532 env => [
533 DBICTEST_SQLANYWHERE_ODBC_DSN => 1,
534 DBICTEST_SQLANYWHERE_ODBC_USER => 0,
535 DBICTEST_SQLANYWHERE_ODBC_PASS => 0,
536 ],
199fbc45 537 },
538
539 test_rdbms_firebird => {
e163f484 540 include => 'rdbms_firebird',
e3a7746c 541 env => [
542 DBICTEST_FIREBIRD_DSN => 1,
543 DBICTEST_FIREBIRD_USER => 0,
544 DBICTEST_FIREBIRD_PASS => 0,
545 ],
199fbc45 546 },
547
548 test_rdbms_firebird_interbase => {
e163f484 549 include => 'rdbms_firebird_interbase',
e3a7746c 550 env => [
551 DBICTEST_FIREBIRD_INTERBASE_DSN => 1,
552 DBICTEST_FIREBIRD_INTERBASE_USER => 0,
553 DBICTEST_FIREBIRD_INTERBASE_PASS => 0,
554 ],
199fbc45 555 },
556
e02b39b4 557 test_rdbms_firebird_odbc => {
e163f484 558 include => 'rdbms_firebird_odbc',
e3a7746c 559 env => [
560 DBICTEST_FIREBIRD_ODBC_DSN => 1,
561 DBICTEST_FIREBIRD_ODBC_USER => 0,
562 DBICTEST_FIREBIRD_ODBC_PASS => 0,
563 ],
e02b39b4 564 },
565
42168332 566 test_memcached => {
e3a7746c 567 env => [
568 DBICTEST_MEMCACHED => 1,
569 ],
42168332 570 req => {
e3a7746c 571 'Cache::Memcached' => 0,
42168332 572 },
573 },
574
344f1f52 575 dist_dir => {
576 req => {
3ade80ee 577 %$test_and_dist_json_any,
b81d8515 578 'ExtUtils::MakeMaker' => '6.64',
06fc872a 579 'Pod::Inherit' => '0.91',
580 },
344f1f52 581 },
582
583 dist_upload => {
584 req => {
585 'CPAN::Uploader' => '0.103001',
586 },
587 },
8057ed01 588};
589
f6b26571 590
3ca0dcf0 591
592### Public API
593
afb8fc52 594sub import {
595 my $class = shift;
596
597 if (@_) {
598
599 my $action = shift;
600
601 if ($action eq '-die_without') {
602 my $err;
603 {
604 local $@;
605 eval { $class->die_unless_req_ok_for(\@_); 1 }
606 or $err = $@;
607 }
608 die "\n$err\n" if $err;
609 }
610 elsif ($action eq '-list_missing') {
611 print $class->modreq_missing_for(\@_);
612 print "\n";
613 exit 0;
614 }
cb551b07 615 elsif ($action eq '-skip_all_without') {
616
617 # sanity check - make sure ->current_test is 0 and no plan has been declared
618 do {
619 local $@;
620 defined eval {
621 Test::Builder->new->current_test
622 or
623 Test::Builder->new->has_plan
624 };
625 } and croak("Unable to invoke -skip_all_without after testing has started");
626
627 if ( my $missing = $class->req_missing_for(\@_) ) {
628
629 die ("\nMandatory requirements not satisfied during release-testing: $missing\n\n")
630 if $ENV{RELEASE_TESTING} and $class->_groups_to_reqs(\@_)->{release_testing_mandatory};
631
632 print "1..0 # SKIP requirements not satisfied: $missing\n";
633 exit 0;
634 }
635 }
afb8fc52 636 elsif ($action =~ /^-/) {
637 croak "Unknown import-time action '$action'";
638 }
639 else {
640 croak "$class is not an exporter, unable to import '$action'";
641 }
642 }
643
644 1;
645}
646
647sub unimport {
648 croak( __PACKAGE__ . " does not implement unimport" );
649}
650
3ca0dcf0 651# OO for (mistakenly considered) ease of extensibility, not due to any need to
652# carry state of any sort. This API is currently used outside, so leave as-is.
653# FIXME - make sure to not propagate this further if module is extracted as a
654# standalone library - keep the stupidity to a DBIC-secific shim!
655#
fb39747c 656sub req_list_for {
d1bd396f 657 shift->_groups_to_reqs(shift)->{effective_modreqs};
e3a7746c 658}
659
660sub modreq_list_for {
d1bd396f 661 shift->_groups_to_reqs(shift)->{modreqs};
fb39747c 662}
663
3ca0dcf0 664sub req_group_list {
31c31b8d 665 +{ map
666 { $_ => $_[0]->_groups_to_reqs($_) }
667 keys %$dbic_reqs
668 }
3ca0dcf0 669}
fb39747c 670
d1bd396f 671sub req_errorlist_for { shift->modreq_errorlist_for(shift) } # deprecated
5ffa39c7 672sub modreq_errorlist_for {
d1bd396f 673 my ($self, $groups) = @_;
674 $self->_errorlist_for_modreqs( $self->_groups_to_reqs($groups)->{modreqs} );
344f1f52 675}
676
fb39747c 677sub req_ok_for {
d1bd396f 678 shift->req_missing_for(shift) ? 0 : 1;
e3a7746c 679}
680
681sub req_missing_for {
d1bd396f 682 my ($self, $groups) = @_;
e3a7746c 683
d1bd396f 684 my $reqs = $self->_groups_to_reqs($groups);
685 my $mods_missing = $self->modreq_missing_for($groups);
e3a7746c 686
687 return '' if
688 ! $mods_missing
689 and
690 ! $reqs->{missing_envvars}
31c31b8d 691 ;
e3a7746c 692
693 my @res = $mods_missing || ();
694
d1f653cf 695 push @res, 'the following group(s) of environment variables: ' . join ' and ', sort map
e3a7746c 696 { __envvar_group_desc($_) }
697 @{$reqs->{missing_envvars}}
698 if $reqs->{missing_envvars};
699
700 return (
701 ( join ' as well as ', @res )
702 .
703 ( $reqs->{modreqs_fully_documented} ? " (see @{[ ref $self || $self ]} documentation for details)" : '' ),
704 );
fb39747c 705}
706
e3a7746c 707sub modreq_missing_for {
d1bd396f 708 my ($self, $groups) = @_;
fb39747c 709
d1bd396f 710 my $reqs = $self->_groups_to_reqs($groups);
e3a7746c 711 my $modreq_errors = $self->_errorlist_for_modreqs($reqs->{modreqs})
712 or return '';
fb39747c 713
e3a7746c 714 join ' ', map
715 { $reqs->{modreqs}{$_} ? qq("$_~>=$reqs->{modreqs}{$_}") : $_ }
716 sort { lc($a) cmp lc($b) } keys %$modreq_errors
31c31b8d 717 ;
fb39747c 718}
719
3ca0dcf0 720sub die_unless_req_ok_for {
d1bd396f 721 if (my $err = shift->req_missing_for(shift) ) {
e3a7746c 722 die "Unable to continue due to missing requirements: $err\n";
31c31b8d 723 }
fb39747c 724}
725
3ca0dcf0 726
727
e3a7746c 728### Private functions
729
730# potentially shorten group desc
731sub __envvar_group_desc {
732 my @envs = @{$_[0]};
733
734 my (@res, $last_prefix);
735 while (my $ev = shift @envs) {
736 my ($pref, $sep, $suff) = split / ([\_\-]) (?= [^\_\-]+ \z )/x, $ev;
737
738 if ( defined $sep and ($last_prefix||'') eq $pref ) {
739 push @res, "...${sep}${suff}"
740 }
741 else {
742 push @res, $ev;
743 }
744
745 $last_prefix = $pref if $sep;
746 }
747
748 join '/', @res;
749}
750
751
752
79b1bf0a 753### Private OO API
31c31b8d 754our %req_unavailability_cache;
755
e3a7746c 756# this method is just a lister and envvar/metadata checker - it does not try to load anything
e163f484 757my $processed_groups = {};
31c31b8d 758sub _groups_to_reqs {
759 my ($self, $groups) = @_;
760
761 $groups = [ $groups || () ]
762 unless ref $groups eq 'ARRAY';
763
764 croak "@{[ (caller(1))[3] ]}() expects a requirement group name or arrayref of group names"
765 unless @$groups;
766
767 my $ret = {
768 modreqs => {},
769 modreqs_fully_documented => 1,
770 };
3ca0dcf0 771
e163f484 772 for my $group ( grep { ! $processed_groups->{$_} } @$groups ) {
d8799bab 773
31c31b8d 774 $group =~ /\A [A-Za-z][0-9A-Z_a-z]* \z/x
775 or croak "Invalid requirement group name '$group': only ascii alphanumerics and _ are allowed";
d8799bab 776
e163f484 777 croak "Requirement group '$group' is not defined" unless defined $dbic_reqs->{$group};
778
779 my $group_reqs = $dbic_reqs->{$group}{req};
d8799bab 780
31c31b8d 781 # sanity-check
782 for (keys %$group_reqs) {
d8799bab 783
31c31b8d 784 $_ =~ /\A [A-Z_a-z][0-9A-Z_a-z]* (?:::[0-9A-Z_a-z]+)* \z /x
785 or croak "Requirement '$_' in group '$group' is not a valid module name";
786
787 # !!!DO NOT CHANGE!!!
788 # remember - version.pm may not be available on the system
789 croak "Requirement '$_' in group '$group' specifies an invalid version '$group_reqs->{$_}' (only plain non-underscored floating point decimals are supported)"
790 if ( ($group_reqs->{$_}||0) !~ / \A [0-9]+ (?: \. [0-9]+ )? \z /x );
d8799bab 791 }
792
e3a7746c 793 # check if we have all required envvars if such names are defined
794 my ($some_envs_required, $some_envs_missing);
795 if (my @e = @{$dbic_reqs->{$group}{env} || [] }) {
796
797 croak "Unexpected 'env' attribute under group '$group' (only allowed in test_* groups)"
798 unless $group =~ /^test_/;
799
800 croak "Unexpected *odd* list in 'env' under group '$group'"
801 if @e % 2;
802
803 my @group_envnames_list;
804
805 # deconstruct the whole thing
806 while (@e) {
807 push @group_envnames_list, my $envname = shift @e;
808
809 # env required or not
810 next unless shift @e;
811
812 $some_envs_required ||= 1;
813
814 $some_envs_missing ||= (
815 ! defined $ENV{$envname}
816 or
817 ! length $ENV{$envname}
818 );
819 }
820
821 croak "None of the envvars in group '$group' declared as required, making the requirement moot"
822 unless $some_envs_required;
823
824 push @{$ret->{missing_envvars}}, \@group_envnames_list if $some_envs_missing;
825 }
826
e163f484 827 # get the reqs for includes if any
828 my $inc_reqs;
829 if (my $incs = $dbic_reqs->{$group}{include}) {
830 $incs = [ $incs ] unless ref $incs eq 'ARRAY';
831
832 croak "Malformed 'include' for group '$group': must be another existing group name or arrayref of existing group names"
833 unless @$incs;
834
835 local $processed_groups->{$group} = 1;
836
837 my $subreqs = $self->_groups_to_reqs($incs);
838
839 croak "Includes with variable effective_modreqs not yet supported"
840 if $subreqs->{effective_modreqs_differ};
841
842 $inc_reqs = $subreqs->{modreqs};
843
844 }
845
31c31b8d 846 # assemble into the final ret
e3a7746c 847 for my $type (
848 'modreqs',
849 $some_envs_missing ? () : 'effective_modreqs'
850 ) {
e163f484 851 for my $req_bag ($group_reqs, $inc_reqs||()) {
852 for my $mod (keys %$req_bag) {
31c31b8d 853
e163f484 854 $ret->{$type}{$mod} = $req_bag->{$mod}||0 if (
31c31b8d 855
e163f484 856 ! exists $ret->{$type}{$mod}
857 or
858 # we sanitized the version to be numeric above - we can just -gt it
859 ($req_bag->{$mod}||0) > $ret->{$type}{$mod}
fb39747c 860
e163f484 861 );
862 }
e3a7746c 863 }
fb39747c 864 }
31c31b8d 865
e163f484 866 $ret->{effective_modreqs_differ} ||= !!$some_envs_missing;
867
31c31b8d 868 $ret->{modreqs_fully_documented} &&= !!$dbic_reqs->{$group}{pod};
cb551b07 869
870 $ret->{release_testing_mandatory} ||= !!$dbic_reqs->{$group}{release_testing_mandatory};
31c31b8d 871 }
872
873 return $ret;
874}
875
876
877# this method tries to load specified modreqs and returns a hashref of
878# module/loaderror pairs for anything that failed
879sub _errorlist_for_modreqs {
880 # args supposedly already went through _groups_to_reqs and are therefore sanitized
881 # safe to eval at will
882 my ($self, $reqs) = @_;
883
884 my $ret;
885
886 for my $m ( keys %$reqs ) {
887 my $v = $reqs->{$m};
888
889 if (! exists $req_unavailability_cache{$m}{$v} ) {
890 local $@;
891 eval( "require $m;" . ( $v ? "$m->VERSION(q($v))" : '' ) );
892 $req_unavailability_cache{$m}{$v} = $@;
fb39747c 893 }
894
31c31b8d 895 $ret->{$m} = $req_unavailability_cache{$m}{$v}
896 if $req_unavailability_cache{$m}{$v};
897 }
898
899 $ret;
fb39747c 900}
901
31c31b8d 902
e3fc11e1 903# This is to be called by the author only (automatically in Makefile.PL)
f6b26571 904sub _gen_pod {
47589465 905 my ($class, $distver, $pod_dir) = @_;
31fa1764 906
47589465 907 die "No POD root dir supplied" unless $pod_dir;
31fa1764 908
ccebe1f1 909 $distver ||=
31fa1764 910 eval { require DBIx::Class; DBIx::Class->VERSION; }
911 ||
ccebe1f1 912 die
31fa1764 913"\n\n---------------------------------------------------------------------\n" .
914'Unable to load core DBIx::Class module to determine current version, '.
915'possibly due to missing dependencies. Author-mode autodocumentation ' .
916"halted\n\n" . $@ .
917"\n\n---------------------------------------------------------------------\n"
31fa1764 918 ;
919
3d4c5a84 920 # do not ask for a recent version, use 1.x API calls
47589465 921 # this *may* execute on a smoker with old perl or whatnot
922 require File::Path;
923
924 (my $modfn = __PACKAGE__ . '.pm') =~ s|::|/|g;
925
926 (my $podfn = "$pod_dir/$modfn") =~ s/\.pm$/\.pod/;
927 (my $dir = $podfn) =~ s|/[^/]+$||;
928
929 File::Path::mkpath([$dir]);
930
31c31b8d 931 my $sqltver = $class->req_list_for('deploy')->{'SQL::Translator'}
e3fc11e1 932 or die "Hrmm? No sqlt dep?";
7e3dc46f 933
3ca0dcf0 934
935 my @chunks;
936
937#@@
938#@@ HEADER
939#@@
79b1bf0a 940 push @chunks, <<"EOC";
af4ac504 941#########################################################################
942##################### A U T O G E N E R A T E D ########################
943#########################################################################
944#
945# The contents of this POD file are auto-generated. Any changes you make
946# will be lost. If you need to change the generated text edit _gen_pod()
947# at the end of $modfn
948#
79b1bf0a 949
950=head1 NAME
951
952$class - Optional module dependency specifications (for module authors)
af4ac504 953EOC
3ca0dcf0 954
955
956#@@
957#@@ SYNOPSIS HEADING
958#@@
79b1bf0a 959 push @chunks, <<"EOC";
960=head1 SYNOPSIS
961
962Somewhere in your build-file (e.g. L<ExtUtils::MakeMaker>'s F<Makefile.PL>):
7e3dc46f 963
964 ...
965
79b1bf0a 966 \$EUMM_ARGS{CONFIGURE_REQUIRES} = {
967 \%{ \$EUMM_ARGS{CONFIGURE_REQUIRES} || {} },
968 'DBIx::Class' => '$distver',
969 };
7e3dc46f 970
79b1bf0a 971 ...
7e3dc46f 972
79b1bf0a 973 my %DBIC_DEPLOY_DEPS = %{ eval {
974 require $class;
975 $class->req_list_for('deploy');
976 } || {} };
7e3dc46f 977
79b1bf0a 978 \$EUMM_ARGS{PREREQ_PM} = {
979 \%DBIC_DEPLOY_DEPS,
980 \%{ \$EUMM_ARGS{PREREQ_PM} || {} },
981 };
7e3dc46f 982
983 ...
984
79b1bf0a 985 ExtUtils::MakeMaker::WriteMakefile(\%EUMM_ARGS);
986
987B<Note>: The C<eval> protection within the example is due to support for
988requirements during L<the C<configure> build phase|CPAN::Meta::Spec/Phases>
989not being available on a sufficient portion of production installations of
990Perl. Robust support for such dependency requirements is available in the
991L<CPAN> installer only since version C<1.94_56> first made available for
992production with perl version C<5.12>. It is the belief of the current
993maintainer that support for requirements during the C<configure> build phase
994will not be sufficiently ubiquitous until the B<year 2020> at the earliest,
995hence the extra care demonstrated above. It should also be noted that some
9963rd party installers (e.g. L<cpanminus|App::cpanminus>) do the right thing
997with configure requirements independent from the versions of perl and CPAN
998available.
999EOC
3ca0dcf0 1000
1001
1002#@@
1003#@@ DESCRIPTION HEADING
1004#@@
79b1bf0a 1005 push @chunks, <<'EOC';
1006=head1 DESCRIPTION
1007
f6b26571 1008Some of the less-frequently used features of L<DBIx::Class> have external
1009module dependencies on their own. In order not to burden the average user
79b1bf0a 1010with modules they will never use, these optional dependencies are not included
f6b26571 1011in the base Makefile.PL. Instead an exception with a descriptive message is
79b1bf0a 1012thrown when a specific feature can't find one or several modules required for
1013its operation. This module is the central holding place for the current list
7e3dc46f 1014of such dependencies, for DBIx::Class core authors, and DBIx::Class extension
1015authors alike.
79b1bf0a 1016
1017Dependencies are organized in L<groups|/CURRENT REQUIREMENT GROUPS> where each
1018group can list one or more required modules, with an optional minimum version
e3a7746c 1019(or 0 for any version). In addition groups prefixed with C<test_> can specify
1020a set of environment variables, some (or all) of which are marked as required
1021for the group to be considered by L</req_list_for>
1022
1023Each group name (or a combination thereof) can be used in the
1024L<public methods|/METHODS> as described below.
79b1bf0a 1025EOC
3ca0dcf0 1026
1027
1028#@@
1029#@@ REQUIREMENT GROUPLIST HEADING
1030#@@
79b1bf0a 1031 push @chunks, '=head1 CURRENT REQUIREMENT GROUPS';
f6b26571 1032
31c31b8d 1033 for my $group (sort keys %$dbic_reqs) {
1034 my $p = $dbic_reqs->{$group}{pod}
f6b26571 1035 or next;
1036
e163f484 1037 my $modlist = $class->modreq_list_for($group);
f6b26571 1038
1039 next unless keys %$modlist;
1040
1041 push @chunks, (
1042 "=head2 $p->{title}",
1043 "$p->{desc}",
1044 '=over',
1045 ( map { "=item * $_" . ($modlist->{$_} ? " >= $modlist->{$_}" : '') } (sort keys %$modlist) ),
1046 '=back',
1047 "Requirement group: B<$group>",
1048 );
1049 }
1050
3ca0dcf0 1051
1052#@@
1053#@@ API DOCUMENTATION HEADING
1054#@@
79b1bf0a 1055 push @chunks, <<'EOC';
1056
afb8fc52 1057=head1 IMPORT-LIKE ACTIONS
1058
1059Even though this module is not an L<Exporter>, it recognizes several C<actions>
1060supplied to its C<import> method.
1061
cb551b07 1062=head2 -skip_all_without
1063
1064=over
1065
1066=item Arguments: @group_names
1067
1068=back
1069
1070A convenience wrapper for use during testing:
1071EOC
1072
1073 push @chunks, " use $class -skip_all_without => qw(admin test_rdbms_mysql);";
1074
1075 push @chunks, 'Roughly equivalent to the following code:';
1076
1077 push @chunks, sprintf <<'EOS', ($class) x 2;
1078
1079 BEGIN {
1080 require %s;
1081 if ( my $missing = %s->req_missing_for(\@group_names_) ) {
1082 print "1..0 # SKIP requirements not satisfied: $missing\n";
1083 exit 0;
1084 }
1085 }
1086EOS
1087
1088 push @chunks, <<'EOC';
1089
1090It also takes into account the C<RELEASE_TESTING> environment variable and
1091behaves like L</-die_without> for any requirement groups marked as
1092C<release_testing_mandatory>.
1093
afb8fc52 1094=head2 -die_without
1095
1096=over
1097
1098=item Arguments: @group_names
1099
1100=back
1101
1102A convenience wrapper around L</die_unless_req_ok_for>:
1103EOC
1104
1105 push @chunks, " use $class -die_without => qw(deploy admin);";
1106
1107 push @chunks, <<'EOC';
1108
1109=head2 -list_missing
1110
1111=over
1112
1113=item Arguments: @group_names
1114
1115=back
1116
1117A convenience wrapper around L</modreq_missing_for>:
1118
1119 perl -Ilib -MDBIx::Class::Optional::Dependencies=-list_missing,deploy,admin | cpanm
1120
79b1bf0a 1121=head1 METHODS
1122
1123=head2 req_group_list
1124
1125=over
1126
1127=item Arguments: none
1128
1129=item Return Value: \%list_of_requirement_groups
1130
1131=back
1132
e3fc11e1 1133This method should be used by DBIx::Class packagers, to get a hashref of all
31c31b8d 1134dependencies B<keyed> by dependency group. Each key (group name), or a combination
1135thereof (as an arrayref) can be supplied to the methods below.
79b1bf0a 1136The B<values> of the returned hash are currently a set of options B<without a
1137well defined structure>. If you have use for any of the contents - contact the
1138maintainers, instead of treating this as public (left alone stable) API.
1139
1140=head2 req_list_for
1141
1142=over
1143
31c31b8d 1144=item Arguments: $group_name | \@group_names
79b1bf0a 1145
31c31b8d 1146=item Return Value: \%set_of_module_version_pairs
79b1bf0a 1147
1148=back
1149
f6b26571 1150This method should be used by DBIx::Class extension authors, to determine the
31c31b8d 1151version of modules a specific set of features requires for this version of
e3a7746c 1152DBIx::Class (regardless of their availability on the system).
1153See the L</SYNOPSIS> for a real-world example.
1154
1155When handling C<test_*> groups this method behaves B<differently> from
1156L</modreq_list_for> below (and is the only such inconsistency among the
1157C<req_*> methods). If a particular group declares as requirements some
1158C<environment variables> and these requirements are not satisfied (the envvars
1159are unset) - then the C<module requirements> of this group are not included in
1160the returned list.
1161
1162=head2 modreq_list_for
1163
1164=over
1165
1166=item Arguments: $group_name | \@group_names
1167
1168=item Return Value: \%set_of_module_version_pairs
1169
1170=back
1171
1172Same as L</req_list_for> but does not take into consideration any
1173C<environment variable requirements> - returns just the list of required
1174modules.
79b1bf0a 1175
1176=head2 req_ok_for
1177
1178=over
1179
31c31b8d 1180=item Arguments: $group_name | \@group_names
79b1bf0a 1181
1182=item Return Value: 1|0
1183
1184=back
1185
e3a7746c 1186Returns true or false depending on whether all modules/envvars required by
1187the group(s) are loadable/set on the system.
79b1bf0a 1188
1189=head2 req_missing_for
1190
1191=over
1192
31c31b8d 1193=item Arguments: $group_name | \@group_names
79b1bf0a 1194
1195=item Return Value: $error_message_string
1196
1197=back
1198
31c31b8d 1199Returns a single-line string suitable for inclusion in larger error messages.
e3a7746c 1200This method would normally be used by DBIx::Class core features, to indicate to
1201the user that they need to install specific modules and/or set specific
1202environment variables before being able to use a specific feature set.
f6b26571 1203
e3fc11e1 1204For example if some of the requirements for C<deploy> are not available,
1205the returned string could look like:
79b1bf0a 1206EOC
f6b26571 1207
79b1bf0a 1208 push @chunks, qq{ "SQL::Translator~>=$sqltver" (see $class documentation for details)};
f6b26571 1209
79b1bf0a 1210 push @chunks, <<'EOC';
f6b26571 1211The author is expected to prepend the necessary text to this message before
e3a7746c 1212returning the actual error seen by the user. See also L</modreq_missing_for>
1213
1214=head2 modreq_missing_for
f6b26571 1215
e3a7746c 1216=over
1217
1218=item Arguments: $group_name | \@group_names
1219
1220=item Return Value: $error_message_string
1221
1222=back
1223
1224Same as L</req_missing_for> except that the error string is guaranteed to be
1225either empty, or contain a set of module requirement specifications suitable
1226for piping to e.g. L<cpanminus|App::cpanminus>. The method explicitly does not
1227attempt to validate the state of required environment variables (if any).
1228
1229For instance if some of the requirements for C<deploy> are not available,
1230the returned string could look like:
1231EOC
1232
1233 push @chunks, qq{ "SQL::Translator~>=$sqltver"};
1234
1235 push @chunks, <<'EOC';
afb8fc52 1236
1237See also L</-list_missing>.
1238
79b1bf0a 1239=head2 die_unless_req_ok_for
1240
1241=over
1242
31c31b8d 1243=item Arguments: $group_name | \@group_names
79b1bf0a 1244
1245=back
1246
31c31b8d 1247Checks if L</req_ok_for> passes for the supplied group(s), and
344f1f52 1248in case of failure throws an exception including the information
afb8fc52 1249from L</req_missing_for>. See also L</-die_without>.
79b1bf0a 1250
5ffa39c7 1251=head2 modreq_errorlist_for
79b1bf0a 1252
1253=over
1254
31c31b8d 1255=item Arguments: $group_name | \@group_names
79b1bf0a 1256
31c31b8d 1257=item Return Value: \%set_of_loaderrors_per_module
79b1bf0a 1258
1259=back
1260
4a0eed52 1261Returns a hashref containing the actual errors that occurred while attempting
31c31b8d 1262to load each module in the requirement group(s).
5ffa39c7 1263
1264=head2 req_errorlist_for
1265
1266Deprecated method name, equivalent (via proxy) to L</modreq_errorlist_for>.
1267
79b1bf0a 1268EOC
3ca0dcf0 1269
1270#@@
1271#@@ FOOTER
1272#@@
79b1bf0a 1273 push @chunks, <<'EOC';
1274=head1 FURTHER QUESTIONS?
1275
1276Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
1277
1278=head1 COPYRIGHT AND LICENSE
1279
a2bd3796 1280This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
1281by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
1282redistribute it and/or modify it under the same terms as the
1283L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.
79b1bf0a 1284EOC
3ca0dcf0 1285
3f5e367a 1286 eval {
1287 open (my $fh, '>', $podfn) or die;
1288 print $fh join ("\n\n", @chunks) or die;
1289 print $fh "\n" or die;
1290 close ($fh) or die;
1291 } or croak( "Unable to write $podfn: " . ( $! || $@ || 'unknown error') );
f6b26571 1292}
1293
8057ed01 12941;