1 package DBIx::Class::Optional::Dependencies;
3 ### This may look crazy, but it in fact tangibly ( by 50(!)% ) shortens
4 # the skip-test time when everything requested is unavailable
6 if ( $ENV{RELEASE_TESTING} ) {
7 require warnings and warnings->import;
8 require strict and strict->import;
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
21 # POD is generated automatically by calling _gen_pod from the
22 # Makefile.PL in $AUTHOR mode
24 # *DELIBERATELY* not making a group for these - they must disappear
25 # forever as optdeps in the first place
28 'MooseX::Types' => '0.21',
29 'MooseX::Types::LoadableClass' => '0.011',
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
39 'JSON::Any' => '1.23',
43 _json_xs_compatible_json_any => {
45 'JSON::Any' => '1.31',
49 # a common placeholder for engines with IC::DT support based off DT::F::S
50 _ic_dt_strptime_based => {
54 'DateTime::Format::Strptime' => '1.2',
60 _rdbms_generic_odbc => {
66 _rdbms_generic_ado => {
72 # must list any dep used by adhoc testing
73 # this prevents the "skips due to forgotten deps" issue
76 'Class::DBI::Plugin::DeepAbstractSearch' => '0',
77 'Class::DBI' => '3.000005',
78 'Date::Simple' => '3.03',
80 'Class::Unload' => '0.07',
82 'Time::Piece::MySQL' => '0',
89 title => 'Storage::Replicated',
90 desc => 'Modules required for L<DBIx::Class::Storage::DBI::Replicated>',
95 include => 'replicated',
101 config_file_reader => {
103 title => 'Generic config reader',
104 desc => 'Modules required for generic config file parsing, currently Config::Any (rarely used at runtime)',
107 'Config::Any' => '0.20',
112 include => [qw( _json_any config_file_reader )],
115 'MooseX::Types::Path::Class' => '0.05',
116 'MooseX::Types::JSON' => '0.02',
119 title => 'DBIx::Class::Admin',
120 desc => 'Modules required for the DBIx::Class administrative library',
127 'Getopt::Long::Descriptive' => '0.081',
128 'Text::CSV' => '1.16',
131 title => 'dbicadmin',
132 desc => 'Modules required for the CLI DBIx::Class interface dbicadmin',
138 'SQL::Translator' => '0.11018',
141 title => 'Storage::DBI::deploy()',
142 desc => 'Modules required for L<DBIx::Class::Storage::DBI/deployment_statements> and L<DBIx::Class::Schema/deploy>',
148 'DateTime' => '0.55',
149 'DateTime::TimeZone::OlsonDB' => 0,
152 title => 'InflateColumn::DateTime support',
154 'Modules required for L<DBIx::Class::InflateColumn::DateTime>. '
155 . 'Note that this group does not require much on its own, but '
156 . 'instead is augmented by various RDBMS-specific groups. See the '
157 . 'documentation of each C<rbms_*> group for details',
163 'Math::BigInt' => '1.80',
164 'Math::Base36' => '0.07',
170 'Class::Data::Inheritable' => '0',
171 'Class::Trigger' => '0',
172 'DBIx::ContextualFetch' => '0',
176 title => 'DBIx::Class::CDBICompat support',
177 desc => 'Modules required for L<DBIx::Class::CDBICompat>'
183 'Test::Pod' => '1.42',
185 release_testing_mandatory => 1,
188 test_podcoverage => {
190 'Test::Pod::Coverage' => '1.08',
191 'Pod::Coverage' => '0.20',
193 release_testing_mandatory => 1,
198 'Test::EOL' => '1.0',
199 'Test::NoTabs' => '0.9',
201 release_testing_mandatory => 1,
206 'Test::Strict' => '0.20',
208 release_testing_mandatory => 1,
211 test_prettydebug => {
212 include => '_json_any',
215 test_admin_script => {
216 include => [qw( admin_script _json_xs_compatible_json_any )],
220 'Cpanel::JSON::XS' => 0,
223 # for t/admin/10script.t
224 ? ('Win32::ShellQuote' => 0)
225 # DWIW does not compile (./configure even) on win32
226 : ('JSON::DWIW' => 0 )
231 test_leaks_heavy => {
233 'Class::MethodCache' => '0.02',
234 'PadWalker' => '1.06',
240 title => 'Binary datatype support (certain RDBMS)',
242 'Some RDBMS engines require specific versions of the respective DBD '
243 . 'driver for binary data support. Note that this group does not '
244 . 'require anything on its own, but instead is augmented by various '
245 . 'RDBMS-specific groups. See the documentation of each rbms_* group '
250 # this is just for completeness as SQLite
251 # is a core dep of DBIC for testing
257 title => 'SQLite support',
258 desc => 'Modules required to connect to SQLite',
263 'DateTime::Format::SQLite' => '0',
269 # centralize the specification, as we have ICDT tests which can
270 # test the full behavior of RDBMS-specific ICDT on top of bare SQLite
275 'DateTime::Format::Pg' => '0.16004',
282 include => [qw( ic_dt _ic_dt_pg_base )],
286 include => '_ic_dt_pg_base',
291 title => 'PostgreSQL support',
292 desc => 'Modules required to connect to PostgreSQL',
297 'DBD::Pg' => '2.009002'
303 _rdbms_mssql_common => {
304 include => '_ic_dt_strptime_based',
307 rdbms_mssql_odbc => {
308 include => [qw( _rdbms_generic_odbc _rdbms_mssql_common )],
310 title => 'MSSQL support via DBD::ODBC',
311 desc => 'Modules required to connect to MSSQL via DBD::ODBC',
315 rdbms_mssql_sybase => {
316 include => '_rdbms_mssql_common',
321 title => 'MSSQL support via DBD::Sybase',
322 desc => 'Modules required to connect to MSSQL via DBD::Sybase',
327 include => [qw( _rdbms_generic_ado _rdbms_mssql_common )],
329 title => 'MSSQL support via DBD::ADO (Windows only)',
330 desc => 'Modules required to connect to MSSQL via DBD::ADO. This particular DBD is available on Windows only',
334 _rdbms_msaccess_common => {
335 include => '_ic_dt_strptime_based',
338 rdbms_msaccess_odbc => {
339 include => [qw( _rdbms_generic_odbc _rdbms_msaccess_common )],
341 title => 'MS Access support via DBD::ODBC',
342 desc => 'Modules required to connect to MS Access via DBD::ODBC',
346 rdbms_msaccess_ado => {
347 include => [qw( _rdbms_generic_ado _rdbms_msaccess_common )],
349 title => 'MS Access support via DBD::ADO (Windows only)',
350 desc => 'Modules required to connect to MS Access via DBD::ADO. This particular DBD is available on Windows only',
354 # centralize the specification, as we have ICDT tests which can
355 # test the full behavior of RDBMS-specific ICDT on top of bare SQLite
356 _ic_dt_mysql_base => {
360 'DateTime::Format::MySQL' => '0',
367 include => [qw( ic_dt _ic_dt_mysql_base )],
371 include => '_ic_dt_mysql_base',
376 title => 'MySQL support',
377 desc => 'Modules required to connect to MySQL',
382 include => 'id_shortener',
387 title => 'Oracle support',
388 desc => 'Modules required to connect to Oracle',
393 'DateTime::Format::Oracle' => '0',
400 include => '_ic_dt_strptime_based',
405 title => 'Sybase ASE support',
406 desc => 'Modules required to connect to Sybase ASE',
410 _rdbms_db2_common => {
414 'DateTime::Format::DB2' => '0',
421 include => '_rdbms_db2_common',
426 title => 'DB2 support',
427 desc => 'Modules required to connect to DB2',
432 include => [qw( _rdbms_generic_odbc _rdbms_db2_common )],
434 title => 'DB2 on AS/400 support',
435 desc => 'Modules required to connect to DB2 on AS/400',
440 include => '_ic_dt_strptime_based',
442 'DBD::Informix' => 0,
445 title => 'Informix support',
446 desc => 'Modules required to connect to Informix',
450 _rdbms_sqlanywhere_common => {
451 include => '_ic_dt_strptime_based',
454 rdbms_sqlanywhere => {
455 include => '_rdbms_sqlanywhere_common',
457 'DBD::SQLAnywhere' => 0,
460 title => 'SQLAnywhere support',
461 desc => 'Modules required to connect to SQLAnywhere',
465 rdbms_sqlanywhere_odbc => {
466 include => [qw( _rdbms_generic_odbc _rdbms_sqlanywhere_common )],
468 title => 'SQLAnywhere support via DBD::ODBC',
469 desc => 'Modules required to connect to SQLAnywhere via DBD::ODBC',
473 _rdbms_firebird_common => {
474 include => '_ic_dt_strptime_based',
478 include => '_rdbms_firebird_common',
480 'DBD::Firebird' => 0,
483 title => 'Firebird support',
484 desc => 'Modules required to connect to Firebird',
488 rdbms_firebird_interbase => {
489 include => '_rdbms_firebird_common',
491 'DBD::InterBase' => 0,
494 title => 'Firebird support via DBD::InterBase',
495 desc => 'Modules required to connect to Firebird via DBD::InterBase',
499 rdbms_firebird_odbc => {
500 include => [qw( _rdbms_generic_odbc _rdbms_firebird_common )],
502 title => 'Firebird support via DBD::ODBC',
503 desc => 'Modules required to connect to Firebird via DBD::ODBC',
507 test_rdbms_sqlite => {
508 include => 'rdbms_sqlite',
511 ### IMPORTANT - do not raise this dependency
512 ### even though many bugfixes are present in newer versions, the general DBIC
513 ### rule is to bend over backwards for available DBDs (given upgrading them is
514 ### often *not* easy or even possible)
516 'DBD::SQLite' => '1.29',
521 include => 'rdbms_pg',
523 DBICTEST_PG_DSN => 1,
524 DBICTEST_PG_USER => 0,
525 DBICTEST_PG_PASS => 0,
529 test_rdbms_mssql_odbc => {
530 include => 'rdbms_mssql_odbc',
532 DBICTEST_MSSQL_ODBC_DSN => 1,
533 DBICTEST_MSSQL_ODBC_USER => 0,
534 DBICTEST_MSSQL_ODBC_PASS => 0,
538 test_rdbms_mssql_ado => {
539 include => 'rdbms_mssql_ado',
541 DBICTEST_MSSQL_ADO_DSN => 1,
542 DBICTEST_MSSQL_ADO_USER => 0,
543 DBICTEST_MSSQL_ADO_PASS => 0,
547 test_rdbms_mssql_sybase => {
548 include => 'rdbms_mssql_sybase',
550 DBICTEST_MSSQL_DSN => 1,
551 DBICTEST_MSSQL_USER => 0,
552 DBICTEST_MSSQL_PASS => 0,
556 test_rdbms_msaccess_odbc => {
557 include => 'rdbms_msaccess_odbc',
559 DBICTEST_MSACCESS_ODBC_DSN => 1,
560 DBICTEST_MSACCESS_ODBC_USER => 0,
561 DBICTEST_MSACCESS_ODBC_PASS => 0,
568 test_rdbms_msaccess_ado => {
569 include => 'rdbms_msaccess_ado',
571 DBICTEST_MSACCESS_ADO_DSN => 1,
572 DBICTEST_MSACCESS_ADO_USER => 0,
573 DBICTEST_MSACCESS_ADO_PASS => 0,
580 test_rdbms_mysql => {
581 include => 'rdbms_mysql',
583 DBICTEST_MYSQL_DSN => 1,
584 DBICTEST_MYSQL_USER => 0,
585 DBICTEST_MYSQL_PASS => 0,
589 test_rdbms_oracle => {
590 include => 'rdbms_oracle',
592 DBICTEST_ORA_DSN => 1,
593 DBICTEST_ORA_USER => 0,
594 DBICTEST_ORA_PASS => 0,
597 'DBD::Oracle' => '1.24',
602 include => 'rdbms_ase',
604 DBICTEST_SYBASE_DSN => 1,
605 DBICTEST_SYBASE_USER => 0,
606 DBICTEST_SYBASE_PASS => 0,
611 include => 'rdbms_db2',
613 DBICTEST_DB2_DSN => 1,
614 DBICTEST_DB2_USER => 0,
615 DBICTEST_DB2_PASS => 0,
619 test_rdbms_db2_400 => {
620 include => 'rdbms_db2_400',
622 DBICTEST_DB2_400_DSN => 1,
623 DBICTEST_DB2_400_USER => 0,
624 DBICTEST_DB2_400_PASS => 0,
628 test_rdbms_informix => {
629 include => 'rdbms_informix',
631 DBICTEST_INFORMIX_DSN => 1,
632 DBICTEST_INFORMIX_USER => 0,
633 DBICTEST_INFORMIX_PASS => 0,
637 test_rdbms_sqlanywhere => {
638 include => 'rdbms_sqlanywhere',
640 DBICTEST_SQLANYWHERE_DSN => 1,
641 DBICTEST_SQLANYWHERE_USER => 0,
642 DBICTEST_SQLANYWHERE_PASS => 0,
646 test_rdbms_sqlanywhere_odbc => {
647 include => 'rdbms_sqlanywhere_odbc',
649 DBICTEST_SQLANYWHERE_ODBC_DSN => 1,
650 DBICTEST_SQLANYWHERE_ODBC_USER => 0,
651 DBICTEST_SQLANYWHERE_ODBC_PASS => 0,
655 test_rdbms_firebird => {
656 include => 'rdbms_firebird',
658 DBICTEST_FIREBIRD_DSN => 1,
659 DBICTEST_FIREBIRD_USER => 0,
660 DBICTEST_FIREBIRD_PASS => 0,
664 test_rdbms_firebird_interbase => {
665 include => 'rdbms_firebird_interbase',
667 DBICTEST_FIREBIRD_INTERBASE_DSN => 1,
668 DBICTEST_FIREBIRD_INTERBASE_USER => 0,
669 DBICTEST_FIREBIRD_INTERBASE_PASS => 0,
673 test_rdbms_firebird_odbc => {
674 include => 'rdbms_firebird_odbc',
676 DBICTEST_FIREBIRD_ODBC_DSN => 1,
677 DBICTEST_FIREBIRD_ODBC_USER => 0,
678 DBICTEST_FIREBIRD_ODBC_PASS => 0,
684 DBICTEST_MEMCACHED => 1,
687 'Cache::Memcached' => 0,
692 # we need to run the dbicadmin so we can self-generate its POD
693 # also we do not want surprises in case JSON::XS is in the path
694 # so make sure we get an always-working JSON::Any
697 _json_xs_compatible_json_any
706 'ExtUtils::MakeMaker' => '6.64',
707 'Module::Install' => '1.06',
708 'Pod::Inherit' => '0.91',
714 'CPAN::Uploader' => '0.103001',
730 if ($action eq '-die_without') {
734 eval { $class->die_unless_req_ok_for(\@_); 1 }
737 die "\n$err\n" if $err;
739 elsif ($action eq '-list_missing') {
740 print $class->modreq_missing_for(\@_);
744 elsif ($action eq '-skip_all_without') {
746 # sanity check - make sure ->current_test is 0 and no plan has been declared
750 Test::Builder->new->current_test
752 Test::Builder->new->has_plan
754 } and croak("Unable to invoke -skip_all_without after testing has started");
756 if ( my $missing = $class->req_missing_for(\@_) ) {
758 die ("\nMandatory requirements not satisfied during release-testing: $missing\n\n")
759 if $ENV{RELEASE_TESTING} and $class->_groups_to_reqs(\@_)->{release_testing_mandatory};
761 print "1..0 # SKIP requirements not satisfied: $missing\n";
765 elsif ($action =~ /^-/) {
766 croak "Unknown import-time action '$action'";
769 croak "$class is not an exporter, unable to import '$action'";
777 croak( __PACKAGE__ . " does not implement unimport" );
780 # OO for (mistakenly considered) ease of extensibility, not due to any need to
781 # carry state of any sort. This API is currently used outside, so leave as-is.
782 # FIXME - make sure to not propagate this further if module is extracted as a
783 # standalone library - keep the stupidity to a DBIC-secific shim!
786 shift->_groups_to_reqs(shift)->{effective_modreqs};
789 sub modreq_list_for {
790 shift->_groups_to_reqs(shift)->{modreqs};
795 { $_ => $_[0]->_groups_to_reqs($_) }
796 grep { $_ !~ /^_/ } keys %$dbic_reqs
800 sub req_errorlist_for { shift->modreq_errorlist_for(shift) } # deprecated
801 sub modreq_errorlist_for {
802 my ($self, $groups) = @_;
803 $self->_errorlist_for_modreqs( $self->_groups_to_reqs($groups)->{modreqs} );
807 shift->req_missing_for(shift) ? 0 : 1;
810 sub req_missing_for {
811 my ($self, $groups) = @_;
813 my $reqs = $self->_groups_to_reqs($groups);
815 my $mods_missing = $reqs->{missing_envvars}
816 ? $self->_list_physically_missing_modules( $reqs->{modreqs} )
817 : $self->modreq_missing_for($groups)
823 ! $reqs->{missing_envvars}
826 my @res = $mods_missing || ();
828 push @res, 'the following group(s) of environment variables: ' . join ' and ', sort map
829 { __envvar_group_desc($_) }
830 @{$reqs->{missing_envvars}}
831 if $reqs->{missing_envvars};
834 ( join ' as well as ', @res )
836 ( $reqs->{modreqs_fully_documented} ? " (see @{[ ref $self || $self ]} documentation for details)" : '' ),
840 sub modreq_missing_for {
841 my ($self, $groups) = @_;
843 my $reqs = $self->_groups_to_reqs($groups);
844 my $modreq_errors = $self->_errorlist_for_modreqs($reqs->{modreqs})
848 { $reqs->{modreqs}{$_} ? "$_~$reqs->{modreqs}{$_}" : $_ }
849 sort { lc($a) cmp lc($b) } keys %$modreq_errors
855 my ($self, $groups) = @_;
857 $tb ||= do { local $@; eval { Test::Builder->new } }
858 or croak "Calling skip_without() before loading Test::Builder makes no sense";
860 if ( my $err = $self->req_missing_for($groups) ) {
861 my ($fn, $ln) = (caller(0))[1,2];
862 $tb->skip("block in $fn around line $ln requires $err");
870 sub die_unless_req_ok_for {
871 if (my $err = shift->req_missing_for(shift) ) {
872 die "Unable to continue due to missing requirements: $err\n";
878 ### Private functions
880 # potentially shorten group desc
881 sub __envvar_group_desc {
884 my (@res, $last_prefix);
885 while (my $ev = shift @envs) {
886 my ($pref, $sep, $suff) = split / ([\_\-]) (?= [^\_\-]+ \z )/x, $ev;
888 if ( defined $sep and ($last_prefix||'') eq $pref ) {
889 push @res, "...${sep}${suff}"
895 $last_prefix = $pref if $sep;
901 my $groupname_re = qr/ [a-z_] [0-9_a-z]* /x;
902 my $modname_re = qr/ [A-Z_a-z] [0-9A-Z_a-z]* (?:::[0-9A-Z_a-z]+)* /x;
903 my $modver_re = qr/ [0-9]+ (?: \. [0-9]+ )? /x;
905 # Expand includes from a random group in a specific order:
906 # nonvariable groups first, then their includes, then the variable groups,
907 # then their includes.
908 # This allows reliably marking the rest of the mod reqs as variable (this is
909 # also why variable includes are currently not allowed)
910 sub __expand_includes {
911 my ($groups, $seen) = @_;
913 # !! DIFFERENT !! behavior and return depending on invocation mode
914 # (easier to recurse this way)
915 my $is_toplevel = $seen
920 my ($res_per_type, $missing_envvars);
922 # breadth-first evaluation, with non-variable includes on top
923 for my $g (@$groups) {
925 croak "Invalid requirement group name '$g': only ascii alphanumerics and _ are allowed"
926 if $g !~ qr/ \A $groupname_re \z/x;
928 my $r = $dbic_reqs->{$g}
929 or croak "Requirement group '$g' is not defined";
931 # always do this check *before* the $seen check
932 croak "Group '$g' with variable effective_modreqs can not be specified as an 'include'"
933 if ( $r->{env} and ! $is_toplevel );
935 next if $seen->{$g}++;
937 my $req_type = 'static';
939 if ( my @e = @{$r->{env}||[]} ) {
941 croak "Unexpected 'env' attribute under group '$g' (only allowed in test_* groups)"
942 unless $g =~ /^test_/;
944 croak "Unexpected *odd* list in 'env' under group '$g'"
947 # deconstruct the whole thing
948 my (@group_envnames_list, $some_envs_required, $some_required_missing);
950 push @group_envnames_list, my $envname = shift @e;
952 # env required or not
953 next unless shift @e;
955 $some_envs_required ||= 1;
957 $some_required_missing ||= (
958 ! defined $ENV{$envname}
960 ! length $ENV{$envname}
964 croak "None of the envvars in group '$g' declared as required, making the requirement moot"
965 unless $some_envs_required;
967 if ($some_required_missing) {
968 push @{$missing_envvars->{$g}}, \@group_envnames_list;
969 $req_type = 'variable';
973 push @{$res_per_type->{"base_${req_type}"}}, $g;
975 if (my $i = $dbic_reqs->{$g}{include}) {
976 $i = [ $i ] unless ref $i eq 'ARRAY';
978 croak "Malformed 'include' for group '$g': must be another existing group name or arrayref of existing group names"
981 push @{$res_per_type->{"incs_${req_type}"}}, @$i;
986 @{ $res_per_type->{"base_${_}"} || [] },
987 ( $res_per_type->{"incs_${_}"} ? __expand_includes( $res_per_type->{"incs_${_}"}, $seen ) : () ),
988 } qw(static variable);
990 return ! $is_toplevel ? @ret : do {
993 idx => 1 + keys %$rv,
994 missing_envvars => $missing_envvars->{$_},
996 $rv->{$_}{user_requested} = 1 for @$groups;
1002 our %req_unavailability_cache;
1004 # this method is just a lister and envvar/metadata checker - it does not try to load anything
1005 sub _groups_to_reqs {
1006 my ($self, $want) = @_;
1008 $want = [ $want || () ]
1009 unless ref $want eq 'ARRAY';
1011 croak "@{[ (caller(1))[3] ]}() expects a requirement group name or arrayref of group names"
1016 modreqs_fully_documented => 1,
1020 for my $piece (@$want) {
1021 if ($piece =~ qr/ \A $groupname_re \z /x) {
1022 push @$groups, $piece;
1024 elsif ( my ($mod, $ver) = $piece =~ qr/ \A ($modname_re) \>\= ($modver_re) \z /x ) {
1025 croak "Ad hoc module specification lists '$mod' twice"
1026 if exists $ret->{modreqs}{$mod};
1028 croak "Ad hoc module specification '${mod} >= $ver' (or greater) not listed in the test_adhoc optdep group" if (
1029 ! defined $dbic_reqs->{test_adhoc}{req}{$mod}
1031 $dbic_reqs->{test_adhoc}{req}{$mod} < $ver
1034 $ret->{modreqs}{$mod} = $ver;
1035 $ret->{modreqs_fully_documented} = 0;
1038 croak "Unsupported argument '$piece' supplied to @{[ (caller(1))[3] ]}()"
1042 my $all_groups = __expand_includes($groups);
1044 # pre-assemble list of augmentations, perform basic sanity checks
1045 # Note that below we *DO NOT* respect the source/target reationship, but
1046 # instead always default to augment the "later" group
1047 # This is done so that the "stable/variable" boundary keeps working as
1050 for my $requesting_group (keys %$all_groups) {
1051 if (my $ag = $dbic_reqs->{$requesting_group}{augment}) {
1052 for my $target_group (keys %$ag) {
1054 croak "Group '$requesting_group' claims to augment a non-existent group '$target_group'"
1055 unless $dbic_reqs->{$target_group};
1057 croak "Augmentation combined with variable effective_modreqs currently unsupported for group '$requesting_group'"
1058 if $dbic_reqs->{$requesting_group}{env};
1060 croak "Augmentation of group '$target_group' with variable effective_modreqs unsupported (requested by '$requesting_group')"
1061 if $dbic_reqs->{$target_group}{env};
1063 if (my @foreign = grep { $_ ne 'req' } keys %{$ag->{$target_group}} ) {
1064 croak "Only 'req' augmentations are currently supported (group '$requesting_group' attempts to alter '$foreign[0]' of group '$target_group'";
1067 $ret->{augments}{$target_group} = 1;
1069 # no augmentation for stuff that hasn't been selected
1070 if ( $all_groups->{$target_group} and my $ar = $ag->{$target_group}{req} ) {
1071 push @{$augmentations->{
1072 ( $all_groups->{$requesting_group}{idx} < $all_groups->{$target_group}{idx} )
1081 for my $group (sort { $all_groups->{$a}{idx} <=> $all_groups->{$b}{idx} } keys %$all_groups ) {
1083 my $group_reqs = $dbic_reqs->{$group}{req};
1086 for my $req_bag ($group_reqs, @{ $augmentations->{$group} || [] } ) {
1087 for (keys %$req_bag) {
1089 $_ =~ / \A $modname_re \z /x
1090 or croak "Requirement '$_' in group '$group' is not a valid module name";
1092 # !!!DO NOT CHANGE!!!
1093 # remember - version.pm may not be available on the system
1094 croak "Requirement '$_' in group '$group' specifies an invalid version '$req_bag->{$_}' (only plain non-underscored floating point decimals are supported)"
1095 if ( ($req_bag->{$_}||0) !~ qr/ \A $modver_re \z /x );
1099 if (my $e = $all_groups->{$group}{missing_envvars}) {
1100 push @{$ret->{missing_envvars}}, @$e;
1103 # assemble into the final ret
1106 ( $ret->{missing_envvars} ? () : 'effective_modreqs' ),
1108 for my $req_bag ($group_reqs, @{ $augmentations->{$group} || [] } ) {
1109 for my $mod (keys %$req_bag) {
1111 $ret->{$type}{$mod} = $req_bag->{$mod}||0 if (
1113 ! exists $ret->{$type}{$mod}
1115 # we sanitized the version to be numeric above - we can just -gt it
1116 ($req_bag->{$mod}||0) > $ret->{$type}{$mod}
1123 $ret->{modreqs_fully_documented} &&= !!$dbic_reqs->{$group}{pod}
1124 if $all_groups->{$group}{user_requested};
1126 $ret->{release_testing_mandatory} ||= !!$dbic_reqs->{$group}{release_testing_mandatory};
1133 # this method tries to find/load specified modreqs and returns a hashref of
1134 # module/loaderror pairs for anything that failed
1135 sub _errorlist_for_modreqs {
1136 # args supposedly already went through _groups_to_reqs and are therefore sanitized
1137 # safe to eval at will
1138 my ($self, $reqs) = @_;
1142 for my $m ( keys %$reqs ) {
1143 my $v = $reqs->{$m};
1145 if (! exists $req_unavailability_cache{$m}{$v} ) {
1147 eval( "require $m;" . ( $v ? "$m->VERSION(q($v))" : '' ) );
1148 $req_unavailability_cache{$m}{$v} = $@;
1151 $ret->{$m} = $req_unavailability_cache{$m}{$v}
1152 if $req_unavailability_cache{$m}{$v};
1158 # Unlike the above DO NOT try to load anything
1159 # This is executed when some needed envvars are not available
1160 # which in turn means a module load will never be reached anyway
1161 # This is important because some modules (especially DBDs) can be
1162 # *really* fickle when a require() is attempted, with pretty confusing
1163 # side-effects (especially on windows)
1164 sub _list_physically_missing_modules {
1165 my ($self, $modreqs) = @_;
1167 # in case there is a coderef in @INC there is nothing we can definitively prove
1168 # so short circuit directly
1169 return '' if grep { length ref $_ } @INC;
1171 my @definitely_missing;
1172 for my $mod (keys %$modreqs) {
1173 (my $fn = $mod . '.pm') =~ s|::|/|g;
1175 push @definitely_missing, $mod unless grep
1176 # this should work on any combination of slashes
1177 { $_ and -d $_ and -f "$_/$fn" and -r "$_/$fn" }
1183 { $modreqs->{$_} ? "$_~$modreqs->{$_}" : $_ }
1184 sort { lc($a) cmp lc($b) } @definitely_missing
1189 # This is to be called by the author only (automatically in Makefile.PL)
1191 my ($class, $distver, $pod_dir) = @_;
1193 die "No POD root dir supplied" unless $pod_dir;
1196 eval { require DBIx::Class; DBIx::Class->VERSION; }
1199 "\n\n---------------------------------------------------------------------\n" .
1200 'Unable to load core DBIx::Class module to determine current version, '.
1201 'possibly due to missing dependencies. Author-mode autodocumentation ' .
1203 "\n\n---------------------------------------------------------------------\n"
1206 # do not ask for a recent version, use 1.x API calls
1207 # this *may* execute on a smoker with old perl or whatnot
1210 (my $modfn = __PACKAGE__ . '.pm') =~ s|::|/|g;
1212 (my $podfn = "$pod_dir/$modfn") =~ s/\.pm$/\.pod/;
1213 (my $dir = $podfn) =~ s|/[^/]+$||;
1215 File::Path::mkpath([$dir]);
1217 my $sqltver = $class->req_list_for('deploy')->{'SQL::Translator'}
1218 or die "Hrmm? No sqlt dep?";
1226 push @chunks, <<"EOC";
1227 #########################################################################
1228 ##################### A U T O G E N E R A T E D ########################
1229 #########################################################################
1231 # The contents of this POD file are auto-generated. Any changes you make
1232 # will be lost. If you need to change the generated text edit _gen_pod()
1233 # at the end of $modfn
1238 $class - Optional module dependency specifications (for module authors)
1243 #@@ SYNOPSIS HEADING
1245 push @chunks, <<"EOC";
1248 Somewhere in your build-file (e.g. L<ExtUtils::MakeMaker>'s F<Makefile.PL>):
1252 \$EUMM_ARGS{CONFIGURE_REQUIRES} = {
1253 \%{ \$EUMM_ARGS{CONFIGURE_REQUIRES} || {} },
1254 'DBIx::Class' => '$distver',
1259 my %DBIC_DEPLOY_AND_ORACLE_DEPS = %{ eval {
1261 $class->req_list_for([qw( deploy rdbms_oracle ic_dt )]);
1264 \$EUMM_ARGS{PREREQ_PM} = {
1265 \%DBIC_DEPLOY_AND_ORACLE_DEPS,
1266 \%{ \$EUMM_ARGS{PREREQ_PM} || {} },
1271 ExtUtils::MakeMaker::WriteMakefile(\%EUMM_ARGS);
1273 B<Note>: The C<eval> protection within the example is due to support for
1274 requirements during L<the C<configure> build phase|CPAN::Meta::Spec/Phases>
1275 not being available on a sufficient portion of production installations of
1276 Perl. Robust support for such dependency requirements is available in the
1277 L<CPAN> installer only since version C<1.94_56> first made available for
1278 production with perl version C<5.12>. It is the belief of the current
1279 maintainer that support for requirements during the C<configure> build phase
1280 will not be sufficiently ubiquitous until the B<year 2020> at the earliest,
1281 hence the extra care demonstrated above. It should also be noted that some
1282 3rd party installers (e.g. L<cpanminus|App::cpanminus>) do the right thing
1283 with configure requirements independent from the versions of perl and CPAN
1289 #@@ DESCRIPTION HEADING
1291 push @chunks, <<'EOC';
1294 Some of the less-frequently used features of L<DBIx::Class> have external
1295 module dependencies on their own. In order not to burden the average user
1296 with modules they will never use, these optional dependencies are not included
1297 in the base Makefile.PL. Instead an exception with a descriptive message is
1298 thrown when a specific feature can't find one or several modules required for
1299 its operation. This module is the central holding place for the current list
1300 of such dependencies, for DBIx::Class core authors, and DBIx::Class extension
1303 Dependencies are organized in L<groups|/CURRENT REQUIREMENT GROUPS> where each
1304 group can list one or more required modules, with an optional minimum version
1305 (or 0 for any version). In addition groups prefixed with C<test_> can specify
1306 a set of environment variables, some (or all) of which are marked as required
1307 for the group to be considered by L</req_list_for>
1309 Each group name (or a combination thereof) can be used in the
1310 L<public methods|/METHODS> as described below.
1315 #@@ REQUIREMENT GROUPLIST HEADING
1317 push @chunks, '=head1 CURRENT REQUIREMENT GROUPS';
1319 my $standalone_info;
1321 for my $group (sort keys %$dbic_reqs) {
1323 my $info = $standalone_info->{$group} ||= $class->_groups_to_reqs($group);
1326 $info->{modreqs_fully_documented}
1328 ( $info->{augments} or $info->{modreqs} )
1331 my $p = $dbic_reqs->{$group}{pod};
1334 "=head2 $p->{title}",
1340 if ( keys %{ $info->{modreqs}||{} } ) {
1342 { "=item * $_" . ($info->{modreqs}{$_} ? " >= $info->{modreqs}{$_}" : '') }
1343 ( sort keys %{ $info->{modreqs} } )
1347 push @chunks, '=item * No standalone requirements',
1350 push @chunks, '=back';
1352 for my $ag ( sort keys %{ $info->{augments} || {} } ) {
1353 my $ag_info = $standalone_info->{$ag} ||= $class->_groups_to_reqs($ag);
1355 my $newreqs = $class->modreq_list_for([ $group, $ag ]);
1356 for (keys %$newreqs) {
1357 delete $newreqs->{$_} if (
1358 ( defined $info->{modreqs}{$_} and $info->{modreqs}{$_} == $newreqs->{$_} )
1360 ( defined $ag_info->{modreqs}{$_} and $ag_info->{modreqs}{$_} == $newreqs->{$_} )
1364 if (keys %$newreqs) {
1366 "Combined with L</$ag> additionally requires:",
1369 { "=item * $_" . ($newreqs->{$_} ? " >= $newreqs->{$_}" : '') }
1370 ( sort keys %$newreqs )
1380 #@@ API DOCUMENTATION HEADING
1382 push @chunks, <<'EOC';
1384 =head1 IMPORT-LIKE ACTIONS
1386 Even though this module is not an L<Exporter>, it recognizes several C<actions>
1387 supplied to its C<import> method.
1389 =head2 -skip_all_without
1393 =item Arguments: @group_names
1397 A convenience wrapper for use during testing:
1400 push @chunks, " use $class -skip_all_without => qw(admin test_rdbms_mysql);";
1402 push @chunks, 'Roughly equivalent to the following code:';
1404 push @chunks, sprintf <<'EOS', ($class) x 2;
1408 if ( my $missing = %s->req_missing_for(\@group_names_) ) {
1409 print "1..0 # SKIP requirements not satisfied: $missing\n";
1415 push @chunks, <<'EOC';
1417 It also takes into account the C<RELEASE_TESTING> environment variable and
1418 behaves like L</-die_without> for any requirement groups marked as
1419 C<release_testing_mandatory>.
1425 =item Arguments: @group_names
1429 A convenience wrapper around L</die_unless_req_ok_for>:
1432 push @chunks, " use $class -die_without => qw(deploy admin);";
1434 push @chunks, <<'EOC';
1436 =head2 -list_missing
1440 =item Arguments: @group_names
1444 A convenience wrapper around L</modreq_missing_for>:
1446 perl -Ilib -MDBIx::Class::Optional::Dependencies=-list_missing,deploy,admin | cpanm
1450 =head2 req_group_list
1454 =item Arguments: none
1456 =item Return Value: \%list_of_requirement_groups
1460 This method should be used by DBIx::Class packagers, to get a hashref of all
1461 dependencies B<keyed> by dependency group. Each key (group name), or a combination
1462 thereof (as an arrayref) can be supplied to the methods below.
1463 The B<values> of the returned hash are currently a set of options B<without a
1464 well defined structure>. If you have use for any of the contents - contact the
1465 maintainers, instead of treating this as public (left alone stable) API.
1471 =item Arguments: $group_name | \@group_names
1473 =item Return Value: \%set_of_module_version_pairs
1477 This method should be used by DBIx::Class extension authors, to determine the
1478 version of modules a specific set of features requires for this version of
1479 DBIx::Class (regardless of their availability on the system).
1480 See the L</SYNOPSIS> for a real-world example.
1482 When handling C<test_*> groups this method behaves B<differently> from
1483 L</modreq_list_for> below (and is the only such inconsistency among the
1484 C<req_*> methods). If a particular group declares as requirements some
1485 C<environment variables> and these requirements are not satisfied (the envvars
1486 are unset) - then the C<module requirements> of this group are not included in
1489 =head2 modreq_list_for
1493 =item Arguments: $group_name | \@group_names
1495 =item Return Value: \%set_of_module_version_pairs
1499 Same as L</req_list_for> but does not take into consideration any
1500 C<environment variable requirements> - returns just the list of required
1507 =item Arguments: $group_name | \@group_names
1509 =item Return Value: 1|0
1513 Returns true or false depending on whether all modules/envvars required by
1514 the group(s) are loadable/set on the system.
1516 =head2 req_missing_for
1520 =item Arguments: $group_name | \@group_names
1522 =item Return Value: $error_message_string
1526 Returns a single-line string suitable for inclusion in larger error messages.
1527 This method would normally be used by DBIx::Class core features, to indicate to
1528 the user that they need to install specific modules and/or set specific
1529 environment variables before being able to use a specific feature set.
1531 For example if some of the requirements for C<deploy> are not available,
1532 the returned string could look like:
1535 push @chunks, qq{ "SQL::Translator~$sqltver" (see $class documentation for details)};
1537 push @chunks, <<'EOC';
1538 The author is expected to prepend the necessary text to this message before
1539 returning the actual error seen by the user. See also L</modreq_missing_for>
1541 =head2 modreq_missing_for
1545 =item Arguments: $group_name | \@group_names
1547 =item Return Value: $error_message_string
1551 Same as L</req_missing_for> except that the error string is guaranteed to be
1552 either empty, or contain a set of module requirement specifications suitable
1553 for piping to e.g. L<cpanminus|App::cpanminus>. The method explicitly does not
1554 attempt to validate the state of required environment variables (if any).
1556 For instance if some of the requirements for C<deploy> are not available,
1557 the returned string could look like:
1560 push @chunks, qq{ "SQL::Translator~$sqltver"};
1562 push @chunks, <<'EOC';
1564 See also L</-list_missing>.
1570 =item Arguments: $group_name | \@group_names
1574 A convenience wrapper around L<skip|Test::More/SKIP>. It does not take neither
1575 a reason (it is generated by L</req_missing_for>) nor an amount of skipped tests
1576 (it is always C<1>, thus mandating unconditional use of
1577 L<done_testing|Test::More/done_testing>). Most useful in combination with ad hoc
1578 requirement specifications:
1581 push @chunks, <<EOC;
1583 $class->skip_without([ deploy YAML>=0.90 ]);
1589 push @chunks, <<'EOC';
1591 =head2 die_unless_req_ok_for
1595 =item Arguments: $group_name | \@group_names
1599 Checks if L</req_ok_for> passes for the supplied group(s), and
1600 in case of failure throws an exception including the information
1601 from L</req_missing_for>. See also L</-die_without>.
1603 =head2 modreq_errorlist_for
1607 =item Arguments: $group_name | \@group_names
1609 =item Return Value: \%set_of_loaderrors_per_module
1613 Returns a hashref containing the actual errors that occurred while attempting
1614 to load each module in the requirement group(s).
1616 =head2 req_errorlist_for
1618 Deprecated method name, equivalent (via proxy) to L</modreq_errorlist_for>.
1625 push @chunks, <<'EOC';
1626 =head1 FURTHER QUESTIONS?
1628 Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
1630 =head1 COPYRIGHT AND LICENSE
1632 This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
1633 by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
1634 redistribute it and/or modify it under the same terms as the
1635 L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.
1639 open (my $fh, '>', $podfn) or die;
1640 print $fh join ("\n\n", @chunks) or die;
1641 print $fh "\n" or die;
1643 } or croak( "Unable to write $podfn: " . ( $! || $@ || 'unknown error') );