#!/usr/bin/perl
use strict;
use warnings;
use File::Glob qw(bsd_glob);
# Initialise variables {{{1
my $REPO_LIST = '/etc/hildon-application-manager/catalogues';
my $DPKG_LIST = '/var/lib/dpkg/status';
my $APT_SRC = '/var/lib/apt/lists';
my $APT_LIST = '/etc/apt/sources.list.d/hildon-application-manager.list';
my %repo_urls = (
'Ovi' => 'downloads.maemo.nokia.com_fremantle_ovi',
'Nokia Applications' => 'downloads.maemo.nokia.com_fremantle_ssu_apps',
'maemo.org' => 'repository.maemo.org_extras',
);
my %priorities = (
'maemo.org' => 1,
'repository.maemo.org_extras-testing' => 2,
'repository.maemo.org_extras-devel' => 3,
);
my %repo_pkgs;
# Read in (optional) parameter {{{1
my $list_repo = shift;
# Main processing {{{1
read_repos();
if ( defined $list_repo ) {
$list_repo = find_repo($list_repo);
exit 1 if ( not defined $list_repo );
repo_packages($list_repo);
} else {
foreach my $repo ( keys %repo_urls ) {
next if ( $repo_urls{$repo} eq 'Disabled' );
repo_packages($repo);
}
}
output_packages();
# Read in the repository names and locations {{{1
sub read_repos { #{{{2
my $in_repo = 0;
my ($name, $uri);
add_ssu_repo();
open my $infile, '<', $REPO_LIST || die;
while ( my $line = <$infile> ) {
$line =~ s/[\r\n]+\z//smx;
if ( $line =~ m{\A\s*}smx ) {
$in_repo = 1;
} elsif ( $line =~ m{\A\s*}smx ) {
$in_repo = 0;
next if ( not defined $name );
next if ( not defined $uri );
$uri =~ s{/}{_}gsmx;
$repo_urls{$name} = $uri;
if ( exists $priorities{$uri} ) {
$priorities{$name} = $priorities{$uri};
delete $priorities{$uri};
}
} elsif ( not $in_repo ) {
next;
} elsif ( $line =~ m{\A\s*https?://(.*?)/?}smx ) {
$uri = $1;
} elsif ( $line =~ m{\A\s*(.*?)}smx ) {
$name = $1;
} elsif ( $line =~ m{\A\s*}smx ) {
$uri = 'Disabled';
}
}
close $infile;
return;
}
sub add_ssu_repo { #{{{2
open my $aptfile, '<', $APT_LIST || die;
while ( my $line = <$aptfile> ) {
$line =~ s/[\r\n]+\z//smx;
if ( $line =~ m{\Adeb\s+https://downloads.maemo.nokia.com/fremantle/ssu/(\S+)}smx ) {
my $var = $1;
next if ( $var =~ /\Aapps/smx );
$repo_urls{'Nokia System Software Updates'} = "downloads.maemo.nokia.com_fremantle_ssu_$var";
last;
}
}
close $aptfile;
return;
}
# Read in the list of applications in a repository {{{1
sub repo_packages {
my $repo_name = shift;
my $repo_url = $repo_urls{$repo_name};
foreach my $file ( bsd_glob("${APT_SRC}/${repo_url}_*Packages") ) {
my ( $pkg, $ver );
open my $infile, '<', $file || die;
while ( my $line = <$infile> ) {
$line =~ s/[\r\n]+\z//smx;
if ( $line =~ /\APackage:\s+(.*)/smx ) {
$pkg = lc $1;
} elsif ( $line =~ /\AVersion:\s+(.*)/smx ) {
$ver = format_version($1);
$repo_pkgs{$pkg}{$repo_name}{$ver}++;
}
}
close $infile;
}
return;
}
# Read through installed applications and output which repository for each {{{1
sub output_packages { #{{{2
my ( $pkg, $ver, $name, $status );
open my $infile, '<', $DPKG_LIST || die;
while ( my $line = <$infile> ) {
$line =~ s/[\r\n]+\z//smx;
if ( $line =~ /\APackage:\s+(.*)/smx ) {
my $new_pkg = $1;
if ( ( defined $pkg ) and ( defined $status ) ) {
process_pkg( $pkg, $ver, $name );
}
$pkg = $new_pkg;
$ver = undef;
$status = undef;
$name = undef;
next if ( $pkg =~ /l10n/smx );
}
next if ( not defined $pkg );
if ( $line =~ /\AStatus:\s+(.*)/smx ) {
$status = $1;
if ( $status ne "install ok installed" ) {
$pkg = undef;
}
} elsif ( $line =~ /\AVersion:\s+(.*)/smx ) {
$ver = format_version($1);
} elsif ( $line =~ /\AMaemo-Display-Name:\s+(.*)/smx ) {
$name = $1;
}
}
close $infile;
if ( ( defined $pkg ) and ( defined $status ) ) {
process_pkg( $pkg, $ver, $name );
}
return;
}
sub process_pkg { #{{{2
my ( $pkg, $ver, $name ) = @_;
if ( ( not defined $list_repo ) and ( not defined $repo_pkgs{$pkg} ) ) {
if ( ( defined $name ) and ( $name ne $pkg ) ) {
$pkg .= " ($name)";
}
print {*STDOUT} "Unknown\t$pkg\n";
return;
}
my $seen_ver = 0;
if ( defined $list_repo ) {
$seen_ver = 1;
} else {
while ( my ($repo_name, $repo_vers) = each %{$repo_pkgs{$pkg}} ) {
next if ( not exists $repo_vers->{$ver} );
$seen_ver = 1;
}
}
while ( my ($repo_name, $repo_vers) = each %{$repo_pkgs{$pkg}} ) {
next if ( ( $seen_ver == 1 ) and ( not exists $repo_vers->{$ver} ) );
next if ( not check_priority( $pkg, $ver, $repo_name ) );
if ( not $seen_ver ) {
foreach my $repo_ver ( keys %{$repo_vers} ) {
print_package( $pkg, $repo_ver, $name, $repo_name );
}
} else {
print_package( $pkg, undef, $name, $repo_name );
}
}
return;
}
sub print_package { #{{{2
my ( $pkg, $ver, $name, $repo_name ) = @_;
if ( ( defined $name ) and ( $name ne $pkg ) ) {
$pkg .= " ($name)";
}
if ( defined $ver ) {
$pkg .= " (Version: $ver)";
}
if ( defined $list_repo ) {
print {*STDOUT} "$pkg\n";
} else {
print {*STDOUT} "$repo_name\t$pkg\n";
}
return;
}
sub check_priority { #{{{2
my ( $pkg_name, $pkg_ver, $repo_name ) = @_;
return 1 if ( not exists $priorities{$repo_name} );
my $cur_prio = $priorities{$repo_name};
my $best_prio = 1;
foreach my $repo ( keys %priorities ) {
next if ( $priorities{$repo} >= $cur_prio );
next if ( not exists $repo_pkgs{$pkg_name}{$repo} );
next if ( not exists $repo_pkgs{$pkg_name}{$repo}{$pkg_ver} );
$best_prio = 0;
}
return $best_prio;
}
# Utility_functions {{{1
sub format_version { #{{{2
my $version = shift;
if ( $version !~ /\A\d+:/ ) {
$version = '0:' . $version;
}
return $version;
}
sub basename { #{{{2
my ( $filename, $extension ) = @_;
if ( $filename =~ m{/([^/]+)\z}smx ) {
$filename = $1;
}
if ( defined $extension ) {
$filename =~ s/\Q$extension\E\z//smx;
}
return $filename;
}
sub find_repo { #{{{2
my $repo_name = shift;
if ( defined $repo_urls{$repo_name} ) {
return $repo_name;
}
foreach my $repo ( keys %repo_urls ) {
next if ( uc $repo_name ne uc $repo );
if ( $repo_urls{$repo} eq 'Disabled' ) {
print {*STDOUT} "Unable to process - repository is disabled\n";
return;
}
return $repo;
}
list_repos($repo_name);
return;
}
sub list_repos { #{{{2
my $repo_name = shift;
my $disabled = 0;
print {*STDOUT} "Unable to find requested repository: $repo_name\n";
print {*STDOUT} "Available repositories are:\n";
foreach my $repo (keys %repo_urls) {
if ( $repo_urls{$repo} eq 'Disabled' ) {
$disabled = 1;
next;
}
print {*STDOUT} "\t$repo\n";
}
if ( $disabled ) {
print {*STDOUT} "Disabled repositories are:\n";
foreach my $repo (keys %repo_urls) {
next if ( $repo_urls{$repo} ne 'Disabled' );
print {*STDOUT} "\t$repo\n";
}
}
return;
}
# vim: foldmethod=marker ts=2