From: Gunnar Wrobel Date: Sun, 3 Oct 2010 17:42:44 +0000 (+0200) Subject: Refactor the dependency setup and add a draft for the distibute module. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=be3dccb87a7e307703b25a03095cb86be3786aac;p=horde.git Refactor the dependency setup and add a draft for the distibute module. --- diff --git a/components/lib/Components.php b/components/lib/Components.php index c6da6a1bb..3d6db5b06 100644 --- a/components/lib/Components.php +++ b/components/lib/Components.php @@ -47,10 +47,9 @@ class Components && $parameters['dependencies'] instanceOf Components_Dependencies) { $dependencies = $parameters['dependencies']; } else { - $dependencies = new Components_Dependencies_Injector( - $config - ); + $dependencies = new Components_Dependencies_Injector(); } + $dependencies->initConfig($config); $modules = self::_prepareModules($dependencies); $config->handleModules($modules); try { diff --git a/components/lib/Components/Dependencies.php b/components/lib/Components/Dependencies.php index 229f907f9..57c6c458c 100644 --- a/components/lib/Components/Dependencies.php +++ b/components/lib/Components/Dependencies.php @@ -30,6 +30,29 @@ interface Components_Dependencies { /** + * Initial configuration setup. + * + * @param Components_Config $config The configuration. + * + * @return NULL + */ + public function initConfig(Components_Config $config); + + /** + * Returns the continuous integration setup handler. + * + * @return Components_Runner_CiSetup The CI setup handler. + */ + public function getRunnerCiSetup(); + + /** + * Returns the distribution handler for a package. + * + * @return Components_Runner_Distribute The distribution handler. + */ + public function getRunnerDistribute(); + + /** * Returns the installer for a package. * * @return Components_Runner_Installer The installer. diff --git a/components/lib/Components/Dependencies/Injector.php b/components/lib/Components/Dependencies/Injector.php index 0cc4ca64e..a043534cb 100644 --- a/components/lib/Components/Dependencies/Injector.php +++ b/components/lib/Components/Dependencies/Injector.php @@ -33,16 +33,45 @@ implements Components_Dependencies { /** * Constructor. + */ + public function __construct() + { + parent::__construct(new Horde_Injector_TopLevel()); + } + + /** + * Initial configuration setup. * * @param Components_Config $config The configuration. + * + * @return NULL */ - public function __construct(Components_Config $config) + public function initConfig(Components_Config $config) { - parent::__construct(new Horde_Injector_TopLevel()); $this->setInstance('Components_Config', $config); } /** + * Returns the continuous integration setup handler. + * + * @return Components_Runner_CiSetup The CI setup handler. + */ + public function getRunnerCiSetup() + { + return $this->getInstance('Components_Runner_CiSetup'); + } + + /** + * Returns the distribution handler for a package. + * + * @return Components_Runner_Distribute The distribution handler. + */ + public function getRunnerDistribute() + { + return $this->getInstance('Components_Runner_Distribute'); + } + + /** * Returns the installer for a package. * * @return Components_Runner_Installer The installer. diff --git a/components/lib/Components/Module/Distribute.php b/components/lib/Components/Module/Distribute.php new file mode 100644 index 000000000..c60f32f4c --- /dev/null +++ b/components/lib/Components/Module/Distribute.php @@ -0,0 +1,93 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Components + */ + +/** + * Components_Module_Distribute:: prepares a distribution package for a + * component. + * + * 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_Module_Distribute +extends Components_Module_Base +{ + /** + * Return the title for the option group representing this module. + * + * @return string The group title. + */ + public function getOptionGroupTitle() + { + return 'Distribute'; + } + + /** + * Return the description for the option group representing this module. + * + * @return string The group description. + */ + public function getOptionGroupDescription() + { + return 'This module prepares a distribution package (e.g. RPM, APT, Ebuild, ...) from a component.'; + } + + /** + * Return the options for this module. + * + * @return array The group options. + */ + public function getOptionGroupOptions() + { + return array( + new Horde_Argv_Option( + '-D', + '--distribute', + array( + 'action' => 'store', + 'help' => 'Prepare the component package in the specified DISTRIBUTE location' + ) + ), + new Horde_Argv_Option( + '-t', + '--template', + array( + 'action' => 'store', + 'help' => 'Location of a template that will be rewritten into the final package definition.' + ) + ), + ); + } + + /** + * Determine if this module should act. Run all required actions if it has + * been instructed to do so. + * + * @return NULL + */ + public function handle(Components_Config $config) + { + $options = $config->getOptions(); + if (!empty($options['distribute'])) { + $this->_dependencies->getRunnerDistribute()->run(); + } + } +} diff --git a/components/lib/Components/Runner/Distribute.php b/components/lib/Components/Runner/Distribute.php new file mode 100644 index 000000000..e437e36ac --- /dev/null +++ b/components/lib/Components/Runner/Distribute.php @@ -0,0 +1,67 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Components + */ + +/** + * Components_Runner_Distribute:: prepares a distribution package for a + * component. + * + * 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_Runner_Distribute +{ + /** + * The configuration for the current job. + * + * @var Components_Config + */ + private $_config; + + /** + * The package handler. + * + * @var Components_Pear_Package + */ + private $_package; + + /** + * Constructor. + * + * @param Components_Config $config The configuration for the current job. + * @param Components_Pear_Package $package Package handler. + */ + public function __construct( + Components_Config $config, + Components_Pear_Package $package + ) { + $this->_config = $config; + $this->_package = $package; + } + + public function run() + { + $options = $this->_config->getOptions(); + $arguments = $this->_config->getArguments(); + $location = realpath($options['distribute']); + + } +} diff --git a/components/package.xml b/components/package.xml index 14c4f057f..9f94f2cc7 100644 --- a/components/package.xml +++ b/components/package.xml @@ -24,8 +24,8 @@ jan@horde.org yes - 2010-09-06 - + 2010-10-03 + 0.0.1 0.0.1 @@ -57,20 +57,22 @@ + + + + - - - + @@ -80,9 +82,7 @@ - - - + @@ -100,9 +100,15 @@ + + + + + + @@ -112,6 +118,7 @@ + @@ -169,9 +176,13 @@ + + + + @@ -184,6 +195,8 @@ + + @@ -197,7 +210,7 @@ alpha alpha - 2010-09-06 + 2010-10-03 LGPL * Initial release diff --git a/components/test/Components/Autoload.php b/components/test/Components/Autoload.php index b347717c8..2fde5e569 100644 --- a/components/test/Components/Autoload.php +++ b/components/test/Components/Autoload.php @@ -30,6 +30,10 @@ if (!spl_autoload_functions()) { ); } +if (!class_exists('Components')) { + set_include_path(dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . 'lib' . PATH_SEPARATOR . get_include_path()); +} + /** Catch strict standards */ error_reporting(E_ALL | E_STRICT); @@ -38,4 +42,5 @@ error_reporting(E_ALL | E_STRICT); require_once dirname(__FILE__) . '/StoryTestCase.php'; /** Load stubs */ +require_once dirname(__FILE__) . '/Stub/Cli.php'; require_once dirname(__FILE__) . '/Stub/Parser.php'; diff --git a/components/test/Components/Integration/Components/Module/CiSetupTest.php b/components/test/Components/Integration/Components/Module/CiSetupTest.php new file mode 100644 index 000000000..9c8cc0ed5 --- /dev/null +++ b/components/test/Components/Integration/Components/Module/CiSetupTest.php @@ -0,0 +1,97 @@ + + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Components + */ + +/** + * Prepare the test setup. + */ +require_once dirname(__FILE__) . '/../../../Autoload.php'; + +/** + * Test the Components package. + * + * 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 + * @subpackage UnitTests + * @author Gunnar Wrobel + * @license http://www.fsf.org/copyleft/lgpl.html LGPL + * @link http://pear.horde.org/index.php?package=Components + */ +class Components_Integration_Components_Module_CiSetupTest +extends Components_StoryTestCase +{ + /** + * @scenario + */ + public function theCisetupModuleAddsTheCOptionInTheHelpOutput() + { + $this->given('the default Components setup') + ->when('calling the package with the help option') + ->then('the help will contain the option', '-c\s*CISETUP,\s*--cisetup=CISETUP'); + } + + /** + * @scenario + */ + public function theCisetupModuleAddsTheCapitalCOptionInTheHelpOutput() + { + $this->given('the default Components setup') + ->when('calling the package with the help option') + ->then('the help will contain the option', '-C\s*CIPREBUILD,\s*--ciprebuild=CIPREBUILD'); + } + + /** + * @scenario + */ + public function theCisetupOptionsFailsWithoutAValidPearrcOption() + { + $this->given('the default Components setup') + ->when( + 'calling the package with the cisetup option and paths', + 'test', + dirname(dirname(dirname(dirname(__FILE__)))) . '/fixture/simple' + ) + ->then('the call will fail with', 'You are required to set the path to a PEAR environment for this package'); + } + + /** + * @scenario + */ + public function theCisetupOptionCreatesATemplateBaseCiConfigurationForAComponent() + { + $this->given('the default Components setup') + ->when( + 'calling the package with the cisetup, pearrc options and path', + dirname(dirname(dirname(dirname(__FILE__)))) . '/fixture/simple' + ) + ->then('the CI configuration will be installed.'); + } + + /** + * @scenario + */ + public function theCisetupOptionCreatesATemplateBaseCiBuildScriptForAComponent() + { + $this->given('the default Components setup') + ->when( + 'calling the package with the ciprebuild, pearrc options and path', + dirname(dirname(dirname(dirname(__FILE__)))) . '/fixture/simple' + ) + ->then('the CI build script will be installed.'); + } +} \ No newline at end of file diff --git a/components/test/Components/Integration/ComponentsTest.php b/components/test/Components/Integration/ComponentsTest.php index 6941070be..0068dc29c 100644 --- a/components/test/Components/Integration/ComponentsTest.php +++ b/components/test/Components/Integration/ComponentsTest.php @@ -78,7 +78,43 @@ extends Components_StoryTestCase /** * @scenario */ - public function theThePOptionProvidesAnUpdatedPackageXml() + public function thePOptionFailsWithoutAValidPackagePath() + { + $this->given('the default Components setup') + ->when('calling the package with the packagexml option and the path', '') + ->then('the call will fail with', 'Please specify the path of the PEAR package!'); + } + + /** + * @scenario + */ + public function thePOptionFailsWithoutAValidDirectoryPath() + { + $this->given('the default Components setup') + ->when( + 'calling the package with the packagexml option and the path', + dirname(dirname(__FILE__)) . '/fixture/DOESNOTEXIST' + ) + ->then('the call will fail with', 'specifies no directory'); + } + + /** + * @scenario + */ + public function thePOptionFailsWithoutAValidPackage() + { + $this->given('the default Components setup') + ->when( + 'calling the package with the packagexml option and the path', + dirname(dirname(__FILE__)) . '/fixture' + ) + ->then('the call will fail with', 'There is no package.xml at'); + } + + /** + * @scenario + */ + public function thePOptionProvidesAnUpdatedPackageXml() { $this->given('the default Components setup') ->when('calling the package with the packagexml option and a Horde element') diff --git a/components/test/Components/StoryTestCase.php b/components/test/Components/StoryTestCase.php index 01fd6a228..a35312690 100644 --- a/components/test/Components/StoryTestCase.php +++ b/components/test/Components/StoryTestCase.php @@ -74,12 +74,7 @@ extends PHPUnit_Extensions_Story_TestCase '--help', dirname(__FILE__) . '/fixture/empty' ); - ob_start(); - $parameters = array(); - $parameters['cli']['parser']['class'] = 'Components_Stub_Parser'; - Components::main($parameters); - $world['output'] = ob_get_contents(); - ob_end_clean(); + $world['output'] = $this->_callStrictComponents(); break; case 'calling the package with the packagexml option and a Horde element': $_SERVER['argv'] = array( @@ -87,29 +82,52 @@ extends PHPUnit_Extensions_Story_TestCase '--packagexml', dirname(__FILE__) . '/fixture/simple' ); - ob_start(); - $parameters = array(); - $parameters['cli']['parser']['class'] = 'Components_Stub_Parser'; - $old_errorreporting = error_reporting(E_ALL & ~E_STRICT); - Components::main($parameters); - error_reporting($old_errorreporting); - $world['output'] = ob_get_contents(); - ob_end_clean(); + $world['output'] = $this->_callUnstrictComponents(); + break; + case 'calling the package with the packagexml option and the path': + $_SERVER['argv'] = array( + 'horde-components', + '--packagexml', + $arguments[0] + ); + $world['output'] = $this->_callStrictComponents(); + break; + case 'calling the package with the cisetup option and paths': + $_SERVER['argv'] = array( + 'horde-components', + '--cisetup=' . $arguments[0], + $arguments[1] + ); + $world['output'] = $this->_callStrictComponents(); + break; + case 'calling the package with the cisetup, pearrc options and path': + $tmp = $this->_getTemporaryDirectory(); + $_SERVER['argv'] = array( + 'horde-components', + '--cisetup=' . $tmp, + '--pearrc=' . $tmp . DIRECTORY_SEPARATOR . '.pearrc', + $arguments[0] + ); + $world['output'] = $this->_callUnstrictComponents(); + break; + case 'calling the package with the ciprebuild, pearrc options and path': + $tmp = $this->_getTemporaryDirectory(); + $_SERVER['argv'] = array( + 'horde-components', + '--ciprebuild=' . $tmp, + '--pearrc=' . $tmp . DIRECTORY_SEPARATOR . '.pearrc', + $arguments[0] + ); + $world['output'] = $this->_callUnstrictComponents(); break; case 'calling the package with the install option and a Horde element': $_SERVER['argv'] = array( 'horde-components', + '--channelxmlpath=' . dirname(__FILE__) . '/fixture/channels', '--install=' . $this->_getTemporaryDirectory(), dirname(__FILE__) . '/../../' ); - ob_start(); - $parameters = array(); - $parameters['cli']['parser']['class'] = 'Components_Stub_Parser'; - $old_errorreporting = error_reporting(E_ALL & ~E_STRICT); - Components::main($parameters); - error_reporting($old_errorreporting); - $world['output'] = ob_get_contents(); - ob_end_clean(); + $world['output'] = $this->_callUnstrictComponents(); break; default: return $this->notImplemented($action); @@ -158,6 +176,12 @@ extends PHPUnit_Extensions_Story_TestCase $world['output'] ); break; + case 'the help will contain the option': + $this->assertRegExp( + '/' . $arguments[0] . '/', + $world['output'] + ); + break; case 'the new package.xml of the Horde element will be printed.': $this->assertRegExp( '//', @@ -180,7 +204,6 @@ extends PHPUnit_Extensions_Story_TestCase ); break; case 'the non-Horde dependencies of the Horde element will get installed from the network.': - var_dump($world['output']); $this->assertTrue( file_exists( $this->_temp_dir . DIRECTORY_SEPARATOR @@ -212,6 +235,28 @@ extends PHPUnit_Extensions_Story_TestCase ) ); break; + case 'the CI configuration will be installed.': + $this->assertTrue( + file_exists( + $this->_temp_dir . DIRECTORY_SEPARATOR + . 'config.xml' + ) + ); + break; + case 'the CI build script will be installed.': + $this->assertTrue( + file_exists( + $this->_temp_dir . DIRECTORY_SEPARATOR + . 'build.xml' + ) + ); + break; + case 'the call will fail with': + $this->assertContains( + $arguments[0], + $world['output'] + ); + break; default: return $this->notImplemented($action); } @@ -241,5 +286,42 @@ extends PHPUnit_Extensions_Story_TestCase reset($objects); rmdir($dir); } - } + } + + private function _callStrictComponents(array $parameters = array()) + { + return $this->_callComponents($parameters, array($this, '_callStrict')); + } + + private function _callUnstrictComponents(array $parameters = array()) + { + return $this->_callComponents($parameters, array($this, '_callUnstrict')); + } + + private function _callComponents(array $parameters, $callback) + { + ob_start(); + $parameters['cli']['parser']['class'] = 'Components_Stub_Parser'; + $parameters['dependencies'] = new Components_Dependencies_Injector(); + $parameters['dependencies']->setInstance( + 'Horde_Cli', + new Components_Stub_Cli() + ); + call_user_func_array($callback, array($parameters)); + $output = ob_get_contents(); + ob_end_clean(); + return $output; + } + + private function _callUnstrict(array $parameters) + { + $old_errorreporting = error_reporting(E_ALL & ~E_STRICT); + $this->_callStrict($parameters); + error_reporting($old_errorreporting); + } + + private function _callStrict(array $parameters) + { + Components::main($parameters); + } } \ No newline at end of file diff --git a/components/test/Components/Stub/Cli.php b/components/test/Components/Stub/Cli.php new file mode 100644 index 000000000..f6564d189 --- /dev/null +++ b/components/test/Components/Stub/Cli.php @@ -0,0 +1,30 @@ +getMessage(); + } + $this->writeln($this->red('====================')); + $this->writeln(); + $this->writeln($this->red(_("Fatal Error:"))); + $this->writeln($this->red($error)); + $this->writeln(); + $this->writeln((string)$backtrace); + $this->writeln($this->red('====================')); + } +} \ No newline at end of file diff --git a/components/test/Components/Stub/Parser.php b/components/test/Components/Stub/Parser.php index 082b79542..b8efead9f 100644 --- a/components/test/Components/Stub/Parser.php +++ b/components/test/Components/Stub/Parser.php @@ -2,9 +2,22 @@ class Components_Stub_Parser extends Horde_Argv_Parser { + /** + * Print a usage message incorporating $msg to stderr and exit. + * If you override this in a subclass, it should not return -- it + * should either exit or raise an exception. + * + * @param string $msg + */ + public function parserError($msg) + { + $this->printUsage(); + $this->parserExit(2, sprintf("%s: error: %s\n", $this->getProgName(), $msg)); + } + public function parserExit($status = 0, $msg = null) { if ($msg) - fwrite(STDERR, $msg); + echo $msg; } } \ No newline at end of file