Changes and dep-bump
[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 => {
f6b26571 93 #'Test::NoTabs' => '0.9',
a109c954 94 },
95 },
96
97 test_eol => {
98 req => {
f6b26571 99 #'Test::EOL' => '0.6',
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 => {
e666c5fd 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
0d4740b3 198sub _all_optional_requirements {
f6b26571 199 return { map { %{ $reqs->{$_}{req} || {} } } (keys %$reqs) };
8057ed01 200}
201
fb39747c 202sub req_list_for {
203 my ($class, $group) = @_;
204
f6b26571 205 croak "req_list_for() expects a requirement group name"
fb39747c 206 unless $group;
207
f6b26571 208 my $deps = $reqs->{$group}{req}
209 or croak "Requirement group '$group' does not exist";
fb39747c 210
211 return { %$deps };
212}
213
214
215our %req_availability_cache;
216sub req_ok_for {
217 my ($class, $group) = @_;
218
219 croak "req_ok_for() expects a requirement group name"
220 unless $group;
221
222 $class->_check_deps ($group) unless $req_availability_cache{$group};
223
224 return $req_availability_cache{$group}{status};
225}
226
227sub req_missing_for {
228 my ($class, $group) = @_;
229
230 croak "req_missing_for() expects a requirement group name"
231 unless $group;
232
233 $class->_check_deps ($group) unless $req_availability_cache{$group};
234
235 return $req_availability_cache{$group}{missing};
236}
237
238sub req_errorlist_for {
239 my ($class, $group) = @_;
240
241 croak "req_errorlist_for() expects a requirement group name"
242 unless $group;
243
244 $class->_check_deps ($group) unless $req_availability_cache{$group};
245
246 return $req_availability_cache{$group}{errorlist};
247}
248
249sub _check_deps {
250 my ($class, $group) = @_;
251
f6b26571 252 my $deps = $class->req_list_for ($group);
fb39747c 253
254 my %errors;
255 for my $mod (keys %$deps) {
256 if (my $ver = $deps->{$mod}) {
257 eval "use $mod $ver ()";
258 }
259 else {
260 eval "require $mod";
261 }
262
263 $errors{$mod} = $@ if $@;
264 }
265
266 if (keys %errors) {
f6b26571 267 my $missing = join (', ', map { $deps->{$_} ? "$_ >= $deps->{$_}" : $_ } (sort keys %errors) );
268 $missing .= " (see $class for details)" if $reqs->{$group}{pod};
fb39747c 269 $req_availability_cache{$group} = {
270 status => 0,
271 errorlist => { %errors },
f6b26571 272 missing => $missing,
fb39747c 273 };
274 }
275 else {
276 $req_availability_cache{$group} = {
277 status => 1,
278 errorlist => {},
279 missing => '',
280 };
281 }
282}
283
7e3dc46f 284# This is to be called by the author onbly (automatically in Makefile.PL)
f6b26571 285sub _gen_pod {
286 my $class = shift;
af4ac504 287 my $modfn = __PACKAGE__ . '.pm';
288 $modfn =~ s/\:\:/\//g;
f6b26571 289
7e3dc46f 290 require DBIx::Class;
291 my $distver = DBIx::Class->VERSION;
292
f6b26571 293 my @chunks = (
af4ac504 294 <<"EOC",
295#########################################################################
296##################### A U T O G E N E R A T E D ########################
297#########################################################################
298#
299# The contents of this POD file are auto-generated. Any changes you make
300# will be lost. If you need to change the generated text edit _gen_pod()
301# at the end of $modfn
302#
303EOC
f6b26571 304 '=head1 NAME',
7e3dc46f 305 "$class - Optional module dependency specifications (for module authors)",
306 '=head1 SYNOPSIS (EXPERIMENTAL)',
307 <<EOS,
308B<THE USAGE SHOWN HERE IS EXPERIMENTAL>
309
310Somewhere in your build-file (e.g. L<Module::Install>'s Makefile.PL):
311
312 ...
313
314 configure_requires 'DBIx::Class' => '$distver';
315
316 require $class;
317
318 my \$deploy_deps = $class->req_list_for ('deploy');
319
320 for (keys %\$deploy_deps) {
321 requires \$_ => \$deploy_deps->{\$_};
322 }
323
324 ...
325
326Note that there are some caveats regarding C<configure_requires()>, more info
327can be found at L<Module::Install/configure_requires>
328EOS
f6b26571 329 '=head1 DESCRIPTION',
330 <<'EOD',
331Some of the less-frequently used features of L<DBIx::Class> have external
332module dependencies on their own. In order not to burden the average user
333with modules he will never use, these optional dependencies are not included
334in the base Makefile.PL. Instead an exception with a descriptive message is
335thrown when a specific feature is missing one or several modules required for
336its operation. This module is the central holding place for the current list
7e3dc46f 337of such dependencies, for DBIx::Class core authors, and DBIx::Class extension
338authors alike.
f6b26571 339EOD
340 '=head1 CURRENT REQUIREMENT GROUPS',
341 <<'EOD',
342Dependencies are organized in C<groups> and each group can list one or more
343required modules, with an optional minimum version (or 0 for any version).
344The group name can be used in the
345EOD
346 );
347
348 for my $group (sort keys %$reqs) {
349 my $p = $reqs->{$group}{pod}
350 or next;
351
352 my $modlist = $reqs->{$group}{req}
353 or next;
354
355 next unless keys %$modlist;
356
357 push @chunks, (
358 "=head2 $p->{title}",
359 "$p->{desc}",
360 '=over',
361 ( map { "=item * $_" . ($modlist->{$_} ? " >= $modlist->{$_}" : '') } (sort keys %$modlist) ),
362 '=back',
363 "Requirement group: B<$group>",
364 );
365 }
366
367 push @chunks, (
368 '=head1 METHODS',
369 '=head2 req_list_for',
370 '=over',
371 '=item Arguments: $group_name',
372 '=item Returns: \%list_of_module_version_pairs',
373 '=back',
374 <<EOD,
375This method should be used by DBIx::Class extension authors, to determine the
7e3dc46f 376version of modules a specific feature requires in the B<current> version of
377DBIx::Class. See the L<SYNOPSIS|/SYNOPSIS (EXPERIMENTAL)> for a real-world
378example.
f6b26571 379EOD
380
381 '=head2 req_ok_for',
382 '=over',
383 '=item Arguments: $group_name',
384 '=item Returns: 1|0',
385 '=back',
af4ac504 386 'Returns true or false depending on whether all modules required by C<$group_name> are present on the system and loadable',
f6b26571 387
388 '=head2 req_missing_for',
389 '=over',
390 '=item Arguments: $group_name',
391 '=item Returns: $error_message_string',
392 '=back',
393 <<EOD,
394Returns a single line string suitable for inclusion in larger error messages.
395This method would normally be used by DBIx::Class core-module author, to
396indicate to the user that he needs to install specific modules before he will
397be able to use a specific feature.
398
399For example if the requirements for C<replicated> are not available, the
400returned string would look like:
401
402 Moose >= 0.98, MooseX::Types >= 0.21, namespace::clean (see $class for details)
403
404The author is expected to prepend the necessary text to this message before
405returning the actual error seen by the user.
406EOD
407
408 '=head2 req_errorlist_for',
409 '=over',
410 '=item Arguments: $group_name',
411 '=item Returns: \%list_of_loaderrors_per_module',
412 '=back',
413 <<'EOD',
414Returns a hashref containing the actual errors that occured while attempting
415to load each module in the requirement group.
416EOD
fb8ae353 417 '=head1 AUTHOR',
418 'See L<DBIx::Class/CONTRIBUTORS>.',
419 '=head1 LICENSE',
420 'You may distribute this code under the same terms as Perl itself',
f6b26571 421 );
422
423 my $fn = __FILE__;
424 $fn =~ s/\.pm$/\.pod/;
425
426 open (my $fh, '>', $fn) or croak "Unable to write to $fn: $!";
427 print $fh join ("\n\n", @chunks);
428 close ($fh);
429}
430
8057ed01 4311;