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