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