Merge branch 'master' into 0.08
[dbsrgits/DBIx-Class-Schema-Loader.git] / lib / DBIx / Class / Schema / Loader / Optional / Dependencies.pm
CommitLineData
ef8e9c69 1package DBIx::Class::Schema::Loader::Optional::Dependencies;
2
3use warnings;
4use strict;
5
6use Carp;
7
8# Stolen from DBIx::Class
9
10# NO EXTERNAL NON-5.8.1 CORE DEPENDENCIES EVER (e.g. C::A::G)
11# This module is to be loaded by Makefile.PM on a pristine system
12
13# POD is generated automatically by calling _gen_pod from the
14# Makefile.PL in $AUTHOR mode
15
16my $reqs = {
17 dist => {
18 #'Module::Install::Pod::Inherit' => '0.01',
19 },
20
21 use_moose => {
22 req => {
23 'Moose' => 0,
24 'MooseX::NonMoose' => 0,
25 'namespace::autoclean' => 0,
26 },
27 pod => {
28 title => 'use_moose',
29 desc => 'Modules required for the use_moose option',
30 },
31 },
32};
33
34sub req_list_for {
35 my ($class, $group) = @_;
36
37 croak "req_list_for() expects a requirement group name"
38 unless $group;
39
40 my $deps = $reqs->{$group}{req}
41 or croak "Requirement group '$group' does not exist";
42
43 return { %$deps };
44}
45
46
47our %req_availability_cache;
48sub req_ok_for {
49 my ($class, $group) = @_;
50
51 croak "req_ok_for() expects a requirement group name"
52 unless $group;
53
54 $class->_check_deps ($group) unless $req_availability_cache{$group};
55
56 return $req_availability_cache{$group}{status};
57}
58
59sub req_missing_for {
60 my ($class, $group) = @_;
61
62 croak "req_missing_for() expects a requirement group name"
63 unless $group;
64
65 $class->_check_deps ($group) unless $req_availability_cache{$group};
66
67 return $req_availability_cache{$group}{missing};
68}
69
70sub req_errorlist_for {
71 my ($class, $group) = @_;
72
73 croak "req_errorlist_for() expects a requirement group name"
74 unless $group;
75
76 $class->_check_deps ($group) unless $req_availability_cache{$group};
77
78 return $req_availability_cache{$group}{errorlist};
79}
80
81sub _check_deps {
82 my ($class, $group) = @_;
83
84 my $deps = $class->req_list_for ($group);
85
86 my %errors;
87 for my $mod (keys %$deps) {
88 if (my $ver = $deps->{$mod}) {
89 eval "use $mod $ver ()";
90 }
91 else {
92 eval "require $mod";
93 }
94
95 $errors{$mod} = $@ if $@;
96 }
97
98 if (keys %errors) {
99 my $missing = join (', ', map { $deps->{$_} ? "$_ >= $deps->{$_}" : $_ } (sort keys %errors) );
100 $missing .= " (see $class for details)" if $reqs->{$group}{pod};
101 $req_availability_cache{$group} = {
102 status => 0,
103 errorlist => { %errors },
104 missing => $missing,
105 };
106 }
107 else {
108 $req_availability_cache{$group} = {
109 status => 1,
110 errorlist => {},
111 missing => '',
112 };
113 }
114}
115
116sub req_group_list {
117 return { map { $_ => { %{ $reqs->{$_}{req} || {} } } } (keys %$reqs) };
118}
119
120# This is to be called by the author only (automatically in Makefile.PL)
121sub _gen_pod {
122
123 my $class = shift;
124 my $modfn = __PACKAGE__ . '.pm';
125 $modfn =~ s/\:\:/\//g;
126
127 my $podfn = __FILE__;
128 $podfn =~ s/\.pm$/\.pod/;
129
130 my $distver =
131 eval { require DBIx::Class::Schema::Loader; DBIx::Class::Schema::Loader->VERSION; }
132 ||
133 do {
134 warn
135"\n\n---------------------------------------------------------------------\n" .
136'Unable to load the DBIx::Class::Schema::Loader module to determine current ' .
137'version, possibly due to missing dependencies. Author-mode autodocumentation ' .
138"halted\n\n" . $@ .
139"\n\n---------------------------------------------------------------------\n"
140 ;
141 '*UNKNOWN*'; # rv
142 }
143 ;
144
145 my @chunks = (
146 <<"EOC",
147#########################################################################
148##################### A U T O G E N E R A T E D ########################
149#########################################################################
150#
151# The contents of this POD file are auto-generated. Any changes you make
152# will be lost. If you need to change the generated text edit _gen_pod()
153# at the end of $modfn
154#
155EOC
156 '=head1 NAME',
157 "$class - Optional module dependency specifications (for module authors)",
158 '=head1 SYNOPSIS',
159 <<EOS,
160Somewhere in your build-file (e.g. L<Module::Install>'s Makefile.PL):
161
162 ...
163
164 configure_requires 'DBIx::Class::Schema::Loader' => '$distver';
165
166 require $class;
167
168 my \$use_moose_deps = $class->req_list_for ('use_moose');
169
170 for (keys %\$use_moose_deps) {
171 requires \$_ => \$use_moose_deps->{\$_};
172 }
173
174 ...
175
176Note that there are some caveats regarding C<configure_requires()>, more info
177can be found at L<Module::Install/configure_requires>
178EOS
179 '=head1 DESCRIPTION',
180 <<'EOD',
181Some of the features of L<DBIx::Class::Schema::Loader> have external
182module dependencies on their own. In order not to burden the average user
183with modules he will never use, these optional dependencies are not included
184in the base Makefile.PL. Instead an exception with a descriptive message is
185thrown when a specific feature is missing one or several modules required for
186its operation. This module is the central holding place for the current list
187of such dependencies.
188EOD
189 '=head1 CURRENT REQUIREMENT GROUPS',
190 <<'EOD',
191Dependencies are organized in C<groups> and each group can list one or more
192required modules, with an optional minimum version (or 0 for any version).
193EOD
194 );
195
196 for my $group (sort keys %$reqs) {
197 my $p = $reqs->{$group}{pod}
198 or next;
199
200 my $modlist = $reqs->{$group}{req}
201 or next;
202
203 next unless keys %$modlist;
204
205 push @chunks, (
206 "=head2 $p->{title}",
207 "$p->{desc}",
208 '=over',
209 ( map { "=item * $_" . ($modlist->{$_} ? " >= $modlist->{$_}" : '') } (sort keys %$modlist) ),
210 '=back',
211 "Requirement group: B<$group>",
212 );
213 }
214
215 push @chunks, (
216 '=head1 METHODS',
217 '=head2 req_group_list',
218 '=over',
219 '=item Arguments: $none',
220 '=item Returns: \%list_of_requirement_groups',
221 '=back',
222 <<EOD,
223This method should be used by DBIx::Class packagers, to get a hashref of all
224dependencies keyed by dependency group. Each key (group name) can be supplied
225to one of the group-specific methods below.
226EOD
227
228 '=head2 req_list_for',
229 '=over',
230 '=item Arguments: $group_name',
231 '=item Returns: \%list_of_module_version_pairs',
232 '=back',
233 <<EOD,
234This method should be used by DBIx::Class extension authors, to determine the
235version of modules a specific feature requires in the B<current> version of
236L<DBIx::Class::Schema::Loader>. See the L</SYNOPSIS> for a real-world
237example.
238EOD
239
240 '=head2 req_ok_for',
241 '=over',
242 '=item Arguments: $group_name',
243 '=item Returns: 1|0',
244 '=back',
245 'Returns true or false depending on whether all modules required by C<$group_name> are present on the system and loadable',
246
247 '=head2 req_missing_for',
248 '=over',
249 '=item Arguments: $group_name',
250 '=item Returns: $error_message_string',
251 '=back',
252 <<EOD,
253Returns a single line string suitable for inclusion in larger error messages.
254This method would normally be used by L<DBIx::Class::Schema::Loader>
255maintainers, to indicate to the user that he needs to install specific modules
256before he will be able to use a specific feature.
257
258For example if some of the requirements for C<use_moose> are not available,
259the returned string could look like:
260
261 Moose >= 0 (see use_moose for details)
262
263The author is expected to prepend the necessary text to this message before
264returning the actual error seen by the user.
265EOD
266
267 '=head2 req_errorlist_for',
268 '=over',
269 '=item Arguments: $group_name',
270 '=item Returns: \%list_of_loaderrors_per_module',
271 '=back',
272 <<'EOD',
273Returns a hashref containing the actual errors that occured while attempting
274to load each module in the requirement group.
275EOD
276 '=head1 AUTHOR',
277 'See L<DBIx::Class/CONTRIBUTORS>.',
278 '=head1 LICENSE',
279 'You may distribute this code under the same terms as Perl itself',
280 );
281
282 open (my $fh, '>', $podfn) or croak "Unable to write to $podfn: $!";
283 print $fh join ("\n\n", @chunks);
284 close ($fh);
285}
286
2871;