Fix detection of pinned versions on APT, complete manual updates check
authorJamie Cameron <jcameron@webmin.com>
Tue, 5 Jan 2010 01:09:09 +0000 (17:09 -0800)
committerJamie Cameron <jcameron@webmin.com>
Tue, 5 Jan 2010 01:09:09 +0000 (17:09 -0800)
package-updates/package-updates-lib.pl
software/apt-lib.pl

index 5e2061d..327fef6 100644 (file)
@@ -85,9 +85,6 @@ if ($nocache || $expired == 2 ||
                push(@rv, $avail);
                }
 
-       # Set pinned versions
-       &set_pinned_versions(\@rv);
-
        # Filter out dupes and sort by name
        @rv = &filter_duplicates(\@rv);
 
@@ -487,63 +484,6 @@ elsif ($software::update_system eq "apt") {
        }
 }
 
-# set_pinned_versions(&packages)
-# If on Debian, set available package versions based on APT pinning
-sub set_pinned_versions
-{
-my ($avail) = @_;
-my @davail = grep { $_->{'system'} eq 'apt' } @$avail;
-return 0 if (!@davail);
-my %namemap = map { $_->{'name'}, $_ } @davail;
-my $rv;
-if (&has_command("apt-show-versions")) {
-       # Use apt-show-versions to find possible upgrades, including backports
-       # and pinned versions.
-       my $out = &backquote_command(
-                       "LANG='' LC_ALL='' apt-show-versions 2>/dev/null");
-       foreach my $l (split(/\r?\n/, $out)) {
-               if ($l =~ /^(\S+)\/\S+\s+upgradeable\s+from\s+(\S+)\s+to\s+(\S+)/) {
-                       # Possible upgrade shown .. apply new version to
-                       # avail object
-                       my ($name, $oldver, $newver) = ($1, $2, $3);
-                       my $pkg = $namemap{$name};
-                       if ($pkg) {
-                               ($pkg->{'epoch'}, $pkg->{'version'}) =
-                                       &split_epoch($newver);
-                               $rv++;
-                               }
-                       }
-               elsif ($l =~ /^(\S+)\/\S+\s+uptodate\s+(\S+)/) {
-                       # Package shown to be up to date
-                       my ($name, $newver) = ($1, $2);
-                       my $pkg = $namemap{$name};
-                       if ($pkg) {
-                               ($pkg->{'epoch'}, $pkg->{'version'}) =
-                                       &split_epoch($newver);
-                               $rv++;
-                               }
-                       }
-               }
-       }
-if (&has_command("apt-cache")) {
-       # Use apt-cache to see pinned versions. This excludes backports though.
-       my $out = &backquote_command(
-                       "LANG='' LC_ALL='' apt-cache policy 2>/dev/null");
-       foreach my $l (split(/\r?\n/, $out)) {
-               if ($l =~ /\s+(\S+)\s+\-\>\s+(\S+)/) {
-                       my ($name, $pin) = ($1, $2);
-                       my $pkg = $namemap{$name};
-                       if ($pkg) {
-                               ($pkg->{'epoch'}, $pkg->{'version'}) =
-                                       &split_epoch($ver);
-                               $rv++;
-                               }
-                       }
-               }
-       }
-return $rv;
-}
-
 # split_epoch(version)
 # Splits a version formatted like 5:x.yy into an epoch and real version
 sub split_epoch
index 0722467..87238ee 100755 (executable)
@@ -167,6 +167,7 @@ foreach my $s (&update_system_search('.*')) {
                }
        }
 
+&set_pinned_versions(\@rv);
 return @rv;
 }
 
@@ -194,7 +195,8 @@ return @rv;
 sub update_system_updates
 {
 if (&has_command("apt-show-versions")) {
-       # This awesome command can give us all updates in one hit
+       # This awesome command can give us all updates in one hit, and takes
+       # pinned versions and backports into account
        local @rv;
        &open_execute_command(PKGS,
                "LANG='' LC_ALL='' apt-show-versions", 1, 1);
@@ -213,7 +215,7 @@ if (&has_command("apt-show-versions")) {
        return @rv;
        }
 else {
-       # Need to manually compose by calling dpkg and apt-cache showpkg ..
+       # Need to manually compose by calling dpkg and apt-cache showpkg
        local %packages;
        local $n = &list_packages();
        local %currentmap;
@@ -257,12 +259,45 @@ else {
                                        }
                                $pkg->{'version'} = $ver;
                                $pkg->{'epoch'} = $epoch;
-                               push(@rv, $pkg);
+                               local $newer =
+                                   $pkg->{'epoch'} <=> $pkg->{'oldepoch'} ||
+                                   &compare_versions($pkg->{'version'},
+                                                     $pkg->{'oldversion'});
+                               if ($newer > 0) {
+                                       push(@rv, $pkg);
+                                       }
                                }
                        }
                close(PKGS);
                }
+       &set_pinned_versions(\@rv);
        return @rv;
        }
 }
 
+# set_pinned_versions(&package-list)
+# Updates the version and epoch fields in a list of available packages based
+# on pinning.
+sub set_pinned_versions
+{
+local ($pkgs) = @_;
+local %pkgmap = map { $_->{'name'}, $_ } @$pkgs;
+&open_execute_command(PKGS,
+       "LANG='' LC_ALL='' apt-cache policy", 1, 1);
+while(<PKGS>) { 
+       s/\r|\n//g;
+       if (/\s+(\S+)\s+\-\>\s+(\S+)/) {
+               my ($name, $pin) = ($1, $2);
+               my $pkg = $pkgmap{$name};
+               if ($pkg) {
+                       $pkg->{'version'} = $pin;
+                       $pkg->{'epoch'} = undef;
+                       if ($pkg->{'version'} =~ s/^(\S+)://) {
+                               $pkg->{'epoch'} = $1;
+                               }
+                       }
+               }
+       }
+close(PKGS);
+}
+