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