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