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