dbicadmin dependencies
[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
8057ed01 19my $reqs = {
20 dist => {
21 #'Module::Install::Pod::Inherit' => '0.01',
22 },
23
24 replicated => {
f6b26571 25 req => {
2b48ebff 26 %$moose_basic,
f6b26571 27 'namespace::clean' => '0.11',
28 'Hash::Merge' => '0.11',
29 },
30 pod => {
31 title => 'Storage::Replicated',
32 desc => 'Modules required for L<DBIx::Class::Storage::DBI::Replicated>',
33 },
8057ed01 34 },
35
36 admin => {
2b48ebff 37 req => {
38 %$moose_basic,
39 'MooseX::Types::Path::Class'=> '0.05',
40 'MooseX::Types::JSON' => '0.02',
41 'Try::Tiny' => '0.02',
42 'namespace::autoclean' => '0.09',
43 'parent' => '0.223',
44 'Getopt::Long::Descriptive' => '0.081',
45 'JSON::Any' => '1.22',
46 'Text::CSV' => '1.16',
47 },
8057ed01 48 },
49
50 deploy => {
f6b26571 51 req => {
52 'SQL::Translator' => '0.11002',
53 },
54 pod => {
55 title => 'Storage::DBI::deploy()',
56 desc => 'Modules required for L<DBIx::Class::Storage::DBI/deploy> and L<DBIx::Class::Storage::DBI/deploymen_statements>',
57 },
8057ed01 58 },
59
60 author => {
f6b26571 61 req => {
62 'Test::Pod' => '1.26',
63 'Test::Pod::Coverage' => '1.08',
64 'Pod::Coverage' => '0.20',
65 #'Test::NoTabs' => '0.9',
66 #'Test::EOL' => '0.6',
67 },
8057ed01 68 },
69
70 core => {
f6b26571 71 req => {
72 # t/52cycle.t
73 'Test::Memory::Cycle' => '0',
74 'Devel::Cycle' => '1.10',
75
76 # t/36datetime.t
77 # t/60core.t
78 'DateTime::Format::SQLite' => '0',
79
80 # t/96_is_deteministic_value.t
81 'DateTime::Format::Strptime'=> '0',
82 },
8057ed01 83 },
84
85 cdbicompat => {
f6b26571 86 req => {
87 'DBIx::ContextualFetch' => '0',
88 'Class::DBI::Plugin::DeepAbstractSearch' => '0',
89 'Class::Trigger' => '0',
90 'Time::Piece::MySQL' => '0',
91 'Clone' => '0',
92 'Date::Simple' => '3.03',
93 },
8057ed01 94 },
95
96 rdbms_pg => {
f6b26571 97 req => {
98 $ENV{DBICTEST_PG_DSN}
99 ? (
100 'Sys::SigAction' => '0',
101 'DBD::Pg' => '2.009002',
102 'DateTime::Format::Pg' => '0',
103 ) : ()
104 },
8057ed01 105 },
106
107 rdbms_mysql => {
f6b26571 108 req => {
109 $ENV{DBICTEST_MYSQL_DSN}
110 ? (
111 'DateTime::Format::MySQL' => '0',
112 'DBD::mysql' => '0',
113 ) : ()
114 },
8057ed01 115 },
116
117 rdbms_oracle => {
f6b26571 118 req => {
119 $ENV{DBICTEST_ORA_DSN}
120 ? (
121 'DateTime::Format::Oracle' => '0',
122 ) : ()
123 },
8057ed01 124 },
125
126 rdbms_ase => {
f6b26571 127 req => {
128 $ENV{DBICTEST_SYBASE_DSN}
129 ? (
130 'DateTime::Format::Sybase' => 0,
131 ) : ()
132 },
8057ed01 133 },
134
135 rdbms_asa => {
f6b26571 136 req => {
137 grep $_, @ENV{qw/DBICTEST_SYBASE_ASA_DSN DBICTEST_SYBASE_ASA_ODBC_DSN/}
138 ? (
139 'DateTime::Format::Strptime' => 0,
140 ) : ()
141 },
8057ed01 142 },
143};
144
f6b26571 145
0d4740b3 146sub _all_optional_requirements {
f6b26571 147 return { map { %{ $reqs->{$_}{req} || {} } } (keys %$reqs) };
8057ed01 148}
149
fb39747c 150sub req_list_for {
151 my ($class, $group) = @_;
152
f6b26571 153 croak "req_list_for() expects a requirement group name"
fb39747c 154 unless $group;
155
f6b26571 156 my $deps = $reqs->{$group}{req}
157 or croak "Requirement group '$group' does not exist";
fb39747c 158
159 return { %$deps };
160}
161
162
163our %req_availability_cache;
164sub req_ok_for {
165 my ($class, $group) = @_;
166
167 croak "req_ok_for() expects a requirement group name"
168 unless $group;
169
170 $class->_check_deps ($group) unless $req_availability_cache{$group};
171
172 return $req_availability_cache{$group}{status};
173}
174
175sub req_missing_for {
176 my ($class, $group) = @_;
177
178 croak "req_missing_for() expects a requirement group name"
179 unless $group;
180
181 $class->_check_deps ($group) unless $req_availability_cache{$group};
182
183 return $req_availability_cache{$group}{missing};
184}
185
186sub req_errorlist_for {
187 my ($class, $group) = @_;
188
189 croak "req_errorlist_for() expects a requirement group name"
190 unless $group;
191
192 $class->_check_deps ($group) unless $req_availability_cache{$group};
193
194 return $req_availability_cache{$group}{errorlist};
195}
196
197sub _check_deps {
198 my ($class, $group) = @_;
199
f6b26571 200 my $deps = $class->req_list_for ($group);
fb39747c 201
202 my %errors;
203 for my $mod (keys %$deps) {
204 if (my $ver = $deps->{$mod}) {
205 eval "use $mod $ver ()";
206 }
207 else {
208 eval "require $mod";
209 }
210
211 $errors{$mod} = $@ if $@;
212 }
213
214 if (keys %errors) {
f6b26571 215 my $missing = join (', ', map { $deps->{$_} ? "$_ >= $deps->{$_}" : $_ } (sort keys %errors) );
216 $missing .= " (see $class for details)" if $reqs->{$group}{pod};
fb39747c 217 $req_availability_cache{$group} = {
218 status => 0,
219 errorlist => { %errors },
f6b26571 220 missing => $missing,
fb39747c 221 };
222 }
223 else {
224 $req_availability_cache{$group} = {
225 status => 1,
226 errorlist => {},
227 missing => '',
228 };
229 }
230}
231
f6b26571 232sub _gen_pod {
233 my $class = shift;
234
235 my @chunks = (
236 '=head1 NAME',
237 "$class - Optional module dependency specifications",
238 '=head1 DESCRIPTION',
239 <<'EOD',
240Some of the less-frequently used features of L<DBIx::Class> have external
241module dependencies on their own. In order not to burden the average user
242with modules he will never use, these optional dependencies are not included
243in the base Makefile.PL. Instead an exception with a descriptive message is
244thrown when a specific feature is missing one or several modules required for
245its operation. This module is the central holding place for the current list
246of such dependencies.
247EOD
248 '=head1 CURRENT REQUIREMENT GROUPS',
249 <<'EOD',
250Dependencies are organized in C<groups> and each group can list one or more
251required modules, with an optional minimum version (or 0 for any version).
252The group name can be used in the
253EOD
254 );
255
256 for my $group (sort keys %$reqs) {
257 my $p = $reqs->{$group}{pod}
258 or next;
259
260 my $modlist = $reqs->{$group}{req}
261 or next;
262
263 next unless keys %$modlist;
264
265 push @chunks, (
266 "=head2 $p->{title}",
267 "$p->{desc}",
268 '=over',
269 ( map { "=item * $_" . ($modlist->{$_} ? " >= $modlist->{$_}" : '') } (sort keys %$modlist) ),
270 '=back',
271 "Requirement group: B<$group>",
272 );
273 }
274
275 push @chunks, (
276 '=head1 METHODS',
277 '=head2 req_list_for',
278 '=over',
279 '=item Arguments: $group_name',
280 '=item Returns: \%list_of_module_version_pairs',
281 '=back',
282 <<EOD,
283This method should be used by DBIx::Class extension authors, to determine the
284version of modules which a specific feature requires in the current version of
285DBIx::Class. For example if you write a module/extension that requires
286DBIx::Class and also requires the availability of
287L<DBIx::Class::Storage::DBI/deploy>, you can do the following in your
288C<Makefile.PL> or C<Build.PL>
289
290 require $class;
291 my \$dep_list = $class->req_list_for ('deploy');
292
293Which will give you a list of module/version pairs necessary for the particular
294feature to function with this version of DBIx::Class.
295EOD
296
297 '=head2 req_ok_for',
298 '=over',
299 '=item Arguments: $group_name',
300 '=item Returns: 1|0',
301 '=back',
302 'Returns true or false depending on whether all modules required by $group_name are present on the system and loadable',
303
304 '=head2 req_missing_for',
305 '=over',
306 '=item Arguments: $group_name',
307 '=item Returns: $error_message_string',
308 '=back',
309 <<EOD,
310Returns a single line string suitable for inclusion in larger error messages.
311This method would normally be used by DBIx::Class core-module author, to
312indicate to the user that he needs to install specific modules before he will
313be able to use a specific feature.
314
315For example if the requirements for C<replicated> are not available, the
316returned string would look like:
317
318 Moose >= 0.98, MooseX::Types >= 0.21, namespace::clean (see $class for details)
319
320The author is expected to prepend the necessary text to this message before
321returning the actual error seen by the user.
322EOD
323
324 '=head2 req_errorlist_for',
325 '=over',
326 '=item Arguments: $group_name',
327 '=item Returns: \%list_of_loaderrors_per_module',
328 '=back',
329 <<'EOD',
330Returns a hashref containing the actual errors that occured while attempting
331to load each module in the requirement group.
332EOD
333
334 );
335
336 my $fn = __FILE__;
337 $fn =~ s/\.pm$/\.pod/;
338
339 open (my $fh, '>', $fn) or croak "Unable to write to $fn: $!";
340 print $fh join ("\n\n", @chunks);
341 close ($fh);
342}
343
8057ed01 3441;