Make sure missing author-deps do not kill makefile creation
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Optional / Dependencies.pm
CommitLineData
8057ed01 1package DBIx::Class::Optional::Dependencies;
2
3use warnings;
4use strict;
5
fb39747c 6use Carp;
7
8# NO EXTERNAL NON-5.8.1 CORE DEPENDENCIES EVER (e.g. C::A::G)
8057ed01 9# This module is to be loaded by Makefile.PM on a pristine system
10
f6b26571 11# POD is generated automatically by calling _gen_pod from the
12# Makefile.PL in $AUTHOR mode
13
2b48ebff 14my $moose_basic = {
15 'Moose' => '0.98',
16 'MooseX::Types' => '0.21',
17};
18
ebcd0e4f 19my $admin_basic = {
20 %$moose_basic,
21 'MooseX::Types::Path::Class' => '0.05',
22 'MooseX::Types::JSON' => '0.02',
cba24c70 23 'JSON::Any' => '1.22',
ebcd0e4f 24 'namespace::autoclean' => '0.09',
ebcd0e4f 25};
26
8057ed01 27my $reqs = {
28 dist => {
29 #'Module::Install::Pod::Inherit' => '0.01',
30 },
31
32 replicated => {
f6b26571 33 req => {
2b48ebff 34 %$moose_basic,
f6b26571 35 'namespace::clean' => '0.11',
e666c5fd 36 'Hash::Merge' => '0.12',
f6b26571 37 },
38 pod => {
39 title => 'Storage::Replicated',
40 desc => 'Modules required for L<DBIx::Class::Storage::DBI::Replicated>',
41 },
8057ed01 42 },
43
44 admin => {
2b48ebff 45 req => {
ebcd0e4f 46 %$admin_basic,
47 },
48 pod => {
49 title => 'DBIx::Class::Admin',
50 desc => 'Modules required for the DBIx::Class administrative library',
51 },
52 },
53
a4a02f15 54 admin_script => {
ebcd0e4f 55 req => {
2b48ebff 56 %$moose_basic,
ebcd0e4f 57 %$admin_basic,
2b48ebff 58 'Getopt::Long::Descriptive' => '0.081',
2b48ebff 59 'Text::CSV' => '1.16',
60 },
e144415f 61 pod => {
62 title => 'dbicadmin',
63 desc => 'Modules required for the CLI DBIx::Class interface dbicadmin',
64 },
8057ed01 65 },
66
67 deploy => {
f6b26571 68 req => {
270edb2b 69 'SQL::Translator' => '0.11005',
f6b26571 70 },
71 pod => {
72 title => 'Storage::DBI::deploy()',
73 desc => 'Modules required for L<DBIx::Class::Storage::DBI/deploy> and L<DBIx::Class::Storage::DBI/deploymen_statements>',
74 },
8057ed01 75 },
76
a109c954 77
78 test_pod => {
f6b26571 79 req => {
14d17d71 80 'Test::Pod' => '1.41',
a109c954 81 },
82 },
83
84 test_podcoverage => {
85 req => {
f6b26571 86 'Test::Pod::Coverage' => '1.08',
87 'Pod::Coverage' => '0.20',
a109c954 88 },
89 },
90
91 test_notabs => {
92 req => {
d146b340 93 'Test::NoTabs' => '0.9',
a109c954 94 },
95 },
96
97 test_eol => {
98 req => {
d146b340 99 'Test::EOL' => '0.6',
f6b26571 100 },
8057ed01 101 },
102
a109c954 103 test_cycle => {
f6b26571 104 req => {
f6b26571 105 'Test::Memory::Cycle' => '0',
106 'Devel::Cycle' => '1.10',
a109c954 107 },
108 },
f6b26571 109
a109c954 110 test_dtrelated => {
111 req => {
f6b26571 112 # t/36datetime.t
113 # t/60core.t
114 'DateTime::Format::SQLite' => '0',
115
116 # t/96_is_deteministic_value.t
117 'DateTime::Format::Strptime'=> '0',
9c92bb1c 118
119 # t/inflate/datetime_mysql.t
120 # (doesn't need Mysql itself)
121 'DateTime::Format::MySQL' => '0',
122
123 # t/inflate/datetime_pg.t
124 # (doesn't need PG itself)
125 'DateTime::Format::Pg' => '0',
f6b26571 126 },
8057ed01 127 },
128
129 cdbicompat => {
f6b26571 130 req => {
131 'DBIx::ContextualFetch' => '0',
132 'Class::DBI::Plugin::DeepAbstractSearch' => '0',
133 'Class::Trigger' => '0',
134 'Time::Piece::MySQL' => '0',
135 'Clone' => '0',
136 'Date::Simple' => '3.03',
137 },
8057ed01 138 },
139
140 rdbms_pg => {
f6b26571 141 req => {
142 $ENV{DBICTEST_PG_DSN}
143 ? (
144 'Sys::SigAction' => '0',
145 'DBD::Pg' => '2.009002',
f6b26571 146 ) : ()
147 },
8057ed01 148 },
149
150 rdbms_mysql => {
f6b26571 151 req => {
152 $ENV{DBICTEST_MYSQL_DSN}
153 ? (
f6b26571 154 'DBD::mysql' => '0',
155 ) : ()
156 },
8057ed01 157 },
158
159 rdbms_oracle => {
f6b26571 160 req => {
161 $ENV{DBICTEST_ORA_DSN}
162 ? (
163 'DateTime::Format::Oracle' => '0',
164 ) : ()
165 },
8057ed01 166 },
167
168 rdbms_ase => {
f6b26571 169 req => {
170 $ENV{DBICTEST_SYBASE_DSN}
171 ? (
172 'DateTime::Format::Sybase' => 0,
173 ) : ()
174 },
8057ed01 175 },
176
177 rdbms_asa => {
f6b26571 178 req => {
bf9ee8dc 179 (scalar grep { $ENV{$_} } (qw/DBICTEST_SYBASE_ASA_DSN DBICTEST_SYBASE_ASA_ODBC_DSN/) )
f6b26571 180 ? (
181 'DateTime::Format::Strptime' => 0,
182 ) : ()
183 },
8057ed01 184 },
f58a165c 185
186 rdbms_db2 => {
187 req => {
188 $ENV{DBICTEST_DB2_DSN}
189 ? (
190 'DBD::DB2' => 0,
191 ) : ()
192 },
193 },
194
8057ed01 195};
196
f6b26571 197
fb39747c 198sub req_list_for {
199 my ($class, $group) = @_;
200
f6b26571 201 croak "req_list_for() expects a requirement group name"
fb39747c 202 unless $group;
203
f6b26571 204 my $deps = $reqs->{$group}{req}
205 or croak "Requirement group '$group' does not exist";
fb39747c 206
207 return { %$deps };
208}
209
210
211our %req_availability_cache;
212sub req_ok_for {
213 my ($class, $group) = @_;
214
215 croak "req_ok_for() expects a requirement group name"
216 unless $group;
217
218 $class->_check_deps ($group) unless $req_availability_cache{$group};
219
220 return $req_availability_cache{$group}{status};
221}
222
223sub req_missing_for {
224 my ($class, $group) = @_;
225
226 croak "req_missing_for() expects a requirement group name"
227 unless $group;
228
229 $class->_check_deps ($group) unless $req_availability_cache{$group};
230
231 return $req_availability_cache{$group}{missing};
232}
233
234sub req_errorlist_for {
235 my ($class, $group) = @_;
236
237 croak "req_errorlist_for() expects a requirement group name"
238 unless $group;
239
240 $class->_check_deps ($group) unless $req_availability_cache{$group};
241
242 return $req_availability_cache{$group}{errorlist};
243}
244
245sub _check_deps {
246 my ($class, $group) = @_;
247
f6b26571 248 my $deps = $class->req_list_for ($group);
fb39747c 249
250 my %errors;
251 for my $mod (keys %$deps) {
252 if (my $ver = $deps->{$mod}) {
253 eval "use $mod $ver ()";
254 }
255 else {
256 eval "require $mod";
257 }
258
259 $errors{$mod} = $@ if $@;
260 }
261
262 if (keys %errors) {
f6b26571 263 my $missing = join (', ', map { $deps->{$_} ? "$_ >= $deps->{$_}" : $_ } (sort keys %errors) );
264 $missing .= " (see $class for details)" if $reqs->{$group}{pod};
fb39747c 265 $req_availability_cache{$group} = {
266 status => 0,
267 errorlist => { %errors },
f6b26571 268 missing => $missing,
fb39747c 269 };
270 }
271 else {
272 $req_availability_cache{$group} = {
273 status => 1,
274 errorlist => {},
275 missing => '',
276 };
277 }
278}
279
e3fc11e1 280sub req_group_list {
281 return { map { $_ => { %{ $reqs->{$_}{req} || {} } } } (keys %$reqs) };
282}
283
284# This is to be called by the author only (automatically in Makefile.PL)
f6b26571 285sub _gen_pod {
31fa1764 286
f6b26571 287 my $class = shift;
af4ac504 288 my $modfn = __PACKAGE__ . '.pm';
289 $modfn =~ s/\:\:/\//g;
f6b26571 290
31fa1764 291 my $podfn = __FILE__;
292 $podfn =~ s/\.pm$/\.pod/;
293
294 my $distver =
295 eval { require DBIx::Class; DBIx::Class->VERSION; }
296 ||
297 do {
298 warn
299"\n\n---------------------------------------------------------------------\n" .
300'Unable to load core DBIx::Class module to determine current version, '.
301'possibly due to missing dependencies. Author-mode autodocumentation ' .
302"halted\n\n" . $@ .
303"\n\n---------------------------------------------------------------------\n"
304 ;
305 '*UNKNOWN*'; # rv
306 }
307 ;
308
e3fc11e1 309 my $sqltver = $class->req_list_for ('deploy')->{'SQL::Translator'}
310 or die "Hrmm? No sqlt dep?";
7e3dc46f 311
f6b26571 312 my @chunks = (
af4ac504 313 <<"EOC",
314#########################################################################
315##################### A U T O G E N E R A T E D ########################
316#########################################################################
317#
318# The contents of this POD file are auto-generated. Any changes you make
319# will be lost. If you need to change the generated text edit _gen_pod()
320# at the end of $modfn
321#
322EOC
f6b26571 323 '=head1 NAME',
7e3dc46f 324 "$class - Optional module dependency specifications (for module authors)",
e3fc11e1 325 '=head1 SYNOPSIS',
7e3dc46f 326 <<EOS,
7e3dc46f 327Somewhere in your build-file (e.g. L<Module::Install>'s Makefile.PL):
328
329 ...
330
331 configure_requires 'DBIx::Class' => '$distver';
332
333 require $class;
334
335 my \$deploy_deps = $class->req_list_for ('deploy');
336
337 for (keys %\$deploy_deps) {
338 requires \$_ => \$deploy_deps->{\$_};
339 }
340
341 ...
342
343Note that there are some caveats regarding C<configure_requires()>, more info
344can be found at L<Module::Install/configure_requires>
345EOS
f6b26571 346 '=head1 DESCRIPTION',
347 <<'EOD',
348Some of the less-frequently used features of L<DBIx::Class> have external
349module dependencies on their own. In order not to burden the average user
350with modules he will never use, these optional dependencies are not included
351in the base Makefile.PL. Instead an exception with a descriptive message is
352thrown when a specific feature is missing one or several modules required for
353its operation. This module is the central holding place for the current list
7e3dc46f 354of such dependencies, for DBIx::Class core authors, and DBIx::Class extension
355authors alike.
f6b26571 356EOD
357 '=head1 CURRENT REQUIREMENT GROUPS',
358 <<'EOD',
359Dependencies are organized in C<groups> and each group can list one or more
360required modules, with an optional minimum version (or 0 for any version).
361The group name can be used in the
362EOD
363 );
364
365 for my $group (sort keys %$reqs) {
366 my $p = $reqs->{$group}{pod}
367 or next;
368
369 my $modlist = $reqs->{$group}{req}
370 or next;
371
372 next unless keys %$modlist;
373
374 push @chunks, (
375 "=head2 $p->{title}",
376 "$p->{desc}",
377 '=over',
378 ( map { "=item * $_" . ($modlist->{$_} ? " >= $modlist->{$_}" : '') } (sort keys %$modlist) ),
379 '=back',
380 "Requirement group: B<$group>",
381 );
382 }
383
384 push @chunks, (
385 '=head1 METHODS',
e3fc11e1 386 '=head2 req_group_list',
387 '=over',
388 '=item Arguments: $none',
389 '=item Returns: \%list_of_requirement_groups',
390 '=back',
391 <<EOD,
392This method should be used by DBIx::Class packagers, to get a hashref of all
393dependencies keyed by dependency group. Each key (group name) can be supplied
394to one of the group-specific methods below.
395EOD
396
f6b26571 397 '=head2 req_list_for',
398 '=over',
399 '=item Arguments: $group_name',
400 '=item Returns: \%list_of_module_version_pairs',
401 '=back',
402 <<EOD,
403This method should be used by DBIx::Class extension authors, to determine the
7e3dc46f 404version of modules a specific feature requires in the B<current> version of
e3fc11e1 405DBIx::Class. See the L</SYNOPSIS> for a real-world
7e3dc46f 406example.
f6b26571 407EOD
408
409 '=head2 req_ok_for',
410 '=over',
411 '=item Arguments: $group_name',
412 '=item Returns: 1|0',
413 '=back',
af4ac504 414 'Returns true or false depending on whether all modules required by C<$group_name> are present on the system and loadable',
f6b26571 415
416 '=head2 req_missing_for',
417 '=over',
418 '=item Arguments: $group_name',
419 '=item Returns: $error_message_string',
420 '=back',
421 <<EOD,
422Returns a single line string suitable for inclusion in larger error messages.
423This method would normally be used by DBIx::Class core-module author, to
424indicate to the user that he needs to install specific modules before he will
425be able to use a specific feature.
426
e3fc11e1 427For example if some of the requirements for C<deploy> are not available,
428the returned string could look like:
f6b26571 429
e3fc11e1 430 SQL::Translator >= $sqltver (see $class for details)
f6b26571 431
432The author is expected to prepend the necessary text to this message before
433returning the actual error seen by the user.
434EOD
435
436 '=head2 req_errorlist_for',
437 '=over',
438 '=item Arguments: $group_name',
439 '=item Returns: \%list_of_loaderrors_per_module',
440 '=back',
441 <<'EOD',
442Returns a hashref containing the actual errors that occured while attempting
443to load each module in the requirement group.
444EOD
fb8ae353 445 '=head1 AUTHOR',
446 'See L<DBIx::Class/CONTRIBUTORS>.',
447 '=head1 LICENSE',
448 'You may distribute this code under the same terms as Perl itself',
f6b26571 449 );
450
31fa1764 451 open (my $fh, '>', $podfn) or croak "Unable to write to $podfn: $!";
f6b26571 452 print $fh join ("\n\n", @chunks);
453 close ($fh);
454}
455
8057ed01 4561;