]> git.pld-linux.org Git - packages/pldcpan.git/commitdiff
- This script helps preparing spec files for CPAN modules. The code
authorradek <radek@pld-linux.org>
Sat, 5 Jun 2004 11:17:05 +0000 (11:17 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
  evolved for a long time and started as a small and really dirty hack;
  the evolution consisted of more and more dirty hacks... so, now it's
  really ugly and unreadable.  You might think that the design is bad.
  Wrong.  It wasn't designed at all. :->  But it works.  To use it,
  just pass paths to *.tar.gz as arguments.  Remember to (at least)
  check the License field.

Changed files:
    pldcpan.pl -> 1.1

pldcpan.pl [new file with mode: 0644]

diff --git a/pldcpan.pl b/pldcpan.pl
new file mode 100644 (file)
index 0000000..9f5ba94
--- /dev/null
@@ -0,0 +1,460 @@
+#!/usr/bin/perl -w
+use strict;
+use vars qw(%opts);
+use Cwd qw(getcwd);
+use Getopt::Long qw(GetOptions);
+use Archive::Any ();
+use Template     ();
+use YAML         ();
+use Digest::MD5  ();
+
+# $Id$
+
+GetOptions(\%opts, 'verbose|v', 'modulebuild|B', 'makemaker|M');
+eval "use Data::Dump qw(pp);" if $opts{verbose};
+die $@ if $@;
+
+# get maximum information from archive name
+sub test_directory {
+       my $fooball = shift;
+       my $info    = shift;
+       return $info->{_tests}->{directory}
+         if defined $info->{_tests}->{directory};
+
+       #       FIXME: use -v
+       unless (
+               $fooball =~ m#^
+               (?:.*/)?
+               (
+                 [a-z][a-z\d]* 
+                 (?:
+                       ([-_])[a-z][a-z\d]*
+                       (?: \2[a-z][a-z\d]*)*
+                 )?
+               )
+               -
+               (\d[\d._-]*)
+               $ #ix
+         )
+       {
+               warn " -- cannot resolve name and version: '$fooball'\n";
+               return $info->{_tests}->{directory} = 0;
+       }
+
+       $info->{ballname} = $1;
+       $info->{namme}    = $1;
+       $info->{version}  = $3;
+       {
+               my $separ = $2;
+               @{$info}{qw(pdir pnam)} = $separ
+                 ? (split /$separ/, $info->{ballname}, 2)
+                 : ($info->{ballname}, undef);
+               $info->{parts} =
+                 [$separ ? (split /$separ/, $info->{ballname}) : ($info->{ballname})];
+       }
+       $info->{_tests}->{directory} = 1;
+}
+
+sub test_archive_name {
+       my (undef, $info) = @_;
+       return $info->{_tests}->{archive_name}
+         if defined $info->{_tests}->{archive_name};
+       (my $d = shift) =~
+         s/\.(?:(?:tar\.)?(?:gz|bz2|Z)|tar|tgz|zip|rar|arj|lha)$//;
+       $info->{_tests}->{archive_name} = test_directory($d, @_);
+}
+
+sub test_has_tests {
+       my $info = shift;
+       return $info->{_tests}->{has_tests}
+         if defined $info->{_tests}->{has_tests};
+       die "not a directory ($info->{dir})!" unless -d $info->{dir};
+
+       if (-d "$info->{dir}/t" || -f "$info->{dir}/test.pl") {
+               $info->{tests}++;
+               return $info->{_tests}->{has_tests} = 1;
+       }
+       $info->{_tests}->{has_tests} = 0;
+}
+
+sub test_has_examples {
+       my $info = shift;
+       return $info->{_tests}->{has_examples}
+         if defined $info->{_tests}->{has_examples};
+       die "not a directory ($info->{dir})!" unless -d $info->{dir};
+
+       $info->{examples} =
+         [grep -e, map { $_, lc $_, uc $_ } qw(Example Examples Eg Sample Samples)];
+       $info->{_tests}->{has_examples} = @{ $info->{examples} } ? 1 : 0;
+}
+
+sub test_has_doc_files {
+       my $info = shift;
+       return $info->{_tests}->{has_doc_files}
+         if defined $info->{_tests}->{has_doc_files};
+       die "not a directory ($info->{dir})!" unless -d $info->{dir};
+       my %tmp;
+       $info->{doc_files} = [
+               grep -e,
+               grep !$tmp{$_}++,
+               map { $_, lc $_, uc $_ }
+                 map { $_, "$_.txt", "$_.TXT" }
+                 qw(AUTHORS BUGS ChangeLog Changes CREDITS doc docs documentation EXTRAS
+                 GOALS HACKING HISTORY INSTALL NEW NEWS NOTES PATCHING README ToDo)
+       ];
+       $info->{_tests}->{has_doc_files} = @{ $info->{doc_files} } ? 1 : 0;
+}
+
+sub test_license {
+       my $info = shift;
+       return $info->{_tests}->{license}
+         if defined $info->{_tests}->{license};
+       if (load_META_yml($info) && $info->{META_yml}->{license}) {
+               $info->{license} =
+                 $info->{META_yml}->{license} =~ /^l?gpl$/
+                 ? uc $info->{META_yml}->{license}
+                 : $info->{META_yml}->{license};
+       }
+       $info->{_tests}->{license} = $info->{license} ? 1 : 0;
+}
+
+sub load_META_yml {
+       my $info = shift;
+       return $info->{_tests}->{license}
+         if defined $info->{_tests}->{license};
+       if (-f 'META.yml') {
+               $info->{META_yml} = YAML::LoadFile('META.yml');
+       }
+       $info->{_tests}->{license} = $info->{META_yml} ? 1 : 0;
+}
+
+sub test_find_pod_file {
+       my $info = shift;
+       return $info->{_tests}->{find_pod_file}
+         if defined $info->{_tests}->{find_pod_file};
+       die "not a directory ($info->{dir})!" unless -d $info->{dir};
+
+       my $pod_file;
+       use File::Iterator;
+
+       my $mfile = (reverse @{ $info->{parts} })[0];
+       my $it    = File::Iterator->new(
+               DIR     => $info->{dir},
+               RECURSE => 1,
+               FILTER  => sub { $_[0] =~ m#(?:^|/)\Q$mfile\E\.(?:pod|pm)$# }
+       );
+       my ($pm, $pod);
+       while (local $_ = $it->next()) {
+               $pod = $_ if /\.pod$/;
+               $pm  = $_ if /\.pm$/;
+       }
+       $pod_file = $pod ? $pod : $pm;
+       if (   !$pod_file
+               && load_META_yml($info)
+               && exists $info->{META_yml}->{version_from})
+       {
+               $pod_file = $info->{META_yml}->{version_from};
+       }
+       $info->{pod_file} = $pod_file;
+
+       warn " -- no \$pod_file: $_\n" unless $pod_file;
+       $info->{_tests}->{find_pod_file} = defined $info->{pod_file} ? 1 : 0;
+}
+
+sub test_find_summ_descr {
+       my $info = shift;
+       return $info->{_tests}->{find_summ_descr}
+         if defined $info->{_tests}->{find_summ_descr};
+
+       test_find_pod_file($info)
+         || return $info->{_tests}->{find_summ_descr} = 0;
+
+       use File::Slurp ();
+
+       (my $file = File::Slurp::read_file($info->{pod_file})) =~ y/\r//d;
+       if ($file =~ /(?:^|\n)=head\d\s+NAME[\t ]*\n\s*(.+)\n+(?:=|$)/) {
+               $info->{summary} = $1;
+               $info->{summary} =~ s/\s+$//g;
+       }
+       else {
+               warn " ,, no summary: $_\n";
+               $info->{summary} = '';
+       }
+       if ($file =~ /\n=head\d DESCRIPTION\s*\n\s*((?:(?<!=head).+\n){1,15})/) {
+               $info->{descr} = $1;
+               use IPC::Run ();
+               my $tmp;
+               IPC::Run::run ["fmt"], \$info->{descr}, \$tmp;
+               $info->{descr} = $tmp if length $tmp;
+               $info->{descr} =~ s/\s+$//g;
+       }
+       else {
+               warn " ,, no description: $_\n";
+               $info->{descr} = '';
+       }
+
+       $info->{_tests}->{find_summ_descr} =
+         ($info->{summary} || $info->{descr}) ? 1 : 0;
+}
+
+sub test_build_style {
+       my $info = shift;
+       return $info->{_tests}->{build_style}
+         if defined $info->{_tests}->{build_style};
+       $info->{uses_makemaker}    = -e 'Makefile.PL';
+       $info->{uses_module_build} = -e 'Build.PL';
+       $info->{uses_makemaker}    = 0
+         if $opts{modulebuild} && $info->{uses_module_build};
+       $info->{uses_module_build} = 0
+         if $opts{makemaker} && $info->{uses_makemaker};
+       $info->{_tests}->{build_style} =
+         ($info->{uses_module_build} || $info->{uses_makemaker}) ? 1 : 0;
+}
+
+sub gen_tarname_unexp {
+       my $info = shift;
+       return
+         unless exists $info->{tarname} && test_directory($info->{dir}, $info);
+       (my $tmp = $info->{tarname}) =~ s#.*/##;
+       $info->{tarname_unexp} = unexpand_macros($info, $tmp);
+}
+
+sub unexpand_macros {
+       my $info = shift;
+       return
+         unless exists $info->{tarname} && test_directory($info->{dir}, $info);
+       my $value = shift;
+       $value =~ s/\Q$info->{pdir}\E/%{pdir}/;
+       $value =~ s/\Q$info->{pnam}\E/%{pnam}/ if $info->{pnam};
+       $value =~ s/\Q$info->{version}\E/%{version}/;
+       $value;
+}
+
+sub test_is_xs {
+       my $info = shift;
+       return $info->{_tests}->{is_xs}
+         if defined $info->{_tests}->{is_xs};
+
+       # Ugly bitch.
+       $info->{_tests}->{is_xs} = (<*.c> || <*.xs>) ? 1 : 0;
+}
+
+for my $arg (@ARGV) {
+       my $info = { _tests => {} };
+
+       if (!-e $arg) {
+               warn "$arg does not exist!\n";
+               next;
+       }
+
+       if (-d $arg) {
+               $info->{dir} = $arg =~ m#^/# ? $arg : getcwd() . "/$arg";
+               test_directory($arg, $info);
+       }
+       else {
+               open my $fh, $arg or die "can't open <$arg>: $!";
+               $info->{source0md5} = Digest::MD5->new->addfile($fh)->hexdigest;
+               close $fh or die "close <$arg>: $!";
+
+               $info->{tarname} = $arg;
+               my $arch = Archive::Any->new($arg);
+               unless ($arch) {
+                       warn " -- unpacking failed, omiting $arg";
+                       next;
+               }
+               if ($arch->is_naughty) {
+                       warn " !! Archive::Any says, that $arg is_naughty. omiting.\n";
+                       next;
+               }
+               test_archive_name($arg, $info);
+               if ($info->{is_impolite} = $arch->is_impolite) {
+                       if (!$info->{_tests}->{archive_name}) {
+                               warn
+                                 "test_archive_name failed and $arg is_impolite; giving up\n";
+                               next;
+                       }
+                       $info->{dir} = getcwd() . "/$info->{ballname}-$info->{version}";
+                       mkdir $info->{dir} or die "can't mkdir <$info->{dir}>, $arg!";
+                       $arch->extract($info->{dir}) or die "Ni! $arg\n";
+               }
+               else {
+                       ($arch->files)[0] =~ m#^(?:\.?/)?([^/]+)(?:/|$)#
+                         or die "can't resolve dir from content of $arg";
+                       $info->{dir} = getcwd() . "/$1";
+                       $arch->extract or die "Nii! $arg\n";
+               }
+       }
+
+       test_find_pod_file($info);
+
+       my $basedir = getcwd;
+
+       $info->{dir} =~ s#/*$##;
+       die " !! not a directory: $info->{dir}" unless -d $info->{dir};
+       warn " .. processing $info->{dir}\n";
+       chdir $info->{dir};
+
+       test_find_summ_descr($info);
+       test_license($info);
+       test_is_xs($info);
+       test_has_tests($info);
+       test_has_examples($info);
+       test_has_doc_files($info);
+       test_build_style($info);
+       gen_tarname_unexp($info);
+
+       $info->{dir} =~ s#.*/##;
+       $info->{dir_unexp} = unexpand_macros($info, $info->{dir});
+
+       chdir $basedir;
+
+       # hack for TT
+       $info = {
+               %$info,
+               map { ; "test_$_" => $info->{_tests}->{$_} }
+                 keys %{ $info->{_tests} }
+       };
+
+       pp $info if $opts{verbose};
+
+       my $spec = join('-', "$basedir/perl", @{ $info->{parts} }) . '.spec';
+       warn " .. writing to $spec\n";
+
+       my $tmpl =
+         Template->new(
+               { INTERPOLATE => 0, POST_CHOMP => 0, EVAL_PERL => 1, ABSOLUTE => 1 });
+       $tmpl->process(\*DATA, $info, $spec)
+         || warn "error parsing $info->{dir}: "
+         . $tmpl->error->type . "\n"
+         . $tmpl->error->info . "\n"
+         . $tmpl->error . "\n";
+}
+
+
+# vim: ts=4 sw=4 noet noai nosi cin
+__DATA__
+# $[% 'Revision$, $Date' %]$
+#
+# Conditional build:
+%bcond_without  tests           # do not perform "make test"
+#
+%include       /usr/lib/rpm/macros.perl
+%define        pdir    [% pdir %]
+[% IF pnam -%]
+%define        pnam    [% pnam %]
+[% END -%]
+Summary:       [% summary %]
+#Summary(pl):  
+Name:          perl-[% pdir %][% IF pnam %]-[% pnam %][% END %]
+Version:       [% version %]
+Release:       1
+[% IF test_license && license == 'perl' -%]
+# same as perl
+License:       GPL v1+ or Artistic
+[% ELSIF test_license -%]
+License:       [% license %]
+[% ELSE -%]
+# same as perl (REMOVE THIS LINE IF NOT TRUE)
+#License:      GPL v1+ or Artistic
+[% END -%]
+Group:         Development/Languages/Perl
+[% IF tarname -%]
+Source0:       http://www.cpan.org/modules/by-module/%{pdir}/[% tarname_unexp %]
+[% ELSIF pnam -%]
+Source0:       http://www.cpan.org/modules/by-module/%{pdir}/%{pdir}-%{pnam}-%{version}.tar.gz
+[% ELSE -%]
+Source0:       http://www.cpan.org/modules/by-module/%{pdir}/%{pdir}-%{version}.tar.gz
+[% END -%]
+# Source0-md5: [% source0md5 %]
+BuildRequires: perl-devel >= 1:5.8
+BuildRequires: rpm-perlprov >= 4.1-13
+[% IF test_has_tests -%]
+%if %{with tests}
+[% FOREACH req = META_yml.requires, META_yml.build_requires -%]
+BuildRequires: perl([% req.key %])[%IF req.value%] >= [% req.value %][%END%]
+[% END -%]
+%endif
+[% END -%]
+[% IF !test_is_xs -%]
+BuildArch:     noarch
+[% END -%]
+BuildRoot:     %{tmpdir}/%{name}-%{version}-root-%(id -u -n)
+
+%description
+[% descr %]
+
+# %description -l pl
+# TODO
+
+%prep
+%setup -q -n [% dir_unexp %][% IF is_impolite %]-c[% END %]
+
+%build
+[% IF uses_makemaker -%]
+%{__perl} Makefile.PL \
+       INSTALLDIRS=vendor
+%{__make}[% IF test_is_xs -%] \
+       OPTIMIZE="%{rpmcflags}"[% END %]
+
+%{?with_tests:%{__make} test}
+[% ELSIF uses_module_build -%]
+%{__perl} Build.PL \
+[% IF test_is_xs %]    config="optimize='%{rpmcflags}'" \[% END -%]
+       destdir=$RPM_BUILD_ROOT \
+       installdirs=vendor
+./Build
+
+%{?with_tests:./Build test}
+[% ELSE -%]
+%{__perl} -MExtUtils::MakeMaker -wle 'WriteMakefile(NAME=>".......")'
+%{__make}[% IF test_is_xs -%] \
+       OPTIMIZE="%{rpmcflags}"[% END %]
+
+%{?with_tests:%{__make} test}
+[% END -%]
+
+%install
+rm -rf $RPM_BUILD_ROOT
+
+[% IF uses_makemaker || !uses_module_build -%]
+%{__make} install \
+       DESTDIR=$RPM_BUILD_ROOT
+[% ELSE -%]
+./Build install
+[% END -%]
+[% IF test_has_examples -%]
+
+install -d $RPM_BUILD_ROOT%{_examplesdir}/%{name}-%{version}
+[% FOREACH eg = examples -%]
+cp -a [% eg %] $RPM_BUILD_ROOT%{_examplesdir}/%{name}-%{version}
+[% END -%]
+[% END -%]
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(644,root,root,755)
+[% IF test_has_doc_files -%]
+%doc[% FOREACH doc = doc_files %] [% doc %][% END %]
+[% END -%]
+[% IF test_is_xs -%]
+%{perl_vendorarch}/%{pdir}/*.pm
+%dir %{perl_vendorarch}/auto/%{pdir}/%{pnam}
+%{perl_vendorarch}/auto/%{pdir}/%{pnam}/*.bs
+%attr(755,root,root) %{perl_vendorarch}/auto/%{pdir}/%{pnam}/*.so
+[% ELSE -%]
+%{perl_vendorlib}/%{pdir}/*.pm
+%{perl_vendorlib}/%{pdir}/%{pnam}
+[% END -%]
+%{_mandir}/man3/*
+[% IF test_has_examples -%]
+%{_examplesdir}/%{name}-%{version}
+[% END -%]
+
+%define date    %(echo `LC_ALL="C" date +"%a %b %d %Y"`)
+%changelog
+* %{date} PLD Team <feedback@pld-linux.org>
+All persons listed below can be reached at <cvs_login>@pld-linux.org
+
+$Log$
This page took 0.047526 seconds and 4 git commands to generate.