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