--- ../cvs/pear-core/PEAR/Command/Install.php	2007-02-13 05:30:05.000000000 +0100
+++ Install.php	2007-03-21 15:18:31.000000000 +0100
@@ -205,9 +205,9 @@
 More than one package may be specified at once.
 '),
         'upgrade-all' => array(
             'summary' => 'Upgrade All Packages',
-            'function' => 'doInstall',
+            'function' => 'doUpgradeAll',
             'shortcut' => 'ua',
             'options' => array(
                 'nodeps' => array(
                     'shortopt' => 'n',
@@ -533,69 +533,39 @@
         if (isset($options['packagingroot']) && $this->config->get('verbose') > 2) {
             $this->ui->outputData('using package root: ' . $options['packagingroot']);
         }
         $reg = &$this->config->getRegistry();
-        if ($command == 'upgrade-all') {
-            $options['upgrade'] = true;
-            $reg = &$this->config->getRegistry();
-            $savechannel = $this->config->get('default_channel');
-            $params = array();
-            foreach ($reg->listChannels() as $channel) {
-                if ($channel == '__uri') {
-                    continue;
-                }
-                $this->config->set('default_channel', $channel);
-                $chan = &$reg->getChannel($channel);
-                if (PEAR::isError($chan)) {
-                    return $this->raiseError($chan);
-                }
-                if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
-                      $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
-                    $dorest = true;
-                    unset($remote);
-                } else {
-                    $dorest = false;
-                    $remote = &$this->config->getRemote($this->config);
-                }
-                $state = $this->config->get('preferred_state');
-                $installed = array_flip($reg->listPackages($channel));
-                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
-                if ($dorest) {
-                    $rest = &$this->config->getREST('1.0', array());
-                    $latest = $rest->listLatestUpgrades($base, $state, $installed, $channel, $reg);
-                } else {
-                    if (empty($state) || $state == 'any') {
-                        $latest = $remote->call("package.listLatestReleases");
-                    } else {
-                        $latest = $remote->call("package.listLatestReleases", $state);
-                    }
-                }
-                PEAR::staticPopErrorHandling();
-                if (PEAR::isError($latest) || !is_array($latest)) {
-                    continue;
-                }
-                foreach ($latest as $package => $info) {
-                    $package = strtolower($package);
-                    if (!isset($installed[$package])) {
-                        // skip packages we don't have installed
-                        continue;
-                    }
-                    $inst_version = $reg->packageInfo($package, 'version', $channel);
-                    if (version_compare("$info[version]", "$inst_version", "le")) {
-                        // installed version is up-to-date
-                        continue;
+ 
+        $packages = array();
+        // parse params
+        foreach($params as $param) {
+            $packages[] = $reg->parsePackageName($param,
+                                                 $this->config->get('default_channel'));
+        }
+
+        if (!isset($options['force']) || !$options['force']) {
+            // when not being forced, only do necessary upgrades/installs
+            if (isset($options['upgrade']) && $options['upgrade']) {
+                $packages = $this->_filterUptodatePackages($packages);
+            } else {
+                foreach ($packages as $i => $package) {
+                    if ($reg->packageExists($package['package'], $package['channel'])) {
+                        $this->ui->outputData('Not installing already installed package '.$package['channel'].'/'.$package['package']);
+                        unset($packages[$i]);
                     }
-                    $params[] = $a = $reg->parsedPackageNameToString(array('package' => $package,
-                        'channel' => $channel));
-                    $this->ui->outputData(array('data' => "Will upgrade $a"), $command);
                 }
             }
-            $this->config->set('default_channel', $savechannel);
         }
+
+        if ($packages == null) {
+            $this->ui->outputData('Nothing to '.$command);
+            return true;
+        }
+
         $this->downloader = &$this->getDownloader($this->ui, $options, $this->config);
         $errors = array();
         $downloaded = array();
-        $downloaded = &$this->downloader->download($params);
+        $downloaded = &$this->downloader->download($packages);
         if (PEAR::isError($downloaded)) {
             return $this->raiseError($downloaded);
         }
         $errors = $this->downloader->getErrorMsgs();
@@ -792,8 +763,33 @@
         return true;
     }
 
     // }}}
+    // {{{ doUpgradeAll()
+
+    function doUpgradeAll($command, $options, $params)
+    {
+        $reg = &$this->config->getRegistry();
+        $installed = array();
+        foreach ($reg->listChannels() as $channel) {
+            if ($channel == '__uri') {
+                continue;
+            }
+
+            // parse name with channel
+            foreach ($reg->listPackages($channel) as $name) {
+                $state = $reg->packageInfo($name, 'release_state', $channel);
+                $installed[] = $channel.'/'.$name.'-'.$state;
+            }
+        }
+
+        $err = $this->doInstall('upgrade', $options, $installed);
+        if (PEAR::isError($err)) {
+            $this->ui->outputData($err->getMessage(), $command);
+        }
+   }
+
+    // }}}
     // {{{ doUninstall()
 
     function doUninstall($command, $options, $params)
     {
@@ -1034,6 +1030,75 @@
         }
         $this->ui->outputData('Install scripts complete', $command);
         return true;
     }
+
+    /**
+     * Given a list of packages, filter out those ones that are already up to dat
+     *
+     * @param $packages: packages, in parsed array format !
+     * @return list of packages that can be upgraded
+     */
+    function _filterUptodatePackages($packages)
+    {
+        $reg = &$this->config->getRegistry();
+        $latestReleases = array();
+
+        $ret = array();
+        foreach($packages as $package) {
+            $channel = $package['channel'];
+            $name = $package['package'];
+
+            if (!isset($latestReleases[$channel])) {
+                // fill in cache for this channel
+                $chan = &$reg->getChannel($channel);
+                if (PEAR::isError($chan)) {
+                    return $this->raiseError($chan);
+                }
+                if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
+                      $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
+                    $dorest = true;
+                    unset($remote);
+                } else {
+                    $dorest = false;
+                    $remote = &$this->config->getRemote($this->config);
+                }
+                PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+                if ($dorest) {
+                    $rest = &$this->config->getREST('1.0', array());
+                    $installed = array_flip($reg->listPackages($channel));
+                    $latest = $rest->listLatestUpgrades($base, null, $installed, $channel, $reg);
+                } else {
+                    $latest = $remote->call("package.listLatestReleases");
+                }
+                PEAR::staticPopErrorHandling();
+                if (PEAR::isError($latest)) {
+                    $this->ui->outputData('Error getting channel info from '.$channel.': '.$latest->getMessage());
+                    continue;
+                }
+
+                // damn cases
+                $allerlatest = array();
+                foreach($latest as $key => $value) {
+                    $allerlatest[strtolower($key)] = $value;
+                }
+                $latestReleases[$channel] = $allerlatest;
+            }
+
+            // check package for latest release
+            if (isset($latestReleases[$channel][$name])) { // if not set, up to date
+                $inst_version = $reg->packageInfo($name, 'version', $channel);
+                $channel_version = $latestReleases[$channel][$name]['version'];
+                if (version_compare($channel_version, $inst_version, "le")) {
+                    // installed version is up-to-date
+                    continue;
+                }
+                $this->ui->outputData('Will upgrade '.$reg->parsedPackageNameToString($package));
+                $ret[] = $package;
+            }
+        }
+
+        return $ret;
+    }
+
 }
 ?>
