~ubuntu-branches/ubuntu/wily/libcpan-meta-perl/wily

« back to all changes in this revision

Viewing changes to lib/CPAN/Meta/Converter.pm

  • Committer: Bazaar Package Importer
  • Author(s): gregor herrmann, Ansgar Burchardt, gregor herrmann
  • Date: 2010-06-08 18:24:53 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100608182453-2t3cf80vqfn52qtk
Tags: 2.101591-1
[ Ansgar Burchardt ]
* New upstream release 2.101590.
* Add (build-)dep on libversion-perl (>= 1:0.8200) | perl (>= 5.12).
* Drop patch spelling.patch: applied upstream.

[ gregor herrmann ]
* New upstream release 2.101591.
* Add /me to Uploaders.

Show diffs side-by-side

added added

removed removed

Lines of Context:
4
4
use autodie;
5
5
package CPAN::Meta::Converter;
6
6
BEGIN {
7
 
  $CPAN::Meta::Converter::VERSION = '2.101461';
 
7
  $CPAN::Meta::Converter::VERSION = '2.101591';
8
8
}
9
9
# ABSTRACT: Convert CPAN distribution metadata structures
10
10
 
11
11
 
12
 
use Carp qw(carp confess);
13
12
use CPAN::Meta::Validator;
14
13
use Storable qw/dclone/;
 
14
use version 0.82 ();
15
15
 
16
16
my %known_specs = (
17
17
    '2'   => 'http://search.cpan.org/perldoc?CPAN::Meta::Spec',
40
40
 
41
41
sub _keep_or_zero { defined($_[0]) ? $_[0] : 0 }
42
42
 
43
 
sub _keep_or_unknown { defined($_[0]) ? $_[0] : "unknown" }
 
43
sub _keep_or_unknown { defined($_[0]) && length($_[0]) ? $_[0] : "unknown" }
44
44
 
45
45
sub _generated_by {
46
46
  my $gen = shift;
222
222
  'namespace' => \&_listify,
223
223
};
224
224
 
 
225
my $no_index_spec_2 = {
 
226
  'file' => \&_listify,
 
227
  'directory' => \&_listify,
 
228
  'package' => \&_listify,
 
229
  'namespace' => \&_listify,
 
230
  ':custom'  => \&_prefix_custom,
 
231
};
 
232
 
225
233
sub _no_index_1_2 {
226
234
  my (undef, undef, $meta) = @_;
227
 
  return _convert($meta->{private}, $no_index_spec_1_2);
 
235
  my $no_index = $meta->{no_index} || $meta->{private};
 
236
  return unless $no_index;
 
237
 
 
238
  # cleanup wrong format
 
239
  if ( ! ref $no_index ) {
 
240
    my $item = $no_index;
 
241
    $no_index = { dir => [ $item ], file => [ $item ] };
 
242
  }
 
243
  elsif ( ref $no_index eq 'ARRAY' ) {
 
244
    my $list = $no_index;
 
245
    $no_index = { dir => [ @$list ], file => [ @$list ] };
 
246
  }
 
247
 
 
248
  # common mistake: files -> file
 
249
  if ( exists $no_index->{files} ) {
 
250
    $no_index->{file} = delete $no_index->{file};
 
251
  }
 
252
  # common mistake: modules -> module
 
253
  if ( exists $no_index->{modules} ) {
 
254
    $no_index->{module} = delete $no_index->{module};
 
255
  }
 
256
  return _convert($no_index, $no_index_spec_1_2);
228
257
}
229
258
 
230
259
sub _no_index_directory {
231
 
  my ($element) = @_;
 
260
  my ($element, $key, $meta, $version) = @_;
232
261
  return unless $element;
 
262
 
 
263
  # cleanup wrong format
 
264
  if ( ! ref $element ) {
 
265
    my $item = $element;
 
266
    $element = { directory => [ $item ], file => [ $item ] };
 
267
  }
 
268
  elsif ( ref $element eq 'ARRAY' ) {
 
269
    my $list = $element;
 
270
    $element = { directory => [ @$list ], file => [ @$list ] };
 
271
  }
 
272
 
233
273
  if ( exists $element->{dir} ) {
234
274
    $element->{directory} = delete $element->{dir};
235
275
  }
236
 
  return _convert($element, $no_index_spec_1_3);
 
276
  # common mistake: files -> file
 
277
  if ( exists $element->{files} ) {
 
278
    $element->{file} = delete $element->{file};
 
279
  }
 
280
  # common mistake: modules -> module
 
281
  if ( exists $element->{modules} ) {
 
282
    $element->{module} = delete $element->{module};
 
283
  }
 
284
  my $spec = $version == 2 ? $no_index_spec_2 : $no_index_spec_1_3;
 
285
  return _convert($element, $spec);
 
286
}
 
287
 
 
288
sub _is_module_name {
 
289
  my $mod = shift;
 
290
  return unless defined $mod && length $mod;
 
291
  return $mod =~ m{^[A-Za-z][A-Za-z0-9_]*(?:::[A-Za-z0-9_]+)*$};
 
292
}
 
293
 
 
294
sub _clean_version {
 
295
  my ($element, $key, $meta, $to_version) = @_;
 
296
  return 0 if ! defined $element;
 
297
 
 
298
  $element =~ s{^\s*}{};
 
299
  $element =~ s{\s*$}{};
 
300
  $element =~ s{^\.}{0.};
 
301
 
 
302
  return 0 if ! length $element;
 
303
  return 0 if ( $element eq 'undef' || $element eq '<undef>' );
 
304
 
 
305
  if ( my $v = eval { version->new($element) } ) {
 
306
    return $v->is_qv ? $v->normal : $element;
 
307
  }
 
308
  else {
 
309
    return 0;
 
310
  }
237
311
}
238
312
 
239
313
sub _version_map {
240
314
  my ($element) = @_;
241
315
  return undef unless defined $element;
242
 
  return $element unless ref $element eq 'HASH';
243
 
  my $new_map = {};
244
 
  for my $k ( keys %$element ) {
245
 
    my $value = $element->{$k};
246
 
    $new_map->{$k} = (defined $value && length $value) ? $value : 0;
247
 
  }
248
 
  return $new_map;
 
316
  if ( ref $element eq 'HASH' ) {
 
317
    my $new_map = {};
 
318
    for my $k ( keys %$element ) {
 
319
      next unless _is_module_name($k);
 
320
      my $value = $element->{$k};
 
321
      if ( ! ( defined $value && length $value ) ) {
 
322
        $new_map->{$k} = 0;
 
323
      }
 
324
      elsif ( $value eq 'undef' || $value eq '<undef>' ) {
 
325
        $new_map->{$k} = 0;
 
326
      }
 
327
      elsif ( _is_module_name( $value ) ) { # some weird, old META have this
 
328
        $new_map->{$k} = 0;
 
329
        $new_map->{$value} = 0;
 
330
      }
 
331
      else {
 
332
        $new_map->{$k} = _clean_version($value);
 
333
      }
 
334
    }
 
335
    return $new_map;
 
336
  }
 
337
  elsif ( ref $element eq 'ARRAY' ) {
 
338
    my $hashref = { map { $_ => 0 } @$element };
 
339
    return _version_map($hashref); # cleanup any weird stuff
 
340
  }
 
341
  elsif ( ref $element eq '' && length $element ) {
 
342
    return { $element => 0 }
 
343
  }
 
344
  return;
249
345
}
250
346
 
251
 
sub _prereqs {
 
347
sub _prereqs_from_1 {
252
348
  my (undef, undef, $meta) = @_;
253
349
  my $prereqs = {};
254
350
  for my $phase ( qw/build configure/ ) {
263
359
  return $prereqs;
264
360
}
265
361
 
 
362
my $prereqs_spec = {
 
363
  configure => \&_prereqs_rel,
 
364
  build     => \&_prereqs_rel,
 
365
  test      => \&_prereqs_rel,
 
366
  runtime   => \&_prereqs_rel,
 
367
  develop   => \&_prereqs_rel,
 
368
  ':custom'  => \&_prefix_custom,
 
369
};
 
370
 
 
371
my $relation_spec = {
 
372
  requires   => \&_version_map,
 
373
  recommends => \&_version_map,
 
374
  suggests   => \&_version_map,
 
375
  conflicts  => \&_version_map,
 
376
  ':custom'  => \&_prefix_custom,
 
377
};
 
378
 
 
379
sub _cleanup_prereqs {
 
380
  my ($prereqs, $key, $meta, $to_version) = @_;
 
381
  return unless $prereqs && ref $prereqs eq 'HASH';
 
382
  return _convert( $prereqs, $prereqs_spec, $to_version );
 
383
}
 
384
 
 
385
sub _prereqs_rel {
 
386
  my ($relation, $key, $meta, $to_version) = @_;
 
387
  return unless $relation && ref $relation eq 'HASH';
 
388
  return _convert( $relation, $relation_spec, $to_version );
 
389
}
 
390
 
 
391
 
266
392
BEGIN {
267
393
  my @old_prereqs = qw(
268
394
    requires
323
449
  return $features;
324
450
}
325
451
 
326
 
 
327
 
sub _optional_features_2 {
 
452
sub _upgrade_optional_features {
328
453
  my (undef, undef, $meta) = @_;
329
454
  return undef unless exists $meta->{optional_features};
330
455
  my $origin = $meta->{optional_features};
332
457
  for my $name ( keys %$origin ) {
333
458
    $features->{$name} = {
334
459
      description => $origin->{$name}{description},
335
 
      prereqs => _prereqs(undef, undef, $origin->{$name}),
 
460
      prereqs => _prereqs_from_1(undef, undef, $origin->{$name}),
336
461
    };
337
462
    delete $features->{$name}{prereqs}{configure};
338
463
  }
339
464
  return $features;
340
465
}
341
466
 
 
467
my $optional_features_2_spec = {
 
468
  description => \&_keep,
 
469
  prereqs => \&_cleanup_prereqs,
 
470
  ':custom'  => \&_prefix_custom,
 
471
};
 
472
 
 
473
sub _feature_2 {
 
474
  my ($element, $key, $meta, $to_version) = @_;
 
475
  return unless $element && ref $element eq 'HASH';
 
476
  _convert( $element, $optional_features_2_spec, $to_version );
 
477
}
 
478
 
 
479
sub _cleanup_optional_features_2 {
 
480
  my ($element, $key, $meta, $to_version) = @_;
 
481
  return unless $element && ref $element eq 'HASH';
 
482
  my $new_data = {};
 
483
  for my $k ( keys %$element ) {
 
484
    $new_data->{$k} = _feature_2( $element->{$k}, $k, $meta, $to_version );
 
485
  }
 
486
  return unless keys %$new_data;
 
487
  return $new_data;
 
488
}
 
489
 
342
490
sub _optional_features_1_4 {
343
491
  my ($element) = @_;
344
492
  return unless $element;
345
 
  for my $drop ( qw/requires_packages requires_os excluded_os/ ) {
346
 
    delete $element->{$drop};
 
493
  $element = _optional_features_as_map($element);
 
494
  for my $name ( keys %$element ) {
 
495
    for my $drop ( qw/requires_packages requires_os excluded_os/ ) {
 
496
      delete $element->{$name}{$drop};
 
497
    }
 
498
  }
 
499
  return $element;
 
500
}
 
501
 
 
502
sub _optional_features_as_map {
 
503
  my ($element) = @_;
 
504
  return unless $element;
 
505
  if ( ref $element eq 'ARRAY' ) {
 
506
    my %map;
 
507
    for my $feature ( @$element ) {
 
508
      my (@parts) = %$feature;
 
509
      $map{$parts[0]} = $parts[1];
 
510
    }
 
511
    $element = \%map;
347
512
  }
348
513
  return $element;
349
514
}
356
521
  return;
357
522
}
358
523
 
359
 
my $resource2_spec = {
 
524
sub _url_list {
 
525
  my ($element) = @_;
 
526
  return unless $element;
 
527
  $element = _listify( $element );
 
528
  $element = [ grep { _is_urlish($_) } @$element ];
 
529
  return unless @$element;
 
530
  return $element;
 
531
}
 
532
 
 
533
sub _author_list {
 
534
  my ($element) = @_;
 
535
  return [ 'unknown' ] unless $element;
 
536
  $element = _listify( $element );
 
537
  $element = [ map { defined $_ && length $_ ? $_ : 'unknown' } @$element ];
 
538
  return [ 'unknown' ] unless @$element;
 
539
  return $element;
 
540
}
 
541
 
 
542
my $resource2_upgrade = {
360
543
  license    => sub { return _is_urlish($_[0]) ? _listify( $_[0] ) : undef },
361
544
  homepage   => \&_url_or_drop,
362
 
  bugtracker => sub { return _is_urlish($_[0]) ? { web => $_[0] } : undef },
 
545
  bugtracker => sub {
 
546
    my $item = @_;
 
547
    if ( $item =~ m{^mailto:(.*)$} ) { return { mailto => $1 } }
 
548
    elsif( _is_urlish($item) ) { return { web => $_[0] } }
 
549
    else { return undef }
 
550
  },
363
551
  repository => sub { return _is_urlish($_[0]) ? { web => $_[0] } : undef },
364
552
  ':custom'  => \&_prefix_custom,
365
553
};
366
554
 
367
 
sub _resources_2 {
 
555
sub _upgrade_resources_2 {
368
556
  my (undef, undef, $meta, $version) = @_;
369
557
  return undef unless exists $meta->{resources};
370
 
  return _convert($meta->{resources}, $resource2_spec);
 
558
  return _convert($meta->{resources}, $resource2_upgrade);
 
559
}
 
560
 
 
561
my $bugtracker2_spec = {
 
562
  web => \&_url_or_drop,
 
563
  mailto => \&_keep,
 
564
  ':custom'  => \&_prefix_custom,
 
565
};
 
566
 
 
567
sub _repo_type {
 
568
  my ($element, $key, $meta, $to_version) = @_;
 
569
  return $element if defined $element;
 
570
  return unless exists $meta->{url};
 
571
  my $repo_url = $meta->{url};
 
572
  for my $type ( qw/git svn/ ) {
 
573
    return $type if $repo_url =~ m{\A$type};
 
574
  }
 
575
  return;
 
576
}
 
577
 
 
578
my $repository2_spec = {
 
579
  web => \&_url_or_drop,
 
580
  url => \&_url_or_drop,
 
581
  type => \&_repo_type,
 
582
  ':custom'  => \&_prefix_custom,
 
583
};
 
584
 
 
585
my $resources2_cleanup = {
 
586
  license    => \&_url_list,
 
587
  homepage   => \&_url_or_drop,
 
588
  bugtracker => sub { ref $_[0] ? _convert( $_[0], $bugtracker2_spec ) : undef },
 
589
  repository => sub { my $data = shift; ref $data ? _convert( $data, $repository2_spec ) : undef },
 
590
  ':custom'  => \&_prefix_custom,
 
591
};
 
592
 
 
593
sub _cleanup_resources_2 {
 
594
  my ($resources, $key, $meta, $to_version) = @_;
 
595
  return undef unless $resources && ref $resources eq 'HASH';
 
596
  return _convert($resources, $resources2_cleanup, $to_version);
371
597
}
372
598
 
373
599
my $resource1_spec = {
388
614
 
389
615
sub _resources_1_2 {
390
616
  my (undef, undef, $meta) = @_;
391
 
  return undef unless _is_urlish($meta->{license_url});
392
 
  return { license => $meta->{license_url} };
 
617
  my $resources = $meta->{resources} || {};
 
618
  if ( $meta->{license_url} && ! $resources->{license} ) {
 
619
    $resources->{license} = $meta->license_url
 
620
      if _is_urlish($meta->{license_url});
 
621
  }
 
622
  return undef unless keys %$resources;
 
623
  return _convert($resources, $resource1_spec);
393
624
}
394
625
 
395
626
my $resource_downgrade_spec = {
407
638
}
408
639
 
409
640
sub _release_status {
 
641
  my ($element, undef, $meta) = @_;
 
642
  return $element if $element && $element =~ m{\A(?:stable|testing|unstable)\z};
 
643
  return _release_status_from_version(undef, undef, $meta);
 
644
}
 
645
 
 
646
sub _release_status_from_version {
410
647
  my (undef, undef, $meta) = @_;
411
648
  my $version = $meta->{version} || '';
412
649
  return ( $version =~ /_/ ) ? 'testing' : 'stable';
413
650
}
414
651
 
 
652
my $provides_spec = {
 
653
  file => \&_keep,
 
654
  version => \&_clean_version,
 
655
};
 
656
 
 
657
my $provides_spec_2 = {
 
658
  file => \&_keep,
 
659
  version => \&_clean_version,
 
660
  ':custom'  => \&_prefix_custom,
 
661
};
 
662
 
 
663
sub _provides {
 
664
  my ($element, $key, $meta, $to_version) = @_;
 
665
  return unless defined $element && ref $element eq 'HASH';
 
666
  my $spec = $to_version == 2 ? $provides_spec_2 : $provides_spec;
 
667
  my $new_data = {};
 
668
  for my $k ( keys %$element ) {
 
669
    $new_data->{$k} = _convert($element->{$k}, $spec, $to_version);
 
670
  }
 
671
  return $new_data;
 
672
}
 
673
 
415
674
sub _convert {
416
675
  my ($data, $spec, $to_version) = @_;
417
676
 
418
677
  my $new_data = {};
419
 
  for my $key ( %$spec ) {
 
678
  for my $key ( keys %$spec ) {
420
679
    next if $key eq ':custom' || $key eq ':drop';
421
680
    next unless my $fcn = $spec->{$key};
422
681
    die "spec for '$key' is not a coderef"
430
689
 
431
690
  for my $key ( keys %$data ) {
432
691
    next if $drop_list && grep { $key eq $_ } @$drop_list;
433
 
    next if $spec->{$key}; # we handled it
 
692
    next if exists $spec->{$key}; # we handled it
434
693
    $new_data->{ $customizer->($key) } = $data->{$key};
435
694
  }
436
695
 
447
706
  '2-from-1.4' => {
448
707
    # PRIOR MANDATORY
449
708
    'abstract'            => \&_keep_or_unknown,
450
 
    'author'              => sub { _listify( _keep_or_unknown( @_ ) ) },
 
709
    'author'              => \&_author_list,
451
710
    'generated_by'        => \&_generated_by,
452
711
    'license'             => \&_license_2,
453
712
    'meta-spec'           => \&_change_meta_spec,
456
715
    # CHANGED TO MANDATORY
457
716
    'dynamic_config'      => \&_keep_or_one,
458
717
    # ADDED MANDATORY
459
 
    'release_status'      => \&_release_status,
 
718
    'release_status'      => \&_release_status_from_version,
460
719
    # PRIOR OPTIONAL
461
720
    'keywords'            => \&_keep,
462
721
    'no_index'            => \&_no_index_directory,
463
 
    'optional_features'   => \&_optional_features_2,
464
 
    'provides'            => \&_keep,
465
 
    'resources'           => \&_resources_2,
 
722
    'optional_features'   => \&_upgrade_optional_features,
 
723
    'provides'            => \&_provides,
 
724
    'resources'           => \&_upgrade_resources_2,
466
725
    # ADDED OPTIONAL
467
726
    'description'         => \&_keep,
468
 
    'prereqs'             => \&_prereqs,
 
727
    'prereqs'             => \&_prereqs_from_1,
469
728
 
470
729
    # drop these deprecated fields, but only after we convert
471
730
    ':drop' => [ qw(
485
744
  '1.4-from-1.3' => {
486
745
    # PRIOR MANDATORY
487
746
    'abstract'            => \&_keep_or_unknown,
488
 
    'author'              => sub { _listify( _keep_or_unknown( @_ ) ) },
 
747
    'author'              => \&_author_list,
489
748
    'generated_by'        => \&_generated_by,
490
749
    'license'             => \&_license_1,
491
750
    'meta-spec'           => \&_change_meta_spec,
499
758
    'keywords'            => \&_keep,
500
759
    'no_index'            => \&_no_index_directory,
501
760
    'optional_features'   => \&_optional_features_1_4,
502
 
    'provides'            => \&_keep,
 
761
    'provides'            => \&_provides,
503
762
    'recommends'          => \&_version_map,
504
763
    'requires'            => \&_version_map,
505
764
    'resources'           => \&_resources_1_4,
518
777
  '1.3-from-1.2' => {
519
778
    # PRIOR MANDATORY
520
779
    'abstract'            => \&_keep_or_unknown,
521
 
    'author'              => sub { _listify( _keep_or_unknown( @_ ) ) },
 
780
    'author'              => \&_author_list,
522
781
    'generated_by'        => \&_generated_by,
523
782
    'license'             => \&_license_1,
524
783
    'meta-spec'           => \&_change_meta_spec,
531
790
    'dynamic_config'      => \&_keep_or_one,
532
791
    'keywords'            => \&_keep,
533
792
    'no_index'            => \&_no_index_directory,
534
 
    'optional_features'   => \&_keep,
535
 
    'provides'            => \&_keep,
 
793
    'optional_features'   => \&_optional_features_as_map,
 
794
    'provides'            => \&_provides,
536
795
    'recommends'          => \&_version_map,
537
796
    'requires'            => \&_version_map,
538
797
    'resources'           => \&_resources_1_3,
555
814
    'generated_by'        => \&_generated_by,
556
815
    # ADDED MANDATORY
557
816
    'abstract'            => \&_keep_or_unknown,
558
 
    'author'              => sub { _listify( _keep_or_unknown( @_ ) ) },
 
817
    'author'              => \&_author_list,
559
818
    'meta-spec'           => \&_change_meta_spec,
560
819
    # PRIOR OPTIONAL
561
820
    'build_requires'      => \&_version_map,
567
826
    # ADDED OPTIONAL
568
827
    'keywords'            => \&_keep,
569
828
    'no_index'            => \&_no_index_1_2,
570
 
    'optional_features'   => \&_keep,
571
 
    'provides'            => \&_keep,
 
829
    'optional_features'   => \&_optional_features_as_map,
 
830
    'provides'            => \&_provides,
572
831
    'resources'           => \&_resources_1_2,
573
832
 
574
833
    # drop these deprecated fields, but only after we convert
595
854
    'recommends'          => \&_version_map,
596
855
    'requires'            => \&_version_map,
597
856
    # ADDED OPTIONAL
598
 
    'license_url'         => \&_keep,
 
857
    'license_url'         => \&_url_or_drop,
599
858
    'private'             => \&_keep,
600
859
 
601
860
    # other random keys are OK if already valid
607
866
  '1.4-from-2' => {
608
867
    # MANDATORY
609
868
    'abstract'            => \&_keep_or_unknown,
610
 
    'author'              => sub { _listify( _keep_or_unknown( @_ ) ) },
 
869
    'author'              => \&_author_list,
611
870
    'generated_by'        => \&_generated_by,
612
871
    'license'             => \&_downgrade_license,
613
872
    'meta-spec'           => \&_change_meta_spec,
622
881
    'keywords'            => \&_keep,
623
882
    'no_index'            => \&_no_index_directory,
624
883
    'optional_features'   => \&_downgrade_optional_features,
625
 
    'provides'            => \&_keep,
 
884
    'provides'            => \&_provides,
626
885
    'recommends'          => \&_get_recommends,
627
886
    'requires'            => \&_get_requires,
628
887
    'resources'           => \&_downgrade_resources,
640
899
  '1.3-from-1.4' => {
641
900
    # MANDATORY
642
901
    'abstract'            => \&_keep_or_unknown,
643
 
    'author'              => sub { _listify( _keep_or_unknown( @_ ) ) },
 
902
    'author'              => \&_author_list,
644
903
    'generated_by'        => \&_generated_by,
645
904
    'license'             => \&_license_1,
646
905
    'meta-spec'           => \&_change_meta_spec,
653
912
    'dynamic_config'      => \&_keep_or_one,
654
913
    'keywords'            => \&_keep,
655
914
    'no_index'            => \&_no_index_directory,
656
 
    'optional_features'   => \&_keep,
657
 
    'provides'            => \&_keep,
 
915
    'optional_features'   => \&_optional_features_as_map,
 
916
    'provides'            => \&_provides,
658
917
    'recommends'          => \&_version_map,
659
918
    'requires'            => \&_version_map,
660
919
    'resources'           => \&_resources_1_3,
670
929
  '1.2-from-1.3' => {
671
930
    # MANDATORY
672
931
    'abstract'            => \&_keep_or_unknown,
673
 
    'author'              => sub { _listify( _keep_or_unknown( @_ ) ) },
 
932
    'author'              => \&_author_list,
674
933
    'generated_by'        => \&_generated_by,
675
934
    'license'             => \&_license_1,
676
935
    'meta-spec'           => \&_change_meta_spec,
683
942
    'dynamic_config'      => \&_keep_or_one,
684
943
    'keywords'            => \&_keep,
685
944
    'no_index'            => \&_no_index_1_2,
686
 
    'optional_features'   => \&_keep,
687
 
    'provides'            => \&_keep,
 
945
    'optional_features'   => \&_optional_features_as_map,
 
946
    'provides'            => \&_provides,
688
947
    'recommends'          => \&_version_map,
689
948
    'requires'            => \&_version_map,
690
 
    'resources'           => \&_resources_1_2,
 
949
    'resources'           => \&_resources_1_3,
691
950
 
692
951
    # other random keys are OK if already valid
693
952
    ':custom'              => \&_keep,
742
1001
  },
743
1002
);
744
1003
 
 
1004
my %cleanup = (
 
1005
  '2' => {
 
1006
    # PRIOR MANDATORY
 
1007
    'abstract'            => \&_keep_or_unknown,
 
1008
    'author'              => \&_author_list,
 
1009
    'generated_by'        => \&_generated_by,
 
1010
    'license'             => \&_license_2,
 
1011
    'meta-spec'           => \&_change_meta_spec,
 
1012
    'name'                => \&_keep,
 
1013
    'version'             => \&_keep,
 
1014
    # CHANGED TO MANDATORY
 
1015
    'dynamic_config'      => \&_keep_or_one,
 
1016
    # ADDED MANDATORY
 
1017
    'release_status'      => \&_release_status,
 
1018
    # PRIOR OPTIONAL
 
1019
    'keywords'            => \&_keep,
 
1020
    'no_index'            => \&_no_index_directory,
 
1021
    'optional_features'   => \&_cleanup_optional_features_2,
 
1022
    'provides'            => \&_provides,
 
1023
    'resources'           => \&_cleanup_resources_2,
 
1024
    # ADDED OPTIONAL
 
1025
    'description'         => \&_keep,
 
1026
    'prereqs'             => \&_cleanup_prereqs,
 
1027
 
 
1028
    # drop these deprecated fields, but only after we convert
 
1029
    ':drop' => [ qw(
 
1030
        build_requires
 
1031
        configure_requires
 
1032
        conflicts
 
1033
        distribution_type
 
1034
        license_url
 
1035
        private
 
1036
        recommends
 
1037
        requires
 
1038
    ) ],
 
1039
 
 
1040
    # other random keys need x_ prefixing
 
1041
    ':custom'              => \&_prefix_custom,
 
1042
  },
 
1043
  '1.4' => {
 
1044
    # PRIOR MANDATORY
 
1045
    'abstract'            => \&_keep_or_unknown,
 
1046
    'author'              => \&_author_list,
 
1047
    'generated_by'        => \&_generated_by,
 
1048
    'license'             => \&_license_1,
 
1049
    'meta-spec'           => \&_change_meta_spec,
 
1050
    'name'                => \&_keep,
 
1051
    'version'             => \&_keep,
 
1052
    # PRIOR OPTIONAL
 
1053
    'build_requires'      => \&_version_map,
 
1054
    'conflicts'           => \&_version_map,
 
1055
    'distribution_type'   => \&_keep,
 
1056
    'dynamic_config'      => \&_keep_or_one,
 
1057
    'keywords'            => \&_keep,
 
1058
    'no_index'            => \&_no_index_directory,
 
1059
    'optional_features'   => \&_optional_features_1_4,
 
1060
    'provides'            => \&_provides,
 
1061
    'recommends'          => \&_version_map,
 
1062
    'requires'            => \&_version_map,
 
1063
    'resources'           => \&_resources_1_4,
 
1064
    # ADDED OPTIONAL
 
1065
    'configure_requires'  => \&_keep,
 
1066
 
 
1067
    # other random keys are OK if already valid
 
1068
    ':custom'             => \&_keep
 
1069
  },
 
1070
  '1.3' => {
 
1071
    # PRIOR MANDATORY
 
1072
    'abstract'            => \&_keep_or_unknown,
 
1073
    'author'              => \&_author_list,
 
1074
    'generated_by'        => \&_generated_by,
 
1075
    'license'             => \&_license_1,
 
1076
    'meta-spec'           => \&_change_meta_spec,
 
1077
    'name'                => \&_keep,
 
1078
    'version'             => \&_keep,
 
1079
    # PRIOR OPTIONAL
 
1080
    'build_requires'      => \&_version_map,
 
1081
    'conflicts'           => \&_version_map,
 
1082
    'distribution_type'   => \&_keep,
 
1083
    'dynamic_config'      => \&_keep_or_one,
 
1084
    'keywords'            => \&_keep,
 
1085
    'no_index'            => \&_no_index_directory,
 
1086
    'optional_features'   => \&_optional_features_as_map,
 
1087
    'provides'            => \&_provides,
 
1088
    'recommends'          => \&_version_map,
 
1089
    'requires'            => \&_version_map,
 
1090
    'resources'           => \&_resources_1_3,
 
1091
 
 
1092
    # other random keys are OK if already valid
 
1093
    ':custom'             => \&_keep
 
1094
  },
 
1095
  '1.2' => {
 
1096
    # PRIOR MANDATORY
 
1097
    'version'             => \&_keep,
 
1098
    # CHANGED TO MANDATORY
 
1099
    'license'             => \&_license_1,
 
1100
    'name'                => \&_keep,
 
1101
    'generated_by'        => \&_generated_by,
 
1102
    # ADDED MANDATORY
 
1103
    'abstract'            => \&_keep_or_unknown,
 
1104
    'author'              => \&_author_list,
 
1105
    'meta-spec'           => \&_change_meta_spec,
 
1106
    # PRIOR OPTIONAL
 
1107
    'build_requires'      => \&_version_map,
 
1108
    'conflicts'           => \&_version_map,
 
1109
    'distribution_type'   => \&_keep,
 
1110
    'dynamic_config'      => \&_keep_or_one,
 
1111
    'recommends'          => \&_version_map,
 
1112
    'requires'            => \&_version_map,
 
1113
    # ADDED OPTIONAL
 
1114
    'keywords'            => \&_keep,
 
1115
    'no_index'            => \&_no_index_1_2,
 
1116
    'optional_features'   => \&_optional_features_as_map,
 
1117
    'provides'            => \&_provides,
 
1118
    'resources'           => \&_resources_1_2,
 
1119
 
 
1120
    # other random keys are OK if already valid
 
1121
    ':custom'             => \&_keep
 
1122
  },
 
1123
  '1.1' => {
 
1124
    # CHANGED TO MANDATORY
 
1125
    'version'             => \&_keep,
 
1126
    # IMPLIED MANDATORY
 
1127
    'name'                => \&_keep,
 
1128
    'meta-spec'           => \&_change_meta_spec,
 
1129
    # PRIOR OPTIONAL
 
1130
    'build_requires'      => \&_version_map,
 
1131
    'conflicts'           => \&_version_map,
 
1132
    'distribution_type'   => \&_keep,
 
1133
    'dynamic_config'      => \&_keep_or_one,
 
1134
    'generated_by'        => \&_generated_by,
 
1135
    'license'             => \&_license_1,
 
1136
    'recommends'          => \&_version_map,
 
1137
    'requires'            => \&_version_map,
 
1138
    # ADDED OPTIONAL
 
1139
    'license_url'         => \&_url_or_drop,
 
1140
    'private'             => \&_keep,
 
1141
 
 
1142
    # other random keys are OK if already valid
 
1143
    ':custom'             => \&_keep
 
1144
  },
 
1145
  '1.0' => {
 
1146
    # IMPLIED MANDATORY
 
1147
    'name'                => \&_keep,
 
1148
    'meta-spec'           => \&_change_meta_spec,
 
1149
    'version'             => \&_keep,
 
1150
    # IMPLIED OPTIONAL
 
1151
    'build_requires'      => \&_version_map,
 
1152
    'conflicts'           => \&_version_map,
 
1153
    'distribution_type'   => \&_keep,
 
1154
    'dynamic_config'      => \&_keep_or_one,
 
1155
    'generated_by'        => \&_generated_by,
 
1156
    'license'             => \&_license_1,
 
1157
    'recommends'          => \&_version_map,
 
1158
    'requires'            => \&_version_map,
 
1159
 
 
1160
    # other random keys are OK if already valid
 
1161
    ':custom'             => \&_keep,
 
1162
  },
 
1163
);
 
1164
 
745
1165
#--------------------------------------------------------------------------#
746
1166
# Code
747
1167
#--------------------------------------------------------------------------#
771
1191
  my $converted = dclone $self->{data};
772
1192
 
773
1193
  if ( $old_version == $new_version ) {
 
1194
    $converted = _convert( $converted, $cleanup{$old_version}, $old_version );
 
1195
    my $cmv = CPAN::Meta::Validator->new( $converted );
 
1196
    unless ( $cmv->is_valid ) {
 
1197
      my $errs = join("\n", $cmv->errors);
 
1198
      die "Failed to clean-up $old_version metadata. Errors:\n$errs\n";
 
1199
    }
774
1200
    return $converted;
775
1201
  }
776
1202
  elsif ( $old_version > $new_version )  {
783
1209
      my $cmv = CPAN::Meta::Validator->new( $converted );
784
1210
      unless ( $cmv->is_valid ) {
785
1211
        my $errs = join("\n", $cmv->errors);
786
 
        confess "Failed to downconvert metadata to $vers[$i+1]. Errors:\n$errs\n";
 
1212
        die "Failed to downconvert metadata to $vers[$i+1]. Errors:\n$errs\n";
787
1213
      }
788
1214
    }
789
1215
    return $converted;
798
1224
      my $cmv = CPAN::Meta::Validator->new( $converted );
799
1225
      unless ( $cmv->is_valid ) {
800
1226
        my $errs = join("\n", $cmv->errors);
801
 
        confess "Failed to upconvert metadata to $vers[$i+1]. Errors:\n$errs\n";
 
1227
        die "Failed to upconvert metadata to $vers[$i+1]. Errors:\n$errs\n";
802
1228
      }
803
1229
    }
804
1230
    return $converted;
817
1243
 
818
1244
=head1 VERSION
819
1245
 
820
 
version 2.101461
 
1246
version 2.101591
821
1247
 
822
1248
=head1 SYNOPSIS
823
1249
 
849
1275
 
850
1276
  my $new_struct = $cmc->convert( version => "2" );
851
1277
 
852
 
Returns a new hash reference with the metadata converted to a
853
 
different form.
 
1278
Returns a new hash reference with the metadata converted to a different form.
 
1279
C<convert> will die if any conversion/standardization still results in an
 
1280
invalid structure.
854
1281
 
855
1282
Valid parameters include:
856
1283
 
 
1284
=over
 
1285
 
 
1286
=item *
 
1287
 
 
1288
C<version> -- Indicates the desired specification version (e.g. "1.0", "1.1" ... "1.4", "2").
 
1289
Defaults to the latest version of the CPAN Meta Spec.
 
1290
 
 
1291
=back
 
1292
 
 
1293
Conversion proceeds through each version in turn.  For example, a version 1.2
 
1294
structure might be converted to 1.3 then 1.4 then finally to version 2. The
 
1295
conversion process attempts to clean-up simple errors and standardize data.
 
1296
For example, if C<author> is given as a scalar, it will converted to an array
 
1297
reference containing the item. (Converting a structure to its own version will
 
1298
also clean-up and standardize.)
 
1299
 
 
1300
When data are cleaned and standardized, missing or invalid fields will be
 
1301
replaced with sensible defaults when possible.  This may be lossy or imprecise.
 
1302
For example, some badly structured META.yml files on CPAN have prerequisite
 
1303
modules listed as both keys and values:
 
1304
 
 
1305
  requires => { 'Foo::Bar' => 'Bam::Baz' }
 
1306
 
 
1307
These would be split and each converted to a prerequisite with a minimum
 
1308
version of zero.
 
1309
 
 
1310
When some mandatory fields are missing or invalid, the conversion will attempt
 
1311
to provide a sensible default or will fill them with a value of 'unknown'.  For
 
1312
example a missing or unrecognized C<license> field will result in a C<license>
 
1313
field of 'unknown'.  Fields that may get an 'unknown' include:
 
1314
 
857
1315
=over 4
858
1316
 
859
1317
=item *
860
1318
 
861
 
version
862
 
 
863
 
Indicates the desired specification version (e.g. "1.0", "1.1" ... "1.4", "2").
864
 
Converting a structure to its own version will just return a copy of the
865
 
structure. Defaults to the latest version of the CPAN Meta Spec.
 
1319
abstract
 
1320
 
 
1321
=item *
 
1322
 
 
1323
author
 
1324
 
 
1325
=item *
 
1326
 
 
1327
license
866
1328
 
867
1329
=back
868
1330
 
869
 
The conversion process attempts to clean-up and standardize data during
870
 
converstion.  For example, if C<author> is given as a scalar, it will converted
871
 
to an array reference containing the item.
872
 
 
873
 
Conversion proceeds through each version in turn.  For example, a version 1.2
874
 
structure is converted to 1.3 then 1.4 then finally version 2.  C<convert> will
875
 
die if any conversion results in an invalid structure.
876
 
 
877
1331
=head1 BUGS
878
1332
 
879
1333
Please report any bugs or feature using the CPAN Request Tracker.