Implement and use new more efficient function on YUM systems for getting
authorJamie Cameron <jcameron@webmin.com>
Mon, 4 Jan 2010 22:47:42 +0000 (14:47 -0800)
committerJamie Cameron <jcameron@webmin.com>
Mon, 4 Jan 2010 22:47:42 +0000 (14:47 -0800)
package updates.

package-updates/package-updates-lib.pl
software/CHANGELOG
software/yum-lib.pl

index df46096..978916e 100644 (file)
@@ -11,6 +11,7 @@ use Data::Dumper;
 
 $available_cache_file = "$module_config_directory/available.cache";
 $current_cache_file = "$module_config_directory/current.cache";
+$updates_cache_file = "$module_config_directory/updates.cache";
 $cron_cmd = "$module_config_directory/update.pl";
 
 $yum_cache_file = "$module_config_directory/yumcache";
@@ -246,6 +247,37 @@ if (defined(&software::update_system_available)) {
 return ( );
 }
 
+sub supports_updates_available
+{
+return defined(&software::update_system_updates);
+}
+
+# updates_available(no-cache)
+# Returns an array of hash refs of package updates available, according to
+# the update system, with caching.
+sub updates_available
+{
+my ($nocache) = @_;
+if (!defined(@updates_available_cache)) {
+       if ($nocache || &cache_expired($updates_cache_file)) {
+               # Get from original source
+               @updates_available_cache = &software::update_system_updates();
+               foreach my $a (@updates_available_cache) {
+                       $a->{'update'} = $a->{'name'};
+                       $a->{'system'} = $software::update_system;
+                       }
+               &write_cache_file($updates_cache_file,
+                                 \@updates_available_cache);
+               }
+       else {
+               # Use on-disk cache
+               @updates_available_cache =
+                       &read_cache_file($updates_cache_file);
+               }
+       }
+return @updates_available_cache;
+}
+
 # package_install(package, [system])
 # Install some package, either from an update system or from Webmin. Returns
 # a list of updated package names.
@@ -314,28 +346,52 @@ sub list_possible_updates
 my ($nocache) = @_;
 my @rv;
 my @current = &list_current($nocache);
-my @avail = &list_available($nocache == 1);
-my %availmap;
-foreach my $a (@avail) {
-       my $oa = $availmap{$a->{'name'},$a->{'system'}};
-       if (!$oa || &compare_versions($a, $oa) > 0) {
-               $availmap{$a->{'name'},$a->{'system'}} = $a;
+if (&supports_updates_available()) {
+       my %currentmap;
+       foreach my $c (@current) {
+               $currentmap{$c->{'name'},$c->{'system'}} ||= $c;
                }
-       }
-foreach my $c (sort { $a->{'name'} cmp $b->{'name'} } @current) {
-       # Work out the status
-       my $a = $availmap{$c->{'name'},$c->{'system'}};
-       if ($a->{'version'} && &compare_versions($a, $c) > 0) {
-               # A regular update is available
+       foreach my $a (&updates_available($nocache == 1)) {
+               my $c = $currentmap{$a->{'name'},$a->{'system'}};
+               next if (!$c);
+               next if ($a->{'version'} eq $c->{'version'});
                push(@rv, { 'name' => $a->{'name'},
                            'update' => $a->{'update'},
                            'system' => $a->{'system'},
                            'version' => $a->{'version'},
                            'oldversion' => $c->{'version'},
                            'epoch' => $a->{'epoch'},
+                           'oldepoch' => $c->{'epoch'},
                            'security' => $a->{'security'},
-                           'desc' => $c->{'desc'} || $a->{'desc'},
-                           'severity' => 0 });
+                           'desc' => $c->{'desc'} || $a->{'desc'} });
+               }
+       }
+else {
+       # Compute from current and available list
+       my @avail = &list_available($nocache == 1);
+       my %availmap;
+       foreach my $a (@avail) {
+               my $oa = $availmap{$a->{'name'},$a->{'system'}};
+               if (!$oa || &compare_versions($a, $oa) > 0) {
+                       $availmap{$a->{'name'},$a->{'system'}} = $a;
+                       }
+               }
+       foreach my $c (sort { $a->{'name'} cmp $b->{'name'} } @current) {
+               # Work out the status
+               my $a = $availmap{$c->{'name'},$c->{'system'}};
+               if ($a->{'version'} && &compare_versions($a, $c) > 0) {
+                       # A regular update is available
+                       push(@rv, { 'name' => $a->{'name'},
+                                   'update' => $a->{'update'},
+                                   'system' => $a->{'system'},
+                                   'version' => $a->{'version'},
+                                   'oldversion' => $c->{'version'},
+                                   'epoch' => $a->{'epoch'},
+                                   'oldepoch' => $c->{'epoch'},
+                                   'security' => $a->{'security'},
+                                   'desc' => $c->{'desc'} || $a->{'desc'},
+                                   'severity' => 0 });
+                       }
                }
        }
 return @rv;
index dbd185c..270d1f9 100644 (file)
@@ -30,3 +30,6 @@ The selected package and update systems are now checked when the module is opene
 ---- Changes since 1.470 ----
 On Solaris, added support for the pkgutil command from Blastwave for installing packages, which replaces the old pkg-get.
 On Solaris, package versions are now shown in the package list and tree.
+---- Changes since 1.500 ----
+Fixed several bugs related to YUM available package updates.
+Added the update_system_updates function to more efficiently find available packages for YUM and APT.
index dd15dbc..f0bc12b 100755 (executable)
@@ -196,21 +196,53 @@ while(<PKG>) {
                }
        }
 close(PKG);
+&set_yum_security_field(\%done);
+return @rv;
+}
 
-# Also run list-sec to find out which are security updates
-&open_execute_command(PKG, "yum list-sec", 1, 1);
+# set_yum_security_field(&package-hash)
+# Set security field on packages which are security updates
+sub set_yum_security_field
+{
+local ($done) = @_;
+&open_execute_command(PKG, "yum list-sec 2>/dev/null", 1, 1);
 while(<PKG>) {
        s/\r|\n//g;
        if (/^\S+\s+security\s+(\S+?)\-([0-9]\S+)\.([^\.]+)$/) {
                local ($name, $ver) = ($1, $2);
-               if ($done{$name}) {
-                       $done{$name}->{'source'} = 'security';
-                       $done{$name}->{'security'} = 1;
+               if ($done->{$name}) {
+                       $done->{$name}->{'source'} = 'security';
+                       $done->{$name}->{'security'} = 1;
                        }
                }
        }
 close(PKG);
+}
 
+# update_system_updates()
+# Returns a list of package updates available from yum
+sub update_system_updates
+{
+local @rv;
+local %done;
+&open_execute_command(PKG, "yum check-update 2>/dev/null", 1, 1);
+while(<PKG>) {
+        s/\r|\n//g;
+       if (/^(\S+)\.([^\.]+)\s+(\S+)\s+(\S+)/) {
+               local $pkg = { 'name' => $1,
+                              'arch' => $2,
+                              'version' => $3,
+                              'source' => $4 };
+               $pkg->{'version'} = $1;
+               if ($pkg->{'version'} =~ s/^(\S+)://) {
+                       $pkg->{'epoch'} = $1;
+                       }
+               $done{$pkg} = $pkg->{'name'};
+               push(@rv, $pkg);
+               }
+       }
+close(PKG);
+&set_yum_security_field(\%done);
 return @rv;
 }