This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Update Parse-CPAN-Meta to CPAN version 1.4405
[perl5.git] / cpan / Parse-CPAN-Meta / lib / Parse / CPAN / Meta.pm
1 use strict;
2 package Parse::CPAN::Meta;
3 # ABSTRACT: Parse META.yml and META.json CPAN metadata files
4 our $VERSION = '1.4405'; # VERSION
5
6 use Carp 'croak';
7
8 # UTF Support?
9 sub HAVE_UTF8 () { $] >= 5.007003 }
10 sub IO_LAYER () { $] >= 5.008001 ? ":utf8" : "" }  
11
12 BEGIN {
13         if ( HAVE_UTF8 ) {
14                 # The string eval helps hide this from Test::MinimumVersion
15                 eval "require utf8;";
16                 die "Failed to load UTF-8 support" if $@;
17         }
18
19         # Class structure
20         require 5.004;
21         require Exporter;
22         @Parse::CPAN::Meta::ISA       = qw{ Exporter      };
23         @Parse::CPAN::Meta::EXPORT_OK = qw{ Load LoadFile };
24 }
25
26 sub load_file {
27   my ($class, $filename) = @_;
28
29   if ($filename =~ /\.ya?ml$/) {
30     return $class->load_yaml_string(_slurp($filename));
31   }
32
33   if ($filename =~ /\.json$/) {
34     return $class->load_json_string(_slurp($filename));
35   }
36
37   croak("file type cannot be determined by filename");
38 }
39
40 sub load_yaml_string {
41   my ($class, $string) = @_;
42   my $backend = $class->yaml_backend();
43   my $data = eval { no strict 'refs'; &{"$backend\::Load"}($string) };
44   if ( $@ ) { 
45     croak $backend->can('errstr') ? $backend->errstr : $@
46   }
47   return $data || {}; # in case document was valid but empty
48 }
49
50 sub load_json_string {
51   my ($class, $string) = @_;
52   return $class->json_backend()->new->decode($string);
53 }
54
55 sub yaml_backend {
56   local $Module::Load::Conditional::CHECK_INC_HASH = 1;
57   if (! defined $ENV{PERL_YAML_BACKEND} ) {
58     _can_load( 'CPAN::Meta::YAML', 0.002 )
59       or croak "CPAN::Meta::YAML 0.002 is not available\n";
60     return "CPAN::Meta::YAML";
61   }
62   else {
63     my $backend = $ENV{PERL_YAML_BACKEND};
64     _can_load( $backend )
65       or croak "Could not load PERL_YAML_BACKEND '$backend'\n";
66     $backend->can("Load")
67       or croak "PERL_YAML_BACKEND '$backend' does not implement Load()\n";
68     return $backend;
69   }
70 }
71
72 sub json_backend {
73   local $Module::Load::Conditional::CHECK_INC_HASH = 1;
74   if (! $ENV{PERL_JSON_BACKEND} or $ENV{PERL_JSON_BACKEND} eq 'JSON::PP') {
75     _can_load( 'JSON::PP' => 2.27103 )
76       or croak "JSON::PP 2.27103 is not available\n";
77     return 'JSON::PP';
78   }
79   else {
80     _can_load( 'JSON' => 2.5 )
81       or croak  "JSON 2.5 is required for " .
82                 "\$ENV{PERL_JSON_BACKEND} = '$ENV{PERL_JSON_BACKEND}'\n";
83     return "JSON";
84   }
85 }
86
87 sub _slurp {
88   open my $fh, "<" . IO_LAYER, "$_[0]"
89     or die "can't open $_[0] for reading: $!";
90   return do { local $/; <$fh> };
91 }
92   
93 sub _can_load {
94   my ($module, $version) = @_;
95   (my $file = $module) =~ s{::}{/}g;
96   $file .= ".pm";
97   return 1 if $INC{$file};
98   return 0 if exists $INC{$file}; # prior load failed
99   eval { require $file; 1 }
100     or return 0;
101   if ( defined $version ) {
102     eval { $module->VERSION($version); 1 }
103       or return 0;
104   }
105   return 1;
106 }
107
108 # Kept for backwards compatibility only
109 # Create an object from a file
110 sub LoadFile ($) {
111   require CPAN::Meta::YAML;
112   my $object = CPAN::Meta::YAML::LoadFile(shift)
113     or die CPAN::Meta::YAML->errstr;
114   return $object;
115 }
116
117 # Parse a document from a string.
118 sub Load ($) {
119   require CPAN::Meta::YAML;
120   my $object = CPAN::Meta::YAML::Load(shift)
121     or die CPAN::Meta::YAML->errstr;
122   return $object;
123 }
124
125 1;
126
127 __END__
128
129 =pod
130
131 =encoding utf-8
132
133 =head1 NAME
134
135 Parse::CPAN::Meta - Parse META.yml and META.json CPAN metadata files
136
137 =head1 VERSION
138
139 version 1.4405
140
141 =head1 SYNOPSIS
142
143     #############################################
144     # In your file
145     
146     ---
147     name: My-Distribution
148     version: 1.23
149     resources:
150       homepage: "http://example.com/dist/My-Distribution"
151     
152     
153     #############################################
154     # In your program
155     
156     use Parse::CPAN::Meta;
157     
158     my $distmeta = Parse::CPAN::Meta->load_file('META.yml');
159     
160     # Reading properties
161     my $name     = $distmeta->{name};
162     my $version  = $distmeta->{version};
163     my $homepage = $distmeta->{resources}{homepage};
164
165 =head1 DESCRIPTION
166
167 B<Parse::CPAN::Meta> is a parser for F<META.json> and F<META.yml> files, using
168 L<JSON::PP> and/or L<CPAN::Meta::YAML>.
169
170 B<Parse::CPAN::Meta> provides three methods: C<load_file>, C<load_json_string>,
171 and C<load_yaml_string>.  These will read and deserialize CPAN metafiles, and
172 are described below in detail.
173
174 B<Parse::CPAN::Meta> provides a legacy API of only two functions,
175 based on the YAML functions of the same name. Wherever possible,
176 identical calling semantics are used.  These may only be used with YAML sources.
177
178 All error reporting is done with exceptions (die'ing).
179
180 Note that META files are expected to be in UTF-8 encoding, only.  When
181 converted string data, it must first be decoded from UTF-8.
182
183 =for Pod::Coverage HAVE_UTF8 IO_LAYER
184
185 =head1 METHODS
186
187 =head2 load_file
188
189   my $metadata_structure = Parse::CPAN::Meta->load_file('META.json');
190
191   my $metadata_structure = Parse::CPAN::Meta->load_file('META.yml');
192
193 This method will read the named file and deserialize it to a data structure,
194 determining whether it should be JSON or YAML based on the filename.  On
195 Perl 5.8.1 or later, the file will be read using the ":utf8" IO layer.
196
197 =head2 load_yaml_string
198
199   my $metadata_structure = Parse::CPAN::Meta->load_yaml_string($yaml_string);
200
201 This method deserializes the given string of YAML and returns the first
202 document in it.  (CPAN metadata files should always have only one document.)
203 If the source was UTF-8 encoded, the string must be decoded before calling
204 C<load_yaml_string>.
205
206 =head2 load_json_string
207
208   my $metadata_structure = Parse::CPAN::Meta->load_json_string($json_string);
209
210 This method deserializes the given string of JSON and the result.  
211 If the source was UTF-8 encoded, the string must be decoded before calling
212 C<load_json_string>.
213
214 =head2 yaml_backend
215
216   my $backend = Parse::CPAN::Meta->yaml_backend;
217
218 Returns the module name of the YAML serializer. See L</ENVIRONMENT>
219 for details.
220
221 =head2 json_backend
222
223   my $backend = Parse::CPAN::Meta->json_backend;
224
225 Returns the module name of the JSON serializer.  This will either
226 be L<JSON::PP> or L<JSON>.  Even if C<PERL_JSON_BACKEND> is set,
227 this will return L<JSON> as further delegation is handled by
228 the L<JSON> module.  See L</ENVIRONMENT> for details.
229
230 =head1 FUNCTIONS
231
232 For maintenance clarity, no functions are exported.  These functions are
233 available for backwards compatibility only and are best avoided in favor of
234 C<load_file>.
235
236 =head2 Load
237
238   my @yaml = Parse::CPAN::Meta::Load( $string );
239
240 Parses a string containing a valid YAML stream into a list of Perl data
241 structures.
242
243 =head2 LoadFile
244
245   my @yaml = Parse::CPAN::Meta::LoadFile( 'META.yml' );
246
247 Reads the YAML stream from a file instead of a string.
248
249 =head1 ENVIRONMENT
250
251 =head2 PERL_JSON_BACKEND
252
253 By default, L<JSON::PP> will be used for deserializing JSON data. If the
254 C<PERL_JSON_BACKEND> environment variable exists, is true and is not
255 "JSON::PP", then the L<JSON> module (version 2.5 or greater) will be loaded and
256 used to interpret C<PERL_JSON_BACKEND>.  If L<JSON> is not installed or is too
257 old, an exception will be thrown.
258
259 =head2 PERL_YAML_BACKEND
260
261 By default, L<CPAN::Meta::YAML> will be used for deserializing YAML data. If
262 the C<PERL_YAML_BACKEND> environment variable is defined, then it is interpreted
263 as a module to use for deserialization.  The given module must be installed,
264 must load correctly and must implement the C<Load()> function or an exception
265 will be thrown.
266
267 =for :stopwords cpan testmatrix url annocpan anno bugtracker rt cpants kwalitee diff irc mailto metadata placeholders metacpan
268
269 =head1 SUPPORT
270
271 =head2 Bugs / Feature Requests
272
273 Please report any bugs or feature requests through the issue tracker
274 at L<https://rt.cpan.org/Public/Dist/Display.html?Name=Parse-CPAN-Meta>.
275 You will be notified automatically of any progress on your issue.
276
277 =head2 Source Code
278
279 This is open source software.  The code repository is available for
280 public review and contribution under the terms of the license.
281
282 L<http://github.com/Perl-Toolchain-Gang/Parse-CPAN-Meta>
283
284   git clone git://github.com/Perl-Toolchain-Gang/Parse-CPAN-Meta.git
285
286 =head1 AUTHOR
287
288 Adam Kennedy <adamk@cpan.org>
289
290 =head1 CONTRIBUTORS
291
292 =over 4
293
294 =item *
295
296 David Golden <dagolden@cpan.org>
297
298 =item *
299
300 Joshua ben Jore <jjore@cpan.org>
301
302 =item *
303
304 Ricardo SIGNES <rjbs@cpan.org>
305
306 =item *
307
308 Steffen Müller <smueller@cpan.org>
309
310 =back
311
312 =head1 COPYRIGHT AND LICENSE
313
314 This software is copyright (c) 2013 by Adam Kennedy and Contributors.
315
316 This is free software; you can redistribute it and/or modify it under
317 the same terms as the Perl 5 programming language system itself.
318
319 =cut