File Coverage

blib/lib/DBIx/Class/Optional/Dependencies.pm
Criterion Covered Total %
statement 170 244 69.6
branch 106 176 60.2
condition 41 89 46.0
subroutine 18 21 85.7
pod 10 11 90.9
total 345 541 63.7


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