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