Do not install packages twice, catch more PEAR errors, be more explicit when installi...
authorGunnar Wrobel <p@rdus.de>
Tue, 26 Oct 2010 15:21:17 +0000 (17:21 +0200)
committerGunnar Wrobel <p@rdus.de>
Tue, 26 Oct 2010 15:21:17 +0000 (17:21 +0200)
components/lib/Components/Helper/InstallationRun.php
components/lib/Components/Helper/Tree/Element.php
components/lib/Components/Pear/InstallLocation.php

index 6449042..24d22ed 100644 (file)
@@ -90,13 +90,29 @@ class Components_Helper_InstallationRun
      * @param string $package The package that should be installed.
      * @param string $channel The channel of the package.
      * @param string $reason  Optional reason for adding the package.
+     * @param array  $to_add  The local packages currently being added.
      *
      * @return NULL
      */
-    public function installExternalPackageOnce($channel, $package, $reason = '')
+    public function installExternalPackageOnce($channel, $package, $reason = '', array &$to_add = null)
     {
         $key = $channel . '/' . $package;
         if (!in_array($key, $this->_installed_packages)) {
+            if (empty($to_add)) {
+                $to_add = array($key);
+            }
+            foreach ($this->_environment->identifyRequiredLocalDependencies($channel, $package) as $required) {
+                $rkey = $required['channel'] . '/' . $required['name'];
+                if (in_array($rkey, $to_add)) {
+                    continue;
+                }
+                $to_add[] = $rkey;
+                $rreason = sprintf(' [required by %s]', $package);
+                $this->installExternalPackageOnce(
+                    $required['channel'], $required['name'], $rreason, &$to_add
+                );
+            }
+                
             $this->_environment->addPackageFromPackage(
                 $channel, $package, $reason
             );
index c515e26..650cef9 100644 (file)
@@ -82,17 +82,21 @@ class Components_Helper_Tree_Element
      *
      * @param Components_Helper_InstallationRun $run     The current installation run.
      * @param array                             $visited The packages already visited.
+     * @param string                            $reason  Optional reason for adding the package.
      *
      * @return NULL
      */
-    public function installInTree(Components_Helper_InstallationRun $run, array $visited = array())
-    {
+    public function installInTree(
+        Components_Helper_InstallationRun $run,
+        array $visited = array(),
+        $reason = ''
+    ) {
         if (in_array($this->_package_file, $visited)) {
             return;
         }
         $visited[] = $this->_package_file;
-        $reason = sprintf(' [required by %s]', $this->_package->getName());
-        $run->installChannelsOnce($this->_package->listAllRequiredChannels(), $reason);
+        $new_reason = sprintf(' [required by %s]', $this->_package->getName());
+        $run->installChannelsOnce($this->_package->listAllRequiredChannels(), $new_reason);
         foreach ($this->_package->listAllExternalDependencies() as $dependency) {
             // Refrain from installing optional pecl packages
             if (isset($dependency['optional'])
@@ -101,7 +105,7 @@ class Components_Helper_Tree_Element
                 continue;
             }
             $run->installExternalPackageOnce(
-                $dependency['channel'], $dependency['name'], $reason
+                $dependency['channel'], $dependency['name'], $new_reason
             );
         }
         foreach (
@@ -109,7 +113,7 @@ class Components_Helper_Tree_Element
                 $this->_package->listAllHordeDependencies()
             ) as $child
         ) {
-            $child->installInTree($run, $visited);
+            $child->installInTree($run, $visited, $new_reason);
         }
         $run->installHordePackageOnce($this->_package_file, $reason);
     }
index f10960f..511385a 100644 (file)
@@ -312,7 +312,6 @@ class Components_Pear_InstallLocation
             new PEAR_Frontend_CLI(),
             $this->getPearConfig()
         );
-        $installer->setErrorHandling(PEAR_ERROR_EXCEPTION);
         return $installer;
     }
 
@@ -335,10 +334,12 @@ class Components_Pear_InstallLocation
             )
         );
         ob_start();
-        $installer->doInstall(
-            'install',
-            array('nodeps' => true),
-            array($package)
+        Components_Exception_Pear::catchError(
+            $installer->doInstall(
+                'install',
+                array('nodeps' => true),
+                array($package)
+            )
         );
         $this->_output->pear(ob_get_clean());
         $this->_output->ok(
@@ -351,51 +352,66 @@ class Components_Pear_InstallLocation
     }
 
     /**
+     * Identify any dependencies we need when installing via downloaded packages.
+     *
+     * @param string $channel The channel name for the package.
+     * @param string $package The name of the package of the path of the tarball.
+     *
+     * @return array The added packages.
+     */
+    public function identifyRequiredLocalDependencies($channel, $package)
+    {
+        if ($local = $this->_identifyMatchingLocalPackage($package)) {
+            $dependencies = array();
+            $pkg = new PEAR_PackageFile($this->getPearConfig());
+            $pkg = $pkg->fromTgzFile($local, PEAR_VALIDATE_NORMAL);
+            $deps = $pkg->getDeps();
+            if (empty($deps)) {
+                return array();
+            }
+            foreach ($deps as $dependency) {
+                if ($dependency['type'] != 'pkg') {
+                    continue;
+                }
+                if (isset($dependency['optional']) && $dependency['optional'] == 'no') {
+                    $dependencies[] = $dependency;
+                }
+            }
+            return $dependencies;
+        }
+        return array();
+    }
+
+    /**
      * Add a package based on a package name or package tarball.
      *
      * @param string $channel The channel name for the package.
      * @param string $package The name of the package of the path of the tarball.
      * @param string $reason  Optional reason for adding the package.
-     * @param array  $locals  Packages currently being installed.
      *
      * @return NULL
      */
-    public function addPackageFromPackage($channel, $package, $reason = '', array $locals = null)
+    public function addPackageFromPackage($channel, $package, $reason = '')
     {
         $installer = $this->getInstallationHandler();
         $this->_output->ok(
             sprintf(
-                'About to add package %s%s',
+                'About to add package %s/%s%s',
+                $channel,
                 $package,
                 $reason
             )
         );
         if ($local = $this->_identifyMatchingLocalPackage($package)) {
-            if (empty($locals)) {
-                $locals = array($package);
-            } else {
-                $locals[] = $package;
-            }
-            $pkg = new PEAR_PackageFile($this->getPearConfig());
-            $pkg = $pkg->fromTgzFile($local, PEAR_VALIDATE_NORMAL);
-            foreach ($pkg->getDeps() as $dependency) {
-                if ($dependency['type'] != 'pkg') {
-                    continue;
-                }
-                if (isset($dependency['optional']) && $dependency['optional'] == 'no') {
-                    if (in_array($dependency['name'], $locals)) {
-                        continue;
-                    }
-                    $this->addPackageFromPackage($dependency['channel'], $dependency['name'], $reason, $locals);
-                }
-            }
             ob_start();
-            $installer->doInstall(
-                'install',
-                array(
-                    'offline' => true
-                ),
-                array($local)
+            Components_Exception_Pear::catchError(
+                $installer->doInstall(
+                    'install',
+                    array(
+                        'offline' => true
+                    ),
+                    array($local)
+                )
             );
             $this->_output->pear(ob_get_clean());
         } else {
@@ -406,18 +422,21 @@ class Components_Pear_InstallLocation
                 )
             );
             ob_start();
-            $installer->doInstall(
-                'install',
-                array(
-                    'channel' => $channel,
-                ),
-                array($package)
+            Components_Exception_Pear::catchError(
+                $installer->doInstall(
+                    'install',
+                    array(
+                        'channel' => $channel,
+                    ),
+                    array($package)
+                )
             );
             $this->_output->pear(ob_get_clean());
         }
         $this->_output->ok(
             sprintf(
-                'Successfully added package %s%s',
+                'Successfully added package %s/%s%s',
+                $channel,
                 $package,
                 $reason
             )