]> git.pld-linux.org Git - packages/pldcpan.git/blame - pldcpan.pl
- removed obsolete CVS parts
[packages/pldcpan.git] / pldcpan.pl
CommitLineData
6f720ca8 1#!/usr/bin/perl -w
fa776f89
AG
2# Requirements:
3# perl-Pod-Tree perl-Archive-Any perl-Template-Toolkit perl-YAML perl-IO-String
f40abe9d 4# perl-File-Find-Rule perl-Module-CoreList
0a2c7e19
ER
5
6=head1 NAME
7
8pldcpan - A Perl module packager
9
10=head1 SYNOPSIS
11
12 pldcpan.pl [ OPTIONS ] DIST [ DIST2 DIST3 ... ]
13
14=head1 DESCRIPTION
15
16This program uncompresses given archives in the current directory and -- more
17or less successfully -- attempts to write corresponding perl-*.spec files.
18
19DIST can be a directory, a compressed archive, URL to fetch or module name
20(Foo::Bar) to be found on search.cpan.org.
21
22=head1 TODO
23
24Some things we're working on/thinking about:
25
ace62bef 26=over
27
28=item 1.
29
30use poldek to search whether dir should be packaged:
31
0a2c7e19
ER
32 $ poldek -q --cmd search -f /usr/share/perl5/vendor_perl/Text
33 perl-base-5.8.7-4
ace62bef 34
35=item 2.
36
37first could be checked if the dir is contained by perl-base (will be faster than querying poldek)
38
39=item 3.
40
41Detect Module::AutoInstall and add --skipdeps to Makefile.PL.
42
43=back
0a2c7e19
ER
44
45=head1 BUGS
46
47Every software has bugs, if you find one and it's really annoying for you, try
48opening bugreport at: F<http://bugs.pld-linux.org>
49
50=head1 AUTHOR
51
52Radoslaw Zielinski <radek@pld-linux.org>.
53This manual page was composed by Elan Ruusamae <glen@pld-linux.org>
54
55=head1 LICENSE AND COPYRIGHT
56
57Copyright (c) 2004-2008 PLD Linux Distribution
58
59This product is free and distributed under the Gnu Public License (GPL).
60
61=cut
62
63
6f720ca8 64use strict;
0a7642e7 65
66use Cwd qw( getcwd );
67use Getopt::Long qw( GetOptions );
68use IPC::Run qw( run timeout );
69use Pod::Select qw( podselect );
875713fa 70use YAML::Any qw(LoadFile);
0a7642e7 71
72use Pod::Tree ();
73use Archive::Any ();
74use Template ();
0a7642e7 75use Digest::MD5 ();
76use IO::String ();
f40abe9d 77use File::Find::Rule ();
0a7642e7 78use Module::CoreList ();
79use LWP::Simple ();
857f480b 80
093f435f 81our $VERSION = sprintf "%d.%02d", q$Revision$ =~ /(\d+)/g;
0a7642e7 82our %opts;
157e61cd 83GetOptions(\%opts, 'verbose|v', 'modulebuild|B', 'makemaker|M', 'force');
6f720ca8 84eval "use Data::Dump qw(pp);" if $opts{verbose};
7ad57c63 85die $@ if $@;
6f720ca8 86
7c639a18 87unless (@ARGV) {
88 die <<'EOF';
89usage:
dbdc4dab 90 pldcpan.pl [ OPTIONS ] DIST [ DIST2 DIST3 ... ]
7c639a18 91
92options:
93 -v|--verbose shout, and shout loud
e208a9ad 94 -B|--modulebuild prefer Module::Build (default)
95 -M|--makemaker prefer ExtUtils::MakeMaker
157e61cd 96 --force overwrite existing *.spec files
7c639a18 97
98This program uncompresses given archives in the current directory
99and -- more or less successfully -- attempts to write corresponding
100perl-*.spec files.
101
dbdc4dab 102DIST can be a directory, a compressed archive, URL to fetch or module
103name (Foo::Bar) to be found on search.cpan.org.
104
7c639a18 105$Id$
106EOF
107}
108
d0f6eca7 109# get maximum information from directory name
6f720ca8 110sub test_directory {
111 my $fooball = shift;
112 my $info = shift;
113 return $info->{_tests}->{directory}
114 if defined $info->{_tests}->{directory};
115
d0f6eca7 116 # FIXME: use -v (hmm, what did I meant?)
6f720ca8 117 unless (
118 $fooball =~ m#^
119 (?:.*/)?
120 (
121 [a-z][a-z\d]*
122 (?:
123 ([-_])[a-z][a-z\d]*
124 (?: \2[a-z][a-z\d]*)*
125 )?
126 )
127 -
9690aef0 128 v?(\d[\d._-]*[a-z]?\d*)
7c639a18 129 /*$ #ix
6f720ca8 130 )
131 {
132 warn " -- cannot resolve name and version: '$fooball'\n";
133 return $info->{_tests}->{directory} = 0;
134 }
135
136 $info->{ballname} = $1;
137 $info->{namme} = $1;
138 $info->{version} = $3;
139 {
140 my $separ = $2;
141 @{$info}{qw(pdir pnam)} = $separ
142 ? (split /$separ/, $info->{ballname}, 2)
143 : ($info->{ballname}, undef);
144 $info->{parts} =
145 [$separ ? (split /$separ/, $info->{ballname}) : ($info->{ballname})];
146 }
581ece85 147 $info->{parts_joined} = join '::', @{ $info->{parts} };
6f720ca8 148 $info->{_tests}->{directory} = 1;
149}
150
151sub test_archive_name {
152 my (undef, $info) = @_;
153 return $info->{_tests}->{archive_name}
154 if defined $info->{_tests}->{archive_name};
155 (my $d = shift) =~
156 s/\.(?:(?:tar\.)?(?:gz|bz2|Z)|tar|tgz|zip|rar|arj|lha)$//;
157 $info->{_tests}->{archive_name} = test_directory($d, @_);
158}
159
160sub test_has_tests {
161 my $info = shift;
162 return $info->{_tests}->{has_tests}
163 if defined $info->{_tests}->{has_tests};
164 die "not a directory ($info->{dir})!" unless -d $info->{dir};
165
166 if (-d "$info->{dir}/t" || -f "$info->{dir}/test.pl") {
167 $info->{tests}++;
168 return $info->{_tests}->{has_tests} = 1;
169 }
170 $info->{_tests}->{has_tests} = 0;
171}
172
173sub test_has_examples {
174 my $info = shift;
175 return $info->{_tests}->{has_examples}
176 if defined $info->{_tests}->{has_examples};
177 die "not a directory ($info->{dir})!" unless -d $info->{dir};
178
179 $info->{examples} =
7ad57c63 180 [grep -e,
181 map { $_, lc $_, uc $_ } qw(Example Examples Eg Sample Samples)];
6f720ca8 182 $info->{_tests}->{has_examples} = @{ $info->{examples} } ? 1 : 0;
183}
184
185sub test_has_doc_files {
186 my $info = shift;
187 return $info->{_tests}->{has_doc_files}
188 if defined $info->{_tests}->{has_doc_files};
189 die "not a directory ($info->{dir})!" unless -d $info->{dir};
190 my %tmp;
191 $info->{doc_files} = [
192 grep -e,
193 grep !$tmp{$_}++,
ac04816f 194 map { $_, "$_.txt", "$_.TXT" }
6f720ca8 195 map { $_, lc $_, uc $_ }
6f720ca8 196 qw(AUTHORS BUGS ChangeLog Changes CREDITS doc docs documentation EXTRAS
1c2120f3 197 GOALS HACKING HISTORY INSTALL NEW NEWS NOTES PATCHING README DISCLAIMER
198 ToDo)
6f720ca8 199 ];
200 $info->{_tests}->{has_doc_files} = @{ $info->{doc_files} } ? 1 : 0;
201}
202
203sub test_license {
204 my $info = shift;
205 return $info->{_tests}->{license}
206 if defined $info->{_tests}->{license};
207 if (load_META_yml($info) && $info->{META_yml}->{license}) {
208 $info->{license} =
209 $info->{META_yml}->{license} =~ /^l?gpl$/
210 ? uc $info->{META_yml}->{license}
211 : $info->{META_yml}->{license};
3524180a 212 # This depends on test_find_summ_descr2
213 } elsif (my $license = $info->{pod_license}) {
214 $info->{license} = 'perl' if $license =~ /same terms as perl/i;
6f720ca8 215 }
216 $info->{_tests}->{license} = $info->{license} ? 1 : 0;
217}
218
219sub load_META_yml {
220 my $info = shift;
221 return $info->{_tests}->{license}
222 if defined $info->{_tests}->{license};
223 if (-f 'META.yml') {
875713fa 224 $info->{META_yml} = LoadFile('META.yml');
6f720ca8 225 }
4981c549 226
227 _remove_core_meta_requires($info, 'requires');
228 _remove_core_meta_requires($info, 'build_requires');
229
6f720ca8 230 $info->{_tests}->{license} = $info->{META_yml} ? 1 : 0;
231}
232
4981c549 233sub _remove_core_meta_requires {
234 my ($info, $key) = @_;
235
236 return if ref($info->{META_yml}->{$key}) ne 'HASH';
237
889889ac 238 # avoid perl(perl) >= 5.6... requires
239 delete $info->{META_yml}->{$key}->{perl};
240
4981c549 241 while (my ($module, $version) = each %{ $info->{META_yml}->{$key} }) {
242 my $result;
243 print "Checking dependency: $module $version\n" if $opts{verbose};
244 if ($version) {
245 $result = Module::CoreList->first_release($module, $version);
246 } else {
247 $result = Module::CoreList->first_release($module);
248 }
249 # $] - perl version
250 if ( $result and $result < $] ) {
251 if ($opts{verbose}) {
252 print "Module $module availablie in core since $result, skipping\n"
253 }
254 delete $info->{META_yml}->{$key}->{$module};
255 }
256 }
257}
258
6f720ca8 259sub test_find_pod_file {
260 my $info = shift;
261 return $info->{_tests}->{find_pod_file}
262 if defined $info->{_tests}->{find_pod_file};
263 die "not a directory ($info->{dir})!" unless -d $info->{dir};
264
265 my $pod_file;
6f720ca8 266
3524180a 267 my $mfile = @{ $info->{parts} }[-1];
af079f8a 268 if (!defined $mfile) {
269 warn " .. unable to search for \$pod_file without parts\n";
270 return $info->{_tests}->{find_pod_file} = 0;
271 }
f40abe9d 272
6f720ca8 273 my ($pm, $pod);
f40abe9d 274 for my $f ( grep !m#/t/#, File::Find::Rule->file->name( "$mfile.pod", "$mfile.pm", )->in( $info->{dir} ) ) {
6f870f0f 275 $pod = $f if $f =~ /\.pod$/;
276 $pm = $f if $f =~ /\.pm$/;
6f720ca8 277 }
278 $pod_file = $pod ? $pod : $pm;
279 if ( !$pod_file
280 && load_META_yml($info)
281 && exists $info->{META_yml}->{version_from})
282 {
283 $pod_file = $info->{META_yml}->{version_from};
284 }
d0f6eca7 285
286 unless ($pod_file) {
287 warn " -- no \$pod_file <@{$info->{parts}}>\n";
288 return $info->{_tests}->{find_pod_file} = 0;
289 }
290
291 my $tree = new Pod::Tree;
292 $tree->load_file($pod_file);
293 unless ($tree->has_pod) {
294 warn " ,, no POD in $pod_file\n";
295 return $info->{_tests}->{find_pod_file} = 0;
296 }
297
af079f8a 298 $info->{_podtree} = $tree;
299 $info->{pod_file} = $pod_file;
d0f6eca7 300 $info->{_tests}->{find_pod_file} = 1;
301}
6f720ca8 302
d0f6eca7 303# workaround for Pod::Parser not supporting "\r\n" line endings
304{
016e2ea6 305 no warnings 'redefine';
d0f6eca7 306
307 sub Pod::Parser::preprocess_line {
308 (my $text = $_[1]) =~ y/\r//d;
309 $text;
310 }
6f720ca8 311}
312
98a3ea33 313sub test_find_summ_descr2 {
314 my $info = shift;
315
316 return $info->{_tests}->{find_summ_descr} = 0
317 unless test_find_pod_file($info);
318
319 my $tree = $info->{_podtree};
320 my $handler = _get_node_handler();
321 $tree->walk( $handler );
322 ($info->{summary}, $info->{descr}, $info->{pod_license}) = $handler->('data');
323}
324
325# This subroutine return closure to be used as a node handler in Pod::Tree walk() method
326sub _get_node_handler {
327 # state informaion
328 my $next_is_summary;
329 my $we_are_in_license;
330 my $we_are_in_description;
331 my $nodes_since_description_start;
332 # data we will return
333 my ($summary, $description, $license);
334
335 return sub {
336 my $node = shift;
337
338 # If not called with a node, then return collected data
339 if (!ref $node) {
340 $summary =~ s/^ \s* (.*?) \s* $/$1/gxm;
98a3ea33 341 return ($summary, $description, $license);
342 }
343
344 # We want to dive into root node. Note that this is the only
345 # place we ever descend into tree
346 return 1 if $node->is_root;
347
348 # If we have encountered any head command then abort collecting
349 # summary and description
350 my $command = $node->get_command;
ef80ea17 351 if ($node->is_command and $command =~ /head/) {
98a3ea33 352 if ($command eq 'head1' or $nodes_since_description_start > 3) {
353 $we_are_in_description = 0;
354 }
355 $next_is_summary = 0;
356 $we_are_in_license = 0;
357 }
358
359 # If previous element started an summary section, then treat
360 # this one as summary text.
361 if ($next_is_summary) {
157e61cd 362 ($summary = $node->get_deep_text) =~ y/\r//d;
98a3ea33 363 $summary =~ s/^\s+(.*?)\s+$/$1/;
364 $next_is_summary = 0;
365 return;
366 }
367 if ($we_are_in_license) {
157e61cd 368 ($license .= $node->get_text) =~ y/\r//d;
98a3ea33 369 return;
370 }
371
372 # If we started collecting description then add any ordinary
373 # node to collected description
374 if ($we_are_in_description) {
375 if ($nodes_since_description_start > 5) {
376 $we_are_in_description = 0;
377 }
378 elsif ($node->is_ordinary or $node->is_verbatim) {
157e61cd 379 ($description .= $node->get_deep_text) =~ y/\r//d;
98a3ea33 380 $nodes_since_description_start++;
381 }
382 else {
383 return;
384 }
385 }
386
387 # OK, next will be sumary text
388 if ($node->is_c_head1 and $node->get_text =~ /^\s*NAME\s*$/) {
389 $next_is_summary = 1;
390 }
391 # OK, description nodes will proceeed (until another head command)
392 if ($node->is_c_head1 and $node->get_text =~ /DESCRIPTION/) {
393 $we_are_in_description = 1;
394 $nodes_since_description_start = 1;
395 }
396 if ($node->is_c_head1 and $node->get_text =~ /LICENSE|COPYRIGHT/) {
397 $we_are_in_license = 1;
398 }
399 return;
400 }
401}
402
6f720ca8 403sub test_find_summ_descr {
404 my $info = shift;
405 return $info->{_tests}->{find_summ_descr}
406 if defined $info->{_tests}->{find_summ_descr};
d0f6eca7 407 return $info->{_tests}->{find_summ_descr} = 0
408 unless test_find_pod_file($info);
409
410 # my $parser = new Pod::Select;
411 # $parser->parse_from_file($info->{pod_file});
412 for my $sec ({ h => 'summary', s => 'NAME' },
413 { h => 'descr', s => 'DESCRIPTION' })
414 {
415 my $H = new IO::String \$info->{ $sec->{h} };
416 podselect({ -output => $H, -sections => [$sec->{s}] },
417 $info->{pod_file});
418 $H->close;
419 $info->{ $sec->{h} } =~ s/^\s*=head.*//;
420 }
6f720ca8 421
0a2c7e19 422=begin comment
ace62bef 423
857f480b 424 my $tree = new Pod::Tree;
425 $tree->load_file($info->{pod_file});
857f480b 426 unless ($tree->has_pod) {
427 warn " ,, no POD in $info->{pod_file}\n";
428 return $info->{_tests}->{find_summ_descr} = 0;
429 }
430
431 my $root = $tree->get_root;
432 $info->{$_} = '' for qw/summary descr/;
433
434 my $state;
435 for my $n (@{ $root->get_children }) {
436 if ($n->is_c_head1) {
437 undef $state;
438 $state = 'summary'
439 if $n->get_text =~ /^\s*NAME\b/ && !$info->{summary};
440 $state = 'descr'
441 if $n->get_text =~ /^\s*DESCRIPTION\b/ && !$info->{descr};
442 next;
443 }
444 $info->{$state} .= $n->get_text if $state;
445 }
ace62bef 446
d0f6eca7 447=cut
448
857f480b 449 $info->{summary} =~ y/\r\n\t / /s;
450 $info->{$_} =~ s/^\s+|\s+$//g for qw/summary descr/;
857f480b 451
452 warn " ,, no summary in $info->{pod_file}\n" unless $info->{summary};
453 warn " ,, no description in $info->{pod_file}\n" unless $info->{descr};
454
0a2c7e19 455=begin comment
ace62bef 456
7ad57c63 457 my $file < io($info->{pod_file});
458 $file =~ y/\r//d;
6f720ca8 459 if ($file =~ /(?:^|\n)=head\d\s+NAME[\t ]*\n\s*(.+)\n+(?:=|$)/) {
460 $info->{summary} = $1;
461 $info->{summary} =~ s/\s+$//g;
462 }
463 else {
464 warn " ,, no summary: $_\n";
465 $info->{summary} = '';
466 }
467 if ($file =~ /\n=head\d DESCRIPTION\s*\n\s*((?:(?<!=head).+\n){1,15})/) {
468 $info->{descr} = $1;
6f720ca8 469 my $tmp;
7ad57c63 470 run ['fmt'], \$info->{descr}, \$tmp;
6f720ca8 471 $info->{descr} = $tmp if length $tmp;
472 $info->{descr} =~ s/\s+$//g;
473 }
474 else {
475 warn " ,, no description: $_\n";
476 $info->{descr} = '';
477 }
ace62bef 478
857f480b 479=cut
6f720ca8 480
481 $info->{_tests}->{find_summ_descr} =
482 ($info->{summary} || $info->{descr}) ? 1 : 0;
483}
484
485sub test_build_style {
486 my $info = shift;
487 return $info->{_tests}->{build_style}
488 if defined $info->{_tests}->{build_style};
489 $info->{uses_makemaker} = -e 'Makefile.PL';
490 $info->{uses_module_build} = -e 'Build.PL';
491 $info->{uses_makemaker} = 0
492 if $opts{modulebuild} && $info->{uses_module_build};
493 $info->{uses_module_build} = 0
494 if $opts{makemaker} && $info->{uses_makemaker};
495 $info->{_tests}->{build_style} =
496 ($info->{uses_module_build} || $info->{uses_makemaker}) ? 1 : 0;
497}
498
499sub gen_tarname_unexp {
500 my $info = shift;
501 return
502 unless exists $info->{tarname} && test_directory($info->{dir}, $info);
503 (my $tmp = $info->{tarname}) =~ s#.*/##;
504 $info->{tarname_unexp} = unexpand_macros($info, $tmp);
505}
506
507sub unexpand_macros {
581ece85 508 my $info = shift;
6f720ca8 509 my $value = shift;
510 $value =~ s/\Q$info->{pdir}\E/%{pdir}/;
511 $value =~ s/\Q$info->{pnam}\E/%{pnam}/ if $info->{pnam};
512 $value =~ s/\Q$info->{version}\E/%{version}/;
513 $value;
514}
515
516sub test_is_xs {
517 my $info = shift;
518 return $info->{_tests}->{is_xs}
519 if defined $info->{_tests}->{is_xs};
520
521 # Ugly bitch.
0a7642e7 522 $info->{_tests}->{is_xs} = ( <*.c> || <*.xs> || <*/*.c> || <*/*.xs> || <*/*/*.c> || <*/*/*.xs> ) ? 1 : 0;
6f720ca8 523}
524
581ece85 525sub run_configure {
7ad57c63 526 my $info = shift;
581ece85 527 test_build_style($info);
528 return $info->{_tests}->{run_configure}
529 if defined $info->{_tests}->{run_configure};
530
531 $info->{tmp_destdir} = getcwd() . "/pldcpan_destdir_$$";
532 system(qw(rm -rf), $info->{tmp_destdir}) if -e $info->{tmp_destdir};
533 my @cmd;
534 if ($info->{_tests}->{build_style}) {
535 @cmd =
536 $info->{uses_makemaker}
537 ? qw(perl Makefile.PL INSTALLDIRS=vendor)
538 : (
539 qw(perl Build.PL installdirs=vendor config="optimize='%{rpmcflags}'"),
540 qw(destdir='$info->{tmp_destdir}')
541 );
542 }
543 else {
544 @cmd = (
545 qw(perl -MExtUtils::MakeMaker -wle),
546 qq#WriteMakefile(NAME=>"$info->{parts_joined}")#,
547 qw(INSTALLDIRS=>vendor)
548 );
549 }
550 $info->{_tests}->{run_configure} = run \@cmd, \undef, \my $out, \my $err,
551 timeout(20);
7ad57c63 552}
553
581ece85 554sub run_build {
7ad57c63 555 my $info = shift;
581ece85 556 return $info->{_tests}->{run_build} if defined $info->{_tests}->{run_build};
557 return $info->{_tests}->{run_build} = 0 unless run_configure($info);
558
559 my @cmd;
560 if ($info->{_tests}->{build_style}) {
561 @cmd =
562 $info->{uses_makemaker}
563 ? qw(make)
564 : qw(perl ./Build);
565 }
566 else {
567 @cmd = qw(make);
568 }
569 $info->{_tests}->{run_build} = run \@cmd, \undef, \my $out, \my $err,
570 timeout(60);
7ad57c63 571}
572
581ece85 573sub run_test {
7ad57c63 574 my $info = shift;
581ece85 575 return $info->{_tests}->{run_test} if defined $info->{_tests}->{run_test};
576 return $info->{_tests}->{run_test} = 0 unless run_build($info);
577
578 my @cmd;
579 if ($info->{_tests}->{build_style}) {
580 @cmd =
581 $info->{uses_makemaker}
582 ? qw(make test)
583 : qw(perl ./Build test);
584 }
585 else {
586 @cmd = qw(make test);
587 }
588 $info->{_tests}->{run_test} = run \@cmd, \undef, \my $out, \my $err,
589 timeout(360);
590}
591
592sub run_install {
593 my $info = shift;
594 return $info->{_tests}->{run_install}
595 if defined $info->{_tests}->{run_install};
596 return $info->{_tests}->{run_install} = 0 unless run_build($info);
597
598 my @cmd;
599 if ($info->{_tests}->{build_style}) {
600 @cmd =
601 $info->{uses_makemaker}
602 ? (qw(make install), "DESTDIR='$info->{tmp_destdir}'")
603 : qw(perl ./Build install);
604 }
605 else {
d0f6eca7 606 @cmd = (qw(make install), "DESTDIR='$info->{tmp_destdir}'");
581ece85 607 }
d0f6eca7 608 die "nfy";
7ad57c63 609}
610
581ece85 611sub find_files {
7ad57c63 612 my $info = shift;
581ece85 613 return $info->{_tests}->{find_files}
614 if defined $info->{_tests}->{find_files};
615 return $info->{_tests}->{find_files} = 0 unless run_install($info);
d0f6eca7 616 die "nfy";
7ad57c63 617}
618
0a7642e7 619sub build_reqs_list {
620 my $info = shift;
621 my $rr = $info->{META_yml}->{requires};
622 my $br = $info->{META_yml}->{build_requires};
623 my %RR = map format_r_or_br( $_, $rr->{$_} ), keys %$rr;
624 my %BR = map format_r_or_br( $_, $br->{$_} ), keys %$br;
625 $info->{requires} = \%RR;
626 $info->{build_requires} = \%BR;
627}
628
629sub format_r_or_br {
630 my ( $package, $version ) = @_;
631 my $rpmreq = "perl($package)";
632 ( my $possible = "perl-$package" ) =~ s/::/-/g;
633 if ( run( [ 'rpm', '-q', $possible ], \my ( undef, $out, $err ) )
634 or run( [ 'rpm', '-q', '--whatprovides', $possible ], \my ( undef, $out2, $err2 ) ) )
635 {
636 return $possible => $version; # we have this package or it is provided by something else
637 }
638 elsif ( run( [ 'rpm', '-q', '--qf', '%{NAME}\n', '--whatprovides', $rpmreq ], \my ( undef, $out3, $err3 ) ) ) {
639 my @providers = grep !/^perl-(?:base|modules|devel)$/, split /\s+/, $out3; # might be more than one
640 return unless @providers; # core, ignore
641 return $providers[0] => $version if @providers == 1;
642 }
643 return $rpmreq => $version; # fallback
644}
645
6f720ca8 646for my $arg (@ARGV) {
647 my $info = { _tests => {} };
648
dbdc4dab 649 if (-e $arg) {
650 ## local file; otherwise... hackish trash code :-]
651 ## TODO: %pdir / %pnam in %URL
652 }
653 elsif (my ($tarname) =
93d2e9d3 654 $arg =~ m# ^ (?:https?|ftp):// [^/]+/ (?:[^/]+/)* ([^/]+) $ #x)
dbdc4dab 655 {
656 $info->{url} = $arg;
657 warn " -- fetching '$tarname'\n";
dbdc4dab 658 my $response = LWP::Simple::mirror($info->{url}, $tarname);
659 if (HTTP::Status::is_error($response)) {
660 warn " !! fetching '$tarname' failed: code $response. omiting.\n";
661 next;
662 }
663 $arg = $tarname;
664 }
157e61cd 665 elsif ($arg =~ /^[a-z\d_]+(?:(?:::|-)[a-z\d_]+)*$/i) {
dbdc4dab 666 (my $dist = $arg) =~ s/::/-/g;
667 warn " -- searching for '$dist' on search.cpan.org\n";
668 my $scpan = LWP::Simple::get("http://search.cpan.org/dist/$dist/");
669 if ( !defined $scpan
670 || $scpan =~ /cannot be found, did you mean one of these/
671 || $scpan !~ m#<a href="/CPAN/authors/id/([^"]+/([^/"]+))">Download</a>#)
672 {
673 warn " !! searching for '$dist' on search.cpan.org failed\n";
674 next;
675 }
676 $info->{url} = "http://www.cpan.org/modules/by-authors/id/$1";
677 my ($tarname) = $2;
678 warn " .. found $info->{url}\n";
679 my $response = LWP::Simple::mirror($info->{url}, $tarname);
680 if (HTTP::Status::is_error($response)) {
681 warn " !! fetching '$tarname' failed: code $response. omiting.\n";
682 next;
683 }
684 $arg = $tarname;
685 }
686 else {
157e61cd 687 warn " !! omiting '$arg': !-e or bad URL\n";
6f720ca8 688 next;
689 }
690
691 if (-d $arg) {
692 $info->{dir} = $arg =~ m#^/# ? $arg : getcwd() . "/$arg";
693 test_directory($arg, $info);
694 }
695 else {
696 open my $fh, $arg or die "can't open <$arg>: $!";
697 $info->{source0md5} = Digest::MD5->new->addfile($fh)->hexdigest;
698 close $fh or die "close <$arg>: $!";
699
700 $info->{tarname} = $arg;
701 my $arch = Archive::Any->new($arg);
702 unless ($arch) {
703 warn " -- unpacking failed, omiting $arg";
704 next;
705 }
706 if ($arch->is_naughty) {
707 warn " !! Archive::Any says, that $arg is_naughty. omiting.\n";
708 next;
709 }
710 test_archive_name($arg, $info);
711 if ($info->{is_impolite} = $arch->is_impolite) {
712 if (!$info->{_tests}->{archive_name}) {
713 warn
714 "test_archive_name failed and $arg is_impolite; giving up\n";
715 next;
716 }
717 $info->{dir} = getcwd() . "/$info->{ballname}-$info->{version}";
718 mkdir $info->{dir} or die "can't mkdir <$info->{dir}>, $arg!";
719 $arch->extract($info->{dir}) or die "Ni! $arg\n";
720 }
721 else {
722 ($arch->files)[0] =~ m#^(?:\.?/)?([^/]+)(?:/|$)#
723 or die "can't resolve dir from content of $arg";
724 $info->{dir} = getcwd() . "/$1";
725 $arch->extract or die "Nii! $arg\n";
726 }
727 }
728
729 test_find_pod_file($info);
730
731 my $basedir = getcwd;
732
93d2e9d3 733 $info->{dir} =~ s{/*$}{};
6f720ca8 734 die " !! not a directory: $info->{dir}" unless -d $info->{dir};
735 warn " .. processing $info->{dir}\n";
736 chdir $info->{dir};
737
98a3ea33 738# test_find_summ_descr($info);
739 test_find_summ_descr2($info);
6f720ca8 740 test_license($info);
741 test_is_xs($info);
742 test_has_tests($info);
743 test_has_examples($info);
744 test_has_doc_files($info);
745 test_build_style($info);
746 gen_tarname_unexp($info);
0a7642e7 747 build_reqs_list($info);
6f720ca8 748
749 $info->{dir} =~ s#.*/##;
750 $info->{dir_unexp} = unexpand_macros($info, $info->{dir});
751
0a7642e7 752 # try to fixup the URL
753 if ($info->{url} && $info->{url} =~ m,/by-authors/id/, && $info->{pdir}) {
754 my $base_url = "http://www.cpan.org/modules/by-module/$info->{pdir}/";
755 if (LWP::Simple::head($base_url . $info->{tarname})) {
756 $info->{url} = $base_url . unexpand_macros($info, $info->{tarname});
757 }
758 }
759
6f720ca8 760 chdir $basedir;
761
762 # hack for TT
763 $info = {
764 %$info,
765 map { ; "test_$_" => $info->{_tests}->{$_} }
766 keys %{ $info->{_tests} }
767 };
768
857f480b 769 pp($info) if $opts{verbose};
6f720ca8 770
157e61cd 771 die " !! I find the idea of overwriting perl.spec disgusting."
772 unless @{ $info->{parts} };
6f720ca8 773 my $spec = join('-', "$basedir/perl", @{ $info->{parts} }) . '.spec';
157e61cd 774 warn " .. writing to '$spec'" . (-e $spec ? " ... which exists...\n" : "\n");
775 die " !! I'm not to overwriting '$spec' without --force\n"
776 if -e $spec && !$opts{force};
6f720ca8 777
857f480b 778 my $rotfl = tell DATA;
581ece85 779 my $tmpl =
6f720ca8 780 Template->new(
781 { INTERPOLATE => 0, POST_CHOMP => 0, EVAL_PERL => 1, ABSOLUTE => 1 });
782 $tmpl->process(\*DATA, $info, $spec)
783 || warn "error parsing $info->{dir}: "
784 . $tmpl->error->type . "\n"
785 . $tmpl->error->info . "\n"
786 . $tmpl->error . "\n";
857f480b 787 seek DATA, $rotfl, 0;
6f720ca8 788}
789
6f720ca8 790# vim: ts=4 sw=4 noet noai nosi cin
791__DATA__
6f720ca8 792#
793# Conditional build:
dc543d6a 794%bcond_without tests # do not perform "make test"
8a5c54f9 795#
9b09f988 796%define pdir [% pdir %]
6f720ca8 797[% IF pnam -%]
9b09f988 798%define pnam [% pnam %]
6f720ca8 799[% END -%]
9b09f988 800%include /usr/lib/rpm/macros.perl
93d2e9d3 801Summary: [% summary.replace('[\r\n\t ]+', ' ') |trim %]
abc368d6 802#Summary(pl.UTF-8):
6f720ca8 803Name: perl-[% pdir %][% IF pnam %]-[% pnam %][% END %]
804Version: [% version %]
07eda004 805Release: 1
6f720ca8 806[% IF test_license && license == 'perl' -%]
807# same as perl
808License: GPL v1+ or Artistic
809[% ELSIF test_license -%]
810License: [% license %]
811[% ELSE -%]
812# same as perl (REMOVE THIS LINE IF NOT TRUE)
813#License: GPL v1+ or Artistic
814[% END -%]
815Group: Development/Languages/Perl
dbdc4dab 816[% IF url -%]
817Source0: [% url %]
818[% ELSIF tarname -%]
e523e325 819Source0: http://www.cpan.org/modules/by-module/[% pdir %]/[% tarname_unexp %]
6f720ca8 820[% ELSIF pnam -%]
e523e325 821Source0: http://www.cpan.org/modules/by-module/[% pdir %]/%{pdir}-%{pnam}-%{version}.tar.gz
6f720ca8 822[% ELSE -%]
e523e325 823Source0: http://www.cpan.org/modules/by-module/[% pdir %]/%{pdir}-%{version}.tar.gz
6f720ca8 824[% END -%]
857f480b 825[% IF source0md5 -%]
826# Source0-md5: [% source0md5 %]
827[% END -%]
e523e325
JB
828# generic URL, check or change before uncommenting
829[% IF pnam -%]
e523e325 830#URL: http://search.cpan.org/dist/[% pdir %]-[% pnam %]/
41aff60a
JB
831[% ELSE -%]
832#URL: http://search.cpan.org/dist/[% pdir %]/
e523e325 833[% END -%]
93d2e9d3 834[% IF uses_module_build -%]
835[% req = 'perl-Module-Build' -%]
836BuildRequires: perl-Module-Build[% ' >= ' _ build_requires.$req IF build_requires.$req %]
837[% build_requires.delete('perl-Module-Build') -%]
838[% END -%]
028d6bb6 839BuildRequires: perl-devel >= 1:5.8.0
6f720ca8 840BuildRequires: rpm-perlprov >= 4.1-13
841[% IF test_has_tests -%]
4f699482 842%if %{with tests}
0a7642e7 843[% FOREACH req IN requires.keys.sort -%]
844BuildRequires: [% req %][% ' >= ' _ requires.$req IF requires.$req %]
75f5735b 845[% END -%]
0a7642e7 846[% FOREACH req IN build_requires.keys.sort -%]
847[% NEXT IF requires.exists(req) -%]
848BuildRequires: [% req %][% ' >= ' _ build_requires.$req IF build_requires.$req %]
6f720ca8 849[% END -%]
850%endif
851[% END -%]
852[% IF !test_is_xs -%]
853BuildArch: noarch
854[% END -%]
855BuildRoot: %{tmpdir}/%{name}-%{version}-root-%(id -u -n)
856
857%description
858[% descr %]
859
abc368d6 860# %description -l pl.UTF-8
6f720ca8 861# TODO
862
863%prep
864%setup -q -n [% dir_unexp %][% IF is_impolite %]-c[% END %]
865
866%build
fe997d58 867[%- IF uses_module_build %]
6f720ca8 868%{__perl} Build.PL \
fe997d58 869[%- IF test_is_xs %]
870 config="optimize='%{rpmcflags}'" \
871[%- END %]
6f720ca8 872 destdir=$RPM_BUILD_ROOT \
873 installdirs=vendor
874./Build
875
876%{?with_tests:./Build test}
fe997d58 877[%- ELSIF uses_makemaker %]
e208a9ad 878%{__perl} Makefile.PL \
879 INSTALLDIRS=vendor
880%{__make}[% IF test_is_xs -%] \
84bd603a 881 CC="%{__cc}" \
e208a9ad 882 OPTIMIZE="%{rpmcflags}"[% END %]
883
884%{?with_tests:%{__make} test}
fe997d58 885[%- ELSE %]
e1a9df87 886%{__perl} -MExtUtils::MakeMaker -wle 'WriteMakefile(NAME=>"[% parts_joined %]")' \
887 INSTALLDIRS=vendor
6f720ca8 888%{__make}[% IF test_is_xs -%] \
84bd603a 889 CC="%{__cc}" \
6f720ca8 890 OPTIMIZE="%{rpmcflags}"[% END %]
891
892%{?with_tests:%{__make} test}
fe997d58 893[%- END %]
6f720ca8 894
895%install
896rm -rf $RPM_BUILD_ROOT
897
e208a9ad 898[% IF uses_module_build || !uses_makemaker -%]
899./Build install
900[% ELSE -%]
2c280bf9 901%{__make} pure_install \
6f720ca8 902 DESTDIR=$RPM_BUILD_ROOT
6f720ca8 903[% END -%]
904[% IF test_has_examples -%]
905
906install -d $RPM_BUILD_ROOT%{_examplesdir}/%{name}-%{version}
907[% FOREACH eg = examples -%]
908cp -a [% eg %] $RPM_BUILD_ROOT%{_examplesdir}/%{name}-%{version}
909[% END -%]
910[% END -%]
911
912%clean
913rm -rf $RPM_BUILD_ROOT
914
915%files
916%defattr(644,root,root,755)
917[% IF test_has_doc_files -%]
918%doc[% FOREACH doc = doc_files %] [% doc %][% END %]
919[% END -%]
920[% IF test_is_xs -%]
c94a8aeb 921%{perl_vendorarch}/[% pdir %]/*.pm
922%dir %{perl_vendorarch}/auto/[% pdir %]/[% pnam %]
923%{perl_vendorarch}/auto/[% pdir %]/[% pnam %]/*.bs
924%attr(755,root,root) %{perl_vendorarch}/auto/[% pdir %]/[% pnam %]/*.so
6f720ca8 925[% ELSE -%]
038260e3 926[%- number = parts.size - 1 -%]
927%{perl_vendorlib}/[% parts.first(number).join('/') %]/*.pm
928%{perl_vendorlib}/[% pdir %]/[% parts.last(number).join('/') %]
6f720ca8 929[% END -%]
930%{_mandir}/man3/*
931[% IF test_has_examples -%]
932%{_examplesdir}/%{name}-%{version}
933[% END -%]
This page took 0.226512 seconds and 4 git commands to generate.