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