File Coverage

blib/lib/ExtUtils/MY_Metafile.pm
Criterion Covered Total %
statement 154 205 75.1
branch 39 80 48.7
condition 31 84 36.9
subroutine 14 14 100.0
pod 1 1 100.0
total 239 384 62.2


line stmt bran cond sub pod time code
1             ## ----------------------------------------------------------------------------
2             # ExtUtils::MY_Metafile
3             # -----------------------------------------------------------------------------
4             # Mastering programmed by YAMASHINA Hio
5             #
6             # Copyright 2006-2008 YAMASHINA Hio
7             # -----------------------------------------------------------------------------
8             # $Id: /perl/ExtUtils-MY_Metafile/lib/ExtUtils/MY_Metafile.pm 622 2008-01-28T02:56:40.366647Z hio $
9             # -----------------------------------------------------------------------------
10             package ExtUtils::MY_Metafile;
11 5     5   139061 use strict;
  5         13  
  5         183  
12             #use warnings; # warnings pragma was first released with perl 5.006.
13 5     5   11420 use ExtUtils::MakeMaker;
  5         632839  
  5         797  
14              
15 5     5   43 use vars qw($VERSION @EXPORT);
  5         16  
  5         344  
16              
17             $VERSION = '0.09';
18             @EXPORT = qw(my_metafile);
19              
20 5     5   26 use vars qw(%META_PARAMS); # DISTNAME(pkgname)=>HASHREF.
  5         9  
  5         172  
21              
22 5     5   24 use vars qw($DEFAULT_META_SPEC_VERSION);
  5         9  
  5         901  
23             $DEFAULT_META_SPEC_VERSION = '1.3';
24              
25             1;
26              
27             # -----------------------------------------------------------------------------
28             # for: use inc::ExtUtils::MY_Metafile;
29             #
30             sub inc::ExtUtils::MY_Metafile::import
31             {
32 1     1   116 my $pkg = 'ExtUtils::MY_Metafile';
33 1         13 push(@inc::ExtUtils::MY_Metafile::ISA, $pkg);
34 1         6 goto &import;
35             }
36              
37             # -----------------------------------------------------------------------------
38             # import.
39             #
40             sub import
41             {
42 10     10   2831 my $pkg = shift;
43 10 100 100     83 my @syms = (!@_ || grep{/^:all$/}@_) ? @EXPORT : @_;
44 10         33 my $callerpkg = caller;
45            
46 10         65 foreach my $name (@syms)
47             {
48 10         101 my $sub = $pkg->can($name);
49 10 100       78 $sub or next;
50 5     5   29 no strict 'refs';
  5         9  
  5         26152  
51 9         14 *{$callerpkg.'::'.$name} = $sub;
  9         71  
52             }
53 10 50       45 if( !grep{ /^:no_setup$/ } @_ )
  3         12  
54             {
55             # override.
56 10         126 *MM::metafile_target = \&_mm_metafile;
57             }
58             }
59              
60             # -----------------------------------------------------------------------------
61             # _diag_version();
62             #
63             sub _diag_version
64             {
65 1     1   36 my $mmver = $ExtUtils::MakeMaker::VERSION;
66 1         3 my $mmvernum = $mmver;
67 1 50       17 if( $mmvernum =~ /^(\d+)\.(\d+)_(\d+)\z/ )
68             {
69 0         0 $mmvernum = "$1.$2$3";
70 0         0 $mmver .= "=$mmvernum";
71             }
72 1 50       6 if( $mmvernum >= 6.30 )
73             {
74 1         7024 print STDERR "# ExtUtils::MY_Metafile for MM 6.30 or later ($mmver).\n";
75             }else
76             {
77 0         0 print STDERR "# ExtUtils::MY_Metafile for MM 6.25 or earlier ($mmver).\n";
78             }
79             }
80              
81             # -----------------------------------------------------------------------------
82             # my_metafile($distname => $param);
83             # my_metafile($param);
84             #
85             sub my_metafile
86             {
87 3   33 3 1 1244 my $distname = @_>=2 && shift;
88 3         4 my $param = shift;
89 3 50       12 UNIVERSAL::isa($distname,'HASH') and $distname = $distname->{DISTNAME};
90 3   50     16 $distname ||= '';
91 3         4 $distname =~ s/::/-/g;
92 3 50       11 $META_PARAMS{$distname} and warn "# overwrite previous meta config $distname.\n";
93 3         10 $META_PARAMS{$distname} = $param;
94             }
95              
96             # -----------------------------------------------------------------------------
97             # _mm_metafile($MM)
98             # altanative of MM::metafile_target.
99             # takes $MM object and returns makefile text.
100             #
101             sub _mm_metafile
102             {
103 2     2   72 my $this = shift;
104            
105 2 100       47 if( $this->{NO_META} )
106             {
107             return
108 1         3 "metafile:\n" .
109             "\t\$(NOECHO) \$(NOOP)\n";
110             }
111            
112             # generate META.yml text.
113             #
114 1         4 my $meta = _gen_meta_yml($this);
115 1         5 my @write_meta = (
116             '$(NOECHO) $(ECHO) Generating META.yml',
117             $this->echo($meta, 'META_new.yml'),
118             );
119            
120             # format as makefile text.
121             #
122 1         68 my ($make_target, $metaout_file);
123 1         2 my $mmvernum = $ExtUtils::MakeMaker::VERSION;
124 1 50       5 if( $mmvernum =~ /^(\d+)\.(\d+)_(\d+)\z/ )
125             {
126 0         0 $mmvernum = "$1.$2$3";
127             }
128 1 50       3 if( $mmvernum >= 6.30 )
129             {
130 1         2 $make_target = "# for MM 6.30 or later.\n";
131 1         7 $make_target .= "metafile : create_distdir\n";
132 1         2 $metaout_file = '$(DISTVNAME)/META.yml';
133             }else
134             {
135 0         0 $make_target = "# for MM 6.25 or earlier.\n";
136 0         0 $make_target .= "metafile :\n";
137 0         0 $metaout_file = 'META.yml',
138             }
139            
140 1         2 my $rename_meta = "-\$(NOECHO) \$(MV) META_new.yml $metaout_file";
141 1         2 my $make_body = join('', map{"\t$_\n"} @write_meta, $rename_meta);
  22         45  
142 1         8 "$make_target$make_body";
143             }
144              
145             # -----------------------------------------------------------------------------
146             # _gen_meta_yml($MM);
147             # generate META.yml text.
148             #
149             sub _gen_meta_yml
150             {
151             # from MakeMaker-6.30.
152 2     2   45 my $this = shift;
153 2         4 my $param = shift;
154 2         3 my $check_meta_spec = 1;
155 2 50       7 if( !$param )
156             {
157 2   66     38 $param = $META_PARAMS{$this->{DISTNAME}} || $META_PARAMS{''};
158 2 100       7 if( !$param )
159             {
160 1         1 $param = {};
161 1         3 $check_meta_spec = 0;
162             }
163             }
164 2 50       7 if( $META_PARAMS{':all'} )
165             {
166             # special key.
167 0         0 $param = { %{$META_PARAMS{':all'}}, %$param };
  0         0  
168             }
169              
170             # meta_spec and meta_spec_version.
171 2   33     11 my $meta_spec = $param->{meta_spec} || $param->{'meta-spec'};
172 2 50 33     11 if($param->{meta_spec} && $param->{'meta-spec'} )
173             {
174 0         0 warn "both meta_spec and meta-spec exist.\n";
175             }
176 2   50     16 $meta_spec &&= {%$meta_spec}; # sharrow-copy.
177 2   50     12 $meta_spec ||= {};
178 2 50 33     12 if( exists($param->{meta_spec_version}) && exists($meta_spec->{version}) )
179             {
180 0         0 warn "both meta_spec_vesrion and meta_spec.version exist.\n";
181             }
182 2   33     30 $meta_spec->{version} ||= $param->{meta_spec_version} || $DEFAULT_META_SPEC_VERSION;
      33        
183 2   33     14 $meta_spec->{url} ||= "http://module-build.sourceforge.net/META-spec-v$meta_spec->{version}.html";
184              
185             # requires:, build_requires:
186             my $requires_to_yaml = sub{
187 4     4   6 my $key = shift;
188 4         8 my $hash = shift;
189 4         5 my $yaml = '';
190 4         30 my ($maxkeylen) = sort{$b<=>$a} map{length($_)} keys %$hash;
  0         0  
  0         0  
191 4         7 my ($maxvallen) = sort{$b<=>$a} map{length($_)} values %$hash;
  0         0  
  0         0  
192 4         10 foreach my $name ( sort { lc $a cmp lc $b } keys %$hash )
  0         0  
193             {
194 0         0 my $ver = $hash->{$name};
195 0         0 $yaml .= sprintf " %-*s %*s\n", $maxkeylen+1, "$name:", $maxvallen, $ver;
196             }
197 4         8 chomp $yaml;
198 4 50       14 $yaml ? "$key:\n$yaml" : '';
199 2         45 };
200 2   33     15 my $requires = $requires_to_yaml->(requires => $param->{requires} || $this->{PREREQ_PM});
201 2         8 my $build_requires = $requires_to_yaml->(build_requires => $param->{build_requires});
202            
203             # no_index:
204 2         4 my $no_index = $param->{no_index};
205 2 50 33     15 if( !$no_index || !$no_index->{directory} )
206             {
207 2         5 my @dirs = grep{-d $_} (qw(
  20         137  
208             inc t
209             ex eg example examples sample samples demo demos
210             ));
211 2   50     21 $no_index = @dirs && +{ directory => \@dirs };
212             }
213 2 50       12 $no_index = $no_index ? _yaml_out({no_index=>$no_index}) : '';
214 2         6 chomp $no_index;
215 2 50 33     10 if( $param->{no_index} && !$ENV{NO_NO_INDEX_CHECK} )
216             {
217 0         0 my $warned;
218 0         0 foreach my $key (keys %{$param->{no_index}})
  0         0  
219             {
220             # dir is in spec-v1.2, directory is from spec-v1.3.
221 0 0 0     0 if( $key eq 'dir' && $meta_spec->{version}>=1.3 )
222             {
223 0   0     0 $warned ||= print STDERR "\n";
224 0         0 warn "$key should be `directory' in META-spec-v1.3 and later.\n";
225 0         0 next;
226             }
227 0 0       0 $key =~ /^(file|dir|directory|package|namespace)$/ and next;
228 0   0     0 $warned ||= print STDERR "\n";
229 0         0 warn "$key is invalid field for no_index.\n";
230             }
231 0 0       0 $warned and print STDERR "\n";
232             }
233            
234             # abstract is from file.
235 2         3 my $abstract = '';
236 2 50 0     7 if( $this->{ABSTRACT} )
    0          
237             {
238 2         7 $abstract = _yaml_out({abstract => $this->{ABSTRACT}});
239             }elsif( $this->{ABSTRACT_FROM} && open(my$fh, "< $this->{ABSTRACT_FROM}") )
240             {
241 0         0 while(<$fh>)
242             {
243 0 0       0 /^=head1 NAME$/ or next;
244 0         0 (my $pkg = $this->{DISTNAME}) =~ s/-/::/g;
245 0         0 while(<$fh>)
246             {
247 0 0       0 /^=/ and last;
248 0 0       0 /^(\Q$pkg\E\s+-+\s+)(.*)/ or next;
249 0         0 $abstract = $2;
250 0         0 last;
251             }
252 0         0 last;
253             }
254 0 0       0 $abstract = $abstract ? _yaml_out({abstract=>$abstract}) : '';
255             }
256 2         4 chomp $abstract;
257            
258             # build yaml object as hash.
259 2         4 my $yaml = {}; # key=>"value as yaml-text".
260              
261             # first, set from arguments for WriteMakefile().
262 2         5 $yaml->{name} = $this->{DISTNAME};
263 2         5 $yaml->{version} = $this->{VERSION};
264 2         6 $yaml->{version_from} = $this->{VERSION_FROM};
265 2         4 $yaml->{installdirs} = $this->{INSTALLDIRS};
266 2         5 $yaml->{author} = $this->{AUTHOR};
267 2         3 $yaml->{license} = $this->{LICENSE};
268 2         6 foreach my $key (keys %$yaml)
269             {
270 12 100       25 if( $yaml->{$key} )
271             {
272 8         11 my $pad = ' 'x(12-length($key));
273 8         28 $yaml->{$key} = sprintf('%s:%s %s', $key, $pad, $yaml->{$key});
274             }
275             }
276 2         4 $yaml->{abstract} = $abstract;
277 2         5 $yaml->{no_index} = $no_index;
278 2         3 $yaml->{requires} = $requires;
279 2         10 $yaml->{build_requires} = $build_requires;
280            
281 2         5 $yaml->{distribution_type} = 'distribution_type: module';
282 2         35 $yaml->{generated_by} = "generated_by: ExtUtils::MY_Metafile version $VERSION, EUMM-$ExtUtils::MakeMaker::VERSION.";
283              
284 2         9 $yaml->{'meta-spec'} = "meta-spec:\n";
285 2         8 $yaml->{'meta-spec'} .= " version: ".delete($meta_spec->{version})."\n";
286 2         8 $yaml->{'meta-spec'} .= " url: ".delete($meta_spec->{url})."\n";
287              
288             # next, set from arguments for my_metafile().
289 2         16 my $extras = {};
290 2         7 foreach my $key (sort keys %$param)
291             {
292 0 0       0 grep{$key eq $_} qw(no_index requires build_requires meta_spec meta-spec meta_spec_version) and next;
  0         0  
293 0         0 my $line = _yaml_out->({$key=>$param->{$key}});
294 0 0       0 if( exists($yaml->{$key}) )
295             {
296 0         0 chomp $line;
297 0         0 $yaml->{$key} = $line;
298             }else
299             {
300 0         0 $extras->{$key} = $line;
301             }
302             }
303 2         8 $yaml->{extras} = join('', map{$extras->{$_}} sort keys %$extras);
  0         0  
304              
305             # then, check required keys by yaml-spec.
306 2         14 my @required_keys = qw(meta-spec name version abstract author license generated_by);
307 2         4 foreach my $key (@required_keys)
308             {
309 14 100       27 $check_meta_spec or next;
310 7   33     27 my $ok = $yaml->{$key} && $yaml->{$key}=~/\w/;
311 7 50 33     18 $ok ||= $extras->{$key} and next;
312 0         0 warn "$key is required for meta-spec v1.2 ($this->{DISTNAME}).\n";
313             }
314              
315 2 0 33     10 if( exists($param->{license}) && exists($this->{LICENSE}) && $param->{license} ne $this->{LICENSE} )
      33        
316             {
317 0         0 warn "WriteMakefile.LICENSE ($this->{LICENSE}) is different from my_metafile.license ($param->{license}).";
318             }
319              
320 2   50     6 $yaml->{license} ||= 'license: unknown';
321 2         9 foreach my $key (keys %$yaml)
322             {
323 28 100       38 $key eq 'extras' and next;
324 26   66     65 $yaml->{$key} ||= "#$key:";
325             }
326 2   33     15 $yaml->{extras} &&= "\n# extras.\n$yaml->{extras}";
327              
328 2         10 foreach my $key (qw(abstract license))
329             {
330 4         7 my $pad = ' 'x(12-length($key));
331 4         89 $yaml->{$key} =~ s/^$key: +(.+)\z/$key:$pad $1/;
332             }
333              
334             # packing into singple text.
335 2         22 my $meta = <
336             # http://module-build.sourceforge.net/META-spec.html
337             $yaml->{name}
338             $yaml->{version}
339             $yaml->{version_from}
340             $yaml->{installdirs}
341             $yaml->{author}
342             $yaml->{abstract}
343             $yaml->{license}
344             $yaml->{requires}
345             $yaml->{build_requires}
346             $yaml->{no_index}
347             $yaml->{extras}
348             $yaml->{distribution_type}
349             $yaml->{generated_by}
350             $yaml->{'meta-spec'}
351             YAML
352             #print "$meta";
353 2         26 $meta;
354             }
355              
356             # -----------------------------------------------------------------------------
357             # generate simple yaml.
358             #
359             sub _yaml_out
360             {
361 12     12   15 my $obj = shift;
362            
363 12   100     31 my $depth = shift || 0;
364 12         15 my $out = '';
365            
366 12 50       55 if( !defined($obj) )
    100          
    100          
    50          
367             {
368 0         0 $out = " "x$depth."~\n";
369             }elsif( !ref($obj) )
370             {
371 4         10 $out = " "x$depth.$obj."\n";
372             }elsif( ref($obj)eq'ARRAY' )
373             {
374 2         4 my @e = map{_yaml_out->($_, $depth+1)} @$obj;
  4         12  
375 2         4 @e = map{ " "x$depth."- ".substr($_, ($depth+1)*2)} @e;
  4         15  
376 2         17 $out = join('', @e);
377 2   33     11 $out ||= " "x$depth."[]";
378             }elsif( ref($obj)eq'HASH' )
379             {
380 6         14 foreach my $k (sort keys %$obj)
381             {
382 6         16 $out .= " "x$depth."$k:";
383 6 100       41 $out .= ref($obj->{$k}) ? "\n"._yaml_out($obj->{$k}, $depth+1) : " $obj->{$k}\n";
384             }
385 6   33     14 $out ||= " "x$depth."{}";
386             }else
387             {
388 0         0 die "not supported: $obj";
389             }
390 12         31 $out;
391             }
392              
393             # -----------------------------------------------------------------------------
394             # End of Code.
395             # -----------------------------------------------------------------------------
396              
397             __END__