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