From 4efe096dee67b13b1e316e8784242ed0482cb6b9 Mon Sep 17 00:00:00 2001
From: Gunnar Wrobel
Date: Wed, 13 Oct 2010 16:11:22 +0200
Subject: [PATCH] Extract the tree handling into a separate helper that should
later also allow to get a quick overview on package dependencies.
---
.../lib/Components/Helper/InstallationRun.php | 122 +++++++++++++++++++
components/lib/Components/Helper/Tree.php | 131 +++++++++++++++++++++
components/lib/Components/Helper/Tree/Element.php | 94 +++++++++++++++
components/lib/Components/Module/Installer.php | 2 +-
components/lib/Components/Pear/Factory.php | 20 ++++
components/lib/Components/Runner/Installer.php | 78 ++----------
components/test/Components/StoryTestCase.php | 2 +-
7 files changed, 381 insertions(+), 68 deletions(-)
create mode 100644 components/lib/Components/Helper/InstallationRun.php
create mode 100644 components/lib/Components/Helper/Tree.php
create mode 100644 components/lib/Components/Helper/Tree/Element.php
diff --git a/components/lib/Components/Helper/InstallationRun.php b/components/lib/Components/Helper/InstallationRun.php
new file mode 100644
index 000000000..5f833be7f
--- /dev/null
+++ b/components/lib/Components/Helper/InstallationRun.php
@@ -0,0 +1,122 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Components
+ */
+
+/**
+ * Components_Helper_InstallationRun:: provides a utility that records what has
+ * already happened during an installation run.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Horde
+ * @package Components
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Components
+ */
+class Components_Helper_InstallationRun
+{
+ /**
+ * The environment we establish the tree for.
+ *
+ * @var Components_Pear_InstallLocation
+ */
+ private $_environment;
+
+ /**
+ * The list of channels already installed.
+ *
+ * @var array
+ */
+ private $_installed_channels = array();
+
+ /**
+ * The list of packages already installed.
+ *
+ * @var array
+ */
+ private $_installed_packages = array();
+
+ /**
+ * Constructor.
+ *
+ * @param Components_Pear_InstallLocation $environment The environment we
+ * establish the tree for.
+ */
+ public function __construct(
+ Components_Pear_InstallLocation $environment
+ ) {
+ $this->_environment = $environment;
+ }
+
+ /**
+ * Ensure that the listed channels are available within the installation
+ * environment. The channels are only going to be installed once during the
+ * installation run represented by this instance.
+ *
+ * @return NULL
+ */
+ public function installChannelsOnce(array $channels)
+ {
+ foreach ($channels as $channel) {
+ if (!in_array($channel, $this->_installed_channels)) {
+ $this->_environment->provideChannel($channel);
+ $this->_installed_channels[] = $channel;
+ }
+ }
+ }
+
+ /**
+ * Ensure that the external package is available within the installation
+ * environment. The package is only going to be installed once during the
+ * installation run represented by this instance.
+ *
+ * @param string $package The package that should be installed.
+ * @param string $channel The channel of the package.
+ *
+ * @return NULL
+ */
+ public function installExternalPackageOnce($channel, $package)
+ {
+ $key = $channel . '/' . $package;
+ if (!in_array($key, $this->_installed_packages)) {
+ $this->_environment->addPackageFromPackage(
+ $channel, $package
+ );
+ $this->_installed_packages[] = $key;
+ }
+ }
+
+ /**
+ * Ensure that the horde package is available within the installation
+ * environment. The package is only going to be installed once during the
+ * installation run represented by this instance.
+ *
+ * @param string $package_file The package file indicating which Horde
+ * source package should be installed.
+ *
+ * @return NULL
+ */
+ public function installHordePackageOnce($package_file)
+ {
+ if (!in_array($package_file, $this->_installed_packages)) {
+ $this->_environment->addPackageFromSource(
+ $package_file
+ );
+ $this->_installed_packages[] = $package_file;
+ }
+ }
+}
\ No newline at end of file
diff --git a/components/lib/Components/Helper/Tree.php b/components/lib/Components/Helper/Tree.php
new file mode 100644
index 000000000..ac9d510f7
--- /dev/null
+++ b/components/lib/Components/Helper/Tree.php
@@ -0,0 +1,131 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Components
+ */
+
+/**
+ * Components_Helper_Tree:: handles a tree of dependencies and takes the Horde
+ * component layout into account.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Horde
+ * @package Components
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Components
+ */
+class Components_Helper_Tree
+{
+ /**
+ * The factory for PEAR dependencies.
+ *
+ * @var Components_Pear_Factory
+ */
+ private $_factory;
+
+ /**
+ * The environment we establish the tree for.
+ *
+ * @var Components_Pear_InstallLocation
+ */
+ private $_environment;
+
+ /**
+ * The root path for the Horde package hierarchy.
+ *
+ * @var string
+ */
+ private $_root_path;
+
+ /**
+ * Constructor.
+ *
+ * @param Components_Pear_Factory $factory The factory for PEAR
+ * dependencies.
+ * @param Components_Pear_InstallLocation $environment The PEAR environment.
+ * @param string $root_path The basic root path for
+ * Horde packages.
+ *
+ */
+ public function __construct(
+ Components_Pear_Factory $factory,
+ Components_Pear_InstallLocation $environment,
+ $root_path
+ ) {
+ $this->_factory = $factory;
+ $this->_environment = $environment;
+ $this->_root_path = $root_path;
+ }
+
+ /**
+ * Install the tree of packages into the specified environment.
+ *
+ * @param string $package_file Path to the package file
+ * representing the element
+ * at the root of the
+ * dependency tree.
+ * @return NULL
+ */
+ public function installTreeInEnvironment($package_file) {
+ $this->_getHordeChildElement($package_file)
+ ->installInTree(
+ new Components_Helper_InstallationRun($this->_environment)
+ );
+ }
+
+ /**
+ * Get the children for an element.
+ *
+ * @param array $dependencies The dependencies of a package to be
+ * transformed in elements.
+ * @return array The list of children elements.
+ */
+ public function getChildren(array $dependencies)
+ {
+ $children = array();
+ foreach ($dependencies as $dependency) {
+ $package_file = $this->_root_path . DIRECTORY_SEPARATOR
+ . $dependency['name'] . DIRECTORY_SEPARATOR . 'package.xml';
+ if (!file_exists($package_file)) {
+ $package_file = $this->_root_path . DIRECTORY_SEPARATOR
+ . 'framework' . DIRECTORY_SEPARATOR . $dependency['name']
+ . DIRECTORY_SEPARATOR . 'package.xml';
+ }
+ $children[] = $this->_getHordeChildElement($package_file);
+ }
+ return $children;
+ }
+
+ /**
+ * Return a Horde child element.
+ *
+ * @param string $package_file Path to the package
+ * file representing the
+ * element at the root
+ * of the dependency tree.
+ * @return NULL
+ */
+ private function _getHordeChildElement($package_file)
+ {
+ return new Components_Helper_Tree_Element(
+ $this->_factory->createPackageForEnvironment(
+ $package_file, $this->_environment
+ ),
+ $package_file,
+ $this
+ );
+ }
+}
\ No newline at end of file
diff --git a/components/lib/Components/Helper/Tree/Element.php b/components/lib/Components/Helper/Tree/Element.php
new file mode 100644
index 000000000..989a494af
--- /dev/null
+++ b/components/lib/Components/Helper/Tree/Element.php
@@ -0,0 +1,94 @@
+
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Components
+ */
+
+/**
+ * Components_Helper_Tree_Element:: provides utility methods for a single
+ * element of the tree.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @category Horde
+ * @package Components
+ * @author Gunnar Wrobel
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @link http://pear.horde.org/index.php?package=Components
+ */
+class Components_Helper_Tree_Element
+{
+ /**
+ * The package represented by this element.
+ *
+ * @var Components_Pear_Package
+ */
+ private $_package;
+
+ /**
+ * The path to the package file defining this element.
+ *
+ * @var string
+ */
+ private $_package_file;
+
+ /**
+ * The parent tree for this child.
+ *
+ * @var Components_Helper_Tree
+ */
+ private $_tree;
+
+ /**
+ * Constructor.
+ *
+ * @param Components_Pear_Package $package The root of the dependency tree.
+ * @param string $package_file The path to the package file.
+ * @param Components_Helper_Tree $tree The parent tree for this child.
+ */
+ public function __construct(
+ Components_Pear_Package $package,
+ $package_file,
+ Components_Helper_Tree $tree
+ ) {
+ $this->_package = $package;
+ $this->_package_file = $package_file;
+ $this->_tree = $tree;
+ }
+
+ /**
+ * Install the tree of packages into the environment.
+ *
+ * @param Components_Helper_InstallationRun $run The current installation run.
+ *
+ * @return NULL
+ */
+ public function installInTree(Components_Helper_InstallationRun $run)
+ {
+ $run->installChannelsOnce($this->_package->listAllRequiredChannels());
+ foreach ($this->_package->listAllExternalDependencies() as $dependency) {
+ $run->installExternalPackageOnce(
+ $dependency['channel'], $dependency['name']
+ );
+ }
+ foreach (
+ $this->_tree->getChildren(
+ $this->_package->listAllHordeDependencies()
+ ) as $child
+ ) {
+ $child->installInTree($run);
+ }
+ $run->installHordePackageOnce($this->_package_file);
+ }
+}
\ No newline at end of file
diff --git a/components/lib/Components/Module/Installer.php b/components/lib/Components/Module/Installer.php
index 1e51eb5cf..011d3666b 100644
--- a/components/lib/Components/Module/Installer.php
+++ b/components/lib/Components/Module/Installer.php
@@ -63,7 +63,7 @@ extends Components_Module_Base
'--install',
array(
'action' => 'store',
- 'help' => 'Install the element into the specified absolute INSTALL location'
+ 'help' => 'Install the element into the PEAR environment represented by this PEAR configuration file'
)
),
new Horde_Argv_Option(
diff --git a/components/lib/Components/Pear/Factory.php b/components/lib/Components/Pear/Factory.php
index 04e0f9ed7..918d0ca75 100644
--- a/components/lib/Components/Pear/Factory.php
+++ b/components/lib/Components/Pear/Factory.php
@@ -114,6 +114,26 @@ class Components_Pear_Factory
}
/**
+ * Create a tree helper for a specific PEAR environment..
+ *
+ * @param string $config_file The path to the configuration file.
+ * @param string $root_path The basic root path for Horde packages.
+ * @param array $options The application options
+ *
+ * @return Components_Helper_Tree The tree helper.
+ */
+ public function createTreeHelper($config_file, $root_path, array $options)
+ {
+ $environment = $this->_dependencies->createInstance('Components_Pear_InstallLocation');
+ $environment->setLocation(
+ dirname($config_file),
+ basename($config_file)
+ );
+ $environment->setResourceDirectories($options);
+ return new Components_Helper_Tree($this, $environment, $root_path);
+ }
+
+ /**
* Return the PEAR Package representation.
*
* @param string $package_xml_path Path to the package.xml file.
diff --git a/components/lib/Components/Runner/Installer.php b/components/lib/Components/Runner/Installer.php
index 48c1c3103..065bb69e8 100644
--- a/components/lib/Components/Runner/Installer.php
+++ b/components/lib/Components/Runner/Installer.php
@@ -39,9 +39,9 @@ class Components_Runner_Installer
private $_config;
/**
- * The factory for PEAR handlers.
+ * The factory for PEAR dependencies.
*
- * @var Components_Factory
+ * @var Components_Pear_Factory
*/
private $_factory;
@@ -50,8 +50,8 @@ class Components_Runner_Installer
*
* @param Components_Config $config The configuration for the current
* job.
- * @param Components_Pear_Factory $factory Generator for all required PEAR
- * components.
+ * @param Components_Pear_Factory $factory The factory for PEAR
+ * dependencies.
*/
public function __construct(
Components_Config $config,
@@ -64,70 +64,16 @@ class Components_Runner_Installer
public function run()
{
$options = $this->_config->getOptions();
- $location = realpath($options['install']);
- if (!$location) {
- $location = $options['install'];
+ $environment = realpath($options['install']);
+ if (!$environment) {
+ $environment = $options['install'];
}
- $environment = $this->_factory
- ->createInstallLocation($location . DIRECTORY_SEPARATOR . '.pearrc');
- $environment->setResourceDirectories($options);
- $pear_config = $environment->getPearConfig();
-
$arguments = $this->_config->getArguments();
- $element = basename(realpath($arguments[0]));
- $root_path = dirname(realpath($arguments[0]));
-
- $this->_run = array();
-
- $this->_installHordeDependency(
- $environment,
- $root_path,
- $element
- );
- }
-
- /**
- * Install a Horde dependency from the current tree (the framework).
- *
- * @param string $root_path Root path to the Horde framework.
- * @param string $dependency Package name of the dependency.
- */
- private function _installHordeDependency($environment, $root_path, $dependency)
- {
- $package_file = $root_path . DIRECTORY_SEPARATOR
- . $dependency . DIRECTORY_SEPARATOR . 'package.xml';
- if (!file_exists($package_file)) {
- $package_file = $root_path . DIRECTORY_SEPARATOR . 'framework' . DIRECTORY_SEPARATOR
- . $dependency . DIRECTORY_SEPARATOR . 'package.xml';
- }
-
- $pkg = $this->_factory->createPackageForEnvironment($package_file, $environment);
- $environment->provideChannels($pkg->listAllRequiredChannels());
- foreach ($pkg->listAllExternalDependencies() as $dependency) {
- $key = $dependency['channel'] . '/' . $dependency['name'];
- if (in_array($key, $this->_run)) {
- continue;
- }
- $environment->addPackageFromPackage(
- $dependency['channel'], $dependency['name']
+ $this->_factory
+ ->createTreeHelper(
+ $environment, dirname(realpath($arguments[0])), $options
+ )->installTreeInEnvironment(
+ realpath($arguments[0]) . DIRECTORY_SEPARATOR . 'package.xml'
);
- $this->_run[] = $key;
- }
- foreach ($pkg->listAllHordeDependencies() as $dependency) {
- $key = $dependency['channel'] . '/' . $dependency['name'];
- if (in_array($key, $this->_run)) {
- continue;
- }
- $this->_run[] = $key;
- $this->_installHordeDependency($environment, $root_path, $dependency['name']);
- }
- if (in_array($package_file, $this->_run)) {
- return;
- }
-
- $environment->addPackageFromSource(
- $package_file
- );
- $this->_run[] = $package_file;
}
}
diff --git a/components/test/Components/StoryTestCase.php b/components/test/Components/StoryTestCase.php
index 39929a133..6a1bf25ad 100644
--- a/components/test/Components/StoryTestCase.php
+++ b/components/test/Components/StoryTestCase.php
@@ -177,7 +177,7 @@ extends PHPUnit_Extensions_Story_TestCase
'horde-components',
'--channelxmlpath=' . dirname(__FILE__) . '/fixture/channels',
'--sourcepath=' . dirname(__FILE__) . '/fixture/packages',
- '--install=' . $this->_getTemporaryDirectory(),
+ '--install=' . $this->_getTemporaryDirectory() . DIRECTORY_SEPARATOR . '.pearrc',
dirname(__FILE__) . '/fixture/framework/Install'
);
$world['output'] = $this->_callUnstrictComponents();
--
2.11.0