generate svg of DBICTest::Schema in author mode
[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
1888e80f 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
668 include => [qw( admin_script _json_xs_compatible_json_any )],
344f1f52 669 req => {
b81d8515 670 'ExtUtils::MakeMaker' => '6.64',
06fc872a 671 'Pod::Inherit' => '0.91',
ad93ee36 672 'GraphViz' => '0',
673 }
344f1f52 674 },
675
676 dist_upload => {
677 req => {
678 'CPAN::Uploader' => '0.103001',
679 },
680 },
8057ed01 681};
682
f6b26571 683
3ca0dcf0 684
685### Public API
686
afb8fc52 687sub import {
688 my $class = shift;
689
690 if (@_) {
691
692 my $action = shift;
693
694 if ($action eq '-die_without') {
695 my $err;
696 {
697 local $@;
698 eval { $class->die_unless_req_ok_for(\@_); 1 }
699 or $err = $@;
700 }
701 die "\n$err\n" if $err;
702 }
703 elsif ($action eq '-list_missing') {
704 print $class->modreq_missing_for(\@_);
705 print "\n";
706 exit 0;
707 }
cb551b07 708 elsif ($action eq '-skip_all_without') {
709
710 # sanity check - make sure ->current_test is 0 and no plan has been declared
711 do {
712 local $@;
713 defined eval {
714 Test::Builder->new->current_test
715 or
716 Test::Builder->new->has_plan
717 };
718 } and croak("Unable to invoke -skip_all_without after testing has started");
719
720 if ( my $missing = $class->req_missing_for(\@_) ) {
721
722 die ("\nMandatory requirements not satisfied during release-testing: $missing\n\n")
723 if $ENV{RELEASE_TESTING} and $class->_groups_to_reqs(\@_)->{release_testing_mandatory};
724
725 print "1..0 # SKIP requirements not satisfied: $missing\n";
726 exit 0;
727 }
728 }
afb8fc52 729 elsif ($action =~ /^-/) {
730 croak "Unknown import-time action '$action'";
731 }
732 else {
733 croak "$class is not an exporter, unable to import '$action'";
734 }
735 }
736
737 1;
738}
739
740sub unimport {
741 croak( __PACKAGE__ . " does not implement unimport" );
742}
743
3ca0dcf0 744# OO for (mistakenly considered) ease of extensibility, not due to any need to
745# carry state of any sort. This API is currently used outside, so leave as-is.
746# FIXME - make sure to not propagate this further if module is extracted as a
747# standalone library - keep the stupidity to a DBIC-secific shim!
748#
fb39747c 749sub req_list_for {
d1bd396f 750 shift->_groups_to_reqs(shift)->{effective_modreqs};
e3a7746c 751}
752
753sub modreq_list_for {
d1bd396f 754 shift->_groups_to_reqs(shift)->{modreqs};
fb39747c 755}
756
3ca0dcf0 757sub req_group_list {
31c31b8d 758 +{ map
759 { $_ => $_[0]->_groups_to_reqs($_) }
60256113 760 grep { $_ !~ /^_/ } keys %$dbic_reqs
31c31b8d 761 }
3ca0dcf0 762}
fb39747c 763
d1bd396f 764sub req_errorlist_for { shift->modreq_errorlist_for(shift) } # deprecated
5ffa39c7 765sub modreq_errorlist_for {
d1bd396f 766 my ($self, $groups) = @_;
767 $self->_errorlist_for_modreqs( $self->_groups_to_reqs($groups)->{modreqs} );
344f1f52 768}
769
fb39747c 770sub req_ok_for {
d1bd396f 771 shift->req_missing_for(shift) ? 0 : 1;
e3a7746c 772}
773
774sub req_missing_for {
d1bd396f 775 my ($self, $groups) = @_;
e3a7746c 776
d1bd396f 777 my $reqs = $self->_groups_to_reqs($groups);
250d9e55 778
779 my $mods_missing = $reqs->{missing_envvars}
780 ? $self->_list_physically_missing_modules( $reqs->{modreqs} )
781 : $self->modreq_missing_for($groups)
782 ;
e3a7746c 783
784 return '' if
785 ! $mods_missing
786 and
787 ! $reqs->{missing_envvars}
31c31b8d 788 ;
e3a7746c 789
790 my @res = $mods_missing || ();
791
d1f653cf 792 push @res, 'the following group(s) of environment variables: ' . join ' and ', sort map
e3a7746c 793 { __envvar_group_desc($_) }
794 @{$reqs->{missing_envvars}}
795 if $reqs->{missing_envvars};
796
797 return (
798 ( join ' as well as ', @res )
799 .
800 ( $reqs->{modreqs_fully_documented} ? " (see @{[ ref $self || $self ]} documentation for details)" : '' ),
801 );
fb39747c 802}
803
e3a7746c 804sub modreq_missing_for {
d1bd396f 805 my ($self, $groups) = @_;
fb39747c 806
d1bd396f 807 my $reqs = $self->_groups_to_reqs($groups);
e3a7746c 808 my $modreq_errors = $self->_errorlist_for_modreqs($reqs->{modreqs})
809 or return '';
fb39747c 810
e3a7746c 811 join ' ', map
812 { $reqs->{modreqs}{$_} ? qq("$_~>=$reqs->{modreqs}{$_}") : $_ }
813 sort { lc($a) cmp lc($b) } keys %$modreq_errors
31c31b8d 814 ;
fb39747c 815}
816
461e818a 817my $tb;
818sub skip_without {
819 my ($self, $groups) = @_;
820
821 $tb ||= do { local $@; eval { Test::Builder->new } }
822 or croak "Calling skip_without() before loading Test::Builder makes no sense";
823
824 if ( my $err = $self->req_missing_for($groups) ) {
825 my ($fn, $ln) = (caller(0))[1,2];
826 $tb->skip("block in $fn around line $ln requires $err");
827 local $^W = 0;
828 last SKIP;
829 }
830
831 1;
832}
833
3ca0dcf0 834sub die_unless_req_ok_for {
d1bd396f 835 if (my $err = shift->req_missing_for(shift) ) {
e3a7746c 836 die "Unable to continue due to missing requirements: $err\n";
31c31b8d 837 }
fb39747c 838}
839
3ca0dcf0 840
841
e3a7746c 842### Private functions
843
844# potentially shorten group desc
845sub __envvar_group_desc {
846 my @envs = @{$_[0]};
847
848 my (@res, $last_prefix);
849 while (my $ev = shift @envs) {
850 my ($pref, $sep, $suff) = split / ([\_\-]) (?= [^\_\-]+ \z )/x, $ev;
851
852 if ( defined $sep and ($last_prefix||'') eq $pref ) {
853 push @res, "...${sep}${suff}"
854 }
855 else {
856 push @res, $ev;
857 }
858
859 $last_prefix = $pref if $sep;
860 }
861
862 join '/', @res;
863}
864
461e818a 865my $groupname_re = qr/ [A-Z_a-z][0-9A-Z_a-z]* /x;
866my $modname_re = qr/ [A-Z_a-z] [0-9A-Z_a-z]* (?:::[0-9A-Z_a-z]+)* /x;
867my $modver_re = qr/ [0-9]+ (?: \. [0-9]+ )? /x;
868
a3f8bd01 869# Expand includes from a random group in a specific order:
870# nonvariable groups first, then their includes, then the variable groups,
871# then their includes.
872# This allows reliably marking the rest of the mod reqs as variable (this is
873# also why variable includes are currently not allowed)
874sub __expand_includes {
875 my ($groups, $seen) = @_;
876
877 # !! DIFFERENT !! behavior and return depending on invocation mode
878 # (easier to recurse this way)
879 my $is_toplevel = $seen
880 ? 0
881 : !! ($seen = {})
882 ;
3ca0dcf0 883
a3f8bd01 884 my ($res_per_type, $missing_envvars);
d8799bab 885
a3f8bd01 886 # breadth-first evaluation, with non-variable includes on top
887 for my $g (@$groups) {
d8799bab 888
a3f8bd01 889 croak "Invalid requirement group name '$g': only ascii alphanumerics and _ are allowed"
461e818a 890 if $g !~ qr/ \A $groupname_re \z/x;
e163f484 891
a3f8bd01 892 my $r = $dbic_reqs->{$g}
893 or croak "Requirement group '$g' is not defined";
d8799bab 894
a3f8bd01 895 # always do this check *before* the $seen check
896 croak "Group '$g' with variable effective_modreqs can not be specified as an 'include'"
897 if ( $r->{env} and ! $is_toplevel );
d8799bab 898
a3f8bd01 899 next if $seen->{$g}++;
31c31b8d 900
a3f8bd01 901 my $req_type = 'static';
d8799bab 902
a3f8bd01 903 if ( my @e = @{$r->{env}||[]} ) {
e3a7746c 904
a3f8bd01 905 croak "Unexpected 'env' attribute under group '$g' (only allowed in test_* groups)"
906 unless $g =~ /^test_/;
e3a7746c 907
a3f8bd01 908 croak "Unexpected *odd* list in 'env' under group '$g'"
e3a7746c 909 if @e % 2;
910
e3a7746c 911 # deconstruct the whole thing
a3f8bd01 912 my (@group_envnames_list, $some_envs_required, $some_required_missing);
e3a7746c 913 while (@e) {
914 push @group_envnames_list, my $envname = shift @e;
915
916 # env required or not
917 next unless shift @e;
918
919 $some_envs_required ||= 1;
920
a3f8bd01 921 $some_required_missing ||= (
e3a7746c 922 ! defined $ENV{$envname}
923 or
924 ! length $ENV{$envname}
925 );
926 }
927
a3f8bd01 928 croak "None of the envvars in group '$g' declared as required, making the requirement moot"
e3a7746c 929 unless $some_envs_required;
930
a3f8bd01 931 if ($some_required_missing) {
932 push @{$missing_envvars->{$g}}, \@group_envnames_list;
933 $req_type = 'variable';
934 }
935 }
936
937 push @{$res_per_type->{"base_${req_type}"}}, $g;
938
939 if (my $i = $dbic_reqs->{$g}{include}) {
940 $i = [ $i ] unless ref $i eq 'ARRAY';
941
942 croak "Malformed 'include' for group '$g': must be another existing group name or arrayref of existing group names"
943 unless @$i;
944
945 push @{$res_per_type->{"incs_${req_type}"}}, @$i;
e3a7746c 946 }
a3f8bd01 947 }
948
949 my @ret = map {
950 @{ $res_per_type->{"base_${_}"} || [] },
951 ( $res_per_type->{"incs_${_}"} ? __expand_includes( $res_per_type->{"incs_${_}"}, $seen ) : () ),
952 } qw(static variable);
953
954 return ! $is_toplevel ? @ret : do {
955 my $rv = {};
956 $rv->{$_} = {
957 idx => 1 + keys %$rv,
958 missing_envvars => $missing_envvars->{$_},
959 } for @ret;
2baba3d9 960 $rv->{$_}{user_requested} = 1 for @$groups;
a3f8bd01 961 $rv;
962 };
963}
964
965### Private OO API
966our %req_unavailability_cache;
967
968# this method is just a lister and envvar/metadata checker - it does not try to load anything
969sub _groups_to_reqs {
461e818a 970 my ($self, $want) = @_;
a3f8bd01 971
461e818a 972 $want = [ $want || () ]
973 unless ref $want eq 'ARRAY';
a3f8bd01 974
975 croak "@{[ (caller(1))[3] ]}() expects a requirement group name or arrayref of group names"
461e818a 976 unless @$want;
e3a7746c 977
a3f8bd01 978 my $ret = {
979 modreqs => {},
980 modreqs_fully_documented => 1,
981 };
e163f484 982
461e818a 983 my $groups;
984 for my $piece (@$want) {
985 if ($piece =~ qr/ \A $groupname_re \z /x) {
986 push @$groups, $piece;
987 }
988 elsif ( my ($mod, $ver) = $piece =~ qr/ \A ($modname_re) \>\= ($modver_re) \z /x ) {
989 croak "Ad hoc module specification lists '$mod' twice"
990 if exists $ret->{modreqs}{$mod};
991
992 croak "Ad hoc module specification '${mod} >= $ver' (or greater) not listed in the test_adhoc optdep group" if (
993 ! defined $dbic_reqs->{test_adhoc}{req}{$mod}
994 or
995 $dbic_reqs->{test_adhoc}{req}{$mod} < $ver
996 );
997
998 $ret->{modreqs}{$mod} = $ver;
999 $ret->{modreqs_fully_documented} = 0;
1000 }
1001 else {
1002 croak "Unsupported argument '$piece' supplied to @{[ (caller(1))[3] ]}()"
1003 }
1004 }
1005
a3f8bd01 1006 my $all_groups = __expand_includes($groups);
e163f484 1007
2baba3d9 1008 # pre-assemble list of augmentations, perform basic sanity checks
1009 # Note that below we *DO NOT* respect the source/target reationship, but
1010 # instead always default to augment the "later" group
1011 # This is done so that the "stable/variable" boundary keeps working as
1012 # expected
1013 my $augmentations;
1014 for my $requesting_group (keys %$all_groups) {
1015 if (my $ag = $dbic_reqs->{$requesting_group}{augment}) {
1016 for my $target_group (keys %$ag) {
1017
1018 croak "Group '$requesting_group' claims to augment a non-existent group '$target_group'"
1019 unless $dbic_reqs->{$target_group};
1020
1021 croak "Augmentation combined with variable effective_modreqs currently unsupported for group '$requesting_group'"
1022 if $dbic_reqs->{$requesting_group}{env};
1023
1024 croak "Augmentation of group '$target_group' with variable effective_modreqs unsupported (requested by '$requesting_group')"
1025 if $dbic_reqs->{$target_group}{env};
1026
1027 if (my @foreign = grep { $_ ne 'req' } keys %{$ag->{$target_group}} ) {
1028 croak "Only 'req' augmentations are currently supported (group '$requesting_group' attempts to alter '$foreign[0]' of group '$target_group'";
1029 }
1030
1031 $ret->{augments}{$target_group} = 1;
1032
1033 # no augmentation for stuff that hasn't been selected
1034 if ( $all_groups->{$target_group} and my $ar = $ag->{$target_group}{req} ) {
1035 push @{$augmentations->{
1036 ( $all_groups->{$requesting_group}{idx} < $all_groups->{$target_group}{idx} )
1037 ? $target_group
1038 : $requesting_group
1039 }}, $ar;
1040 }
1041 }
1042 }
1043 }
1044
a3f8bd01 1045 for my $group (sort { $all_groups->{$a}{idx} <=> $all_groups->{$b}{idx} } keys %$all_groups ) {
e163f484 1046
a3f8bd01 1047 my $group_reqs = $dbic_reqs->{$group}{req};
e163f484 1048
a3f8bd01 1049 # sanity-check
2baba3d9 1050 for my $req_bag ($group_reqs, @{ $augmentations->{$group} || [] } ) {
1051 for (keys %$req_bag) {
e163f484 1052
461e818a 1053 $_ =~ / \A $modname_re \z /x
2baba3d9 1054 or croak "Requirement '$_' in group '$group' is not a valid module name";
a3f8bd01 1055
2baba3d9 1056 # !!!DO NOT CHANGE!!!
1057 # remember - version.pm may not be available on the system
1058 croak "Requirement '$_' in group '$group' specifies an invalid version '$req_bag->{$_}' (only plain non-underscored floating point decimals are supported)"
461e818a 1059 if ( ($req_bag->{$_}||0) !~ qr/ \A $modver_re \z /x );
2baba3d9 1060 }
a3f8bd01 1061 }
e163f484 1062
a3f8bd01 1063 if (my $e = $all_groups->{$group}{missing_envvars}) {
1064 push @{$ret->{missing_envvars}}, @$e;
e163f484 1065 }
1066
31c31b8d 1067 # assemble into the final ret
e3a7746c 1068 for my $type (
1069 'modreqs',
a3f8bd01 1070 ( $ret->{missing_envvars} ? () : 'effective_modreqs' ),
e3a7746c 1071 ) {
2baba3d9 1072 for my $req_bag ($group_reqs, @{ $augmentations->{$group} || [] } ) {
e163f484 1073 for my $mod (keys %$req_bag) {
31c31b8d 1074
e163f484 1075 $ret->{$type}{$mod} = $req_bag->{$mod}||0 if (
31c31b8d 1076
e163f484 1077 ! exists $ret->{$type}{$mod}
1078 or
1079 # we sanitized the version to be numeric above - we can just -gt it
1080 ($req_bag->{$mod}||0) > $ret->{$type}{$mod}
fb39747c 1081
e163f484 1082 );
1083 }
e3a7746c 1084 }
fb39747c 1085 }
31c31b8d 1086
2baba3d9 1087 $ret->{modreqs_fully_documented} &&= !!$dbic_reqs->{$group}{pod}
1088 if $all_groups->{$group}{user_requested};
cb551b07 1089
1090 $ret->{release_testing_mandatory} ||= !!$dbic_reqs->{$group}{release_testing_mandatory};
31c31b8d 1091 }
1092
1093 return $ret;
1094}
1095
1096
250d9e55 1097# this method tries to find/load specified modreqs and returns a hashref of
31c31b8d 1098# module/loaderror pairs for anything that failed
1099sub _errorlist_for_modreqs {
1100 # args supposedly already went through _groups_to_reqs and are therefore sanitized
1101 # safe to eval at will
1102 my ($self, $reqs) = @_;
1103
1104 my $ret;
1105
1106 for my $m ( keys %$reqs ) {
1107 my $v = $reqs->{$m};
1108
1109 if (! exists $req_unavailability_cache{$m}{$v} ) {
1110 local $@;
1111 eval( "require $m;" . ( $v ? "$m->VERSION(q($v))" : '' ) );
1112 $req_unavailability_cache{$m}{$v} = $@;
fb39747c 1113 }
1114
31c31b8d 1115 $ret->{$m} = $req_unavailability_cache{$m}{$v}
1116 if $req_unavailability_cache{$m}{$v};
1117 }
1118
1119 $ret;
fb39747c 1120}
1121
250d9e55 1122# Unlike the above DO NOT try to load anything
1123# This is executed when some needed envvars are not available
1124# which in turn means a module load will never be reached anyway
1125# This is important because some modules (especially DBDs) can be
1126# *really* fickle when a require() is attempted, with pretty confusing
1127# side-effects (especially on windows)
1128sub _list_physically_missing_modules {
1129 my ($self, $modreqs) = @_;
1130
1131 # in case there is a coderef in @INC there is nothing we can definitively prove
1132 # so short circuit directly
1133 return '' if grep { length ref $_ } @INC;
1134
1135 my @definitely_missing;
1136 for my $mod (keys %$modreqs) {
1137 (my $fn = $mod . '.pm') =~ s|::|/|g;
1138
1139 push @definitely_missing, $mod unless grep
1140 # this should work on any combination of slashes
1141 { $_ and -d $_ and -f "$_/$fn" and -r "$_/$fn" }
1142 @INC
1143 ;
1144 }
1145
1146 join ' ', map
1147 { $modreqs->{$_} ? qq("$_~>=$modreqs->{$_}") : $_ }
1148 sort { lc($a) cmp lc($b) } @definitely_missing
1149 ;
1150}
1151
31c31b8d 1152
e3fc11e1 1153# This is to be called by the author only (automatically in Makefile.PL)
f6b26571 1154sub _gen_pod {
47589465 1155 my ($class, $distver, $pod_dir) = @_;
31fa1764 1156
47589465 1157 die "No POD root dir supplied" unless $pod_dir;
31fa1764 1158
ccebe1f1 1159 $distver ||=
31fa1764 1160 eval { require DBIx::Class; DBIx::Class->VERSION; }
1161 ||
ccebe1f1 1162 die
31fa1764 1163"\n\n---------------------------------------------------------------------\n" .
1164'Unable to load core DBIx::Class module to determine current version, '.
1165'possibly due to missing dependencies. Author-mode autodocumentation ' .
1166"halted\n\n" . $@ .
1167"\n\n---------------------------------------------------------------------\n"
31fa1764 1168 ;
1169
3d4c5a84 1170 # do not ask for a recent version, use 1.x API calls
47589465 1171 # this *may* execute on a smoker with old perl or whatnot
1172 require File::Path;
1173
1174 (my $modfn = __PACKAGE__ . '.pm') =~ s|::|/|g;
1175
1176 (my $podfn = "$pod_dir/$modfn") =~ s/\.pm$/\.pod/;
1177 (my $dir = $podfn) =~ s|/[^/]+$||;
1178
1179 File::Path::mkpath([$dir]);
1180
31c31b8d 1181 my $sqltver = $class->req_list_for('deploy')->{'SQL::Translator'}
e3fc11e1 1182 or die "Hrmm? No sqlt dep?";
7e3dc46f 1183
3ca0dcf0 1184
1185 my @chunks;
1186
1187#@@
1188#@@ HEADER
1189#@@
79b1bf0a 1190 push @chunks, <<"EOC";
af4ac504 1191#########################################################################
1192##################### A U T O G E N E R A T E D ########################
1193#########################################################################
1194#
1195# The contents of this POD file are auto-generated. Any changes you make
1196# will be lost. If you need to change the generated text edit _gen_pod()
1197# at the end of $modfn
1198#
79b1bf0a 1199
1200=head1 NAME
1201
1202$class - Optional module dependency specifications (for module authors)
af4ac504 1203EOC
3ca0dcf0 1204
1205
1206#@@
1207#@@ SYNOPSIS HEADING
1208#@@
79b1bf0a 1209 push @chunks, <<"EOC";
1210=head1 SYNOPSIS
1211
1212Somewhere in your build-file (e.g. L<ExtUtils::MakeMaker>'s F<Makefile.PL>):
7e3dc46f 1213
1214 ...
1215
79b1bf0a 1216 \$EUMM_ARGS{CONFIGURE_REQUIRES} = {
1217 \%{ \$EUMM_ARGS{CONFIGURE_REQUIRES} || {} },
1218 'DBIx::Class' => '$distver',
1219 };
7e3dc46f 1220
79b1bf0a 1221 ...
7e3dc46f 1222
2baba3d9 1223 my %DBIC_DEPLOY_AND_ORACLE_DEPS = %{ eval {
79b1bf0a 1224 require $class;
2baba3d9 1225 $class->req_list_for([qw( deploy rdbms_oracle icdt )]);
79b1bf0a 1226 } || {} };
7e3dc46f 1227
79b1bf0a 1228 \$EUMM_ARGS{PREREQ_PM} = {
2baba3d9 1229 \%DBIC_DEPLOY_AND_ORACLE_DEPS,
79b1bf0a 1230 \%{ \$EUMM_ARGS{PREREQ_PM} || {} },
1231 };
7e3dc46f 1232
1233 ...
1234
79b1bf0a 1235 ExtUtils::MakeMaker::WriteMakefile(\%EUMM_ARGS);
1236
1237B<Note>: The C<eval> protection within the example is due to support for
1238requirements during L<the C<configure> build phase|CPAN::Meta::Spec/Phases>
1239not being available on a sufficient portion of production installations of
1240Perl. Robust support for such dependency requirements is available in the
1241L<CPAN> installer only since version C<1.94_56> first made available for
1242production with perl version C<5.12>. It is the belief of the current
1243maintainer that support for requirements during the C<configure> build phase
1244will not be sufficiently ubiquitous until the B<year 2020> at the earliest,
1245hence the extra care demonstrated above. It should also be noted that some
12463rd party installers (e.g. L<cpanminus|App::cpanminus>) do the right thing
1247with configure requirements independent from the versions of perl and CPAN
1248available.
1249EOC
3ca0dcf0 1250
1251
1252#@@
1253#@@ DESCRIPTION HEADING
1254#@@
79b1bf0a 1255 push @chunks, <<'EOC';
1256=head1 DESCRIPTION
1257
f6b26571 1258Some of the less-frequently used features of L<DBIx::Class> have external
1259module dependencies on their own. In order not to burden the average user
79b1bf0a 1260with modules they will never use, these optional dependencies are not included
f6b26571 1261in the base Makefile.PL. Instead an exception with a descriptive message is
79b1bf0a 1262thrown when a specific feature can't find one or several modules required for
1263its operation. This module is the central holding place for the current list
7e3dc46f 1264of such dependencies, for DBIx::Class core authors, and DBIx::Class extension
1265authors alike.
79b1bf0a 1266
1267Dependencies are organized in L<groups|/CURRENT REQUIREMENT GROUPS> where each
1268group can list one or more required modules, with an optional minimum version
e3a7746c 1269(or 0 for any version). In addition groups prefixed with C<test_> can specify
1270a set of environment variables, some (or all) of which are marked as required
1271for the group to be considered by L</req_list_for>
1272
1273Each group name (or a combination thereof) can be used in the
1274L<public methods|/METHODS> as described below.
79b1bf0a 1275EOC
3ca0dcf0 1276
1277
1278#@@
1279#@@ REQUIREMENT GROUPLIST HEADING
1280#@@
79b1bf0a 1281 push @chunks, '=head1 CURRENT REQUIREMENT GROUPS';
f6b26571 1282
2baba3d9 1283 my $standalone_info;
1284
31c31b8d 1285 for my $group (sort keys %$dbic_reqs) {
f6b26571 1286
2baba3d9 1287 my $info = $standalone_info->{$group} ||= $class->_groups_to_reqs($group);
f6b26571 1288
2baba3d9 1289 next unless (
1290 $info->{modreqs_fully_documented}
1291 and
1292 ( $info->{augments} or $info->{modreqs} )
1293 );
1294
1295 my $p = $dbic_reqs->{$group}{pod};
f6b26571 1296
1297 push @chunks, (
1298 "=head2 $p->{title}",
2baba3d9 1299 "=head3 $group",
1300 $p->{desc},
f6b26571 1301 '=over',
f6b26571 1302 );
2baba3d9 1303
1304 if ( keys %{ $info->{modreqs}||{} } ) {
1305 push @chunks, map
1306 { "=item * $_" . ($info->{modreqs}{$_} ? " >= $info->{modreqs}{$_}" : '') }
1307 ( sort keys %{ $info->{modreqs} } )
1308 ;
1309 }
1310 else {
1311 push @chunks, '=item * No standalone requirements',
1312 }
1313
1314 push @chunks, '=back';
1315
1316 for my $ag ( sort keys %{ $info->{augments} || {} } ) {
1317 my $ag_info = $standalone_info->{$ag} ||= $class->_groups_to_reqs($ag);
1318
1319 my $newreqs = $class->modreq_list_for([ $group, $ag ]);
1320 for (keys %$newreqs) {
1321 delete $newreqs->{$_} if (
1322 ( defined $info->{modreqs}{$_} and $info->{modreqs}{$_} == $newreqs->{$_} )
1323 or
1324 ( defined $ag_info->{modreqs}{$_} and $ag_info->{modreqs}{$_} == $newreqs->{$_} )
1325 );
1326 }
1327
1328 if (keys %$newreqs) {
1329 push @chunks, (
1330 "Combined with L</$ag> additionally requires:",
1331 '=over',
1332 ( map
1333 { "=item * $_" . ($newreqs->{$_} ? " >= $newreqs->{$_}" : '') }
1334 ( sort keys %$newreqs )
1335 ),
1336 '=back',
1337 );
1338 }
1339 }
f6b26571 1340 }
1341
3ca0dcf0 1342
1343#@@
1344#@@ API DOCUMENTATION HEADING
1345#@@
79b1bf0a 1346 push @chunks, <<'EOC';
1347
afb8fc52 1348=head1 IMPORT-LIKE ACTIONS
1349
1350Even though this module is not an L<Exporter>, it recognizes several C<actions>
1351supplied to its C<import> method.
1352
cb551b07 1353=head2 -skip_all_without
1354
1355=over
1356
1357=item Arguments: @group_names
1358
1359=back
1360
1361A convenience wrapper for use during testing:
1362EOC
1363
1364 push @chunks, " use $class -skip_all_without => qw(admin test_rdbms_mysql);";
1365
1366 push @chunks, 'Roughly equivalent to the following code:';
1367
1368 push @chunks, sprintf <<'EOS', ($class) x 2;
1369
1370 BEGIN {
1371 require %s;
1372 if ( my $missing = %s->req_missing_for(\@group_names_) ) {
1373 print "1..0 # SKIP requirements not satisfied: $missing\n";
1374 exit 0;
1375 }
1376 }
1377EOS
1378
1379 push @chunks, <<'EOC';
1380
1381It also takes into account the C<RELEASE_TESTING> environment variable and
1382behaves like L</-die_without> for any requirement groups marked as
1383C<release_testing_mandatory>.
1384
afb8fc52 1385=head2 -die_without
1386
1387=over
1388
1389=item Arguments: @group_names
1390
1391=back
1392
1393A convenience wrapper around L</die_unless_req_ok_for>:
1394EOC
1395
1396 push @chunks, " use $class -die_without => qw(deploy admin);";
1397
1398 push @chunks, <<'EOC';
1399
1400=head2 -list_missing
1401
1402=over
1403
1404=item Arguments: @group_names
1405
1406=back
1407
1408A convenience wrapper around L</modreq_missing_for>:
1409
1410 perl -Ilib -MDBIx::Class::Optional::Dependencies=-list_missing,deploy,admin | cpanm
1411
79b1bf0a 1412=head1 METHODS
1413
1414=head2 req_group_list
1415
1416=over
1417
1418=item Arguments: none
1419
1420=item Return Value: \%list_of_requirement_groups
1421
1422=back
1423
e3fc11e1 1424This method should be used by DBIx::Class packagers, to get a hashref of all
31c31b8d 1425dependencies B<keyed> by dependency group. Each key (group name), or a combination
1426thereof (as an arrayref) can be supplied to the methods below.
79b1bf0a 1427The B<values> of the returned hash are currently a set of options B<without a
1428well defined structure>. If you have use for any of the contents - contact the
1429maintainers, instead of treating this as public (left alone stable) API.
1430
1431=head2 req_list_for
1432
1433=over
1434
31c31b8d 1435=item Arguments: $group_name | \@group_names
79b1bf0a 1436
31c31b8d 1437=item Return Value: \%set_of_module_version_pairs
79b1bf0a 1438
1439=back
1440
f6b26571 1441This method should be used by DBIx::Class extension authors, to determine the
31c31b8d 1442version of modules a specific set of features requires for this version of
e3a7746c 1443DBIx::Class (regardless of their availability on the system).
1444See the L</SYNOPSIS> for a real-world example.
1445
1446When handling C<test_*> groups this method behaves B<differently> from
1447L</modreq_list_for> below (and is the only such inconsistency among the
1448C<req_*> methods). If a particular group declares as requirements some
1449C<environment variables> and these requirements are not satisfied (the envvars
1450are unset) - then the C<module requirements> of this group are not included in
1451the returned list.
1452
1453=head2 modreq_list_for
1454
1455=over
1456
1457=item Arguments: $group_name | \@group_names
1458
1459=item Return Value: \%set_of_module_version_pairs
1460
1461=back
1462
1463Same as L</req_list_for> but does not take into consideration any
1464C<environment variable requirements> - returns just the list of required
1465modules.
79b1bf0a 1466
1467=head2 req_ok_for
1468
1469=over
1470
31c31b8d 1471=item Arguments: $group_name | \@group_names
79b1bf0a 1472
1473=item Return Value: 1|0
1474
1475=back
1476
e3a7746c 1477Returns true or false depending on whether all modules/envvars required by
1478the group(s) are loadable/set on the system.
79b1bf0a 1479
1480=head2 req_missing_for
1481
1482=over
1483
31c31b8d 1484=item Arguments: $group_name | \@group_names
79b1bf0a 1485
1486=item Return Value: $error_message_string
1487
1488=back
1489
31c31b8d 1490Returns a single-line string suitable for inclusion in larger error messages.
e3a7746c 1491This method would normally be used by DBIx::Class core features, to indicate to
1492the user that they need to install specific modules and/or set specific
1493environment variables before being able to use a specific feature set.
f6b26571 1494
e3fc11e1 1495For example if some of the requirements for C<deploy> are not available,
1496the returned string could look like:
79b1bf0a 1497EOC
f6b26571 1498
79b1bf0a 1499 push @chunks, qq{ "SQL::Translator~>=$sqltver" (see $class documentation for details)};
f6b26571 1500
79b1bf0a 1501 push @chunks, <<'EOC';
f6b26571 1502The author is expected to prepend the necessary text to this message before
e3a7746c 1503returning the actual error seen by the user. See also L</modreq_missing_for>
1504
1505=head2 modreq_missing_for
f6b26571 1506
e3a7746c 1507=over
1508
1509=item Arguments: $group_name | \@group_names
1510
1511=item Return Value: $error_message_string
1512
1513=back
1514
1515Same as L</req_missing_for> except that the error string is guaranteed to be
1516either empty, or contain a set of module requirement specifications suitable
1517for piping to e.g. L<cpanminus|App::cpanminus>. The method explicitly does not
1518attempt to validate the state of required environment variables (if any).
1519
1520For instance if some of the requirements for C<deploy> are not available,
1521the returned string could look like:
1522EOC
1523
1524 push @chunks, qq{ "SQL::Translator~>=$sqltver"};
1525
1526 push @chunks, <<'EOC';
afb8fc52 1527
1528See also L</-list_missing>.
1529
461e818a 1530=head2 skip_without
1531
1532=over
1533
1534=item Arguments: $group_name | \@group_names
1535
1536=back
1537
1538A convenience wrapper around L<skip|Test::More/SKIP>. It does not take neither
1539a reason (it is generated by L</req_missing_for>) nor an amount of skipped tests
1540(it is always C<1>, thus mandating unconditional use of
1541L<done_testing|Test::More/done_testing>). Most useful in combination with ad hoc
1542requirement specifications:
1543EOC
1544
1545 push @chunks, <<EOC;
1546 SKIP: {
1547 $class->skip_without([ deploy YAML>=0.90 ]);
1548
1549 ...
1550 }
1551EOC
1552
1553 push @chunks, <<'EOC';
1554
79b1bf0a 1555=head2 die_unless_req_ok_for
1556
1557=over
1558
31c31b8d 1559=item Arguments: $group_name | \@group_names
79b1bf0a 1560
1561=back
1562
31c31b8d 1563Checks if L</req_ok_for> passes for the supplied group(s), and
344f1f52 1564in case of failure throws an exception including the information
afb8fc52 1565from L</req_missing_for>. See also L</-die_without>.
79b1bf0a 1566
5ffa39c7 1567=head2 modreq_errorlist_for
79b1bf0a 1568
1569=over
1570
31c31b8d 1571=item Arguments: $group_name | \@group_names
79b1bf0a 1572
31c31b8d 1573=item Return Value: \%set_of_loaderrors_per_module
79b1bf0a 1574
1575=back
1576
4a0eed52 1577Returns a hashref containing the actual errors that occurred while attempting
31c31b8d 1578to load each module in the requirement group(s).
5ffa39c7 1579
1580=head2 req_errorlist_for
1581
1582Deprecated method name, equivalent (via proxy) to L</modreq_errorlist_for>.
1583
79b1bf0a 1584EOC
3ca0dcf0 1585
1586#@@
1587#@@ FOOTER
1588#@@
79b1bf0a 1589 push @chunks, <<'EOC';
1590=head1 FURTHER QUESTIONS?
1591
1592Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
1593
1594=head1 COPYRIGHT AND LICENSE
1595
a2bd3796 1596This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
1597by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
1598redistribute it and/or modify it under the same terms as the
1599L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.
79b1bf0a 1600EOC
3ca0dcf0 1601
3f5e367a 1602 eval {
1603 open (my $fh, '>', $podfn) or die;
1604 print $fh join ("\n\n", @chunks) or die;
1605 print $fh "\n" or die;
1606 close ($fh) or die;
1607 } or croak( "Unable to write $podfn: " . ( $! || $@ || 'unknown error') );
f6b26571 1608}
1609
8057ed01 16101;