Merge branch 'master' into topic/constructor_rewrite
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Optional / Dependencies.pm
1 package DBIx::Class::Optional::Dependencies;
2
3 use warnings;
4 use strict;
5
6 use Carp ();
7
8 # NO EXTERNAL NON-5.8.1 CORE DEPENDENCIES EVER (e.g. C::A::G)
9 # This module is to be loaded by Makefile.PM on a pristine system
10
11 # POD is generated automatically by calling _gen_pod from the
12 # Makefile.PL in $AUTHOR mode
13
14 my $json_any = {
15   'JSON::Any'                     => '1.22',
16 };
17
18 my $moose_basic = {
19   'Moose'                         => '0.98',
20   'MooseX::Types'                 => '0.21',
21 };
22
23 my $replicated = {
24   %$moose_basic,
25 };
26
27 my $admin_basic = {
28   %$moose_basic,
29   %$json_any,
30   'MooseX::Types::Path::Class'    => '0.05',
31   'MooseX::Types::JSON'           => '0.02',
32   'namespace::autoclean'          => '0.09',
33 };
34
35 my $admin_script = {
36   %$moose_basic,
37   %$admin_basic,
38   'Getopt::Long::Descriptive' => '0.081',
39   'Text::CSV'                 => '1.16',
40 };
41
42 my $datetime_basic = {
43   'DateTime'                      => '0.55',
44   'DateTime::Format::Strptime'    => '1.2',
45 };
46
47 my $id_shortener = {
48   'Math::BigInt'                  => '1.80',
49   'Math::Base36'                  => '0.07',
50 };
51
52 my $rdbms_sqlite = {
53   'DBD::SQLite'                   => '0',
54 };
55 my $rdbms_pg = {
56   'DBD::Pg'                       => '0',
57 };
58 my $rdbms_mssql_odbc = {
59   'DBD::ODBC'                     => '0',
60 };
61 my $rdbms_mssql_sybase = {
62   'DBD::Sybase'                   => '0',
63 };
64 my $rdbms_mssql_ado = {
65   'DBD::ADO'                      => '0',
66 };
67 my $rdbms_msaccess_odbc = {
68   'DBD::ODBC'                     => '0',
69 };
70 my $rdbms_msaccess_ado = {
71   'DBD::ADO'                      => '0',
72 };
73 my $rdbms_mysql = {
74   'DBD::mysql'                    => '0',
75 };
76 my $rdbms_oracle = {
77   'DBD::Oracle'                   => '0',
78   %$id_shortener,
79 };
80 my $rdbms_ase = {
81   'DBD::Sybase'                   => '0',
82 };
83 my $rdbms_db2 = {
84   'DBD::DB2'                      => '0',
85 };
86 my $rdbms_db2_400 = {
87   'DBD::ODBC'                     => '0',
88 };
89 my $rdbms_informix = {
90   'DBD::Informix'                 => '0',
91 };
92 my $rdbms_sqlanywhere = {
93   'DBD::SQLAnywhere'              => '0',
94 };
95 my $rdbms_sqlanywhere_odbc = {
96   'DBD::ODBC'                     => '0',
97 };
98 my $rdbms_firebird = {
99   'DBD::Firebird'                 => '0',
100 };
101 my $rdbms_firebird_interbase = {
102   'DBD::InterBase'                => '0',
103 };
104 my $rdbms_firebird_odbc = {
105   'DBD::ODBC'                     => '0',
106 };
107
108 my $reqs = {
109   replicated => {
110     req => $replicated,
111     pod => {
112       title => 'Storage::Replicated',
113       desc => 'Modules required for L<DBIx::Class::Storage::DBI::Replicated>',
114     },
115   },
116
117   test_replicated => {
118     req => {
119       %$replicated,
120       'Test::Moose'               => '0',
121     },
122   },
123
124
125   admin => {
126     req => {
127       %$admin_basic,
128     },
129     pod => {
130       title => 'DBIx::Class::Admin',
131       desc => 'Modules required for the DBIx::Class administrative library',
132     },
133   },
134
135   admin_script => {
136     req => {
137       %$admin_script,
138     },
139     pod => {
140       title => 'dbicadmin',
141       desc => 'Modules required for the CLI DBIx::Class interface dbicadmin',
142     },
143   },
144
145   deploy => {
146     req => {
147       'SQL::Translator'           => '0.11016',
148     },
149     pod => {
150       title => 'Storage::DBI::deploy()',
151       desc => 'Modules required for L<DBIx::Class::Storage::DBI/deploy> and L<DBIx::Class::Storage::DBI/deployment_statements>',
152     },
153   },
154
155   id_shortener => {
156     req => $id_shortener,
157   },
158
159   test_component_accessor => {
160     req => {
161       'Class::Unload'             => '0.07',
162     },
163   },
164
165   test_pod => {
166     req => {
167       'Test::Pod'                 => '1.41',
168     },
169   },
170
171   test_podcoverage => {
172     req => {
173       'Test::Pod::Coverage'       => '1.08',
174       'Pod::Coverage'             => '0.20',
175     },
176   },
177
178   test_whitespace => {
179     req => {
180       'Test::EOL'                 => '1.0',
181       'Test::NoTabs'              => '0.9',
182     },
183   },
184
185   test_strictures => {
186     req => {
187       'Test::Strict'              => '0.20',
188     },
189   },
190
191   test_prettydebug => {
192     req => $json_any,
193   },
194
195   test_admin_script => {
196     req => {
197       %$admin_script,
198       'JSON' => 0,
199       'JSON::XS' => 0,
200       $^O eq 'MSWin32'
201         # for t/admin/10script.t
202         ? ('Win32::ShellQuote' => 0)
203         # DWIW does not compile (./configure even) on win32
204         : ('JSON::DWIW' => 0 )
205       ,
206     }
207   },
208
209   test_leaks => {
210     req => {
211       'Test::Memory::Cycle'       => '0',
212       'Devel::Cycle'              => '1.10',
213     },
214   },
215
216   test_dt => {
217     req => $datetime_basic,
218   },
219
220   test_dt_sqlite => {
221     req => {
222       %$datetime_basic,
223       # t/36datetime.t
224       # t/60core.t
225       'DateTime::Format::SQLite'  => '0',
226     },
227   },
228
229   test_dt_mysql => {
230     req => {
231       %$datetime_basic,
232       # t/inflate/datetime_mysql.t
233       # (doesn't need Mysql itself)
234       'DateTime::Format::MySQL'   => '0',
235     },
236   },
237
238   test_dt_pg => {
239     req => {
240       %$datetime_basic,
241       # t/inflate/datetime_pg.t
242       # (doesn't need PG itself)
243       'DateTime::Format::Pg'      => '0.16004',
244     },
245   },
246
247   test_cdbicompat => {
248     req => {
249       'Class::DBI::Plugin::DeepAbstractSearch' => '0',
250       %$datetime_basic,
251       'Time::Piece::MySQL'        => '0',
252       'Date::Simple'              => '3.03',
253     },
254   },
255
256   # this is just for completeness as SQLite
257   # is a core dep of DBIC for testing
258   rdbms_sqlite => {
259     req => {
260       %$rdbms_sqlite,
261     },
262     pod => {
263       title => 'SQLite support',
264       desc => 'Modules required to connect to SQLite',
265     },
266   },
267
268   rdbms_pg => {
269     req => {
270       # when changing this list make sure to adjust xt/optional_deps.t
271       %$rdbms_pg,
272     },
273     pod => {
274       title => 'PostgreSQL support',
275       desc => 'Modules required to connect to PostgreSQL',
276     },
277   },
278
279   rdbms_mssql_odbc => {
280     req => {
281       %$rdbms_mssql_odbc,
282     },
283     pod => {
284       title => 'MSSQL support via DBD::ODBC',
285       desc => 'Modules required to connect to MSSQL via DBD::ODBC',
286     },
287   },
288
289   rdbms_mssql_sybase => {
290     req => {
291       %$rdbms_mssql_sybase,
292     },
293     pod => {
294       title => 'MSSQL support via DBD::Sybase',
295       desc => 'Modules required to connect to MSSQL via DBD::Sybase',
296     },
297   },
298
299   rdbms_mssql_ado => {
300     req => {
301       %$rdbms_mssql_ado,
302     },
303     pod => {
304       title => 'MSSQL support via DBD::ADO (Windows only)',
305       desc => 'Modules required to connect to MSSQL via DBD::ADO. This particular DBD is available on Windows only',
306     },
307   },
308
309   rdbms_msaccess_odbc => {
310     req => {
311       %$rdbms_msaccess_odbc,
312     },
313     pod => {
314       title => 'MS Access support via DBD::ODBC',
315       desc => 'Modules required to connect to MS Access via DBD::ODBC',
316     },
317   },
318
319   rdbms_msaccess_ado => {
320     req => {
321       %$rdbms_msaccess_ado,
322     },
323     pod => {
324       title => 'MS Access support via DBD::ADO (Windows only)',
325       desc => 'Modules required to connect to MS Access via DBD::ADO. This particular DBD is available on Windows only',
326     },
327   },
328
329   rdbms_mysql => {
330     req => {
331       %$rdbms_mysql,
332     },
333     pod => {
334       title => 'MySQL support',
335       desc => 'Modules required to connect to MySQL',
336     },
337   },
338
339   rdbms_oracle => {
340     req => {
341       %$rdbms_oracle,
342     },
343     pod => {
344       title => 'Oracle support',
345       desc => 'Modules required to connect to Oracle',
346     },
347   },
348
349   rdbms_ase => {
350     req => {
351       %$rdbms_ase,
352     },
353     pod => {
354       title => 'Sybase ASE support',
355       desc => 'Modules required to connect to Sybase ASE',
356     },
357   },
358
359   rdbms_db2 => {
360     req => {
361       %$rdbms_db2,
362     },
363     pod => {
364       title => 'DB2 support',
365       desc => 'Modules required to connect to DB2',
366     },
367   },
368
369   rdbms_db2_400 => {
370     req => {
371       %$rdbms_db2_400,
372     },
373     pod => {
374       title => 'DB2 on AS/400 support',
375       desc => 'Modules required to connect to DB2 on AS/400',
376     },
377   },
378
379   rdbms_informix => {
380     req => {
381       %$rdbms_informix,
382     },
383     pod => {
384       title => 'Informix support',
385       desc => 'Modules required to connect to Informix',
386     },
387   },
388
389   rdbms_sqlanywhere => {
390     req => {
391       %$rdbms_sqlanywhere,
392     },
393     pod => {
394       title => 'SQLAnywhere support',
395       desc => 'Modules required to connect to SQLAnywhere',
396     },
397   },
398
399   rdbms_sqlanywhere_odbc => {
400     req => {
401       %$rdbms_sqlanywhere_odbc,
402     },
403     pod => {
404       title => 'SQLAnywhere support via DBD::ODBC',
405       desc => 'Modules required to connect to SQLAnywhere via DBD::ODBC',
406     },
407   },
408
409   rdbms_firebird => {
410     req => {
411       %$rdbms_firebird,
412     },
413     pod => {
414       title => 'Firebird support',
415       desc => 'Modules required to connect to Firebird',
416     },
417   },
418
419   rdbms_firebird_interbase => {
420     req => {
421       %$rdbms_firebird_interbase,
422     },
423     pod => {
424       title => 'Firebird support via DBD::InterBase',
425       desc => 'Modules required to connect to Firebird via DBD::InterBase',
426     },
427   },
428
429   rdbms_firebird_odbc => {
430     req => {
431       %$rdbms_firebird_odbc,
432     },
433     pod => {
434       title => 'Firebird support via DBD::ODBC',
435       desc => 'Modules required to connect to Firebird via DBD::ODBC',
436     },
437   },
438
439 # the order does matter because the rdbms support group might require
440 # a different version that the test group
441   test_rdbms_pg => {
442     req => {
443       $ENV{DBICTEST_PG_DSN}
444         ? (
445           # when changing this list make sure to adjust xt/optional_deps.t
446           %$rdbms_pg,
447           ($^O ne 'MSWin32' ? ('Sys::SigAction' => '0') : ()),
448           'DBD::Pg'               => '2.009002',
449         ) : ()
450     },
451   },
452
453   test_rdbms_mssql_odbc => {
454     req => {
455       $ENV{DBICTEST_MSSQL_ODBC_DSN}
456         ? (
457           %$rdbms_mssql_odbc,
458         ) : ()
459     },
460   },
461
462   test_rdbms_mssql_ado => {
463     req => {
464       $ENV{DBICTEST_MSSQL_ADO_DSN}
465         ? (
466           %$rdbms_mssql_ado,
467         ) : ()
468     },
469   },
470
471   test_rdbms_mssql_sybase => {
472     req => {
473       $ENV{DBICTEST_MSSQL_DSN}
474         ? (
475           %$rdbms_mssql_sybase,
476         ) : ()
477     },
478   },
479
480   test_rdbms_msaccess_odbc => {
481     req => {
482       $ENV{DBICTEST_MSACCESS_ODBC_DSN}
483         ? (
484           %$rdbms_msaccess_odbc,
485           %$datetime_basic,
486           'Data::GUID' => '0',
487         ) : ()
488     },
489   },
490
491   test_rdbms_msaccess_ado => {
492     req => {
493       $ENV{DBICTEST_MSACCESS_ADO_DSN}
494         ? (
495           %$rdbms_msaccess_ado,
496           %$datetime_basic,
497           'Data::GUID' => 0,
498         ) : ()
499     },
500   },
501
502   test_rdbms_mysql => {
503     req => {
504       $ENV{DBICTEST_MYSQL_DSN}
505         ? (
506           %$rdbms_mysql,
507         ) : ()
508     },
509   },
510
511   test_rdbms_oracle => {
512     req => {
513       $ENV{DBICTEST_ORA_DSN}
514         ? (
515           %$rdbms_oracle,
516           'DateTime::Format::Oracle' => '0',
517           'DBD::Oracle'              => '1.24',
518         ) : ()
519     },
520   },
521
522   test_rdbms_ase => {
523     req => {
524       $ENV{DBICTEST_SYBASE_DSN}
525         ? (
526           %$rdbms_ase,
527         ) : ()
528     },
529   },
530
531   test_rdbms_db2 => {
532     req => {
533       $ENV{DBICTEST_DB2_DSN}
534         ? (
535           %$rdbms_db2,
536         ) : ()
537     },
538   },
539
540   test_rdbms_db2_400 => {
541     req => {
542       $ENV{DBICTEST_DB2_400_DSN}
543         ? (
544           %$rdbms_db2_400,
545         ) : ()
546     },
547   },
548
549   test_rdbms_informix => {
550     req => {
551       $ENV{DBICTEST_INFORMIX_DSN}
552         ? (
553           %$rdbms_informix,
554         ) : ()
555     },
556   },
557
558   test_rdbms_sqlanywhere => {
559     req => {
560       $ENV{DBICTEST_SQLANYWHERE_DSN}
561         ? (
562           %$rdbms_sqlanywhere,
563         ) : ()
564     },
565   },
566
567   test_rdbms_sqlanywhere_odbc => {
568     req => {
569       $ENV{DBICTEST_SQLANYWHERE_ODBC_DSN}
570         ? (
571           %$rdbms_sqlanywhere_odbc,
572         ) : ()
573     },
574   },
575
576   test_rdbms_firebird => {
577     req => {
578       $ENV{DBICTEST_FIREBIRD_DSN}
579         ? (
580           %$rdbms_firebird,
581         ) : ()
582     },
583   },
584
585   test_rdbms_firebird_interbase => {
586     req => {
587       $ENV{DBICTEST_FIREBIRD_INTERBASE_DSN}
588         ? (
589           %$rdbms_firebird_interbase,
590         ) : ()
591     },
592   },
593
594   test_rdbms_firebird_odbc => {
595     req => {
596       $ENV{DBICTEST_FIREBIRD_ODBC_DSN}
597         ? (
598           %$rdbms_firebird_odbc,
599         ) : ()
600     },
601   },
602
603   test_memcached => {
604     req => {
605       $ENV{DBICTEST_MEMCACHED}
606         ? (
607           'Cache::Memcached' => 0,
608         ) : ()
609     },
610   },
611
612   dist_dir => {
613     req => {
614       'ExtUtils::MakeMaker' => '6.64',
615       'Pod::Inherit'        => '0.90',
616       'Pod::Tree'           => '0',
617     }
618   },
619
620   dist_upload => {
621     req => {
622       'CPAN::Uploader' => '0.103001',
623     },
624   },
625
626 };
627
628 our %req_availability_cache;
629
630 sub req_list_for {
631   my ($class, $group) = @_;
632
633   Carp::croak "req_list_for() expects a requirement group name"
634     unless $group;
635
636   my $deps = $reqs->{$group}{req}
637     or Carp::croak "Requirement group '$group' does not exist";
638
639   return { %$deps };
640 }
641
642
643 sub die_unless_req_ok_for {
644   my ($class, $group) = @_;
645
646   Carp::croak "die_unless_req_ok_for() expects a requirement group name"
647     unless $group;
648
649   $class->_check_deps($group)->{status}
650     or die sprintf( "Required modules missing, unable to continue: %s\n", $class->_check_deps($group)->{missing} );
651 }
652
653 sub req_ok_for {
654   my ($class, $group) = @_;
655
656   Carp::croak "req_ok_for() expects a requirement group name"
657     unless $group;
658
659   return $class->_check_deps($group)->{status};
660 }
661
662 sub req_missing_for {
663   my ($class, $group) = @_;
664
665   Carp::croak "req_missing_for() expects a requirement group name"
666     unless $group;
667
668   return $class->_check_deps($group)->{missing};
669 }
670
671 sub req_errorlist_for {
672   my ($class, $group) = @_;
673
674   Carp::croak "req_errorlist_for() expects a requirement group name"
675     unless $group;
676
677   return $class->_check_deps($group)->{errorlist};
678 }
679
680 sub _check_deps {
681   my ($class, $group) = @_;
682
683   return $req_availability_cache{$group} ||= do {
684
685     my $deps = $class->req_list_for ($group);
686
687     my %errors;
688     for my $mod (keys %$deps) {
689       my $req_line = "require $mod;";
690       if (my $ver = $deps->{$mod}) {
691         $req_line .= "$mod->VERSION($ver);";
692       }
693
694       eval $req_line;
695
696       $errors{$mod} = $@ if $@;
697     }
698
699     my $res;
700
701     if (keys %errors) {
702       my $missing = join (', ', map { $deps->{$_} ? "$_ >= $deps->{$_}" : $_ } (sort keys %errors) );
703       $missing .= " (see $class for details)" if $reqs->{$group}{pod};
704       $res = {
705         status => 0,
706         errorlist => \%errors,
707         missing => $missing,
708       };
709     }
710     else {
711       $res = {
712         status => 1,
713         errorlist => {},
714         missing => '',
715       };
716     }
717
718     $res;
719   };
720 }
721
722 sub req_group_list {
723   return { map { $_ => { %{ $reqs->{$_}{req} || {} } } } (keys %$reqs) };
724 }
725
726 # This is to be called by the author only (automatically in Makefile.PL)
727 sub _gen_pod {
728   my ($class, $distver, $pod_dir) = @_;
729
730   die "No POD root dir supplied" unless $pod_dir;
731
732   $distver ||=
733     eval { require DBIx::Class; DBIx::Class->VERSION; }
734       ||
735     die
736 "\n\n---------------------------------------------------------------------\n" .
737 'Unable to load core DBIx::Class module to determine current version, '.
738 'possibly due to missing dependencies. Author-mode autodocumentation ' .
739 "halted\n\n" . $@ .
740 "\n\n---------------------------------------------------------------------\n"
741   ;
742
743   # do not ask for a recent version, use 1.x API calls
744   # this *may* execute on a smoker with old perl or whatnot
745   require File::Path;
746
747   (my $modfn = __PACKAGE__ . '.pm') =~ s|::|/|g;
748
749   (my $podfn = "$pod_dir/$modfn") =~ s/\.pm$/\.pod/;
750   (my $dir = $podfn) =~ s|/[^/]+$||;
751
752   File::Path::mkpath([$dir]);
753
754   my $sqltver = $class->req_list_for ('deploy')->{'SQL::Translator'}
755     or die "Hrmm? No sqlt dep?";
756
757   my @chunks = (
758     <<"EOC",
759 #########################################################################
760 #####################  A U T O G E N E R A T E D ########################
761 #########################################################################
762 #
763 # The contents of this POD file are auto-generated.  Any changes you make
764 # will be lost. If you need to change the generated text edit _gen_pod()
765 # at the end of $modfn
766 #
767 EOC
768     '=head1 NAME',
769     "$class - Optional module dependency specifications (for module authors)",
770     '=head1 SYNOPSIS',
771     <<"EOS",
772 Somewhere in your build-file (e.g. L<Module::Install>'s Makefile.PL):
773
774   ...
775
776   configure_requires 'DBIx::Class' => '$distver';
777
778   require $class;
779
780   my \$deploy_deps = $class->req_list_for('deploy');
781
782   for (keys %\$deploy_deps) {
783     requires \$_ => \$deploy_deps->{\$_};
784   }
785
786   ...
787
788 Note that there are some caveats regarding C<configure_requires()>, more info
789 can be found at L<Module::Install/configure_requires>
790 EOS
791     '=head1 DESCRIPTION',
792     <<'EOD',
793 Some of the less-frequently used features of L<DBIx::Class> have external
794 module dependencies on their own. In order not to burden the average user
795 with modules he will never use, these optional dependencies are not included
796 in the base Makefile.PL. Instead an exception with a descriptive message is
797 thrown when a specific feature is missing one or several modules required for
798 its operation. This module is the central holding place for  the current list
799 of such dependencies, for DBIx::Class core authors, and DBIx::Class extension
800 authors alike.
801 EOD
802     '=head1 CURRENT REQUIREMENT GROUPS',
803     <<'EOD',
804 Dependencies are organized in C<groups> and each group can list one or more
805 required modules, with an optional minimum version (or 0 for any version).
806 The group name can be used in the
807 EOD
808   );
809
810   for my $group (sort keys %$reqs) {
811     my $p = $reqs->{$group}{pod}
812       or next;
813
814     my $modlist = $reqs->{$group}{req}
815       or next;
816
817     next unless keys %$modlist;
818
819     push @chunks, (
820       "=head2 $p->{title}",
821       "$p->{desc}",
822       '=over',
823       ( map { "=item * $_" . ($modlist->{$_} ? " >= $modlist->{$_}" : '') } (sort keys %$modlist) ),
824       '=back',
825       "Requirement group: B<$group>",
826     );
827   }
828
829   push @chunks, (
830     '=head1 METHODS',
831     '=head2 req_group_list',
832     '=over',
833     '=item Arguments: none',
834     '=item Return Value: \%list_of_requirement_groups',
835     '=back',
836     <<'EOD',
837 This method should be used by DBIx::Class packagers, to get a hashref of all
838 dependencies keyed by dependency group. Each key (group name) can be supplied
839 to one of the group-specific methods below.
840 EOD
841
842     '=head2 req_list_for',
843     '=over',
844     '=item Arguments: $group_name',
845     '=item Return Value: \%list_of_module_version_pairs',
846     '=back',
847     <<'EOD',
848 This method should be used by DBIx::Class extension authors, to determine the
849 version of modules a specific feature requires in the B<current> version of
850 DBIx::Class. See the L</SYNOPSIS> for a real-world
851 example.
852 EOD
853
854     '=head2 req_ok_for',
855     '=over',
856     '=item Arguments: $group_name',
857     '=item Return Value: 1|0',
858     '=back',
859     <<'EOD',
860 Returns true or false depending on whether all modules required by
861 C<$group_name> are present on the system and loadable.
862 EOD
863
864     '=head2 req_missing_for',
865     '=over',
866     '=item Arguments: $group_name',
867     '=item Return Value: $error_message_string',
868     '=back',
869     <<"EOD",
870 Returns a single line string suitable for inclusion in larger error messages.
871 This method would normally be used by DBIx::Class core-module author, to
872 indicate to the user that he needs to install specific modules before he will
873 be able to use a specific feature.
874
875 For example if some of the requirements for C<deploy> are not available,
876 the returned string could look like:
877
878  SQL::Translator >= $sqltver (see $class for details)
879
880 The author is expected to prepend the necessary text to this message before
881 returning the actual error seen by the user.
882 EOD
883
884     '=head2 die_unless_req_ok_for',
885     '=over',
886     '=item Arguments: $group_name',
887     '=back',
888     <<'EOD',
889 Checks if L</req_ok_for> passes for the supplied C<$group_name>, and
890 in case of failure throws an exception including the information
891 from L</req_missing_for>.
892 EOD
893
894     '=head2 req_errorlist_for',
895     '=over',
896     '=item Arguments: $group_name',
897     '=item Return Value: \%list_of_loaderrors_per_module',
898     '=back',
899     <<'EOD',
900 Returns a hashref containing the actual errors that occured while attempting
901 to load each module in the requirement group.
902 EOD
903     '=head1 AUTHOR',
904     'See L<DBIx::Class/CONTRIBUTORS>.',
905     '=head1 LICENSE',
906     'You may distribute this code under the same terms as Perl itself',
907   );
908
909   open (my $fh, '>', $podfn) or Carp::croak "Unable to write to $podfn: $!";
910   print $fh join ("\n\n", @chunks);
911   print $fh "\n";
912   close ($fh);
913 }
914
915 1;