&& $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 {
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.
{
/**
* 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.
--- /dev/null
+<?php
+/**
+ * Components_Module_Distribute:: prepares a distribution package for a
+ * component.
+ *
+ * PHP version 5
+ *
+ * @category Horde
+ * @package Components
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @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 <wrobel@pardus.de>
+ * @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();
+ }
+ }
+}
--- /dev/null
+<?php
+/**
+ * Components_Runner_Distribute:: prepares a distribution package for a
+ * component.
+ *
+ * PHP version 5
+ *
+ * @category Horde
+ * @package Components
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @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 <wrobel@pardus.de>
+ * @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']);
+
+ }
+}
<email>jan@horde.org</email>
<active>yes</active>
</lead>
- <date>2010-09-06</date>
- <time>09:33:23</time>
+ <date>2010-10-03</date>
+ <time>19:38:19</time>
<version>
<release>0.0.1</release>
<api>0.0.1</api>
<file name="Base.php" role="php" />
<file name="CiSetup.php" role="php" />
<file name="DevPackage.php" role="php" />
+ <file name="Distribute.php" role="php" />
<file name="Installer.php" role="php" />
<file name="PearPackageXml.php" role="php" />
</dir> <!-- /lib/Components/Module -->
<dir name="Pear">
<file name="InstallLocation.php" role="php" />
+ <file name="Package.php" role="php" />
</dir> <!-- /lib/Components/Pear -->
<dir name="Runner">
+ <file name="CiSetup.php" role="php" />
+ <file name="Distribute.php" role="php" />
<file name="Installer.php" role="php" />
</dir> <!-- /lib/Components/Runner -->
<file name="Config.php" role="php" />
<file name="Configs.php" role="php" />
- <file name="Constants.php" role="php">
- <replace from="@data_dir@" to="data_dir" type="pear-config"/>
- </file>
+ <file name="Constants.php" role="php" />
<file name="Dependencies.php" role="php" />
<file name="Exception.php" role="php" />
<file name="Module.php" role="php" />
<file name="Components.php" role="php" />
</dir> <!-- /lib -->
<dir name="script">
- <file name="horde-components.php" role="script">
- <replace from="@php_dir@" to="php_dir" type="pear-config"/>
- </file>
+ <file name="horde-components.php" role="script" />
</dir> <!-- /script -->
<dir name="test">
<dir name="Components">
</dir> <!-- /test/Components/fixture/simple -->
</dir> <!-- /test/Components/fixture -->
<dir name="Integration">
+ <dir name="Components">
+ <dir name="Module">
+ <file name="CiSetupTest.php" role="test" />
+ </dir> <!-- /test/Components/Integration/Components/Module -->
+ </dir> <!-- /test/Components/Integration/Components -->
<file name="ComponentsTest.php" role="test" />
</dir> <!-- /test/Components/Integration -->
<dir name="Stub">
+ <file name="Cli.php" role="test" />
<file name="Parser.php" role="test" />
</dir> <!-- /test/Components/Stub -->
<file name="AllTests.php" role="test" />
</dir> <!-- /test/Components -->
</dir> <!-- /test -->
<file name="COPYING" role="doc" />
+ <file name="TODO" role="data" />
</dir> <!-- / -->
</contents>
<dependencies>
<install as="Components/Module/Base.php" name="lib/Components/Module/Base.php" />
<install as="Components/Module/CiSetup.php" name="lib/Components/Module/CiSetup.php" />
<install as="Components/Module/DevPackage.php" name="lib/Components/Module/DevPackage.php" />
+ <install as="Components/Module/Distribute.php" name="lib/Components/Module/Distribute.php" />
<install as="Components/Module/Installer.php" name="lib/Components/Module/Installer.php" />
<install as="Components/Module/PearPackageXml.php" name="lib/Components/Module/PearPackageXml.php" />
<install as="Components/Pear/InstallLocation.php" name="lib/Components/Pear/InstallLocation.php" />
+ <install as="Components/Pear/Package.php" name="lib/Components/Pear/Package.php" />
+ <install as="Components/Runner/CiSetup.php" name="lib/Components/Runner/CiSetup.php" />
+ <install as="Components/Runner/Distribute.php" name="lib/Components/Runner/Distribute.php" />
<install as="Components/Runner/Installer.php" name="lib/Components/Runner/Installer.php" />
<install as="horde-components" name="script/horde-components.php" />
<install as="Components/AllTests.php" name="test/Components/AllTests.php" />
<install as="Components/fixture/simple/lib/New.php" name="test/Components/fixture/simple/lib/New.php" />
<install as="Components/fixture/simple/lib/Second.php" name="test/Components/fixture/simple/lib/Second.php" />
<install as="Components/Integration/ComponentsTest.php" name="test/Components/Integration/ComponentsTest.php" />
+ <install as="Components/Integration/Components/Module/CiSetupTest.php" name="test/Components/Integration/Components/Module/CiSetupTest.php" />
+ <install as="Components/Stub/Cli.php" name="test/Components/Stub/Cli.php" />
<install as="Components/Stub/Parser.php" name="test/Components/Stub/Parser.php" />
</filelist>
</phprelease>
<release>alpha</release>
<api>alpha</api>
</stability>
- <date>2010-09-06</date>
+ <date>2010-10-03</date>
<license uri="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html">LGPL</license>
<notes>
* Initial release
);
}
+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);
require_once dirname(__FILE__) . '/StoryTestCase.php';
/** Load stubs */
+require_once dirname(__FILE__) . '/Stub/Cli.php';
require_once dirname(__FILE__) . '/Stub/Parser.php';
--- /dev/null
+<?php
+/**
+ * Test the Components package.
+ *
+ * PHP version 5
+ *
+ * @category Horde
+ * @package Components
+ * @subpackage UnitTests
+ * @author Gunnar Wrobel <wrobel@pardus.de>
+ * @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 <wrobel@pardus.de>
+ * @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
/**
* @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')
'--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(
'--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);
$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(
'/<file name="New.php" role="php" \/>/',
);
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
)
);
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);
}
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
--- /dev/null
+<?php
+class Components_Stub_Cli
+extends Horde_Cli
+{
+ /**
+ * Displays a fatal error message.
+ *
+ * @param mixed $error The error text to display, an exception or an
+ * object with a getMessage() method.
+ */
+ public function fatal($error)
+ {
+ if ($error instanceof Exception) {
+ $trace = $error;
+ } else {
+ $trace = debug_backtrace();
+ }
+ $backtrace = new Horde_Support_Backtrace($trace);
+ if (is_object($error) && method_exists($error, 'getMessage')) {
+ $error = $error->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
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