r54159 - // /lib/ /lib/Apt/ /script/ /t/ /tmp/

jozef-guest at users.alioth.debian.org jozef-guest at users.alioth.debian.org
Fri Mar 12 11:00:52 UTC 2010


Author: jozef-guest
Date: Fri Mar 12 10:59:46 2010
New Revision: 54159

URL: http://svn.debian.org/wsvn/?sc=1&rev=54159
Log:
initial apt-pm

Added:
    .gitignore
    Build.PL
    Changes
    MANIFEST
    MANIFEST.SKIP
    META.yml
    README
    lib/
    lib/Apt/
    lib/Apt/PM.pm
    script/
    script/apt-pm   (with props)
    t/
    t/00_compile.t
    t/01_Apt-PM.t
    t/PerlPackages.bz2   (with props)
    t/PerlPackages2.bz2   (with props)
    t/distribution.t
    t/fixme.t
    t/pod-coverage.t
    t/pod-spell.t
    t/pod.t
    tmp/

Added: .gitignore
URL: http://svn.debian.org/wsvn/.gitignore?rev=54159&op=file
==============================================================================
--- .gitignore (added)
+++ .gitignore Fri Mar 12 10:59:46 2010
@@ -1,0 +1,13 @@
+/Makefile
+/blib
+/pm_to_blib
+/META.yml
+/MYMETA.yml
+/Makefile.PL
+/Build
+/_build
+/*.tar.gz
+/MANIFEST.bak
+/cover_db
+/tmp/*
+/Apt-PM-*

Added: Build.PL
URL: http://svn.debian.org/wsvn/Build.PL?rev=54159&op=file
==============================================================================
--- Build.PL (added)
+++ Build.PL Fri Mar 12 10:59:46 2010
@@ -1,0 +1,51 @@
+use strict;
+use warnings;
+use Module::Build;
+
+use 5.010;
+
+my $builder = Module::Build->new(
+    module_name       => 'Apt::PM',
+    license           => 'perl',
+    dist_author       => 'Jozef Kutej <jkutej at cpan.org>',
+    dist_version_from => 'lib/Apt/PM.pm',
+    
+    build_requires => {
+        'Test::More'             => 0,
+        'Test::Differences'      => 0,
+        'Test::Exception'        => 0,
+    },
+    requires => {
+        'Moose'                   => 0,
+        'IO::Uncompress::Bunzip2' => 0,
+        'IO::Any'                 => 0,
+        'Parse::Deb::Control'     => 0.03,
+        'Dpkg::Version'           => 0,
+        'AptPkg::Config'          => 0,
+        'LWP::Simple'             => 0,
+        'Carp'                    => 0,
+        'JSON::Util'              => 0.04,   # atomic writes
+        'Getopt::Long'            => 0,
+        'Pod::Usage'              => 0,
+        'List::MoreUtils'         => 0,
+        'CPAN::Version'           => 0,
+        'Storable'                => 0,
+        'CPAN'                    => 0,
+        'File::is'                => 0,
+    },
+    script_files => [
+        'script/apt-pm',
+    ],
+    add_to_cleanup => [ 'Apt-PM-*' ],
+    create_readme  => 1,
+    sign           => 1,
+    meta_merge => {
+        resources => {
+            repository => 'http://svn.debian.org/viewsvn/pkg-perl/trunk/apt-pm/',
+            bugtracker => 'http://bugs.debian.org/',
+        },
+        keywords => [ qw/ debian perl modules search / ],
+    },
+);
+
+$builder->create_build_script();

Added: Changes
URL: http://svn.debian.org/wsvn/Changes?rev=54159&op=file
==============================================================================
--- Changes (added)
+++ Changes Fri Mar 12 10:59:46 2010
@@ -1,0 +1,4 @@
+Revision history for Apt-PM
+
+0.01    12 Mar 2010
+    * First version, released on an unsuspecting world.

Added: MANIFEST
URL: http://svn.debian.org/wsvn/MANIFEST?rev=54159&op=file
==============================================================================
--- MANIFEST (added)
+++ MANIFEST Fri Mar 12 10:59:46 2010
@@ -1,0 +1,16 @@
+Build.PL
+Changes
+lib/Apt/PM.pm
+MANIFEST			This list of files
+META.yml
+README
+script/apt-pm
+t/00_compile.t
+t/01_Apt-PM.t
+t/distribution.t
+t/fixme.t
+t/PerlPackages.bz2
+t/PerlPackages2.bz2
+t/pod-coverage.t
+t/pod-spell.t
+t/pod.t

Added: MANIFEST.SKIP
URL: http://svn.debian.org/wsvn/MANIFEST.SKIP?rev=54159&op=file
==============================================================================
--- MANIFEST.SKIP (added)
+++ MANIFEST.SKIP Fri Mar 12 10:59:46 2010
@@ -1,0 +1,35 @@
+# Avoid version control files.
+\bRCS\b
+\bCVS\b
+,v$
+\B\.svn\b
+^\.git
+\.cvsignore
+\.svnignore
+
+# Avoid Makemaker generated and utility files.
+^Makefile$
+\bblib
+\bMakeMaker-\d
+\bpm_to_blib$
+\bblibdirs$
+^MANIFEST\.(SKIP|bak)$
+
+# Avoid Module::Build generated and utility files.
+\bBuild$
+\b_build
+\bcover_db
+
+# Avoid temp and backup files.
+~$
+\.tmp$
+\.old$
+\.bak$
+\#$
+\b\.#
+
+^tmp/
+.*\.tar\.gz
+^MYMETA.yml$
+^Apt-PM-
+

Added: META.yml
URL: http://svn.debian.org/wsvn/META.yml?rev=54159&op=file
==============================================================================
--- META.yml (added)
+++ META.yml Fri Mar 12 10:59:46 2010
@@ -1,0 +1,47 @@
+---
+abstract: 'locate Perl Modules in Debian repositories'
+author:
+  - 'Jozef Kutej <jkutej at cpan.org>'
+build_requires:
+  Test::Differences: 0
+  Test::Exception: 0
+  Test::More: 0
+configure_requires:
+  Module::Build: 0.36
+generated_by: 'Module::Build version 0.3603'
+keywords:
+  - debian
+  - perl
+  - modules
+  - search
+license: perl
+meta-spec:
+  url: http://module-build.sourceforge.net/META-spec-v1.4.html
+  version: 1.4
+name: Apt-PM
+provides:
+  Apt::PM:
+    file: lib/Apt/PM.pm
+    version: 0.01
+requires:
+  AptPkg::Config: 0
+  CPAN: 0
+  CPAN::Version: 0
+  Carp: 0
+  Dpkg::Version: 0
+  File::is: 0
+  Getopt::Long: 0
+  IO::Any: 0
+  IO::Uncompress::Bunzip2: 0
+  JSON::Util: 0.04
+  LWP::Simple: 0
+  List::MoreUtils: 0
+  Moose: 0
+  Parse::Deb::Control: 0.03
+  Pod::Usage: 0
+  Storable: 0
+resources:
+  bugtracker: http://bugs.debian.org/
+  license: http://dev.perl.org/licenses/
+  repository: http://svn.debian.org/viewsvn/pkg-perl/trunk/apt-pm/
+version: 0.01

Added: README
URL: http://svn.debian.org/wsvn/README?rev=54159&op=file
==============================================================================
--- README (added)
+++ README Fri Mar 12 10:59:46 2010
@@ -1,0 +1,140 @@
+NAME
+    Apt::PM - locate Perl Modules in Debian repositories
+
+SYNOPSIS
+    Cmd-line:
+
+            apt-pm update
+            apt-pm find Moose
+        
+            # print out all dependencies of an unpacked distribution that are packaged for Debian
+            perl -MApt::PM -MModule::Depends -le \
+                    '$apm=Apt::PM->new();$md=Module::Depends->new->dist_dir(".")->find_modules; %r=(%{$md->requires},%{$md->build_requires}); while (($m, $v) = each %r) { $f=$apm->find($m, $v); print $f->{"min"}->{"package"} if $f->{"min"}  }' \
+                    | sort \
+                    | uniq \
+                    | xargs echo apt-get install
+            # print out all dependencies of an unpacked distribution that are not packaged for Debian
+            perl -MApt::PM -MModule::Depends -le \
+                    '$apm=Apt::PM->new();$md=Module::Depends->new->dist_dir(".")->find_modules; %r=(%{$md->requires},%{$md->build_requires}); while (($m, $v) = each %r) { $f=$apm->find($m, $v); print $m, " ", $v if not $f->{"min"}  }'
+
+    Module:
+
+            my $aptpm = Apt::PM->new(sources => [ 'PerlPackages.bz2' ])
+            $aptpm->update;
+            my %moose_locations = $aptpm->find('Moose');
+
+USAGE
+  COMMAND-LINE USAGE
+    Add sources for Debian releases and components. Here is the complete
+    list that can be reduced just to the wanted ones:
+
+            cat >> /etc/apt/sources.list << __END__
+            # for apt-pm
+            deb http://pkg-perl.alioth.debian.org/~jozef-guest/pmindex/ etch    main contrib non-free
+            deb http://pkg-perl.alioth.debian.org/~jozef-guest/pmindex/ lenny   main contrib non-free
+            deb http://pkg-perl.alioth.debian.org/~jozef-guest/pmindex/ sid     main contrib non-free
+            deb http://pkg-perl.alioth.debian.org/~jozef-guest/pmindex/ squeeze main contrib non-free
+            __END__
+
+    Fetch the indexes:
+
+            apt-pm update
+
+    Look for the CPAN modules:
+
+            $ apt-pm find Moose::Meta::Attribute
+            libmoose-perl_0.98-1_i386: Moose::Meta::Attribute 0.98
+            libmoose-perl_0.54-1_all: Moose::Meta::Attribute 0.54
+            libmoose-perl_0.17-1_all: Moose::Meta::Attribute 0.08
+
+    Look for the non-CPAN modules:
+
+            apt-pm find Purple        
+            # libpurple0_2.4.3-4lenny5_i386: Purple 0.01
+        
+            apt-pm find Dpkg::Version
+            # dpkg-dev_1.14.28_all: Dpkg::Version 0
+
+METHODS
+  new()
+    Object constructor.
+
+    PROPERTIES
+    sources
+        `isa => 'ArrayRef'' of files that will be read to construct the
+        lookup. By default it is filled with files from
+        /var/cache/apt/apt-pm/.
+
+    cachedir
+        Is the folder where indexes cache files will be stored. Default is
+        /var/cache/apt/apt-pm/deb/.
+
+    repo_type
+        `deb|deb-src'
+
+  find($module_name, [$min_version])
+    Returns hash with Perl versions as key and hash value having Debian
+    version and package name. Example:
+
+            {
+                    '0.94' => {
+                            'version' => '0.94-1',
+                            'package' => 'libmoose-perl'
+                            'arch'    => 'i386'
+                    },
+                    '0.97' => {
+                            'version' => '0.97-1',
+                            'package' => 'libmoose-perl'
+                            'arch'    => 'i386'
+                    },
+                    '0.54' => {
+                            'version' => '0.54-1',
+                            'package' => 'libmoose-perl'
+                            'arch'    => 'i386'
+                    },
+            };
+
+    If `$min_version' is set, returns `min' and `max' keys. `max' has always
+    the highest version:
+
+            'max' => {
+                    'version' => '0.97-1',
+                    'package' => 'libmoose-perl'
+                    'arch'    => 'i386'
+            },
+
+    `min' is changing depending on `$min_version'. Examples:
+
+            $min_version = '0.01';
+            'min' => {
+                    'version' => '0.54-1',
+                    'package' => 'libmoose-perl'
+                    'arch'    => 'i386'
+            },
+            $min_version = '0.93';
+            'min' => {
+                    'version' => '0.94-1',
+                    'package' => 'libmoose-perl'
+                    'arch'    => 'i386'
+            },
+            $min_version = '1.00';
+            'min' => undef,
+
+  update
+    Scans the /etc/apt/sources.list and /etc/apt/sources.list.d/*.list
+    repositories for PerlPackages.bz2 and prepares them to be used for find.
+    All PerlPackages.bz2 are stored to /var/cache/apt/apt-pm/.
+
+  clean
+    Remove all files fom cache dir.
+
+AUTHOR
+    jozef at kutej.net, `<jkutej at cpan.org>'
+
+LICENSE AND COPYRIGHT
+    This program is free software; you can redistribute it and/or modify it
+    under the terms of either: the GNU General Public License as published
+    by the Free Software Foundation; or the Artistic License.
+
+    See http://dev.perl.org/licenses/ for more information.
+

Added: lib/Apt/PM.pm
URL: http://svn.debian.org/wsvn/lib/Apt/PM.pm?rev=54159&op=file
==============================================================================
--- lib/Apt/PM.pm (added)
+++ lib/Apt/PM.pm Fri Mar 12 10:59:46 2010
@@ -1,0 +1,430 @@
+package Apt::PM;
+
+=head1 NAME
+
+Apt::PM - locate Perl Modules in Debian repositories
+
+=head1 SYNOPSIS
+
+Cmd-line:
+
+	apt-pm update
+	apt-pm find Moose
+	
+	# print out all dependencies of an unpacked distribution that are packaged for Debian
+	perl -MApt::PM -MModule::Depends -le \
+		'$apm=Apt::PM->new();$md=Module::Depends->new->dist_dir(".")->find_modules; %r=(%{$md->requires},%{$md->build_requires}); while (($m, $v) = each %r) { $f=$apm->find($m, $v); print $f->{"min"}->{"package"} if $f->{"min"}  }' \
+		| sort \
+		| uniq \
+		| xargs echo apt-get install
+	# print out all dependencies of an unpacked distribution that are not packaged for Debian
+	perl -MApt::PM -MModule::Depends -le \
+		'$apm=Apt::PM->new();$md=Module::Depends->new->dist_dir(".")->find_modules; %r=(%{$md->requires},%{$md->build_requires}); while (($m, $v) = each %r) { $f=$apm->find($m, $v); print $m, " ", $v if not $f->{"min"}  }'
+
+
+Module:
+
+	my $aptpm = Apt::PM->new(sources => [ 'PerlPackages.bz2' ])
+	$aptpm->update;
+	my %moose_locations = $aptpm->find('Moose');
+
+=head1 USAGE
+
+=head2 COMMAND-LINE USAGE
+
+Add sources for Debian releases and components. Here is the complete list
+that can be reduced just to the wanted ones:
+
+	cat >> /etc/apt/sources.list << __END__
+	# for apt-pm
+	deb http://pkg-perl.alioth.debian.org/~jozef-guest/pmindex/ etch    main contrib non-free
+	deb http://pkg-perl.alioth.debian.org/~jozef-guest/pmindex/ lenny   main contrib non-free
+	deb http://pkg-perl.alioth.debian.org/~jozef-guest/pmindex/ sid     main contrib non-free
+	deb http://pkg-perl.alioth.debian.org/~jozef-guest/pmindex/ squeeze main contrib non-free
+	__END__
+
+Fetch the indexes:
+
+	apt-pm update
+
+Look for the CPAN modules:
+
+	$ apt-pm find Moose::Meta::Attribute
+	libmoose-perl_0.98-1_i386: Moose::Meta::Attribute 0.98
+	libmoose-perl_0.54-1_all: Moose::Meta::Attribute 0.54
+	libmoose-perl_0.17-1_all: Moose::Meta::Attribute 0.08
+
+Look for the non-CPAN modules:
+	
+	apt-pm find Purple        
+	# libpurple0_2.4.3-4lenny5_i386: Purple 0.01
+	
+	apt-pm find Dpkg::Version
+	# dpkg-dev_1.14.28_all: Dpkg::Version 0
+
+=cut
+
+use warnings;
+use strict;
+
+our $VERSION = '0.01';
+
+use 5.010;
+
+use Moose;
+use IO::Uncompress::Bunzip2 qw(bunzip2 $Bunzip2Error) ;
+use IO::Any;
+use Parse::Deb::Control 0.03;
+use Dpkg::Version 'version_compare';
+use AptPkg::Config '$_config';
+use LWP::Simple 'mirror', 'RC_OK';
+use Carp 'croak';
+use JSON::Util;
+use CPAN::Version;
+use Storable 'dclone';
+use List::MoreUtils 'uniq';
+use File::is;
+use CPAN::Version;
+
+
+
+has 'sources'         => (is => 'rw', isa => 'ArrayRef', lazy => 1, default => sub { [ glob($_[0]->cachedir.'/all.index') ] });
+has '_modules_index'  => (is => 'rw', isa => 'HashRef', lazy => 1, default => sub { $_[0]->_create_modules_index });
+has '_apt_config'     => (is => 'rw', lazy => 1, default => sub { $AptPkg::Config::_config->init; $AptPkg::Config::_config; });
+has 'cachedir'        => (
+	is      => 'rw',
+	lazy    => 1,
+	default => sub {
+		'/var/cache/apt/apt-pm/deb'
+		.($_[0]->repo_type eq 'deb-src' ? '-src' : '' )
+	}
+);
+has 'repo_type'       => (is => 'rw', lazy => 1, default => 'deb');
+
+
+=head1 METHODS
+
+=head2 new()
+
+Object constructor.
+
+=head3 PROPERTIES
+
+=over 4
+
+=item sources
+
+C<< isa => 'ArrayRef' >> of files that will be read to construct the lookup.
+By default it is filled with files from F</var/cache/apt/apt-pm/>.
+
+=item cachedir
+
+Is the folder where indexes cache files will be stored.
+Default is F</var/cache/apt/apt-pm/deb/>.
+
+=item repo_type
+
+C<deb|deb-src>
+
+=back
+
+=head2 find($module_name, [$min_version])
+
+Returns hash with Perl versions as key and hash value having Debian version
+and package name. Example:
+
+	{
+		'0.94' => {
+			'version' => '0.94-1',
+			'package' => 'libmoose-perl'
+			'arch'    => 'i386'
+		},
+		'0.97' => {
+			'version' => '0.97-1',
+			'package' => 'libmoose-perl'
+			'arch'    => 'i386'
+		},
+		'0.54' => {
+			'version' => '0.54-1',
+			'package' => 'libmoose-perl'
+			'arch'    => 'i386'
+		},
+	};
+
+If C<$min_version> is set, returns C<min> and C<max> keys. C<max> has always
+the highest version:
+
+	'max' => {
+		'version' => '0.97-1',
+		'package' => 'libmoose-perl'
+		'arch'    => 'i386'
+	},
+
+C<min> is changing depending on C<$min_version>. Examples:
+
+	$min_version = '0.01';
+	'min' => {
+		'version' => '0.54-1',
+		'package' => 'libmoose-perl'
+		'arch'    => 'i386'
+	},
+	$min_version = '0.93';
+	'min' => {
+		'version' => '0.94-1',
+		'package' => 'libmoose-perl'
+		'arch'    => 'i386'
+	},
+	$min_version = '1.00';
+	'min' => undef,
+
+=cut
+
+sub find {
+	my $self        = shift;
+	my $module      = shift;
+	my $min_version = shift;
+	
+	my $versions_info = $self->_modules_index()->{$module};
+	return if not $versions_info;
+	
+	# clone the info
+	$versions_info = dclone($versions_info);
+	
+	# if not min then we are done
+	return $versions_info
+		if not defined $min_version;
+
+	# sort available versions and grep smaller than requested
+	my @versions =
+		sort { CPAN::Version->vcmp($a, $b) }
+		keys %{$versions_info}
+	;
+
+	$versions_info->{'max'} = $versions_info->{$versions[-1]};
+	@versions = grep { not CPAN::Version->vlt($_, $min_version) } @versions;
+	$versions_info->{'min'} = (@versions ? $versions_info->{$versions[0]} : undef);
+	
+	return $versions_info;
+}
+
+=head2 update
+
+Scans the F</etc/apt/sources.list> and F</etc/apt/sources.list.d/*.list>
+repositories for F<PerlPackages.bz2> and prepares them to be used for find.
+All F<PerlPackages.bz2> are stored to F</var/cache/apt/apt-pm/>.
+
+=cut
+
+sub update {
+	my $self = shift;
+	
+	my @existing = glob($self->cachedir.'/*.bz2');
+	foreach my $url ($self->_etc_apt_sources) {
+		my $filename = $url;
+		$filename =~ s/[^a-zA-Z0-9\-\.]/_/gxms;
+		$filename = $self->cachedir.'/'.$filename;
+		@existing = grep { $_ ne $filename } @existing;
+		if (mirror($url, $filename) == RC_OK) {
+			my $json_filename = $filename; $json_filename =~ s/\.bz2$/.json/;
+			my $content;
+			my $bz_content = IO::Any->slurp($filename);
+			bunzip2 \$bz_content => \$content or die "bunzip2 failed: $Bunzip2Error\n";
+			JSON::Util->encode([$self->_parse_perlpackages_content($content)], $json_filename);
+		}
+	}
+	
+	# remove no longer wanted indexes
+	foreach my $old_filename (@existing) {
+		my $json_filename = $old_filename; $json_filename =~ s/\.bz2$/.json/;
+		unlink($old_filename, $json_filename);
+	}
+
+	my $index_filename = File::Spec->catfile($self->cachedir, 'all.index');
+	my $aptpm = Apt::PM->new(
+		cachedir => $self->cachedir,
+		sources  => [ glob($self->cachedir.'/*.json') ],
+	);
+	JSON::Util->encode($aptpm->_create_modules_index, [$index_filename])
+		if (not -f $index_filename) or File::is->older($index_filename, glob($self->cachedir.'/*.json'));
+}
+
+=head2 clean
+
+Remove all files fom cache dir.
+
+=cut
+
+sub clean {
+	my $self = shift;
+	
+	foreach my $filename (glob($self->cachedir.'/*')) {
+		unlink($filename) or warn 'failed to remove '.$filename."\n";
+	}
+}
+
+sub _etc_apt_sources {
+	my $self = shift;
+	
+	my $repo_type = $self->repo_type;
+	$repo_type = 'deb'
+		if ($repo_type ne 'deb-src');
+
+	my $apt_config = $self->_apt_config;
+	my @sources_files = (
+		$self->_apt_config->get_file('Dir::Etc::sourcelist'),
+		glob( $self->_apt_config->get_dir('Dir::Etc::sourceparts') . '/*.list' ),
+    );
+    
+    my $sources_text = join(
+    	"\n",
+    	map {
+			eval { IO::Any->slurp($_) }
+		} @sources_files
+    );
+
+	my $arch = $apt_config->get('APT::Architecture');
+	my @urls;
+	foreach my $line (split("\n", $sources_text)) {
+		given ($line) {
+			when (/^\s*$/) {};          # skip empty lines
+			when (/^\s*#/) {};          # skip comments
+			when (/^ \s* $repo_type \s+ ([^ ]+) \s+ ([^ ]+) (?: \s+ (.+) | \/ \s*) $/xms) {
+				my ($url, $path, $components_string) = ($1, $2, $3);
+				my @components = grep { $_ } split(/\s+/, $components_string || '');
+				
+				if ($url !~ m{^(:? http:// | ftp:// | file://)}xms) {
+					warn 'unsupported schema - '.$url;
+					next;
+				}
+				
+				if (@components) {
+					push @urls, map {
+						$url.'dists/'.$path.'/'.$_.'/binary-'.$arch.'/PerlPackages.bz2'
+					} @components;
+				}
+				else {
+					push @urls, $url.$path.'/PerlPackages.bz2';
+				}
+			};
+			when (/^ \s* (?: deb | deb-src ) \s /xms) {}; # skip !$repo_type
+			default { warn 'unknown sources.list line - '.$line };
+		}
+	}
+	
+	return uniq @urls;
+}
+
+sub _parse_perlpackages_content {
+	my $self    = shift;
+	my $content = shift;
+	
+	my @content_list;
+	my $idx = Parse::Deb::Control->new($content);
+	foreach my $entry ($idx->get_keys('Perl-Modules')) {
+		my %modules = _parse_perl_modules($entry->{'para'}->{'Perl-Modules'});
+		
+		my %deb = (
+			'version' => _trim($entry->{'para'}->{'Version'}),
+			'package' => (
+				$self->repo_type eq 'deb-src'
+				? _trim($entry->{'para'}->{'Source'}) || _trim($entry->{'para'}->{'Package'})
+				: _trim($entry->{'para'}->{'Package'})
+			),
+			'arch'    => _trim($entry->{'para'}->{'Architecture'}),
+		);
+		
+		push @content_list, { modules => \%modules, deb => \%deb };
+	}
+	
+	return @content_list;
+}
+
+sub _create_modules_index {
+	my $self = shift;
+	my @sources = @{$self->sources};
+	
+	return {}
+		if not @sources;
+	
+	my %modules_index;
+	foreach my $src (@sources) {
+		my @content_list;
+		given ($src) {
+			when (m/\.bz2$/) {
+				my $content;
+				my $bz_content = IO::Any->slurp($src);
+				bunzip2 \$bz_content => \$content or die "bunzip2 failed: $Bunzip2Error\n";
+				@content_list = $self->_parse_perlpackages_content($content);
+			}
+			when (m/all\.index$/) {
+				return eval { JSON::Util->decode([$src]) } || {};
+			}
+			when (m/\.json$/) {
+				@content_list = @{JSON::Util->decode([$src])};
+			}
+			default { @content_list = $self->_parse_perlpackages_content(IO::Any->slurp($src)); }
+		}
+		
+		foreach my $entry (@content_list) {
+			my %modules = %{$entry->{'modules'}};
+			my %deb     = %{$entry->{'deb'}};
+			while (my ($module_name, $version) = each %modules) {
+				# resolve conflicts when two packages has the module with the same version
+				if (exists $modules_index{$module_name}->{$version}) {
+					my $old_version = $modules_index{$module_name}->{$version}->{'version'};
+					my $new_version = $entry->{'deb'}->{'version'};
+					
+					# will not overwrite if the current package has older Debian version
+					next
+						if version_compare($old_version, $new_version) == -1;
+				}
+					
+				$modules_index{$module_name}->{$version} =\%deb;
+			}
+		}
+	}
+	
+	return \%modules_index;
+}
+
+sub _parse_perl_modules {
+	my $text = shift || '';
+	
+	return
+		map  { m/^(.+)\s+ \( \s* ([^\(]+) \s* \)/xms ? ( $1 => $2 ) : () }
+		grep { $_ }                       # remove empty lines
+		map { s/^\s*//; s/\s*$//; $_ }    # trim
+		split("\n", $text)                # split on new lines
+	;
+}
+
+sub _trim {
+	my $text = shift;
+	croak 'too much argauments' if @_;
+	
+	return if not defined $text;
+	
+	$text =~ s/^\s+//xms;
+	$text =~ s/\s+$//xms;
+	
+	return $text;
+}
+
+1;
+
+
+__END__
+
+=head1 AUTHOR
+
+jozef at kutej.net, C<< <jkutej at cpan.org> >>
+
+=head1 LICENSE AND COPYRIGHT
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of either: the GNU General Public License as published
+by the Free Software Foundation; or the Artistic License.
+
+See http://dev.perl.org/licenses/ for more information.
+
+=cut

Added: script/apt-pm
URL: http://svn.debian.org/wsvn/script/apt-pm?rev=54159&op=file
==============================================================================
--- script/apt-pm (added)
+++ script/apt-pm Fri Mar 12 10:59:46 2010
@@ -1,0 +1,103 @@
+#!/usr/bin/perl
+
+=head1 NAME
+
+apt-pm - locate Perl Modules in Debian repositories
+
+=head1 SYNOPSIS
+
+	apt-pm search Moose::Meta::Role
+	apt-pm update
+	apt-pm clean
+	
+options:
+
+	--sources
+		comman separated list of index files to use for search/find
+	--deb-src
+		search in source repositories
+
+=head1 DESCRIPTION
+
+Lookup Perl package in Debian .deb files.
+
+=cut
+
+
+use strict;
+use warnings;
+
+use Getopt::Long;
+use Pod::Usage;
+use Apt::PM 0.01;
+use List::MoreUtils 'none';
+
+exit main();
+
+sub main {
+	my $help;
+	my $sources;
+	my $search_src = 0;
+	GetOptions(
+		'help|h'      => \$help,
+		'sources|s=s' => \$sources,
+		'deb-src'     => \$search_src,
+	) or pod2usage;
+	pod2usage if $help;
+	
+	# the switch makes no sence when sources explicitely set
+	$search_src = 0
+		if $sources;
+	
+	my $cmd     = shift @ARGV;
+	my $package = shift @ARGV;
+	pod2usage if not $cmd;
+	pod2usage if none { $_ eq $cmd } qw(search find update clean);
+	
+	my $aptpm     = Apt::PM->new();
+	my $aptpm_src = Apt::PM->new(repo_type => 'deb-src');
+	$aptpm->sources([split(',', $sources)])
+		if ($sources);
+	
+	# get provides from dbedia.com
+	if ($cmd eq 'update') {
+		$aptpm->update();
+		$aptpm_src->update()
+			if not $sources;
+	}
+	
+	if ($cmd eq 'clean') {
+		$aptpm->clean();
+		$aptpm_src->clean()
+			if not $sources;
+	}
+
+	$aptpm = $aptpm_src
+		if ($search_src);
+	
+	# lookup the package
+	if (($cmd eq 'search') or ($cmd eq 'find')) {
+		pod2usage if not $package;
+		
+		# get provides hash with packages
+		my $version_info = $aptpm->find($package);
+		
+		# nothing to do if the package is not there
+		return 0 if not $version_info;
+		
+		# print all available versions
+		foreach my $version (keys %{$version_info}) {
+			print $version_info->{$version}->{'package'}, '_', $version_info->{$version}->{'version'}, '_', $version_info->{$version}->{'arch'}, ': ', $package, ' ', $version, "\n";
+		}
+	}
+	
+	return 0;
+}
+
+__END__
+
+=head1 SEE ALSO
+
+L<Apt::PM>
+
+=cut

Propchange: script/apt-pm
------------------------------------------------------------------------------
    svn:executable = 

Added: t/00_compile.t
URL: http://svn.debian.org/wsvn/t/00_compile.t?rev=54159&op=file
==============================================================================
--- t/00_compile.t (added)
+++ t/00_compile.t Fri Mar 12 10:59:46 2010
@@ -1,0 +1,9 @@
+use strict;
+use Test::More;
+
+eval "use Test::Compile 0.08";
+plan skip_all => "Test::Compile 0.08 required for testing compilation"
+    if $@;
+
+my @pmdirs = qw(lib blib sbin bin);
+all_pm_files_ok(all_pm_files(@pmdirs));

Added: t/01_Apt-PM.t
URL: http://svn.debian.org/wsvn/t/01_Apt-PM.t?rev=54159&op=file
==============================================================================
--- t/01_Apt-PM.t (added)
+++ t/01_Apt-PM.t Fri Mar 12 10:59:46 2010
@@ -1,0 +1,279 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+#use Test::More 'no_plan';
+use Test::More tests => 12;
+use Test::Differences;
+use Test::Exception;
+
+use FindBin qw($Bin);
+use lib "$Bin/lib";
+
+BEGIN {
+	use_ok ( 'Apt::PM' ) or exit;
+}
+
+exit main();
+
+sub main {
+	INTERNAL_parse_perl_modules: {
+		my $t1 = " MM (0.001001)\n";
+		my $t2 = " \n M1 (1)\n M3 (3)\n M2 (2)\n";
+		my $t3 = " \n BackupManager::Dialog (0)\n BackupManager::Config (0)\n BackupManager::Logger (0)\n";
+		
+		is_deeply(
+			{ Apt::PM::_parse_perl_modules($t1) },
+			{ 'MM' => '0.001001' },
+			'parsing Perl-Modules'
+		);
+		
+		is_deeply(
+			{ Apt::PM::_parse_perl_modules($t2) },
+			{
+				'M1' => '1',
+				'M2' => '2',
+				'M3' => '3',
+			},
+			'parsing Perl-Modules'
+		);
+
+		is_deeply(
+			{ Apt::PM::_parse_perl_modules($t3) },
+			{
+				'BackupManager::Dialog' => '0',
+				'BackupManager::Config' => '0',
+				'BackupManager::Logger' => '0',
+			},
+			'parsing Perl-Modules'
+		);
+	}
+	
+	INTERNAL_modules_index: {
+		my $aptpm = Apt::PM->new(sources => [ File::Spec->catfile($Bin, 'PerlPackages.bz2') ]);
+		
+		my %deb1 = (
+			'version' => '5.230-1',
+			'package' => 'libanyevent-perl',
+			'arch'    => 'all',
+		);
+		my %deb2 = (
+			'version' => '0.21-1',
+			'package' => 'libclass-c3-perl',
+			'arch'    => 'all',
+		);
+
+		eq_or_diff(
+			$aptpm->_modules_index,
+			{
+				'Class::C3' => { '0.21' => \%deb2 },
+				'AnyEvent::Impl::EventLib' => { '0' => \%deb1 },
+				'AnyEvent::Strict' => { '0' => \%deb1 },
+				'AnyEvent::CondVar' => { '0' => \%deb1 },
+				'AnyEvent::TLS' => { '0' => \%deb1 },
+				'AnyEvent::Impl::Qt::Io' => { '0' => \%deb1 },
+				'AnyEvent::Impl::Tk' => { '0' => \%deb1 },
+				'AnyEvent::Impl::Irssi' => { '0' => \%deb1 },
+				'AnyEvent::Impl::IOAsync' => { '0' => \%deb1 },
+				'AnyEvent::CondVar::Base' => { '0' => \%deb1 },
+				'AnyEvent::Util' => { '0' => \%deb1 },
+				'AnyEvent::Base' => { '0' => \%deb1 },
+				'AnyEvent::Impl::Qt' => { '0' => \%deb1 },
+				'AnyEvent::Handle' => { '0' => \%deb1 },
+				'AnyEvent::Impl::Perl' => { '0' => \%deb1 },
+				'AnyEvent' => { '5.23' => \%deb1 },
+				'AnyEvent::DNS' => { '0' => \%deb1 },
+				'AnyEvent::Impl::Qt::Timer' => { '0' => \%deb1 },
+				'AnyEvent::Impl::EV' => { '0' => \%deb1 },
+				'AnyEvent::Debug::shell' => { '0' => \%deb1 },
+				'AnyEvent::Debug' => { '0' => \%deb1 },
+				'AnyEvent::Impl::POE' => { '0' => \%deb1 },
+				'AnyEvent::Impl::Event' => { '0' => \%deb1 },
+				'AE' => { '0' => \%deb1 },
+				'AnyEvent::Socket' => { '0' => \%deb1 },
+				'AnyEvent::Impl::Glib' => { '0' => \%deb1 }
+	        },
+			'building modules index'
+		);
+
+		my $aptpm2 = Apt::PM->new(sources => [
+			File::Spec->catfile($Bin, 'PerlPackages.bz2'),
+			File::Spec->catfile($Bin, 'PerlPackages2.bz2'),
+		]);
+
+		my %deb3 = (
+			'version' => '1.000-1',
+			'package' => 'libanyevent-perl',
+			'arch'    => 'all',
+		);
+		my %deb4 = (
+			'version' => '0.22-1',
+			'package' => 'libclass-c3-perl',
+			'arch'    => 'all',
+		);
+		my %deb5 = (
+			'version' => '4.00-1',
+			'package' => 'libclass-c4-perl',
+			'arch'    => 'all',
+		);
+		my %result2 = (
+			'Class::C3' => {
+				'0.21' => \%deb2,
+				'0.22' => \%deb4,
+			},
+			'AnyEvent::Impl::EventLib' => { '0' => \%deb3 },
+			'AnyEvent::Strict' => { '0' => \%deb3 },
+			'AnyEvent::CondVar' => { '0' => \%deb3 },
+			'AnyEvent::TLS' => { '0' => \%deb3 },
+			'AnyEvent::Impl::Qt::Io' => { '0' => \%deb3 },
+			'AnyEvent::Impl::Tk' => { '0' => \%deb3 },
+			'AnyEvent::Impl::Irssi' => { '0' => \%deb3 },
+			'AnyEvent::Impl::IOAsync' => { '0' => \%deb3 },
+			'AnyEvent::CondVar::Base' => { '0' => \%deb3 },
+			'AnyEvent::Util' => { '0' => \%deb3 },
+			'AnyEvent::Base' => { '0' => \%deb3 },
+			'AnyEvent::Impl::Qt' => { '0' => \%deb3 },
+			'AnyEvent::Handle' => { '0' => \%deb3 },
+			'AnyEvent::Impl::Perl' => { '0' => \%deb3 },
+			'AnyEvent' => {
+				'1.000' => \%deb3,
+				'5.23'  => \%deb1,
+			},
+			'AnyEvent::DNS' => { '0' => \%deb3 },
+			'AnyEvent::Impl::Qt::Timer' => { '0' => \%deb3 },
+			'AnyEvent::Impl::EV' => { '0' => \%deb3 },
+			'AnyEvent::Debug::shell' => { '0' => \%deb3 },
+			'AnyEvent::Debug' => { '0' => \%deb3 },
+			'AnyEvent::Impl::POE' => { '0' => \%deb3 },
+			'AnyEvent::Impl::Event' => { '0' => \%deb3 },
+			'AE' => { '0' => \%deb3 },
+			'AnyEvent::Socket' => { '0' => \%deb3 },
+			'AnyEvent::Impl::Glib' => { '0' => \%deb3 },
+			'Class::C4' => { '4.00' => \%deb5 },
+		);
+
+		eq_or_diff(
+			$aptpm2->_modules_index,
+			\%result2,
+			'building combined modules index'
+		);
+
+		my $aptpm3 = Apt::PM->new(sources => [
+			File::Spec->catfile($Bin, 'PerlPackages2.bz2'),
+			File::Spec->catfile($Bin, 'PerlPackages.bz2'),
+		]);
+		eq_or_diff(
+			$aptpm3->_modules_index,
+			\%result2,
+			'building combiner modules index (reverse input files order)'
+		);
+	}
+	
+	INTERNAL_etc_apt_sources: {
+		my $aptpm = Apt::PM->new();
+		my @web_sources;
+		lives_ok { @web_sources = $aptpm->_etc_apt_sources } 'call parsing of /etc/apt/sources';
+		note('web sources on this machine:', "\n", join("\n", @web_sources));
+	};
+
+	FIND: {
+		my $aptpm = Apt::PM->new(sources => [
+			File::Spec->catfile($Bin, 'PerlPackages.bz2'),
+			File::Spec->catfile($Bin, 'PerlPackages2.bz2'),
+		]);
+		
+		eq_or_diff(
+			$aptpm->find('AnyEvent'), {
+				'1.000' => {
+					arch => 'all',
+					package => 'libanyevent-perl',
+					version => '1.000-1'
+				},
+				'5.23' => {
+					arch => 'all',
+					package => 'libanyevent-perl',
+					version => '5.230-1',
+				}
+			},
+			'find()',
+		);
+
+		eq_or_diff(
+			$aptpm->find('AnyEvent', '0.01'), {
+				'1.000' => {
+					arch => 'all',
+					package => 'libanyevent-perl',
+					version => '1.000-1'
+				},
+				'min' => {
+					arch => 'all',
+					package => 'libanyevent-perl',
+					version => '1.000-1'
+				},
+				'5.23' => {
+					arch => 'all',
+					package => 'libanyevent-perl',
+					version => '5.230-1',
+				},
+				'max' => {
+					arch => 'all',
+					package => 'libanyevent-perl',
+					version => '5.230-1',
+				},
+			},
+			'find(min 0.01)',
+		);
+
+		eq_or_diff(
+			$aptpm->find('AnyEvent', '1.50'), {
+				'1.000' => {
+					arch => 'all',
+					package => 'libanyevent-perl',
+					version => '1.000-1'
+				},
+				'min' => {
+					arch => 'all',
+					package => 'libanyevent-perl',
+					version => '5.230-1',
+				},
+				'5.23' => {
+					arch => 'all',
+					package => 'libanyevent-perl',
+					version => '5.230-1',
+				},
+				'max' => {
+					arch => 'all',
+					package => 'libanyevent-perl',
+					version => '5.230-1',
+				},
+			},
+			'find(min 1.50)',
+		);
+
+		eq_or_diff(
+			$aptpm->find('AnyEvent', '5.3'), {
+				'1.000' => {
+					arch => 'all',
+					package => 'libanyevent-perl',
+					version => '1.000-1'
+				},
+				'5.23' => {
+					arch => 'all',
+					package => 'libanyevent-perl',
+					version => '5.230-1',
+				},
+				'max' => {
+					arch => 'all',
+					package => 'libanyevent-perl',
+					version => '5.230-1',
+				},
+				'min' => undef,
+			},
+			'find(min 5.3)',
+		);
+	}
+	
+	return 0;
+}
+

Added: t/PerlPackages.bz2
URL: http://svn.debian.org/wsvn/t/PerlPackages.bz2?rev=54159&op=file
==============================================================================
Binary file - no diff available.

Propchange: t/PerlPackages.bz2
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: t/PerlPackages2.bz2
URL: http://svn.debian.org/wsvn/t/PerlPackages2.bz2?rev=54159&op=file
==============================================================================
Binary file - no diff available.

Propchange: t/PerlPackages2.bz2
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: t/distribution.t
URL: http://svn.debian.org/wsvn/t/distribution.t?rev=54159&op=file
==============================================================================
--- t/distribution.t (added)
+++ t/distribution.t Fri Mar 12 10:59:46 2010
@@ -1,0 +1,4 @@
+use Test::More;
+
+eval 'use Test::Distribution not => "sig"';
+plan( skip_all => 'Test::Distribution not installed') if $@;

Added: t/fixme.t
URL: http://svn.debian.org/wsvn/t/fixme.t?rev=54159&op=file
==============================================================================
--- t/fixme.t (added)
+++ t/fixme.t Fri Mar 12 10:59:46 2010
@@ -1,0 +1,9 @@
+use strict;
+use warnings;
+use Test::More;
+
+eval "use Test::Fixme";
+plan skip_all => "requires Test::Fixme to run"
+    if $@;
+
+run_tests();

Added: t/pod-coverage.t
URL: http://svn.debian.org/wsvn/t/pod-coverage.t?rev=54159&op=file
==============================================================================
--- t/pod-coverage.t (added)
+++ t/pod-coverage.t Fri Mar 12 10:59:46 2010
@@ -1,0 +1,18 @@
+use strict;
+use warnings;
+use Test::More;
+
+# Ensure a recent version of Test::Pod::Coverage
+my $min_tpc = 1.08;
+eval "use Test::Pod::Coverage $min_tpc";
+plan skip_all => "Test::Pod::Coverage $min_tpc required for testing POD coverage"
+    if $@;
+
+# Test::Pod::Coverage doesn't require a minimum Pod::Coverage version,
+# but older versions don't recognize some common documentation styles
+my $min_pc = 0.18;
+eval "use Pod::Coverage $min_pc";
+plan skip_all => "Pod::Coverage $min_pc required for testing POD coverage"
+    if $@;
+
+all_pod_coverage_ok();

Added: t/pod-spell.t
URL: http://svn.debian.org/wsvn/t/pod-spell.t?rev=54159&op=file
==============================================================================
--- t/pod-spell.t (added)
+++ t/pod-spell.t Fri Mar 12 10:59:46 2010
@@ -1,0 +1,25 @@
+use Test::More;
+
+if (!$ENV{TEST_SPELLING}) {
+    plan skip_all => 
+      "Set the environment variable TEST_SPELLING to enable this test.";
+}
+
+eval 'use Test::Spelling;';
+
+plan skip_all => "Test::Spelling required for testing POD spelling"
+    if $@;
+
+add_stopwords(qw(
+	Jozef Kutej
+	OFC
+	API
+	JSON
+	TBD
+	html
+	RT
+	CPAN
+	AnnoCPAN
+	http
+));
+all_pod_files_spelling_ok();

Added: t/pod.t
URL: http://svn.debian.org/wsvn/t/pod.t?rev=54159&op=file
==============================================================================
--- t/pod.t (added)
+++ t/pod.t Fri Mar 12 10:59:46 2010
@@ -1,0 +1,12 @@
+#!perl -T
+
+use strict;
+use warnings;
+use Test::More;
+
+# Ensure a recent version of Test::Pod
+my $min_tp = 1.22;
+eval "use Test::Pod $min_tp";
+plan skip_all => "Test::Pod $min_tp required for testing POD" if $@;
+
+all_pod_files_ok();




More information about the Pkg-perl-cvs-commits mailing list