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