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