Refactor the dependency setup and add a draft for the distibute module.
authorGunnar Wrobel <p@rdus.de>
Sun, 3 Oct 2010 17:42:44 +0000 (19:42 +0200)
committerGunnar Wrobel <p@rdus.de>
Sun, 3 Oct 2010 17:45:53 +0000 (19:45 +0200)
12 files changed:
components/lib/Components.php
components/lib/Components/Dependencies.php
components/lib/Components/Dependencies/Injector.php
components/lib/Components/Module/Distribute.php [new file with mode: 0644]
components/lib/Components/Runner/Distribute.php [new file with mode: 0644]
components/package.xml
components/test/Components/Autoload.php
components/test/Components/Integration/Components/Module/CiSetupTest.php [new file with mode: 0644]
components/test/Components/Integration/ComponentsTest.php
components/test/Components/StoryTestCase.php
components/test/Components/Stub/Cli.php [new file with mode: 0644]
components/test/Components/Stub/Parser.php

index c6da6a1..3d6db5b 100644 (file)
@@ -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 {
index 229f907..57c6c45 100644 (file)
 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.
index 0cc4ca6..a043534 100644 (file)
@@ -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 (file)
index 0000000..c60f32f
--- /dev/null
@@ -0,0 +1,93 @@
+<?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();
+        }
+    }
+}
diff --git a/components/lib/Components/Runner/Distribute.php b/components/lib/Components/Runner/Distribute.php
new file mode 100644 (file)
index 0000000..e437e36
--- /dev/null
@@ -0,0 +1,67 @@
+<?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']);
+
+    }
+}
index 14c4f05..9f94f2c 100644 (file)
@@ -24,8 +24,8 @@
   <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" />
@@ -80,9 +82,7 @@
     <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
index b347717..2fde5e5 100644 (file)
@@ -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 (file)
index 0000000..9c8cc0e
--- /dev/null
@@ -0,0 +1,97 @@
+<?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
index 6941070..0068dc2 100644 (file)
@@ -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')
index 01fd6a2..a353126 100644 (file)
@@ -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(
                 '/<file name="New.php" role="php" \/>/',
@@ -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 (file)
index 0000000..f6564d1
--- /dev/null
@@ -0,0 +1,30 @@
+<?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
index 082b795..b8efead 100644 (file)
@@ -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