@@ -1,5 +1,28 @@
Revision history for Module::Install::CPANfile
+1.1000 2014-08-29 13:48:13 JST
+ - Make it non-development release
+
+1.0905 2013-12-09 16:26:08 PST
+ - Support mirror syntax (masaki) #22
+
+1.0904 2013-09-21 07:56:31 JST
+ - Removed git/ref accessor from Requirement
+ - Added $requirement->has_options
+
+1.0903 2013-09-20 15:36:30 JST
+ - Added $cpanfile->merged_requirements to get the CPAN::Meta::Requirements for all prereqs
+
+1.0902 2013-09-20 13:45:15 JST
+ - s/rev/ref/ for git options
+
+1.0901 2013-09-19 18:59:55 JST
+ - Remove unused code
+
+1.0900 2013-09-19 18:45:59 JST
+ - Experimental support for git URL specification
+ - Complete rewrite of internal to preserve original prereq statement as much as possible
+
1.0002 2013-09-06 12:26:11 PDT
- Add cpanfile-dump utility (xdg)
@@ -1,4 +1,4 @@
-This software is copyright (c) 2013 by Tatsuhiko Miyagawa.
+This software is copyright (c) 2014 by Tatsuhiko Miyagawa.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
@@ -12,7 +12,7 @@ b) the "Artistic License"
--- The GNU General Public License, Version 1, February 1989 ---
-This software is Copyright (c) 2013 by Tatsuhiko Miyagawa.
+This software is Copyright (c) 2014 by Tatsuhiko Miyagawa.
This is free software, licensed under:
@@ -22,7 +22,7 @@ This is free software, licensed under:
Version 1, February 1989
Copyright (C) 1989 Free Software Foundation, Inc.
- 51 Franklin St, Suite 500, Boston, MA 02110-1335 USA
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -272,7 +272,7 @@ That's all there is to it!
--- The Artistic License 1.0 ---
-This software is Copyright (c) 2013 by Tatsuhiko Miyagawa.
+This software is Copyright (c) 2014 by Tatsuhiko Miyagawa.
This is free software, licensed under:
@@ -1,3 +1,4 @@
+# This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.020.
Changes
LICENSE
MANIFEST
@@ -9,7 +10,9 @@ cpanfile
dist.ini
lib/Module/CPANfile.pm
lib/Module/CPANfile/Environment.pm
-lib/Module/CPANfile/Result.pm
+lib/Module/CPANfile/Prereq.pm
+lib/Module/CPANfile/Prereqs.pm
+lib/Module/CPANfile/Requirement.pm
lib/cpanfile-faq.pod
lib/cpanfile.pod
script/cpanfile-dump
@@ -18,5 +21,7 @@ t/Utils.pm
t/feature.t
t/from_prereqs.t
t/merge.t
+t/mirror.t
t/parse.t
t/release-pod-syntax.t
+t/requirement.t
@@ -4,7 +4,7 @@
"Tatsuhiko Miyagawa"
],
"dynamic_config" : 0,
- "generated_by" : "Dist::Milla version v1.0.4, Dist::Zilla version 4.300037, CPAN::Meta::Converter version 2.132140",
+ "generated_by" : "Dist::Milla version v1.0.5, Dist::Zilla version 5.020, CPAN::Meta::Converter version 2.142060",
"license" : [
"perl_5"
],
@@ -26,7 +26,7 @@
"prereqs" : {
"configure" : {
"requires" : {
- "ExtUtils::MakeMaker" : "6.30"
+ "ExtUtils::MakeMaker" : "0"
}
},
"develop" : {
@@ -40,7 +40,8 @@
},
"requires" : {
"CPAN::Meta" : "2.12091",
- "CPAN::Meta::Prereqs" : "2.12091"
+ "CPAN::Meta::Prereqs" : "2.12091",
+ "parent" : "0"
}
},
"test" : {
@@ -61,11 +62,13 @@
"web" : "https://github.com/miyagawa/cpanfile"
}
},
- "version" : "1.0002",
+ "version" : "1.1000",
"x_contributors" : [
"Atsushi Kato <ktat@cpan.org>",
"David Golden <dagolden@cpan.org>",
"David Steinbrunner <dsteinbrunner@pobox.com>",
+ "Gregory Oschwald <oschwald@gmail.com>",
+ "Kenichi Ishigaki <ishigaki@cpan.org>",
"Masahiro Honma <hiratara@cpan.org>",
"Michiel Beijen <michiel.beijen@gmail.com>",
"grtodd <gtodd@iciti.ca>",
@@ -3,15 +3,15 @@ abstract: 'Parse cpanfile'
author:
- 'Tatsuhiko Miyagawa'
build_requires:
- Test::More: 0.88
+ Test::More: '0.88'
configure_requires:
- ExtUtils::MakeMaker: 6.30
+ ExtUtils::MakeMaker: '0'
dynamic_config: 0
-generated_by: 'Dist::Milla version v1.0.4, Dist::Zilla version 4.300037, CPAN::Meta::Converter version 2.132140'
+generated_by: 'Dist::Milla version v1.0.5, Dist::Zilla version 5.020, CPAN::Meta::Converter version 2.142060'
license: perl
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
- version: 1.4
+ version: '1.4'
name: Module-CPANfile
no_index:
directory:
@@ -22,19 +22,22 @@ no_index:
- eg
- examples
recommends:
- Pod::Usage: 0
+ Pod::Usage: '0'
requires:
- CPAN::Meta: 2.12091
- CPAN::Meta::Prereqs: 2.12091
+ CPAN::Meta: '2.12091'
+ CPAN::Meta::Prereqs: '2.12091'
+ parent: '0'
resources:
bugtracker: https://github.com/miyagawa/cpanfile/issues
homepage: https://github.com/miyagawa/cpanfile
repository: https://github.com/miyagawa/cpanfile.git
-version: 1.0002
+version: '1.1000'
x_contributors:
- 'Atsushi Kato <ktat@cpan.org>'
- 'David Golden <dagolden@cpan.org>'
- 'David Steinbrunner <dsteinbrunner@pobox.com>'
+ - 'Gregory Oschwald <oschwald@gmail.com>'
+ - 'Kenichi Ishigaki <ishigaki@cpan.org>'
- 'Masahiro Honma <hiratara@cpan.org>'
- 'Michiel Beijen <michiel.beijen@gmail.com>'
- 'grtodd <gtodd@iciti.ca>'
@@ -1,19 +1,19 @@
+# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v5.020.
use strict;
use warnings;
-use ExtUtils::MakeMaker 6.30;
+use ExtUtils::MakeMaker ;
my %WriteMakefileArgs = (
"ABSTRACT" => "Parse cpanfile",
"AUTHOR" => "Tatsuhiko Miyagawa",
- "BUILD_REQUIRES" => {},
"CONFIGURE_REQUIRES" => {
- "ExtUtils::MakeMaker" => "6.30"
+ "ExtUtils::MakeMaker" => 0
},
"DISTNAME" => "Module-CPANfile",
"EXE_FILES" => [
@@ -24,42 +24,31 @@ my %WriteMakefileArgs = (
"NAME" => "Module::CPANfile",
"PREREQ_PM" => {
"CPAN::Meta" => "2.12091",
- "CPAN::Meta::Prereqs" => "2.12091"
+ "CPAN::Meta::Prereqs" => "2.12091",
+ "parent" => 0
},
"TEST_REQUIRES" => {
"Test::More" => "0.88"
},
- "VERSION" => "1.0002",
+ "VERSION" => "1.1000",
"test" => {
"TESTS" => "t/*.t"
}
);
-unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
- my $tr = delete $WriteMakefileArgs{TEST_REQUIRES};
- my $br = $WriteMakefileArgs{BUILD_REQUIRES};
- for my $mod ( keys %$tr ) {
- if ( exists $br->{$mod} ) {
- $br->{$mod} = $tr->{$mod} if $tr->{$mod} > $br->{$mod};
- }
- else {
- $br->{$mod} = $tr->{$mod};
- }
- }
-}
+my %FallbackPrereqs = (
+ "CPAN::Meta" => "2.12091",
+ "CPAN::Meta::Prereqs" => "2.12091",
+ "Test::More" => "0.88",
+ "parent" => 0
+);
-unless ( eval { ExtUtils::MakeMaker->VERSION(6.56) } ) {
- my $br = delete $WriteMakefileArgs{BUILD_REQUIRES};
- my $pp = $WriteMakefileArgs{PREREQ_PM};
- for my $mod ( keys %$br ) {
- if ( exists $pp->{$mod} ) {
- $pp->{$mod} = $br->{$mod} if $br->{$mod} > $pp->{$mod};
- }
- else {
- $pp->{$mod} = $br->{$mod};
- }
- }
+
+unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
+ delete $WriteMakefileArgs{TEST_REQUIRES};
+ delete $WriteMakefileArgs{BUILD_REQUIRES};
+ $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs;
}
delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
@@ -67,7 +67,7 @@ METHODS
# read MYMETA's prereqs and print cpanfile representation of it
my $meta = CPAN::Meta->load_file('MYMETA.json');
my $file = Module::CPANfile->from_prereqs($meta->prereqs);
- print $file->to_sring;
+ print $file->to_string;
By default, it omits the phase where there're no modules registered.
If you pass the argument of a true value, it will print them as
@@ -1,5 +1,6 @@
requires 'CPAN::Meta', 2.12091;
requires 'CPAN::Meta::Prereqs', 2.12091;
+requires 'parent';
recommends 'Pod::Usage';
@@ -1,13 +1,14 @@
package Module::CPANfile::Environment;
use strict;
use warnings;
-use Module::CPANfile::Result;
+use Module::CPANfile::Prereqs;
use Carp ();
my @bindings = qw(
on requires recommends suggests conflicts
feature
osname
+ mirror
configure_requires build_requires test_requires author_requires
);
@@ -16,48 +17,156 @@ my $file_id = 1;
sub new {
my($class, $file) = @_;
bless {
- file => $file,
+ file => $file,
+ phase => 'runtime', # default phase
+ feature => undef,
+ features => {},
+ prereqs => Module::CPANfile::Prereqs->new,
+ mirrors => [],
}, $class;
}
sub bind {
- my $class = shift;
+ my $self = shift;
my $pkg = caller;
- my $result = Module::CPANfile::Result->new;
for my $binding (@bindings) {
no strict 'refs';
- *{"$pkg\::$binding"} = sub { $result->$binding(@_) };
+ *{"$pkg\::$binding"} = sub { $self->$binding(@_) };
}
-
- return $result;
}
sub parse {
my($self, $code) = @_;
- my($res, $err);
-
+ my $err;
{
local $@;
$file_id++;
- $res = eval <<EVAL;
+ $self->_evaluate(<<EVAL);
package Module::CPANfile::Sandbox$file_id;
no warnings;
-my \$_result;
-BEGIN { \$_result = Module::CPANfile::Environment->bind }
+BEGIN { \$_environment->bind }
# line 1 "$self->{file}"
$code;
-
-\$_result;
EVAL
$err = $@;
}
if ($err) { die "Parsing $self->{file} failed: $err" };
- return $res;
+ return 1;
+}
+
+sub _evaluate {
+ my $_environment = $_[0];
+ eval $_[1];
+}
+
+sub prereqs { $_[0]->{prereqs} }
+
+sub mirrors { $_[0]->{mirrors} }
+
+# DSL goes from here
+
+sub on {
+ my($self, $phase, $code) = @_;
+ local $self->{phase} = $phase;
+ $code->();
+}
+
+sub feature {
+ my($self, $identifier, $description, $code) = @_;
+
+ # shortcut: feature identifier => sub { ... }
+ if (@_ == 3 && ref($description) eq 'CODE') {
+ $code = $description;
+ $description = $identifier;
+ }
+
+ unless (ref $description eq '' && ref $code eq 'CODE') {
+ Carp::croak("Usage: feature 'identifier', 'Description' => sub { ... }");
+ }
+
+ local $self->{feature} = $identifier;
+ $self->prereqs->add_feature($identifier, $description);
+
+ $code->();
+}
+
+sub osname { die "TODO" }
+
+sub mirror {
+ my($self, $url) = @_;
+ push @{$self->{mirrors}}, $url;
+}
+
+sub requirement_for {
+ my($self, $module, @args) = @_;
+
+ my $requirement = 0;
+ $requirement = shift @args if @args % 2;
+
+ return Module::CPANfile::Requirement->new(
+ name => $module,
+ version => $requirement,
+ @args,
+ );
+}
+
+sub requires {
+ my $self = shift;
+ $self->add_prereq(requires => @_);
+}
+
+sub recommends {
+ my $self = shift;
+ $self->add_prereq(recommends => @_);
+}
+
+sub suggests {
+ my $self = shift;
+ $self->add_prereq(suggests => @_);
+}
+
+sub conflicts {
+ my $self = shift;
+ $self->add_prereq(conflicts => @_);
+}
+
+sub add_prereq {
+ my($self, $type, $module, @args) = @_;
+
+ $self->prereqs->add_prereq(
+ feature => $self->{feature},
+ phase => $self->{phase},
+ type => $type,
+ module => $module,
+ requirement => $self->requirement_for($module, @args),
+ );
+}
+
+# Module::Install compatible shortcuts
+
+sub configure_requires {
+ my($self, @args) = @_;
+ $self->on(configure => sub { $self->requires(@args) });
+}
+
+sub build_requires {
+ my($self, @args) = @_;
+ $self->on(build => sub { $self->requires(@args) });
+}
+
+sub test_requires {
+ my($self, @args) = @_;
+ $self->on(test => sub { $self->requires(@args) });
+}
+
+sub author_requires {
+ my($self, @args) = @_;
+ $self->on(develop => sub { $self->requires(@args) });
}
1;
@@ -0,0 +1,21 @@
+package Module::CPANfile::Prereq;
+use strict;
+
+sub new {
+ my($class, %options) = @_;
+ bless \%options, $class;
+}
+
+sub feature { $_[0]->{feature} }
+sub phase { $_[0]->{phase} }
+sub type { $_[0]->{type} }
+sub module { $_[0]->{module} }
+sub requirement { $_[0]->{requirement} }
+
+sub match_feature {
+ my($self, $identifier) = @_;
+ no warnings 'uninitialized';
+ $self->feature eq $identifier;
+}
+
+1;
@@ -0,0 +1,117 @@
+package Module::CPANfile::Prereqs;
+use strict;
+use Carp ();
+use CPAN::Meta::Feature;
+use Module::CPANfile::Prereq;
+
+sub from_cpan_meta {
+ my($class, $prereqs) = @_;
+
+ my $self = $class->new;
+
+ for my $phase (keys %$prereqs) {
+ for my $type (keys %{ $prereqs->{$phase} }) {
+ while (my($module, $requirement) = each %{ $prereqs->{$phase}{$type} }) {
+ $self->add_prereq(
+ phase => $phase,
+ type => $type,
+ module => $module,
+ requirement => Module::CPANfile::Requirement->new(name => $module, version => $requirement),
+ );
+ }
+ }
+ }
+
+ $self;
+}
+
+sub new {
+ my $class = shift;
+ bless {
+ prereqs => [],
+ features => {},
+ }, $class;
+}
+
+sub add_feature {
+ my($self, $identifier, $description) = @_;
+ $self->{features}{$identifier} = { description => $description };
+}
+
+sub add_prereq {
+ my($self, %args) = @_;
+ $self->add( Module::CPANfile::Prereq->new(%args) );
+}
+
+sub add {
+ my($self, $prereq) = @_;
+ push @{$self->{prereqs}}, $prereq;
+}
+
+sub as_cpan_meta {
+ my $self = shift;
+ $self->{cpanmeta} ||= $self->build_cpan_meta;
+}
+
+sub build_cpan_meta {
+ my($self, $identifier) = @_;
+
+ my $prereq_spec = {};
+ $self->prereq_each($identifier, sub {
+ my $prereq = shift;
+ $prereq_spec->{$prereq->phase}{$prereq->type}{$prereq->module} = $prereq->requirement->version;
+ });
+
+ CPAN::Meta::Prereqs->new($prereq_spec);
+}
+
+sub prereq_each {
+ my($self, $identifier, $code) = @_;
+
+ for my $prereq (@{$self->{prereqs}}) {
+ next unless $prereq->match_feature($identifier);
+ $code->($prereq);
+ }
+}
+
+sub merged_requirements {
+ my $self = shift;
+
+ my $reqs = CPAN::Meta::Requirements->new;
+ for my $prereq (@{$self->{prereqs}}) {
+ $reqs->add_string_requirement($prereq->module, $prereq->requirement->version);
+ }
+
+ $reqs;
+}
+
+sub find {
+ my($self, $module) = @_;
+
+ for my $prereq (@{$self->{prereqs}}) {
+ return $prereq if $prereq->module eq $module;
+ }
+
+ return;
+}
+
+sub identifiers {
+ my $self = shift;
+ keys %{$self->{features}};
+}
+
+sub feature {
+ my($self, $identifier) = @_;
+
+ my $data = $self->{features}{$identifier}
+ or Carp::croak("Unknown feature '$identifier'");
+
+ my $prereqs = $self->build_cpan_meta($identifier);
+
+ CPAN::Meta::Feature->new($identifier, {
+ description => $data->{description},
+ prereqs => $prereqs->as_string_hash,
+ });
+}
+
+1;
@@ -0,0 +1,25 @@
+package Module::CPANfile::Requirement;
+use strict;
+
+sub new {
+ my ($class, %args) = @_;
+
+ $args{version} ||= 0;
+
+ bless +{
+ name => delete $args{name},
+ version => delete $args{version},
+ options => \%args,
+ }, $class;
+}
+
+sub name { $_[0]->{name} }
+sub version { $_[0]->{version} }
+
+sub options { $_[0]->{options} }
+
+sub has_options {
+ keys %{$_[0]->{options}} > 0;
+}
+
+1;
@@ -1,93 +0,0 @@
-package Module::CPANfile::Result;
-use strict;
-
-sub from_prereqs {
- my($class, $spec) = @_;
- bless {
- phase => 'runtime',
- spec => $spec,
- }, $class;
-}
-
-sub new {
- bless {
- phase => 'runtime', # default phase
- features => {},
- feature => undef,
- spec => {},
- }, shift;
-}
-
-sub on {
- my($self, $phase, $code) = @_;
- local $self->{phase} = $phase;
- $code->()
-}
-
-sub feature {
- my($self, $identifier, $description, $code) = @_;
-
- # shortcut: feature identifier => sub { ... }
- if (@_ == 3 && ref($description) eq 'CODE') {
- $code = $description;
- $description = $identifier;
- }
-
- unless (ref $description eq '' && ref $code eq 'CODE') {
- Carp::croak("Usage: feature 'identifier', 'Description' => sub { ... }");
- }
-
- local $self->{feature} = $self->{features}{$identifier}
- = { identifier => $identifier, description => $description, spec => {} };
- $code->();
-}
-
-sub osname { die "TODO" }
-
-sub requires {
- my($self, $module, $requirement) = @_;
- ($self->{feature} ? $self->{feature}{spec} : $self->{spec})
- ->{$self->{phase}}{requires}{$module} = $requirement || 0;
-}
-
-sub recommends {
- my($self, $module, $requirement) = @_;
- ($self->{feature} ? $self->{feature}{spec} : $self->{spec})
- ->{$self->{phase}}{recommends}{$module} = $requirement || 0;
-}
-
-sub suggests {
- my($self, $module, $requirement) = @_;
- ($self->{feature} ? $self->{feature}{spec} : $self->{spec})
- ->{$self->{phase}}{suggests}{$module} = $requirement || 0;
-}
-
-sub conflicts {
- my($self, $module, $requirement) = @_;
- ($self->{feature} ? $self->{feature}{spec} : $self->{spec})
- ->{$self->{phase}}{conflicts}{$module} = $requirement || 0;
-}
-
-# Module::Install compatible shortcuts
-
-sub configure_requires {
- my($self, @args) = @_;
- $self->on(configure => sub { $self->requires(@args) });
-}
-
-sub build_requires {
- my($self, @args) = @_;
- $self->on(build => sub { $self->requires(@args) });
-}
-
-sub test_requires {
- my($self, @args) = @_;
- $self->on(test => sub { $self->requires(@args) });
-}
-
-sub author_requires {
- my($self, @args) = @_;
- $self->on(develop => sub { $self->requires(@args) });
-}
-
-1;
@@ -4,9 +4,9 @@ use warnings;
use Cwd;
use Carp ();
use Module::CPANfile::Environment;
-use Module::CPANfile::Result;
+use Module::CPANfile::Requirement;
-our $VERSION = '1.0002';
+our $VERSION = '1.1000';
sub new {
my($class, $file) = @_;
@@ -37,42 +37,46 @@ sub parse {
};
my $env = Module::CPANfile::Environment->new($file);
- $self->{result} = $env->parse($code) or die $@;
+ $env->parse($code) or die $@;
+
+ $self->{_mirrors} = $env->mirrors;
+ $self->{_prereqs} = $env->prereqs;
}
sub from_prereqs {
my($proto, $prereqs) = @_;
my $self = $proto->new;
- $self->{result} = Module::CPANfile::Result->from_prereqs($prereqs);
+ $self->{_prereqs} = Module::CPANfile::Prereqs->from_cpan_meta($prereqs);
$self;
}
+sub mirrors {
+ my $self = shift;
+ $self->{_mirrors} || [];
+}
+
sub features {
my $self = shift;
- map $self->feature($_), keys %{$self->{result}{features}};
+ map $self->feature($_), $self->{_prereqs}->identifiers;
}
sub feature {
my($self, $identifier) = @_;
-
- my $data = $self->{result}{features}{$identifier}
- or Carp::croak("Unknown feature '$identifier'");
-
- require CPAN::Meta::Feature;
- CPAN::Meta::Feature->new($data->{identifier}, {
- description => $data->{description},
- prereqs => $data->{spec},
- });
+ $self->{_prereqs}->feature($identifier);
}
sub prereq { shift->prereqs }
sub prereqs {
my $self = shift;
- require CPAN::Meta::Prereqs;
- CPAN::Meta::Prereqs->new($self->prereq_specs);
+ $self->{_prereqs}->as_cpan_meta;
+}
+
+sub merged_requirements {
+ my $self = shift;
+ $self->{_prereqs}->merged_requirements;
}
sub effective_prereqs {
@@ -91,7 +95,18 @@ sub prereqs_with {
sub prereq_specs {
my $self = shift;
- $self->{result}{spec};
+ $self->prereqs->as_string_hash;
+}
+
+sub prereq_for_module {
+ my($self, $module) = @_;
+ $self->{_prereqs}->find($module);
+}
+
+sub options_for_module {
+ my($self, $module) = @_;
+ my $prereq = $self->prereq_for_module($module) or return;
+ $prereq->requirement->options;
}
sub merge_meta {
@@ -120,12 +135,14 @@ sub _dump {
sub to_string {
my($self, $include_empty) = @_;
- my $prereqs = $self->{result}{spec};
+ my $mirrors = $self->mirrors;
+ my $prereqs = $self->prereq_specs;
my $code = '';
- $code .= $self->_dump_prereqs($self->{result}{spec}, $include_empty);
+ $code .= $self->_dump_mirrors($mirrors);
+ $code .= $self->_dump_prereqs($prereqs, $include_empty);
- for my $feature (values %{$self->{result}{features}}) {
+ for my $feature ($self->features) {
$code .= sprintf "feature %s, %s => sub {\n", _dump($feature->{identifier}), _dump($feature->{description});
$code .= $self->_dump_prereqs($feature->{spec}, $include_empty, 4);
$code .= "}\n\n";
@@ -135,6 +152,19 @@ sub to_string {
$code;
}
+sub _dump_mirrors {
+ my($self, $mirrors) = @_;
+
+ my $code = "";
+
+ for my $url (@$mirrors) {
+ $code .= "mirror '$url';\n";
+ }
+
+ $code =~ s/\n+$/\n/s;
+ $code;
+}
+
sub _dump_prereqs {
my($self, $prereqs, $include_empty, $base_indent) = @_;
@@ -250,7 +280,7 @@ if you want to convert L<CPAN::Meta::Prereqs> to a new cpanfile.
# read MYMETA's prereqs and print cpanfile representation of it
my $meta = CPAN::Meta->load_file('MYMETA.json');
my $file = Module::CPANfile->from_prereqs($meta->prereqs);
- print $file->to_sring;
+ print $file->to_string;
By default, it omits the phase where there're no modules
registered. If you pass the argument of a true value, it will print
@@ -112,12 +112,17 @@ installation.
L<Module::Build::Pluggable::CPANfile> merges C<cpanfile> dependencies
from C<Build.PL> when dumping out MYMETA information.
+However you're recommended to switch to an authoring system that emits
+C<Build.PL> with parsed CPANfile information, like L<Dist::Zilla>
+mentioned above.
+
=item ExtUtils::MakeMaker
-L<ExtUtils::MakeMaker> has no direct support for cpanfile yet, but you
-could use L<Module::CPANfile>'s C<merge_meta> method to update
-C<MYMETA.json> files with the contents in C<cpanfile>, or convert the
-structure to appropriate options with L<PREREQ_PM> and C<META_MERGE>
-for C<WriteMakefile>.
+L<ExtUtils::MakeMaker::CPANfile> merges C<cpanfile> prerequisites
+when dumping C<MYMETA> files upon installation.
+
+However you're recommended to switch to an authoring system that emits
+C<Makefile.PL> with parsed CPANfile information, like L<Dist::Zilla>
+mentioned above.
=back
@@ -4,8 +4,8 @@ cpanfile - A format for describing CPAN dependencies for Perl applications
=head1 SYNOPSIS
- requires 'Catalyst', '5.8000'; # 5.8000 or newer
- requires 'Catalyst::View::JSON', '>= 0.30, < 0.40';
+ requires 'Plack', '1.0'; # 1.0 or newer
+ requires 'JSON', '>= 2.00, < 2.80';
recommends 'JSON::XS', '2.0';
conflicts 'JSON', '< 1.0';
@@ -25,7 +25,7 @@ cpanfile - A format for describing CPAN dependencies for Perl applications
=head1 VERSION
-This doucment describes cpanfile format version 1.0.
+This document describes cpanfile format version 1.0.
=head1 DESCRIPTION
@@ -76,7 +76,8 @@ cpanfile-dump - Dump prerequisites from a cpanfile
This script reads prereqs from a F<cpanfile> and dumps a raw list of
them to standard output. This is useful for piping these as input to
-another program such as C<cpan>, C<cpanm> or C<cpanp>.
+another program that doesn't support reading cpanfile directly,
+i.e. C<cpan> or C<cpanp>.
By default, it prints configure, build, test and runtime requirements and
recommendations. Command line options can be used to modify the default
@@ -0,0 +1,38 @@
+use strict;
+use Module::CPANfile;
+use Test::More;
+use t::Utils;
+
+{
+ my $r = write_cpanfile(<<FILE);
+mirror 'http://www.cpan.org';
+mirror 'http://backpan.cpan.org';
+
+requires 'DBI';
+requires 'Plack', '0.9970';
+
+on 'test' => sub {
+ requires 'Test::More';
+};
+FILE
+
+ my $file = Module::CPANfile->load;
+
+ my $prereq = $file->prereq;
+ is_deeply $prereq->as_string_hash, {
+ test => {
+ requires => { 'Test::More' => 0 },
+ },
+ runtime => {
+ requires => { 'Plack' => '0.9970', 'DBI' => 0 },
+ },
+ };
+
+ my $mirrors = $file->mirrors;
+ is_deeply $mirrors, [ 'http://www.cpan.org', 'http://backpan.cpan.org' ];
+
+ like $file->to_string, qr{mirror 'http://www.cpan.org';};
+ like $file->to_string, qr{mirror 'http://backpan.cpan.org';};
+}
+
+done_testing;
@@ -7,9 +7,8 @@ BEGIN {
}
}
+# This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests.
use Test::More;
-
-eval "use Test::Pod 1.41";
-plan skip_all => "Test::Pod 1.41 required for testing POD" if $@;
+use Test::Pod 1.41;
all_pod_files_ok();
@@ -0,0 +1,81 @@
+use strict;
+use Module::CPANfile;
+use Test::More;
+use t::Utils;
+
+subtest 'full set' => sub {
+ my $r = write_cpanfile(<<FILE);
+requires 'Plack', '0.9970',
+ git => 'git://github.com/plack/Plack.git', ref => '0.9970';
+FILE
+
+ my $file = Module::CPANfile->load;
+ is_deeply $file->prereq_specs, {
+ runtime => {
+ requires => { 'Plack' => '0.9970' },
+ },
+ };
+
+ my $req = $file->prereqs->requirements_for(runtime => 'requires');
+ is $req->requirements_for_module('Plack'), '0.9970';
+
+ is_deeply $file->options_for_module('Plack'), {
+ git => 'git://github.com/plack/Plack.git',
+ ref => '0.9970',
+ };
+};
+
+subtest 'drop version' => sub {
+ my $r = write_cpanfile(<<FILE);
+requires 'Plack', # drop version
+ git => 'git://github.com/plack/Plack.git', ref => '0.9970';
+FILE
+
+ my $file = Module::CPANfile->load;
+ is_deeply $file->prereq_specs, {
+ runtime => {
+ requires => { 'Plack' => 0 },
+ },
+ };
+
+ is_deeply $file->options_for_module('Plack'), {
+ git => 'git://github.com/plack/Plack.git',
+ ref => '0.9970',
+ };
+};
+
+subtest 'no ref' => sub {
+ my $r = write_cpanfile(<<FILE);
+requires 'Plack', '0.9970', git => 'git://github.com/plack/Plack.git';
+FILE
+
+ my $file = Module::CPANfile->load;
+ is_deeply $file->prereq_specs, {
+ runtime => {
+ requires => { 'Plack' => '0.9970' },
+ },
+ };
+
+ is_deeply $file->options_for_module('Plack'), {
+ git => 'git://github.com/plack/Plack.git',
+ };
+};
+
+subtest 'name and git' => sub {
+ my $r = write_cpanfile(<<FILE);
+requires 'Plack', git => 'git://github.com/plack/Plack.git';
+FILE
+
+ my $file = Module::CPANfile->load;
+ is_deeply $file->prereq_specs, {
+ runtime => {
+ requires => { 'Plack' => 0 },
+ },
+ };
+
+ is_deeply $file->options_for_module('Plack'), {
+ git => 'git://github.com/plack/Plack.git',
+ };
+};
+
+done_testing;