This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
5d1d1f0600d3320e37b743feb14bd2d62596389b
[perl5.git] / cpan / CPAN-Meta / lib / CPAN / Meta / Prereqs.pm
1 use 5.006;
2 use strict;
3 use warnings;
4 package CPAN::Meta::Prereqs;
5 our $VERSION = '2.112150'; # VERSION
6
7
8 use Carp qw(confess);
9 use Scalar::Util qw(blessed);
10 use Version::Requirements 0.101020; # finalize
11
12
13 sub __legal_phases { qw(configure build test runtime develop)   }
14 sub __legal_types  { qw(requires recommends suggests conflicts) }
15
16 # expect a prereq spec from META.json -- rjbs, 2010-04-11
17 sub new {
18   my ($class, $prereq_spec) = @_;
19   $prereq_spec ||= {};
20
21   my %is_legal_phase = map {; $_ => 1 } $class->__legal_phases;
22   my %is_legal_type  = map {; $_ => 1 } $class->__legal_types;
23
24   my %guts;
25   PHASE: for my $phase (keys %$prereq_spec) {
26     next PHASE unless $phase =~ /\Ax_/i or $is_legal_phase{$phase};
27
28     my $phase_spec = $prereq_spec->{ $phase };
29     next PHASE unless keys %$phase_spec;
30
31     TYPE: for my $type (keys %$phase_spec) {
32       next TYPE unless $type =~ /\Ax_/i or $is_legal_type{$type};
33
34       my $spec = $phase_spec->{ $type };
35
36       next TYPE unless keys %$spec;
37
38       $guts{prereqs}{$phase}{$type} = Version::Requirements->from_string_hash(
39         $spec
40       );
41     }
42   }
43
44   return bless \%guts => $class;
45 }
46
47
48 sub requirements_for {
49   my ($self, $phase, $type) = @_;
50
51   confess "requirements_for called without phase" unless defined $phase;
52   confess "requirements_for called without type"  unless defined $type;
53
54   unless ($phase =~ /\Ax_/i or grep { $phase eq $_ } $self->__legal_phases) {
55     confess "requested requirements for unknown phase: $phase";
56   }
57
58   unless ($type =~ /\Ax_/i or grep { $type eq $_ } $self->__legal_types) {
59     confess "requested requirements for unknown type: $type";
60   }
61
62   my $req = ($self->{prereqs}{$phase}{$type} ||= Version::Requirements->new);
63
64   $req->finalize if $self->is_finalized;
65
66   return $req;
67 }
68
69
70 sub with_merged_prereqs {
71   my ($self, $other) = @_;
72
73   my @other = blessed($other) ? $other : @$other;
74
75   my @prereq_objs = ($self, @other);
76
77   my %new_arg;
78
79   for my $phase ($self->__legal_phases) {
80     for my $type ($self->__legal_types) {
81       my $req = Version::Requirements->new;
82
83       for my $prereq (@prereq_objs) {
84         my $this_req = $prereq->requirements_for($phase, $type);
85         next unless $this_req->required_modules;
86
87         $req->add_requirements($this_req);
88       }
89
90       next unless $req->required_modules;
91
92       $new_arg{ $phase }{ $type } = $req->as_string_hash;
93     }
94   }
95
96   return (ref $self)->new(\%new_arg);
97 }
98
99
100 sub as_string_hash {
101   my ($self) = @_;
102
103   my %hash;
104
105   for my $phase ($self->__legal_phases) {
106     for my $type ($self->__legal_types) {
107       my $req = $self->requirements_for($phase, $type);
108       next unless $req->required_modules;
109
110       $hash{ $phase }{ $type } = $req->as_string_hash;
111     }
112   }
113
114   return \%hash;
115 }
116
117
118 sub is_finalized { $_[0]{finalized} }
119
120
121 sub finalize {
122   my ($self) = @_;
123
124   $self->{finalized} = 1;
125
126   for my $phase (keys %{ $self->{prereqs} }) {
127     $_->finalize for values %{ $self->{prereqs}{$phase} };
128   }
129 }
130
131
132 sub clone {
133   my ($self) = @_;
134
135   my $clone = (ref $self)->new( $self->as_string_hash );
136 }
137
138 1;
139
140 # ABSTRACT: a set of distribution prerequisites by phase and type
141
142
143
144 =pod
145
146 =head1 NAME
147
148 CPAN::Meta::Prereqs - a set of distribution prerequisites by phase and type
149
150 =head1 VERSION
151
152 version 2.112150
153
154 =head1 DESCRIPTION
155
156 A CPAN::Meta::Prereqs object represents the prerequisites for a CPAN
157 distribution or one of its optional features.  Each set of prereqs is
158 organized by phase and type, as described in L<CPAN::Meta::Prereqs>.
159
160 =head1 METHODS
161
162 =head2 new
163
164   my $prereq = CPAN::Meta::Prereqs->new( \%prereq_spec );
165
166 This method returns a new set of Prereqs.  The input should look like the
167 contents of the C<prereqs> field described in L<CPAN::Meta::Spec>, meaning
168 something more or less like this:
169
170   my $prereq = CPAN::Meta::Prereqs->new({
171     runtime => {
172       requires => {
173         'Some::Module' => '1.234',
174         ...,
175       },
176       ...,
177     },
178     ...,
179   });
180
181 You can also construct an empty set of prereqs with:
182
183   my $prereqs = CPAN::Meta::Prereqs->new;
184
185 This empty set of prereqs is useful for accumulating new prereqs before finally
186 dumping the whole set into a structure or string.
187
188 =head2 requirements_for
189
190   my $requirements = $prereqs->requirements_for( $phase, $type );
191
192 This method returns a L<Version::Requirements> object for the given phase/type
193 combination.  If no prerequisites are registered for that combination, a new
194 Version::Requirements object will be returned, and it may be added to as
195 needed.
196
197 If C<$phase> or C<$type> are undefined or otherwise invalid, an exception will
198 be raised.
199
200 =head2 with_merged_prereqs
201
202   my $new_prereqs = $prereqs->with_merged_prereqs( $other_prereqs );
203
204   my $new_prereqs = $prereqs->with_merged_prereqs( \@other_prereqs );
205
206 This method returns a new CPAN::Meta::Prereqs objects in which all the
207 other prerequisites given are merged into the current set.  This is primarily
208 provided for combining a distribution's core prereqs with the prereqs of one of
209 its optional features.
210
211 The new prereqs object has no ties to the originals, and altering it further
212 will not alter them.
213
214 =head2 as_string_hash
215
216 This method returns a hashref containing structures suitable for dumping into a
217 distmeta data structure.  It is made up of hashes and strings, only; there will
218 be no Prereqs, Version::Requirements, or C<version> objects inside it.
219
220 =head2 is_finalized
221
222 This method returns true if the set of prereqs has been marked "finalized," and
223 cannot be altered.
224
225 =head2 finalize
226
227 Calling C<finalize> on a Prereqs object will close it for further modification.
228 Attempting to make any changes that would actually alter the prereqs will
229 result in an exception being thrown.
230
231 =head2 clone
232
233   my $cloned_prereqs = $prereqs->clone;
234
235 This method returns a Prereqs object that is identical to the original object,
236 but can be altered without affecting the original object.  Finalization does
237 not survive cloning, meaning that you may clone a finalized set of prereqs and
238 then modify the clone.
239
240 =head1 BUGS
241
242 Please report any bugs or feature using the CPAN Request Tracker.
243 Bugs can be submitted through the web interface at
244 L<http://rt.cpan.org/Dist/Display.html?Queue=CPAN-Meta>
245
246 When submitting a bug or request, please include a test-file or a patch to an
247 existing test-file that illustrates the bug or desired feature.
248
249 =head1 AUTHORS
250
251 =over 4
252
253 =item *
254
255 David Golden <dagolden@cpan.org>
256
257 =item *
258
259 Ricardo Signes <rjbs@cpan.org>
260
261 =back
262
263 =head1 COPYRIGHT AND LICENSE
264
265 This software is copyright (c) 2010 by David Golden and Ricardo Signes.
266
267 This is free software; you can redistribute it and/or modify it under
268 the same terms as the Perl 5 programming language system itself.
269
270 =cut
271
272
273 __END__
274
275
276