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',
83 'DBD::mysql' => '4.023',
90 title => 'Storage::Replicated',
91 desc => 'Modules required for L<DBIx::Class::Storage::DBI::Replicated>',
96 include => 'replicated',
102 config_file_reader => {
104 title => 'Generic config reader',
105 desc => 'Modules required for generic config file parsing, currently Config::Any (rarely used at runtime)',
108 'Config::Any' => '0.20',
113 include => [qw( _json_any config_file_reader )],
116 'MooseX::Types::Path::Class' => '0.05',
117 'MooseX::Types::JSON' => '0.02',
120 title => 'DBIx::Class::Admin',
121 desc => 'Modules required for the DBIx::Class administrative library',
128 'Getopt::Long::Descriptive' => '0.081',
129 'Text::CSV' => '1.16',
132 title => 'dbicadmin',
133 desc => 'Modules required for the CLI DBIx::Class interface dbicadmin',
139 'SQL::Translator' => '0.11018',
142 title => 'Storage::DBI::deploy()',
143 desc => 'Modules required for L<DBIx::Class::Storage::DBI/deployment_statements> and L<DBIx::Class::Schema/deploy>',
149 'Path::Class' => '0.18',
152 title => 'DBIx::Class::InflateColumn::File (Deprecated)',
153 desc => 'Modules required for the deprecated L<DBIx::Class::InflateColumn::File>',
159 'DateTime' => '0.55',
160 'DateTime::TimeZone::OlsonDB' => 0,
163 title => 'InflateColumn::DateTime support',
165 'Modules required for L<DBIx::Class::InflateColumn::DateTime>. '
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<rbms_*> group for details',
174 'Math::BigInt' => '1.80',
175 'Math::Base36' => '0.07',
181 'Class::Data::Inheritable' => '0',
182 'Class::Trigger' => '0',
183 'DBIx::ContextualFetch' => '0',
187 title => 'DBIx::Class::CDBICompat support',
188 desc => 'Modules required for L<DBIx::Class::CDBICompat>'
194 'Test::Pod' => '1.42',
196 release_testing_mandatory => 1,
199 test_podcoverage => {
201 'Test::Pod::Coverage' => '1.08',
202 'Pod::Coverage' => '0.20',
204 release_testing_mandatory => 1,
209 'Test::EOL' => '1.0',
210 'Test::NoTabs' => '0.9',
212 release_testing_mandatory => 1,
217 'Test::Strict' => '0.20',
219 release_testing_mandatory => 1,
222 test_prettydebug => {
223 include => '_json_any',
226 test_admin_script => {
227 include => [qw( admin_script _json_xs_compatible_json_any )],
231 'Cpanel::JSON::XS' => 0,
234 # for t/admin/10script.t
235 ? ('Win32::ShellQuote' => 0)
236 # DWIW does not compile (./configure even) on win32
237 : ('JSON::DWIW' => 0 )
242 test_leaks_heavy => {
244 'Class::MethodCache' => '0.02',
245 'PadWalker' => '1.06',
251 title => 'Binary datatype support (certain RDBMS)',
253 'Some RDBMS engines require specific versions of the respective DBD '
254 . 'driver for binary data support. Note that this group does not '
255 . 'require anything on its own, but instead is augmented by various '
256 . 'RDBMS-specific groups. See the documentation of each rbms_* group '
261 # this is just for completeness as SQLite
262 # is a core dep of DBIC for testing
268 title => 'SQLite support',
269 desc => 'Modules required to connect to SQLite',
274 'DateTime::Format::SQLite' => '0',
280 # centralize the specification, as we have ICDT tests which can
281 # test the full behavior of RDBMS-specific ICDT on top of bare SQLite
286 'DateTime::Format::Pg' => '0.16004',
293 include => [qw( ic_dt _ic_dt_pg_base )],
297 include => '_ic_dt_pg_base',
302 title => 'PostgreSQL support',
303 desc => 'Modules required to connect to PostgreSQL',
308 'DBD::Pg' => '2.009002'
314 _rdbms_mssql_common => {
315 include => '_ic_dt_strptime_based',
318 rdbms_mssql_odbc => {
319 include => [qw( _rdbms_generic_odbc _rdbms_mssql_common )],
321 title => 'MSSQL support via DBD::ODBC',
322 desc => 'Modules required to connect to MSSQL via DBD::ODBC',
326 rdbms_mssql_sybase => {
327 include => '_rdbms_mssql_common',
332 title => 'MSSQL support via DBD::Sybase',
333 desc => 'Modules required to connect to MSSQL via DBD::Sybase',
338 include => [qw( _rdbms_generic_ado _rdbms_mssql_common )],
340 title => 'MSSQL support via DBD::ADO (Windows only)',
341 desc => 'Modules required to connect to MSSQL via DBD::ADO. This particular DBD is available on Windows only',
345 _rdbms_msaccess_common => {
346 include => '_ic_dt_strptime_based',
349 rdbms_msaccess_odbc => {
350 include => [qw( _rdbms_generic_odbc _rdbms_msaccess_common )],
352 title => 'MS Access support via DBD::ODBC',
353 desc => 'Modules required to connect to MS Access via DBD::ODBC',
357 rdbms_msaccess_ado => {
358 include => [qw( _rdbms_generic_ado _rdbms_msaccess_common )],
360 title => 'MS Access support via DBD::ADO (Windows only)',
361 desc => 'Modules required to connect to MS Access via DBD::ADO. This particular DBD is available on Windows only',
365 # centralize the specification, as we have ICDT tests which can
366 # test the full behavior of RDBMS-specific ICDT on top of bare SQLite
367 _ic_dt_mysql_base => {
371 'DateTime::Format::MySQL' => '0',
378 include => [qw( ic_dt _ic_dt_mysql_base )],
382 include => '_ic_dt_mysql_base',
387 title => 'MySQL support',
388 desc => 'Modules required to connect to MySQL',
393 include => 'id_shortener',
398 title => 'Oracle support',
399 desc => 'Modules required to connect to Oracle',
404 'DateTime::Format::Oracle' => '0',
411 include => '_ic_dt_strptime_based',
416 title => 'Sybase ASE support',
417 desc => 'Modules required to connect to Sybase ASE',
421 _rdbms_db2_common => {
425 'DateTime::Format::DB2' => '0',
432 include => '_rdbms_db2_common',
437 title => 'DB2 support',
438 desc => 'Modules required to connect to DB2',
443 include => [qw( _rdbms_generic_odbc _rdbms_db2_common )],
445 title => 'DB2 on AS/400 support',
446 desc => 'Modules required to connect to DB2 on AS/400',
451 include => '_ic_dt_strptime_based',
453 'DBD::Informix' => 0,
456 title => 'Informix support',
457 desc => 'Modules required to connect to Informix',
461 _rdbms_sqlanywhere_common => {
462 include => '_ic_dt_strptime_based',
465 rdbms_sqlanywhere => {
466 include => '_rdbms_sqlanywhere_common',
468 'DBD::SQLAnywhere' => 0,
471 title => 'SQLAnywhere support',
472 desc => 'Modules required to connect to SQLAnywhere',
476 rdbms_sqlanywhere_odbc => {
477 include => [qw( _rdbms_generic_odbc _rdbms_sqlanywhere_common )],
479 title => 'SQLAnywhere support via DBD::ODBC',
480 desc => 'Modules required to connect to SQLAnywhere via DBD::ODBC',
484 _rdbms_firebird_common => {
485 include => '_ic_dt_strptime_based',
489 include => '_rdbms_firebird_common',
491 'DBD::Firebird' => 0,
494 title => 'Firebird support',
495 desc => 'Modules required to connect to Firebird',
499 rdbms_firebird_interbase => {
500 include => '_rdbms_firebird_common',
502 'DBD::InterBase' => 0,
505 title => 'Firebird support via DBD::InterBase',
506 desc => 'Modules required to connect to Firebird via DBD::InterBase',
510 rdbms_firebird_odbc => {
511 include => [qw( _rdbms_generic_odbc _rdbms_firebird_common )],
513 title => 'Firebird support via DBD::ODBC',
514 desc => 'Modules required to connect to Firebird via DBD::ODBC',
518 test_rdbms_sqlite => {
519 include => 'rdbms_sqlite',
522 ### IMPORTANT - do not raise this dependency
523 ### even though many bugfixes are present in newer versions, the general DBIC
524 ### rule is to bend over backwards for available DBDs (given upgrading them is
525 ### often *not* easy or even possible)
527 'DBD::SQLite' => '1.29',
532 include => 'rdbms_pg',
534 DBICTEST_PG_DSN => 1,
535 DBICTEST_PG_USER => 0,
536 DBICTEST_PG_PASS => 0,
540 test_rdbms_mssql_odbc => {
541 include => 'rdbms_mssql_odbc',
543 DBICTEST_MSSQL_ODBC_DSN => 1,
544 DBICTEST_MSSQL_ODBC_USER => 0,
545 DBICTEST_MSSQL_ODBC_PASS => 0,
549 test_rdbms_mssql_ado => {
550 include => 'rdbms_mssql_ado',
552 DBICTEST_MSSQL_ADO_DSN => 1,
553 DBICTEST_MSSQL_ADO_USER => 0,
554 DBICTEST_MSSQL_ADO_PASS => 0,
558 test_rdbms_mssql_sybase => {
559 include => 'rdbms_mssql_sybase',
561 DBICTEST_MSSQL_DSN => 1,
562 DBICTEST_MSSQL_USER => 0,
563 DBICTEST_MSSQL_PASS => 0,
567 test_rdbms_msaccess_odbc => {
568 include => 'rdbms_msaccess_odbc',
570 DBICTEST_MSACCESS_ODBC_DSN => 1,
571 DBICTEST_MSACCESS_ODBC_USER => 0,
572 DBICTEST_MSACCESS_ODBC_PASS => 0,
579 test_rdbms_msaccess_ado => {
580 include => 'rdbms_msaccess_ado',
582 DBICTEST_MSACCESS_ADO_DSN => 1,
583 DBICTEST_MSACCESS_ADO_USER => 0,
584 DBICTEST_MSACCESS_ADO_PASS => 0,
591 test_rdbms_mysql => {
592 include => 'rdbms_mysql',
594 DBICTEST_MYSQL_DSN => 1,
595 DBICTEST_MYSQL_USER => 0,
596 DBICTEST_MYSQL_PASS => 0,
600 test_rdbms_oracle => {
601 include => 'rdbms_oracle',
603 DBICTEST_ORA_DSN => 1,
604 DBICTEST_ORA_USER => 0,
605 DBICTEST_ORA_PASS => 0,
608 'DBD::Oracle' => '1.24',
613 include => 'rdbms_ase',
615 DBICTEST_SYBASE_DSN => 1,
616 DBICTEST_SYBASE_USER => 0,
617 DBICTEST_SYBASE_PASS => 0,
622 include => 'rdbms_db2',
624 DBICTEST_DB2_DSN => 1,
625 DBICTEST_DB2_USER => 0,
626 DBICTEST_DB2_PASS => 0,
630 test_rdbms_db2_400 => {
631 include => 'rdbms_db2_400',
633 DBICTEST_DB2_400_DSN => 1,
634 DBICTEST_DB2_400_USER => 0,
635 DBICTEST_DB2_400_PASS => 0,
639 test_rdbms_informix => {
640 include => 'rdbms_informix',
642 DBICTEST_INFORMIX_DSN => 1,
643 DBICTEST_INFORMIX_USER => 0,
644 DBICTEST_INFORMIX_PASS => 0,
648 test_rdbms_sqlanywhere => {
649 include => 'rdbms_sqlanywhere',
651 DBICTEST_SQLANYWHERE_DSN => 1,
652 DBICTEST_SQLANYWHERE_USER => 0,
653 DBICTEST_SQLANYWHERE_PASS => 0,
657 test_rdbms_sqlanywhere_odbc => {
658 include => 'rdbms_sqlanywhere_odbc',
660 DBICTEST_SQLANYWHERE_ODBC_DSN => 1,
661 DBICTEST_SQLANYWHERE_ODBC_USER => 0,
662 DBICTEST_SQLANYWHERE_ODBC_PASS => 0,
666 test_rdbms_firebird => {
667 include => 'rdbms_firebird',
669 DBICTEST_FIREBIRD_DSN => 1,
670 DBICTEST_FIREBIRD_USER => 0,
671 DBICTEST_FIREBIRD_PASS => 0,
675 test_rdbms_firebird_interbase => {
676 include => 'rdbms_firebird_interbase',
678 DBICTEST_FIREBIRD_INTERBASE_DSN => 1,
679 DBICTEST_FIREBIRD_INTERBASE_USER => 0,
680 DBICTEST_FIREBIRD_INTERBASE_PASS => 0,
684 test_rdbms_firebird_odbc => {
685 include => 'rdbms_firebird_odbc',
687 DBICTEST_FIREBIRD_ODBC_DSN => 1,
688 DBICTEST_FIREBIRD_ODBC_USER => 0,
689 DBICTEST_FIREBIRD_ODBC_PASS => 0,
695 DBICTEST_MEMCACHED => 1,
698 'Cache::Memcached' => 0,
703 # we need to run the dbicadmin so we can self-generate its POD
704 # also we do not want surprises in case JSON::XS is in the path
705 # so make sure we get an always-working JSON::Any
708 _json_xs_compatible_json_any
717 'ExtUtils::MakeMaker' => '6.64',
718 'Module::Install' => '1.06',
719 'Pod::Inherit' => '0.91',
725 'CPAN::Uploader' => '0.103001',
741 if ($action eq '-die_without') {
745 eval { $class->die_unless_req_ok_for(\@_); 1 }
748 die "\n$err\n" if $err;
750 elsif ($action eq '-list_missing') {
751 print $class->modreq_missing_for(\@_);
755 elsif ($action eq '-skip_all_without') {
757 # sanity check - make sure ->current_test is 0 and no plan has been declared
761 Test::Builder->new->current_test
763 Test::Builder->new->has_plan
765 } and croak("Unable to invoke -skip_all_without after testing has started");
767 if ( my $missing = $class->req_missing_for(\@_) ) {
769 die ("\nMandatory requirements not satisfied during release-testing: $missing\n\n")
770 if $ENV{RELEASE_TESTING} and $class->_groups_to_reqs(\@_)->{release_testing_mandatory};
772 print "1..0 # SKIP requirements not satisfied: $missing\n";
776 elsif ($action =~ /^-/) {
777 croak "Unknown import-time action '$action'";
780 croak "$class is not an exporter, unable to import '$action'";
788 croak( __PACKAGE__ . " does not implement unimport" );
791 # OO for (mistakenly considered) ease of extensibility, not due to any need to
792 # carry state of any sort. This API is currently used outside, so leave as-is.
793 # FIXME - make sure to not propagate this further if module is extracted as a
794 # standalone library - keep the stupidity to a DBIC-secific shim!
797 shift->_groups_to_reqs(shift)->{effective_modreqs};
800 sub modreq_list_for {
801 shift->_groups_to_reqs(shift)->{modreqs};
806 { $_ => $_[0]->_groups_to_reqs($_) }
807 grep { $_ !~ /^_/ } keys %$dbic_reqs
811 sub req_errorlist_for { shift->modreq_errorlist_for(shift) } # deprecated
812 sub modreq_errorlist_for {
813 my ($self, $groups) = @_;
814 $self->_errorlist_for_modreqs( $self->_groups_to_reqs($groups)->{modreqs} );
818 shift->req_missing_for(shift) ? 0 : 1;
821 sub req_missing_for {
822 my ($self, $groups) = @_;
824 my $reqs = $self->_groups_to_reqs($groups);
826 my $mods_missing = $reqs->{missing_envvars}
827 ? $self->_list_physically_missing_modules( $reqs->{modreqs} )
828 : $self->modreq_missing_for($groups)
834 ! $reqs->{missing_envvars}
837 my @res = $mods_missing || ();
839 push @res, 'the following group(s) of environment variables: ' . join ' and ', sort map
840 { __envvar_group_desc($_) }
841 @{$reqs->{missing_envvars}}
842 if $reqs->{missing_envvars};
845 ( join ' as well as ', @res )
847 ( $reqs->{modreqs_fully_documented} ? " (see @{[ ref $self || $self ]} documentation for details)" : '' ),
851 sub modreq_missing_for {
852 my ($self, $groups) = @_;
854 my $reqs = $self->_groups_to_reqs($groups);
855 my $modreq_errors = $self->_errorlist_for_modreqs($reqs->{modreqs})
859 { $reqs->{modreqs}{$_} ? "$_~$reqs->{modreqs}{$_}" : $_ }
860 sort { lc($a) cmp lc($b) } keys %$modreq_errors
866 my ($self, $groups) = @_;
868 $tb ||= do { local $@; eval { Test::Builder->new } }
869 or croak "Calling skip_without() before loading Test::Builder makes no sense";
871 if ( my $err = $self->req_missing_for($groups) ) {
872 my ($fn, $ln) = (caller(0))[1,2];
873 $tb->skip("block in $fn around line $ln requires $err");
875 BEGIN { ${^WARNING_BITS} = "" }
883 sub die_unless_req_ok_for {
884 if (my $err = shift->req_missing_for(shift) ) {
885 die "Unable to continue due to missing requirements: $err\n";
891 ### Private functions
893 # potentially shorten group desc
894 sub __envvar_group_desc {
897 my (@res, $last_prefix);
898 while (my $ev = shift @envs) {
899 my ($pref, $sep, $suff) = split / ([\_\-]) (?= [^\_\-]+ \z )/x, $ev;
901 if ( defined $sep and ($last_prefix||'') eq $pref ) {
902 push @res, "...${sep}${suff}"
908 $last_prefix = $pref if $sep;
914 my $groupname_re = qr/ [a-z_] [0-9_a-z]* /x;
915 my $modname_re = qr/ [A-Z_a-z] [0-9A-Z_a-z]* (?:::[0-9A-Z_a-z]+)* /x;
916 my $modver_re = qr/ [0-9]+ (?: \. [0-9]+ )? /x;
918 # Expand includes from a random group in a specific order:
919 # nonvariable groups first, then their includes, then the variable groups,
920 # then their includes.
921 # This allows reliably marking the rest of the mod reqs as variable (this is
922 # also why variable includes are currently not allowed)
923 sub __expand_includes {
924 my ($groups, $seen) = @_;
926 # !! DIFFERENT !! behavior and return depending on invocation mode
927 # (easier to recurse this way)
928 my $is_toplevel = $seen
933 my ($res_per_type, $missing_envvars);
935 # breadth-first evaluation, with non-variable includes on top
936 for my $g (@$groups) {
938 croak "Invalid requirement group name '$g': only ascii alphanumerics and _ are allowed"
939 if $g !~ qr/ \A $groupname_re \z/x;
941 my $r = $dbic_reqs->{$g}
942 or croak "Requirement group '$g' is not defined";
944 # always do this check *before* the $seen check
945 croak "Group '$g' with variable effective_modreqs can not be specified as an 'include'"
946 if ( $r->{env} and ! $is_toplevel );
948 next if $seen->{$g}++;
950 my $req_type = 'static';
952 if ( my @e = @{$r->{env}||[]} ) {
954 croak "Unexpected 'env' attribute under group '$g' (only allowed in test_* groups)"
955 unless $g =~ /^test_/;
957 croak "Unexpected *odd* list in 'env' under group '$g'"
960 # deconstruct the whole thing
961 my (@group_envnames_list, $some_envs_required, $some_required_missing);
963 push @group_envnames_list, my $envname = shift @e;
965 # env required or not
966 next unless shift @e;
968 $some_envs_required ||= 1;
970 $some_required_missing ||= (
971 ! defined $ENV{$envname}
973 ! length $ENV{$envname}
977 croak "None of the envvars in group '$g' declared as required, making the requirement moot"
978 unless $some_envs_required;
980 if ($some_required_missing) {
981 push @{$missing_envvars->{$g}}, \@group_envnames_list;
982 $req_type = 'variable';
986 push @{$res_per_type->{"base_${req_type}"}}, $g;
988 if (my $i = $dbic_reqs->{$g}{include}) {
989 $i = [ $i ] unless ref $i eq 'ARRAY';
991 croak "Malformed 'include' for group '$g': must be another existing group name or arrayref of existing group names"
994 push @{$res_per_type->{"incs_${req_type}"}}, @$i;
999 @{ $res_per_type->{"base_${_}"} || [] },
1000 ( $res_per_type->{"incs_${_}"} ? __expand_includes( $res_per_type->{"incs_${_}"}, $seen ) : () ),
1001 } qw(static variable);
1003 return ! $is_toplevel ? @ret : do {
1006 idx => 1 + keys %$rv,
1007 missing_envvars => $missing_envvars->{$_},
1009 $rv->{$_}{user_requested} = 1 for @$groups;
1015 our %req_unavailability_cache;
1017 # this method is just a lister and envvar/metadata checker - it does not try to load anything
1018 sub _groups_to_reqs {
1019 my ($self, $want) = @_;
1021 $want = [ $want || () ]
1022 unless ref $want eq 'ARRAY';
1024 croak "@{[ (caller(1))[3] ]}() expects a requirement group name or arrayref of group names"
1029 modreqs_fully_documented => 1,
1033 for my $piece (@$want) {
1034 if ($piece =~ qr/ \A $groupname_re \z /x) {
1035 push @$groups, $piece;
1037 elsif ( my ($mod, $ver) = $piece =~ qr/ \A ($modname_re) \>\= ($modver_re) \z /x ) {
1038 croak "Ad hoc module specification lists '$mod' twice"
1039 if exists $ret->{modreqs}{$mod};
1041 croak "Ad hoc module specification '${mod} >= $ver' (or greater) not listed in the test_adhoc optdep group" if (
1042 ! defined $dbic_reqs->{test_adhoc}{req}{$mod}
1044 $dbic_reqs->{test_adhoc}{req}{$mod} < $ver
1047 $ret->{modreqs}{$mod} = $ver;
1048 $ret->{modreqs_fully_documented} = 0;
1051 croak "Unsupported argument '$piece' supplied to @{[ (caller(1))[3] ]}()"
1055 my $all_groups = __expand_includes($groups);
1057 # pre-assemble list of augmentations, perform basic sanity checks
1058 # Note that below we *DO NOT* respect the source/target reationship, but
1059 # instead always default to augment the "later" group
1060 # This is done so that the "stable/variable" boundary keeps working as
1063 for my $requesting_group (keys %$all_groups) {
1064 if (my $ag = $dbic_reqs->{$requesting_group}{augment}) {
1065 for my $target_group (keys %$ag) {
1067 croak "Group '$requesting_group' claims to augment a non-existent group '$target_group'"
1068 unless $dbic_reqs->{$target_group};
1070 croak "Augmentation combined with variable effective_modreqs currently unsupported for group '$requesting_group'"
1071 if $dbic_reqs->{$requesting_group}{env};
1073 croak "Augmentation of group '$target_group' with variable effective_modreqs unsupported (requested by '$requesting_group')"
1074 if $dbic_reqs->{$target_group}{env};
1076 if (my @foreign = grep { $_ ne 'req' } keys %{$ag->{$target_group}} ) {
1077 croak "Only 'req' augmentations are currently supported (group '$requesting_group' attempts to alter '$foreign[0]' of group '$target_group'";
1080 $ret->{augments}{$target_group} = 1;
1082 # no augmentation for stuff that hasn't been selected
1083 if ( $all_groups->{$target_group} and my $ar = $ag->{$target_group}{req} ) {
1084 push @{$augmentations->{
1085 ( $all_groups->{$requesting_group}{idx} < $all_groups->{$target_group}{idx} )
1094 for my $group (sort { $all_groups->{$a}{idx} <=> $all_groups->{$b}{idx} } keys %$all_groups ) {
1096 my $group_reqs = $dbic_reqs->{$group}{req};
1099 for my $req_bag ($group_reqs, @{ $augmentations->{$group} || [] } ) {
1100 for (keys %$req_bag) {
1102 $_ =~ / \A $modname_re \z /x
1103 or croak "Requirement '$_' in group '$group' is not a valid module name";
1105 # !!!DO NOT CHANGE!!!
1106 # remember - version.pm may not be available on the system
1107 croak "Requirement '$_' in group '$group' specifies an invalid version '$req_bag->{$_}' (only plain non-underscored floating point decimals are supported)"
1108 if ( ($req_bag->{$_}||0) !~ qr/ \A $modver_re \z /x );
1112 if (my $e = $all_groups->{$group}{missing_envvars}) {
1113 push @{$ret->{missing_envvars}}, @$e;
1116 # assemble into the final ret
1119 ( $ret->{missing_envvars} ? () : 'effective_modreqs' ),
1121 for my $req_bag ($group_reqs, @{ $augmentations->{$group} || [] } ) {
1122 for my $mod (keys %$req_bag) {
1124 $ret->{$type}{$mod} = $req_bag->{$mod}||0 if (
1126 ! exists $ret->{$type}{$mod}
1128 # we sanitized the version to be numeric above - we can just -gt it
1129 ($req_bag->{$mod}||0) > $ret->{$type}{$mod}
1136 $ret->{modreqs_fully_documented} &&= !!$dbic_reqs->{$group}{pod}
1137 if $all_groups->{$group}{user_requested};
1139 $ret->{release_testing_mandatory} ||= !!$dbic_reqs->{$group}{release_testing_mandatory};
1146 # this method tries to find/load specified modreqs and returns a hashref of
1147 # module/loaderror pairs for anything that failed
1148 sub _errorlist_for_modreqs {
1149 # args supposedly already went through _groups_to_reqs and are therefore sanitized
1150 # safe to eval at will
1151 my ($self, $reqs) = @_;
1155 for my $m ( keys %$reqs ) {
1156 my $v = $reqs->{$m};
1158 if (! exists $req_unavailability_cache{$m}{$v} ) {
1159 # masking this off is important, as it may very well be
1161 local $SIG{__DIE__} if $SIG{__DIE__};
1163 eval( "require $m;" . ( $v ? "$m->VERSION(q($v))" : '' ) );
1164 $req_unavailability_cache{$m}{$v} = $@;
1167 $ret->{$m} = $req_unavailability_cache{$m}{$v}
1168 if $req_unavailability_cache{$m}{$v};
1174 # Unlike the above DO NOT try to load anything
1175 # This is executed when some needed envvars are not available
1176 # which in turn means a module load will never be reached anyway
1177 # This is important because some modules (especially DBDs) can be
1178 # *really* fickle when a require() is attempted, with pretty confusing
1179 # side-effects (especially on windows)
1180 sub _list_physically_missing_modules {
1181 my ($self, $modreqs) = @_;
1183 # in case there is a coderef in @INC there is nothing we can definitively prove
1184 # so short circuit directly
1185 return '' if grep { length ref $_ } @INC;
1187 my @definitely_missing;
1188 for my $mod (keys %$modreqs) {
1189 (my $fn = $mod . '.pm') =~ s|::|/|g;
1191 push @definitely_missing, $mod unless grep
1192 # this should work on any combination of slashes
1193 { $_ and -d $_ and -f "$_/$fn" and -r "$_/$fn" }
1199 { $modreqs->{$_} ? "$_~$modreqs->{$_}" : $_ }
1200 sort { lc($a) cmp lc($b) } @definitely_missing
1205 # This is to be called by the author only (automatically in Makefile.PL)
1207 my ($class, $distver, $pod_dir) = @_;
1209 die "No POD root dir supplied" unless $pod_dir;
1212 eval { require DBIx::Class; DBIx::Class->VERSION; }
1215 "\n\n---------------------------------------------------------------------\n" .
1216 'Unable to load core DBIx::Class module to determine current version, '.
1217 'possibly due to missing dependencies. Author-mode autodocumentation ' .
1219 "\n\n---------------------------------------------------------------------\n"
1222 (my $modfn = __PACKAGE__ . '.pm') =~ s|::|/|g;
1224 (my $podfn = "$pod_dir/$modfn") =~ s/\.pm$/\.pod/;
1226 require DBIx::Class::_Util;
1227 DBIx::Class::_Util::mkdir_p( DBIx::Class::_Util::parent_dir( $podfn ) );
1229 my $sqltver = $class->req_list_for('deploy')->{'SQL::Translator'}
1230 or die "Hrmm? No sqlt dep?";
1238 push @chunks, <<"EOC";
1239 #########################################################################
1240 ##################### A U T O G E N E R A T E D ########################
1241 #########################################################################
1243 # The contents of this POD file are auto-generated. Any changes you make
1244 # will be lost. If you need to change the generated text edit _gen_pod()
1245 # at the end of $modfn
1250 $class - Optional module dependency specifications (for module authors)
1255 #@@ SYNOPSIS HEADING
1257 push @chunks, <<"EOC";
1260 Somewhere in your build-file (e.g. L<ExtUtils::MakeMaker>'s F<Makefile.PL>):
1264 \$EUMM_ARGS{CONFIGURE_REQUIRES} = {
1265 \%{ \$EUMM_ARGS{CONFIGURE_REQUIRES} || {} },
1266 'DBIx::Class' => '$distver',
1271 my %DBIC_DEPLOY_AND_ORACLE_DEPS = %{ eval {
1273 $class->req_list_for([qw( deploy rdbms_oracle ic_dt )]);
1276 \$EUMM_ARGS{PREREQ_PM} = {
1277 \%DBIC_DEPLOY_AND_ORACLE_DEPS,
1278 \%{ \$EUMM_ARGS{PREREQ_PM} || {} },
1283 ExtUtils::MakeMaker::WriteMakefile(\%EUMM_ARGS);
1285 B<Note>: The C<eval> protection within the example is due to support for
1286 requirements during L<the C<configure> build phase|CPAN::Meta::Spec/Phases>
1287 not being available on a sufficient portion of production installations of
1288 Perl. Robust support for such dependency requirements is available in the
1289 L<CPAN> installer only since version C<1.94_56> first made available for
1290 production with perl version C<5.12>. It is the belief of the current
1291 maintainer that support for requirements during the C<configure> build phase
1292 will not be sufficiently ubiquitous until the B<year 2020> at the earliest,
1293 hence the extra care demonstrated above. It should also be noted that some
1294 3rd party installers (e.g. L<cpanminus|App::cpanminus>) do the right thing
1295 with configure requirements independent from the versions of perl and CPAN
1301 #@@ DESCRIPTION HEADING
1303 push @chunks, <<'EOC';
1306 Some of the less-frequently used features of L<DBIx::Class> have external
1307 module dependencies on their own. In order not to burden the average user
1308 with modules they will never use, these optional dependencies are not included
1309 in the base Makefile.PL. Instead an exception with a descriptive message is
1310 thrown when a specific feature can't find one or several modules required for
1311 its operation. This module is the central holding place for the current list
1312 of such dependencies, for DBIx::Class core authors, and DBIx::Class extension
1315 Dependencies are organized in L<groups|/CURRENT REQUIREMENT GROUPS> where each
1316 group can list one or more required modules, with an optional minimum version
1317 (or 0 for any version). In addition groups prefixed with C<test_> can specify
1318 a set of environment variables, some (or all) of which are marked as required
1319 for the group to be considered by L</req_list_for>
1321 Each group name (or a combination thereof) can be used in the
1322 L<public methods|/METHODS> as described below.
1327 #@@ REQUIREMENT GROUPLIST HEADING
1329 push @chunks, '=head1 CURRENT REQUIREMENT GROUPS';
1331 my $standalone_info;
1333 for my $group (sort keys %$dbic_reqs) {
1335 my $info = $standalone_info->{$group} ||= $class->_groups_to_reqs($group);
1338 $info->{modreqs_fully_documented}
1340 ( $info->{augments} or $info->{modreqs} )
1343 my $p = $dbic_reqs->{$group}{pod};
1346 "=head2 $p->{title}",
1352 if ( keys %{ $info->{modreqs}||{} } ) {
1354 { "=item * $_" . ($info->{modreqs}{$_} ? " >= $info->{modreqs}{$_}" : '') }
1355 ( sort keys %{ $info->{modreqs} } )
1359 push @chunks, '=item * No standalone requirements',
1362 push @chunks, '=back';
1364 for my $ag ( sort keys %{ $info->{augments} || {} } ) {
1365 my $ag_info = $standalone_info->{$ag} ||= $class->_groups_to_reqs($ag);
1367 my $newreqs = $class->modreq_list_for([ $group, $ag ]);
1368 for (keys %$newreqs) {
1369 delete $newreqs->{$_} if (
1370 ( defined $info->{modreqs}{$_} and $info->{modreqs}{$_} == $newreqs->{$_} )
1372 ( defined $ag_info->{modreqs}{$_} and $ag_info->{modreqs}{$_} == $newreqs->{$_} )
1376 if (keys %$newreqs) {
1378 "Combined with L</$ag> additionally requires:",
1381 { "=item * $_" . ($newreqs->{$_} ? " >= $newreqs->{$_}" : '') }
1382 ( sort keys %$newreqs )
1392 #@@ API DOCUMENTATION HEADING
1394 push @chunks, <<'EOC';
1396 =head1 IMPORT-LIKE ACTIONS
1398 Even though this module is not an L<Exporter>, it recognizes several C<actions>
1399 supplied to its C<import> method.
1401 =head2 -skip_all_without
1405 =item Arguments: @group_names
1409 A convenience wrapper for use during testing:
1412 push @chunks, " use $class -skip_all_without => qw(admin test_rdbms_mysql);";
1414 push @chunks, 'Roughly equivalent to the following code:';
1416 push @chunks, sprintf <<'EOS', ($class) x 2;
1420 if ( my $missing = %s->req_missing_for(\@group_names_) ) {
1421 print "1..0 # SKIP requirements not satisfied: $missing\n";
1427 push @chunks, <<'EOC';
1429 It also takes into account the C<RELEASE_TESTING> environment variable and
1430 behaves like L</-die_without> for any requirement groups marked as
1431 C<release_testing_mandatory>.
1437 =item Arguments: @group_names
1441 A convenience wrapper around L</die_unless_req_ok_for>:
1444 push @chunks, " use $class -die_without => qw(deploy admin);";
1446 push @chunks, <<'EOC';
1448 =head2 -list_missing
1452 =item Arguments: @group_names
1456 A convenience wrapper around L</modreq_missing_for>:
1458 perl -Ilib -MDBIx::Class::Optional::Dependencies=-list_missing,deploy,admin | cpanm
1462 =head2 req_group_list
1466 =item Arguments: none
1468 =item Return Value: \%list_of_requirement_groups
1472 This method should be used by DBIx::Class packagers, to get a hashref of all
1473 dependencies B<keyed> by dependency group. Each key (group name), or a combination
1474 thereof (as an arrayref) can be supplied to the methods below.
1475 The B<values> of the returned hash are currently a set of options B<without a
1476 well defined structure>. If you have use for any of the contents - contact the
1477 maintainers, instead of treating this as public (left alone stable) API.
1483 =item Arguments: $group_name | \@group_names
1485 =item Return Value: \%set_of_module_version_pairs
1489 This method should be used by DBIx::Class extension authors, to determine the
1490 version of modules a specific set of features requires for this version of
1491 DBIx::Class (regardless of their availability on the system).
1492 See the L</SYNOPSIS> for a real-world example.
1494 When handling C<test_*> groups this method behaves B<differently> from
1495 L</modreq_list_for> below (and is the only such inconsistency among the
1496 C<req_*> methods). If a particular group declares as requirements some
1497 C<environment variables> and these requirements are not satisfied (the envvars
1498 are unset) - then the C<module requirements> of this group are not included in
1501 =head2 modreq_list_for
1505 =item Arguments: $group_name | \@group_names
1507 =item Return Value: \%set_of_module_version_pairs
1511 Same as L</req_list_for> but does not take into consideration any
1512 C<environment variable requirements> - returns just the list of required
1519 =item Arguments: $group_name | \@group_names
1521 =item Return Value: 1|0
1525 Returns true or false depending on whether all modules/envvars required by
1526 the group(s) are loadable/set on the system.
1528 =head2 req_missing_for
1532 =item Arguments: $group_name | \@group_names
1534 =item Return Value: $error_message_string
1538 Returns a single-line string suitable for inclusion in larger error messages.
1539 This method would normally be used by DBIx::Class core features, to indicate to
1540 the user that they need to install specific modules and/or set specific
1541 environment variables before being able to use a specific feature set.
1543 For example if some of the requirements for C<deploy> are not available,
1544 the returned string could look like:
1547 push @chunks, qq{ "SQL::Translator~$sqltver" (see $class documentation for details)};
1549 push @chunks, <<'EOC';
1550 The author is expected to prepend the necessary text to this message before
1551 returning the actual error seen by the user. See also L</modreq_missing_for>
1553 =head2 modreq_missing_for
1557 =item Arguments: $group_name | \@group_names
1559 =item Return Value: $error_message_string
1563 Same as L</req_missing_for> except that the error string is guaranteed to be
1564 either empty, or contain a set of module requirement specifications suitable
1565 for piping to e.g. L<cpanminus|App::cpanminus>. The method explicitly does not
1566 attempt to validate the state of required environment variables (if any).
1568 For instance if some of the requirements for C<deploy> are not available,
1569 the returned string could look like:
1572 push @chunks, qq{ "SQL::Translator~$sqltver"};
1574 push @chunks, <<'EOC';
1576 See also L</-list_missing>.
1582 =item Arguments: $group_name | \@group_names
1586 A convenience wrapper around L<skip|Test::More/SKIP>. It does not take neither
1587 a reason (it is generated by L</req_missing_for>) nor an amount of skipped tests
1588 (it is always C<1>, thus mandating unconditional use of
1589 L<done_testing|Test::More/done_testing>). Most useful in combination with ad hoc
1590 requirement specifications:
1593 push @chunks, <<EOC;
1595 $class->skip_without([ deploy YAML>=0.90 ]);
1601 push @chunks, <<'EOC';
1603 =head2 die_unless_req_ok_for
1607 =item Arguments: $group_name | \@group_names
1611 Checks if L</req_ok_for> passes for the supplied group(s), and
1612 in case of failure throws an exception including the information
1613 from L</req_missing_for>. See also L</-die_without>.
1615 =head2 modreq_errorlist_for
1619 =item Arguments: $group_name | \@group_names
1621 =item Return Value: \%set_of_loaderrors_per_module
1625 Returns a hashref containing the actual errors that occurred while attempting
1626 to load each module in the requirement group(s).
1628 =head2 req_errorlist_for
1630 Deprecated method name, equivalent (via proxy) to L</modreq_errorlist_for>.
1637 push @chunks, <<'EOC';
1638 =head1 FURTHER QUESTIONS?
1640 Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
1642 =head1 COPYRIGHT AND LICENSE
1644 This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
1645 by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
1646 redistribute it and/or modify it under the same terms as the
1647 L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.
1651 open (my $fh, '>', $podfn) or die;
1652 print $fh join ("\n\n", @chunks) or die;
1653 print $fh "\n" or die;
1655 } or croak( "Unable to write $podfn: " . ( $! || $@ || 'unknown error') );