Do not auto-install dist-building dependencies in author mode
[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       'Pod::Inherit' => '0.90',
615       'Pod::Tree'    => '0',
616     }
617   },
618
619   dist_upload => {
620     req => {
621       'CPAN::Uploader' => '0.103001',
622     },
623   },
624
625 };
626
627 our %req_availability_cache;
628
629 sub req_list_for {
630   my ($class, $group) = @_;
631
632   Carp::croak "req_list_for() expects a requirement group name"
633     unless $group;
634
635   my $deps = $reqs->{$group}{req}
636     or Carp::croak "Requirement group '$group' does not exist";
637
638   return { %$deps };
639 }
640
641
642 sub die_unless_req_ok_for {
643   my ($class, $group) = @_;
644
645   Carp::croak "die_unless_req_ok_for() expects a requirement group name"
646     unless $group;
647
648   $class->_check_deps($group)->{status}
649     or die sprintf( "Required modules missing, unable to continue: %s\n", $class->_check_deps($group)->{missing} );
650 }
651
652 sub req_ok_for {
653   my ($class, $group) = @_;
654
655   Carp::croak "req_ok_for() expects a requirement group name"
656     unless $group;
657
658   return $class->_check_deps($group)->{status};
659 }
660
661 sub req_missing_for {
662   my ($class, $group) = @_;
663
664   Carp::croak "req_missing_for() expects a requirement group name"
665     unless $group;
666
667   return $class->_check_deps($group)->{missing};
668 }
669
670 sub req_errorlist_for {
671   my ($class, $group) = @_;
672
673   Carp::croak "req_errorlist_for() expects a requirement group name"
674     unless $group;
675
676   return $class->_check_deps($group)->{errorlist};
677 }
678
679 sub _check_deps {
680   my ($class, $group) = @_;
681
682   return $req_availability_cache{$group} ||= do {
683
684     my $deps = $class->req_list_for ($group);
685
686     my %errors;
687     for my $mod (keys %$deps) {
688       my $req_line = "require $mod;";
689       if (my $ver = $deps->{$mod}) {
690         $req_line .= "$mod->VERSION($ver);";
691       }
692
693       eval $req_line;
694
695       $errors{$mod} = $@ if $@;
696     }
697
698     my $res;
699
700     if (keys %errors) {
701       my $missing = join (', ', map { $deps->{$_} ? "$_ >= $deps->{$_}" : $_ } (sort keys %errors) );
702       $missing .= " (see $class for details)" if $reqs->{$group}{pod};
703       $res = {
704         status => 0,
705         errorlist => \%errors,
706         missing => $missing,
707       };
708     }
709     else {
710       $res = {
711         status => 1,
712         errorlist => {},
713         missing => '',
714       };
715     }
716
717     $res;
718   };
719 }
720
721 sub req_group_list {
722   return { map { $_ => { %{ $reqs->{$_}{req} || {} } } } (keys %$reqs) };
723 }
724
725 # This is to be called by the author only (automatically in Makefile.PL)
726 sub _gen_pod {
727   my ($class, $distver, $pod_dir) = @_;
728
729   die "No POD root dir supplied" unless $pod_dir;
730
731   $distver ||=
732     eval { require DBIx::Class; DBIx::Class->VERSION; }
733       ||
734     die
735 "\n\n---------------------------------------------------------------------\n" .
736 'Unable to load core DBIx::Class module to determine current version, '.
737 'possibly due to missing dependencies. Author-mode autodocumentation ' .
738 "halted\n\n" . $@ .
739 "\n\n---------------------------------------------------------------------\n"
740   ;
741
742   # do not ask for a recent version, use 1.x API calls
743   # this *may* execute on a smoker with old perl or whatnot
744   require File::Path;
745
746   (my $modfn = __PACKAGE__ . '.pm') =~ s|::|/|g;
747
748   (my $podfn = "$pod_dir/$modfn") =~ s/\.pm$/\.pod/;
749   (my $dir = $podfn) =~ s|/[^/]+$||;
750
751   File::Path::mkpath([$dir]);
752
753   my $sqltver = $class->req_list_for ('deploy')->{'SQL::Translator'}
754     or die "Hrmm? No sqlt dep?";
755
756   my @chunks = (
757     <<"EOC",
758 #########################################################################
759 #####################  A U T O G E N E R A T E D ########################
760 #########################################################################
761 #
762 # The contents of this POD file are auto-generated.  Any changes you make
763 # will be lost. If you need to change the generated text edit _gen_pod()
764 # at the end of $modfn
765 #
766 EOC
767     '=head1 NAME',
768     "$class - Optional module dependency specifications (for module authors)",
769     '=head1 SYNOPSIS',
770     <<"EOS",
771 Somewhere in your build-file (e.g. L<Module::Install>'s Makefile.PL):
772
773   ...
774
775   configure_requires 'DBIx::Class' => '$distver';
776
777   require $class;
778
779   my \$deploy_deps = $class->req_list_for('deploy');
780
781   for (keys %\$deploy_deps) {
782     requires \$_ => \$deploy_deps->{\$_};
783   }
784
785   ...
786
787 Note that there are some caveats regarding C<configure_requires()>, more info
788 can be found at L<Module::Install/configure_requires>
789 EOS
790     '=head1 DESCRIPTION',
791     <<'EOD',
792 Some of the less-frequently used features of L<DBIx::Class> have external
793 module dependencies on their own. In order not to burden the average user
794 with modules he will never use, these optional dependencies are not included
795 in the base Makefile.PL. Instead an exception with a descriptive message is
796 thrown when a specific feature is missing one or several modules required for
797 its operation. This module is the central holding place for  the current list
798 of such dependencies, for DBIx::Class core authors, and DBIx::Class extension
799 authors alike.
800 EOD
801     '=head1 CURRENT REQUIREMENT GROUPS',
802     <<'EOD',
803 Dependencies are organized in C<groups> and each group can list one or more
804 required modules, with an optional minimum version (or 0 for any version).
805 The group name can be used in the
806 EOD
807   );
808
809   for my $group (sort keys %$reqs) {
810     my $p = $reqs->{$group}{pod}
811       or next;
812
813     my $modlist = $reqs->{$group}{req}
814       or next;
815
816     next unless keys %$modlist;
817
818     push @chunks, (
819       "=head2 $p->{title}",
820       "$p->{desc}",
821       '=over',
822       ( map { "=item * $_" . ($modlist->{$_} ? " >= $modlist->{$_}" : '') } (sort keys %$modlist) ),
823       '=back',
824       "Requirement group: B<$group>",
825     );
826   }
827
828   push @chunks, (
829     '=head1 METHODS',
830     '=head2 req_group_list',
831     '=over',
832     '=item Arguments: none',
833     '=item Return Value: \%list_of_requirement_groups',
834     '=back',
835     <<'EOD',
836 This method should be used by DBIx::Class packagers, to get a hashref of all
837 dependencies keyed by dependency group. Each key (group name) can be supplied
838 to one of the group-specific methods below.
839 EOD
840
841     '=head2 req_list_for',
842     '=over',
843     '=item Arguments: $group_name',
844     '=item Return Value: \%list_of_module_version_pairs',
845     '=back',
846     <<'EOD',
847 This method should be used by DBIx::Class extension authors, to determine the
848 version of modules a specific feature requires in the B<current> version of
849 DBIx::Class. See the L</SYNOPSIS> for a real-world
850 example.
851 EOD
852
853     '=head2 req_ok_for',
854     '=over',
855     '=item Arguments: $group_name',
856     '=item Return Value: 1|0',
857     '=back',
858     <<'EOD',
859 Returns true or false depending on whether all modules required by
860 C<$group_name> are present on the system and loadable.
861 EOD
862
863     '=head2 req_missing_for',
864     '=over',
865     '=item Arguments: $group_name',
866     '=item Return Value: $error_message_string',
867     '=back',
868     <<"EOD",
869 Returns a single line string suitable for inclusion in larger error messages.
870 This method would normally be used by DBIx::Class core-module author, to
871 indicate to the user that he needs to install specific modules before he will
872 be able to use a specific feature.
873
874 For example if some of the requirements for C<deploy> are not available,
875 the returned string could look like:
876
877  SQL::Translator >= $sqltver (see $class for details)
878
879 The author is expected to prepend the necessary text to this message before
880 returning the actual error seen by the user.
881 EOD
882
883     '=head2 die_unless_req_ok_for',
884     '=over',
885     '=item Arguments: $group_name',
886     '=back',
887     <<'EOD',
888 Checks if L</req_ok_for> passes for the supplied C<$group_name>, and
889 in case of failure throws an exception including the information
890 from L</req_missing_for>.
891 EOD
892
893     '=head2 req_errorlist_for',
894     '=over',
895     '=item Arguments: $group_name',
896     '=item Return Value: \%list_of_loaderrors_per_module',
897     '=back',
898     <<'EOD',
899 Returns a hashref containing the actual errors that occured while attempting
900 to load each module in the requirement group.
901 EOD
902     '=head1 AUTHOR',
903     'See L<DBIx::Class/CONTRIBUTORS>.',
904     '=head1 LICENSE',
905     'You may distribute this code under the same terms as Perl itself',
906   );
907
908   open (my $fh, '>', $podfn) or Carp::croak "Unable to write to $podfn: $!";
909   print $fh join ("\n\n", @chunks);
910   print $fh "\n";
911   close ($fh);
912 }
913
914 1;