summaryrefslogtreecommitdiff
path: root/pkgtools/pkg_p5up2date
diff options
context:
space:
mode:
authorsno <sno@pkgsrc.org>2012-01-30 06:10:58 +0000
committersno <sno@pkgsrc.org>2012-01-30 06:10:58 +0000
commit51d8aaf5d5804a0fd27fdce1f5c82829936debc0 (patch)
tree2d82c2ef7f73a94dadada98acdf884f996c6c372 /pkgtools/pkg_p5up2date
parent492389942334eee7aedd24ed449f7488afb1fcae (diff)
downloadpkgsrc-51d8aaf5d5804a0fd27fdce1f5c82829936debc0.tar.gz
Importing pkg_p5up2date:
pkg_p5up2date checks for outdated Perl5 modules in pkgsrc against the database from Comprehensive Perl Archive Network.
Diffstat (limited to 'pkgtools/pkg_p5up2date')
-rw-r--r--pkgtools/pkg_p5up2date/DESCR2
-rw-r--r--pkgtools/pkg_p5up2date/Makefile50
-rw-r--r--pkgtools/pkg_p5up2date/PLIST3
-rwxr-xr-xpkgtools/pkg_p5up2date/files/pkg_p5up2date.pl404
4 files changed, 459 insertions, 0 deletions
diff --git a/pkgtools/pkg_p5up2date/DESCR b/pkgtools/pkg_p5up2date/DESCR
new file mode 100644
index 00000000000..66b709545b7
--- /dev/null
+++ b/pkgtools/pkg_p5up2date/DESCR
@@ -0,0 +1,2 @@
+pkg_p5up2date checks for outdated Perl5 modules in pkgsrc against
+the database from Comprehensive Perl Archive Network.
diff --git a/pkgtools/pkg_p5up2date/Makefile b/pkgtools/pkg_p5up2date/Makefile
new file mode 100644
index 00000000000..0a306333a15
--- /dev/null
+++ b/pkgtools/pkg_p5up2date/Makefile
@@ -0,0 +1,50 @@
+# $NetBSD: Makefile,v 1.1.1.1 2012/01/30 06:10:58 sno Exp $
+
+DISTNAME= pkg_p5up2date-0.03
+CATEGORIES= pkgtools
+MASTER_SITES= # empty
+DISTFILES= # empty
+
+MAINTAINER= pkgsrc-p5-people@NetBSD.org
+COMMENT= check p5-* pkgsrc packages requiring updates
+
+PKG_INSTALLATION_TYPES= overwrite pkgviews
+PKG_DESTDIR_SUPPORT= user-destdir
+
+USE_TOOLS+= perl:run
+
+WRKSRC= ${WRKDIR}
+NO_BUILD= yes
+USE_LANGUAGES= # none
+
+DEPENDS+= p5-File-Find-Rule>=0.30:../../devel/p5-File-Find-Rule
+DEPENDS+= p5-CPAN-DistnameInfo>=0.02:../../devel/p5-CPAN-DistnameInfo
+
+INSTALLATION_DIRS= bin ${PKGMANDIR}/man8
+
+SUBST_CLASSES+= tools
+SUBST_STAGE.tools= pre-configure
+SUBST_MESSAGE.tools= Substituting tool locations.
+SUBST_FILES.tools= pkg_p5up2date.pl
+SUBST_VARS.tools= PKG_INFO_CMD MAKE PERL5
+
+SUBST_CLASSES+= pkgsrcdir
+SUBST_STAGE.pkgsrcdir= pre-configure
+SUBST_MESSAGE.pkgsrcdir=Recording default path of pkgsrc base directory.
+SUBST_FILES.pkgsrcdir= pkg_p5up2date.pl
+SUBST_SED.pkgsrcdir= -e 's,@PKGSRCDIR@,${PKGSRCDIR},g'
+
+# REPLACE_PERL+= pkg_p5up2date.pl
+
+.include "../../mk/bsd.prefs.mk"
+
+do-extract:
+ cp ${FILESDIR}/pkg_p5up2date.pl ${WRKSRC}
+
+do-install:
+ ${INSTALL_SCRIPT} ${WRKSRC}/pkg_p5up2date.pl \
+ ${DESTDIR}${PREFIX}/bin/pkg_p5up2date
+ pod2man ${DESTDIR}${PREFIX}/bin/pkg_p5up2date \
+ ${DESTDIR}${PREFIX}/${PKGMANDIR}/man8/pkg_p5up2date.8
+
+.include "../../mk/bsd.pkg.mk"
diff --git a/pkgtools/pkg_p5up2date/PLIST b/pkgtools/pkg_p5up2date/PLIST
new file mode 100644
index 00000000000..c26de36b847
--- /dev/null
+++ b/pkgtools/pkg_p5up2date/PLIST
@@ -0,0 +1,3 @@
+@comment $NetBSD: PLIST,v 1.1.1.1 2012/01/30 06:10:58 sno Exp $
+bin/pkg_p5up2date
+man/man8/pkg_p5up2date.8
diff --git a/pkgtools/pkg_p5up2date/files/pkg_p5up2date.pl b/pkgtools/pkg_p5up2date/files/pkg_p5up2date.pl
new file mode 100755
index 00000000000..375d3d06df6
--- /dev/null
+++ b/pkgtools/pkg_p5up2date/files/pkg_p5up2date.pl
@@ -0,0 +1,404 @@
+#!@PERL5@ -w
+
+use strict;
+use warnings;
+use 5.010;
+
+use Carp qw(carp croak);
+use Cwd qw(abs_path);
+use File::Basename;
+use File::Spec;
+use version;
+use File::Find::Rule;
+use Getopt::Long;
+
+use CPAN;
+use CPAN::DistnameInfo;
+use Module::CoreList;
+
+package PkgP5UpToDate::AsciiWriter;
+
+sub new
+{
+ my ($class, $filename) = @_;
+ my %inst;
+ open( $inst{fh}, '>', $filename ) or die "Can't open $filename for writing: $!";
+ return bless( \%inst, $_[0] );
+}
+
+sub DESTROY
+{
+ defined( $_[0]->{finished} ) or $_[0]->finish();
+ defined( $_[0]->{fh} ) and close( $_[0]->{fh} );
+}
+
+sub init
+{
+}
+
+sub write_entry
+{
+ my ($self, $pkgloc, $maint, $comment, $distver, $op, $pkgver, $installed) = @_;
+ $installed = $installed ? " (I)" : "";
+ say {$self->{fh}} $pkgloc . " (" . $maint . ") $comment: ". $distver . " $op " . $pkgver . $installed;
+ return;
+}
+
+sub finish
+{
+ my ($self, $pkg2update, $pkgok, $pkgcrank) = @_;
+ scalar(@_) > 1 and
+ say {$self->{fh}} "$pkg2update p5-packages needing updates, $pkgok p5-packages are up-to-date, $pkgcrank p5-packages needs review";
+ $self->{finished} = 1;
+ return;
+}
+
+package PkgP5UpToDate::HtmlWriter;
+
+our @ISA = ('PkgP5UpToDate::AsciiWriter');
+
+sub init
+{
+ my $self = $_[0];
+ my $intro = <<EOH;
+<html>
+<head>
+ <title>Outdated Perl5 modules in pkgsrc</title>
+</head>
+
+<body>
+ <h1>Outdated Perl5 modules in pkgsrc</h1>
+ <table>
+ <tr><th>Package location</th><th>Maintainer</th><th>Comment</th><th>Operation</th><th>Installed</th></tr>
+EOH
+ say {$self->{fh}} $intro;
+ return;
+}
+
+sub write_entry
+{
+ my ($self, $pkgloc, $maint, $comment, $distver, $op, $pkgver, $installed) = @_;
+ $op =~ s/</&lt;/;
+ $op =~ s/>/&gt;/;
+ my $line = sprintf( " <tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>",
+ $pkgloc, $maint, $comment, $distver . " $op " . $pkgver, $installed ? "Yes" : "-" );
+ say {$self->{fh}} $line;
+ return;
+}
+
+sub finish
+{
+ my ($self, $pkg2update, $pkgok, $pkgcrank) = @_;
+ say {$self->{fh}} " </table>";
+ scalar(@_) > 1 and
+ say {$self->{fh}} "$pkg2update p5-packages needing updates, $pkgok p5-packages are up-to-date, $pkgcrank p5-packages needs review";
+ my $extro = <<EOE;
+</body>
+</html>
+EOE
+ say {$self->{fh}} $extro;
+ return;
+}
+
+package main;
+
+my $make_bin = '@MAKE@';
+my $pkg_info_bin = '@PKG_INFO_CMD@';
+
+sub is_gt
+{
+ my $gt;
+ defined($_[0]) and $_[0] =~ /^v/ and $_[1] !~ /^v/ and $_[1] = "v$_[1]";
+ defined($_[0]) and $_[0] !~ /^v/ and $_[1] =~ /^v/ and $_[0] = "v$_[0]";
+ eval {
+ $gt = defined( $_[0] ) && (version->parse($_[0]) > version->parse($_[1]));
+ };
+ if( $@ ) {
+ $gt = defined( $_[0] ) && ($_[0] gt $_[1]);
+ }
+ return $gt;
+}
+
+sub is_ne
+{
+ my $ne;
+ defined($_[0]) and $_[0] =~ /^v/ and $_[1] !~ /^v/ and $_[1] = "v$_[1]";
+ defined($_[0]) and $_[0] !~ /^v/ and $_[1] =~ /^v/ and $_[0] = "v$_[0]";
+ eval {
+ $ne = defined( $_[0] ) && (version->parse($_[0]) != version->parse($_[1]));
+ };
+ if( $@ ) {
+ $ne = defined( $_[0] ) && ($_[0] ne $_[1]);
+ }
+ return $ne;
+}
+
+sub get_pkg_vars
+{
+ my $varnames = join( " ", @_ );
+ my @vals = qx($make_bin show-vars VARNAMES="$varnames"); chomp @vals;
+ return @vals;
+}
+
+sub get_inst_pkgs
+{
+ my $fh;
+ open( $fh, "$pkg_info_bin |" ) or die "Can't exec pkg_info: $!";
+ my @havepkgs = <$fh>;
+ close( $fh ) or die "Can't close pipe to pkg_info: $!";
+ chomp @havepkgs;
+ @havepkgs = map { ( split( m/\s+/, $_ ) )[0] } grep { 0 == index( $_, 'p5-' ) } @havepkgs;
+ my %havepkgs = map { $_ => 1 } @havepkgs;
+
+ return %havepkgs;
+}
+
+sub get_cpan_versions
+{
+ my $update_idx = $_[0];
+
+ defined( $update_idx ) and $update_idx and
+ $CPAN::Index::LAST_TIME = 0;
+ CPAN::Index->reload( defined( $update_idx ) and $update_idx );
+ $CPAN::Index::LAST_TIME or
+ carp( "Can't reload CPAN Index" );
+
+ my @all_dists = $CPAN::META->all_objects( "CPAN::Distribution" );
+ my %pkgdist;
+
+ foreach my $dist (@all_dists)
+ {
+ my $dinfo = CPAN::DistnameInfo->new( $dist->id() );
+ my ($distname, $distver) = ($dinfo->dist(), $dinfo->version());
+ defined( $distname ) or next;
+ defined( $distver ) or next;
+ if( !defined( $pkgdist{$distname} ) || ( defined( $pkgdist{$distname} ) && is_gt( $distver, $pkgdist{$distname} ) ) )
+ {
+ $pkgdist{$distname} = $distver;
+ }
+ }
+
+ return %pkgdist;
+}
+
+sub get_modules_by_distribution
+{
+ CPAN::Index->reload();
+ $CPAN::Index::LAST_TIME or
+ carp( "Can't reload CPAN Index" );
+
+ my @all_modules = $CPAN::META->all_objects( "CPAN::Module" );
+ my %modsbydist;
+
+ foreach my $module (@all_modules)
+ {
+ my $modname = $module->id();
+ $module->cpan_version() or next;
+ my $distfile = $module->cpan_file();
+ my $dinfo = CPAN::DistnameInfo->new( $distfile );
+ my ($distname, $distver) = ($dinfo->dist(), $dinfo->version());
+ defined( $distname ) or next;
+ defined( $distver ) or next;
+ $modsbydist{$distname} //= [];
+ push( @{$modsbydist{$distname}}, $modname );
+ }
+
+ return %modsbydist;
+}
+
+sub find_pkgsrc_dir
+{
+ defined( $ENV{PKGSRCDIR} ) and return $ENV{PKGSRCDIR};
+
+ foreach my $dir (qw(@PKGSRCDIR@ . .. ../.. /usr/pkgsrc))
+ {
+ -d $dir and -f File::Spec->catfile( $dir, "mk", "bsd.pkg.mk" )
+ and return abs_path($dir); # Cwd::abs_path()
+ }
+
+ return;
+}
+
+my %writers = (
+ ascii => 'PkgP5UpToDate::AsciiWriter',
+ html => 'PkgP5UpToDate::HtmlWriter',
+);
+
+my %opts = (
+ "output-fmt" => "ascii",
+ "output-file" => File::Spec->catfile( $ENV{HOME}, "p5up2date.log" ),
+ "scan-installed" => 1,
+ "update-cpan-index" => 0,
+);
+GetOptions(
+ \%opts,
+ "cpan-home=s",
+ "output-fmt=s",
+ "output-file=s",
+ "scan-installed!",
+ "update-cpan-index!",
+ "help|h",
+ "usage|?"
+) or pod2usage(2);
+
+defined( $opts{help} ) and $opts{help} and pod2usage( { -verbose => 2, -exitval => 0 } );
+defined( $opts{usage} ) and $opts{usage} and pod2usage(1);
+defined( $writers{$opts{'output-fmt'}} ) or pod2usage( { -verbose => 1, -exitval => 1, -message => 'Unknown output format' } );
+
+if( defined($opts{"cpan-home"}) and -e File::Spec->catfile( $opts{'cpan-home'}, 'CPAN', 'MyConfig.pm' ) )
+{
+ my $file = File::Spec->catfile( $opts{'cpan-home'}, 'CPAN', 'MyConfig.pm' );
+
+ # XXX taken from App:Cpan::_load_config()
+ $CPAN::Config = {};
+ delete $INC{'CPAN/Config.pm'};
+
+ my $rc = eval "require '$file'";
+
+ # CPAN::HandleConfig::require_myconfig_or_config looks for this
+ $INC{'CPAN/MyConfig.pm'} = 'fake out!';
+
+ # CPAN::HandleConfig::load looks for this
+ $CPAN::Config_loaded = 'fake out';
+
+ croak( "Could not load [$file]: $@\n") unless $rc;
+}
+else
+{
+ CPAN::HandleConfig->load();
+ defined( $opts{"cpan-home"} ) and -d $opts{"cpan-home"} and
+ $CPAN::Config{cpan_home} = $opts{'cpan-home'}
+}
+
+$CPAN::Config_loaded or die "Can't load CPAN::Config - please setup CPAN first";
+
+my %havepkgs;
+$opts{"scan-installed"} and %havepkgs = get_inst_pkgs();
+
+my $writer = $writers{$opts{'output-fmt'}}->new( $opts{'output-file'} );
+$writer->init();
+
+my %pkgdist = get_cpan_versions( $opts{'update-cpan-index'} );
+my %distmods = get_modules_by_distribution();
+
+my ( $pkg2update, $pkgok, $pkgcrank ) = ( 0, 0, 0 );
+
+my $pkgsrc_base = find_pkgsrc_dir();
+my @p5_pkg_dirs = find( directory => name => "p5-*", in => $pkgsrc_base );
+ @p5_pkg_dirs = sort @p5_pkg_dirs;
+
+foreach my $dn (@p5_pkg_dirs)
+{
+ chdir( $dn );
+ my ($distnm, $extract_sufx, $pkgnm, $maint ) = get_pkg_vars( qw(DISTNAME EXTRACT_SUFX PKGNAME MAINTAINER) );
+ my $pkgver = 0;
+ if( $distnm =~ m/^(.*)-(v?[0-9].*?)$/ )
+ {
+ $distnm = $1;
+ $pkgver = $2;
+ }
+ if( defined( $pkgdist{$distnm} ) && ($pkgdist{$distnm} =~ m/^(.*)$extract_sufx$/ ) )
+ {
+ $pkgdist{$distnm} = $1;
+ }
+
+ my @mods = map { @{$distmods{$_}} } grep { $_ =~ m/^$distnm/ } keys %distmods;
+ foreach my $distmod (@{mods})
+ {
+ my $mod = $CPAN::META->instance( "CPAN::Module", $distmod );
+ if( is_gt( $Module::CoreList::version{$]}->{$distmod}, $mod->cpan_version() ) )
+ {
+ (my $pkgdir = $dn) =~ s,$pkgsrc_base/,,;
+ $writer->write_entry( File::Spec->catfile( $pkgdir, $pkgnm ), $maint, "is older than core for $distmod", $Module::CoreList::version{$]}->{$distmod}, ">", $mod->cpan_version(), defined( $havepkgs{$pkgnm} ) );
+ ++$pkgcrank;
+ last;
+ }
+ }
+
+ if( is_gt($pkgdist{$distnm}, $pkgver ) )
+ {
+ (my $pkgdir = $dn) =~ s,$pkgsrc_base/,,;
+ $writer->write_entry( File::Spec->catfile( $pkgdir, $pkgnm ), $maint, "need update", $pkgdist{$distnm}, ">", $pkgver, defined( $havepkgs{$pkgnm} ) );
+ ++$pkg2update;
+ }
+ elsif( is_ne($pkgdist{$distnm}, $pkgver ) )
+ {
+ (my $pkgdir = $dn) =~ s,$pkgsrc_base/,,;
+ $writer->write_entry( File::Spec->catfile( $pkgdir, $pkgnm ), $maint, "seems to out of sync", $pkgdist{$distnm}, "!=", $pkgver, defined( $havepkgs{$pkgnm} ) );
+ ++$pkgcrank;
+ }
+ else
+ {
+ ++$pkgok;
+ }
+}
+
+$writer->finish( $pkg2update, $pkgok, $pkgcrank );
+
+exit( 0 );
+
+=pod
+
+=head1 NAME
+
+pkg_p5up2date - check p5-* pkgsrc packages whether being up-to-date or need updating
+
+=head1 SYNOPSIS
+
+ pkg_p5up2date [--cpan-home <dir>] [--output-fmt <ascii|html>]
+ [--output-file <filename>]
+ [--[no-]scan-installed] [--[no-]update-cpan-index]
+ [--help] [--usage]
+
+=head1 DESCRIPTION
+
+This script scans pkgsrc directory for outdated cpan packages.
+Packages which will need updates are listed and packages which are
+newer than their cpan pendants are reported as "needs review".
+
+=head1 OPTIONS
+
+=over 8
+
+=item C<--cpan-home>
+
+Specifies home directory for cpan configuration and cache.
+Loads following files:
+
+ ${cpan-home}/CPAN/MyConfig.pm
+ ${cpan-home}/sources/modules/02packages.details.txt.gz
+
+=item C<--output-fmt>
+
+Let you choose the output format, either I<ascii> or I<html>.
+
+Default is ascii.
+
+=item C<--output-file>
+
+Let you specify another target file then C<~/p5up2date.log> for
+writing packages which needs attention.
+
+=item C<--scan-installed|--no-scan-installed>
+
+Specifies whether installed packages shall be marked explicitely.
+
+=item C<--update-cpan-index|--no-update-cpan-index>
+
+Specifies whether cpan index cache shall be forced to update or not.
+
+=item C<--help>
+
+Prints help and exit.
+
+=item C<--usage>
+
+Prints usage and exit.
+
+=back
+
+=head1 AUTHOR
+
+Jens Rehsack <sno@NetBSD.org>
+
+=cut