File Coverage

blib/lib/Module/Build/PPMMaker.pm
Criterion Covered Total %
statement 55 65 84.6
branch 8 20 40.0
condition 1 3 33.3
subroutine 8 8 100.0
pod 0 2 0.0
total 72 98 73.4


line stmt bran cond sub pod time code
1             package Module::Build::PPMMaker;
2              
3 2     2   34 use strict;
  2         20  
  2         294  
4 2     2   28 use warnings;
  2         24  
  2         286  
5 2     2   36 use Config;
  2         8  
  2         3970  
6              
7             our $VERSION = '0.4234';
8             $VERSION = eval $VERSION;
9              
10             # This code is mostly borrowed from ExtUtils::MM_Unix 6.10_03, with a
11             # few tweaks based on the PPD spec at
12             # http://www.xav.com/perl/site/lib/XML/PPD.html
13              
14             # The PPD spec is based on <http://www.w3.org/TR/NOTE-OSD>
15              
16             sub new {
17 5     5 0 19 my $package = shift;
18 5         70 return bless {@_}, $package;
19             }
20              
21             sub make_ppd {
22 5     5 0 68 my ($self, %args) = @_;
23 5         33 my $build = delete $args{build};
24              
25 5         14 my @codebase;
26 5 100       54 if (exists $args{codebase}) {
27 2 50       48 @codebase = ref $args{codebase} ? @{$args{codebase}} : ($args{codebase});
  0         0  
28             } else {
29 3         45 my $distfile = $build->ppm_name . '.tar.gz';
30 3         394 print "Using default codebase '$distfile'\n";
31 3         32 @codebase = ($distfile);
32             }
33              
34 5         51 my %dist;
35 5         24 foreach my $info (qw(name author abstract version)) {
36 20         79 my $method = "dist_$info";
37 20 50       228 $dist{$info} = $build->$method() or die "Can't determine distribution's $info\n";
38             }
39              
40 5         15 $self->_simple_xml_escape($_) foreach $dist{abstract}, @{$dist{author}};
  5         29  
41              
42             # TODO: could add <LICENSE HREF=...> tag if we knew what the URLs were for
43             # various licenses
44 5         48 my $ppd = <<"PPD";
45             <SOFTPKG NAME=\"$dist{name}\" VERSION=\"$dist{version}\">
46             <ABSTRACT>$dist{abstract}</ABSTRACT>
47 5         27 @{[ join "\n", map " <AUTHOR>$_</AUTHOR>", @{$dist{author}} ]}
  5         61  
48             <IMPLEMENTATION>
49             PPD
50              
51             # We don't include recommended dependencies because PPD has no way
52             # to distinguish them from normal dependencies. We don't include
53             # build_requires dependencies because the PPM installer doesn't
54             # build or test before installing. And obviously we don't include
55             # conflicts either.
56              
57 5         17 foreach my $type (qw(requires)) {
58 5         78 my $prereq = $build->$type();
59 5         30 foreach my $modname (sort keys %$prereq) {
60 0 0       0 next if $modname eq 'perl';
61              
62 0         0 my $min_version = '0.0';
63 0         0 foreach my $c ($build->_parse_conditions($prereq->{$modname})) {
64 0         0 my ($op, $version) = $c =~ /^\s* (<=?|>=?|==|!=) \s* ([\w.]+) \s*$/x;
65              
66             # This is a nasty hack because it fails if there is no >= op
67 0 0       0 if ($op eq '>=') {
68 0         0 $min_version = $version;
69 0         0 last;
70             }
71             }
72              
73             # PPM4 spec requires a '::' for top level modules
74 0 0       0 $modname .= '::' unless $modname =~ /::/;
75              
76 0         0 $ppd .= qq! <REQUIRE NAME="$modname" VERSION="$min_version" />\n!;
77             }
78             }
79              
80             # We only include these tags if this module involves XS, on the
81             # assumption that pure Perl modules will work on any OS.
82 5 50       10 if (keys %{$build->find_xs_files}) {
  5         91  
83 5         62 my $perl_version = $self->_ppd_version($build->perl_version);
84 5         77 $ppd .= sprintf(<<'EOF', $self->_varchname($build->config) );
85             <ARCHITECTURE NAME="%s" />
86             EOF
87             }
88              
89 5         765 foreach my $codebase (@codebase) {
90 5         28 $self->_simple_xml_escape($codebase);
91 5         31 $ppd .= sprintf(<<'EOF', $codebase);
92             <CODEBASE HREF="%s" />
93             EOF
94             }
95              
96 5         12 $ppd .= <<'EOF';
97             </IMPLEMENTATION>
98             </SOFTPKG>
99             EOF
100              
101 5         20 my $ppd_file = "$dist{name}.ppd";
102 5 50       633 open(my $fh, '>', $ppd_file)
103             or die "Cannot write to $ppd_file: $!";
104              
105             binmode($fh, ":utf8")
106 5 50 33     183 if $] >= 5.008 && $Config{useperlio};
107 5         441 print $fh $ppd;
108 5         489 close $fh;
109              
110 5         78 return $ppd_file;
111             }
112              
113             sub _ppd_version {
114 7     7   23 my ($self, $version) = @_;
115              
116             # generates something like "0,18,0,0"
117 7         86 return join ',', (split(/\./, $version), (0)x4)[0..3];
118             }
119              
120             sub _varchname { # Copied from PPM.pm
121 7     7   46 my ($self, $config) = @_;
122 7         32 my $varchname = $config->{archname};
123             # Append "-5.8" to architecture name for Perl 5.8 and later
124 7 50       33 if ($] >= 5.008) {
125 7         88 my $vstring = sprintf "%vd", $^V;
126 7         68 $vstring =~ s/\.\d+$//;
127 7         43 $varchname .= "-$vstring";
128             }
129 7         70 return $varchname;
130             }
131              
132             {
133             my %escapes = (
134             "\n" => "\\n",
135             '"' => '&quot;',
136             '&' => '&amp;',
137             '>' => '&gt;',
138             '<' => '&lt;',
139             );
140             my $rx = join '|', keys %escapes;
141              
142             sub _simple_xml_escape {
143 15     15   125 $_[1] =~ s/($rx)/$escapes{$1}/go;
144             }
145             }
146              
147             1;
148             __END__
149              
150              
151             =head1 NAME
152              
153             Module::Build::PPMMaker - Perl Package Manager file creation
154              
155             =head1 SYNOPSIS
156              
157             On the command line, builds a .ppd file:
158             ./Build ppd
159              
160              
161             =head1 DESCRIPTION
162              
163             This package contains the code that builds F<.ppd> "Perl Package
164             Description" files, in support of ActiveState's "Perl Package
165             Manager". Details are here:
166             L<http://aspn.activestate.com/ASPN/Downloads/ActivePerl/PPM/>
167              
168              
169             =head1 AUTHOR
170              
171             Dave Rolsky <autarch@urth.org>, Ken Williams <kwilliams@cpan.org>
172              
173              
174             =head1 COPYRIGHT
175              
176             Copyright (c) 2001-2006 Ken Williams. All rights reserved.
177              
178             This library is free software; you can redistribute it and/or
179             modify it under the same terms as Perl itself.
180              
181              
182             =head1 SEE ALSO
183              
184             perl(1), Module::Build(3)
185              
186             =cut