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