aboutsummaryrefslogtreecommitdiffstats
path: root/3rdparty/PEAR/Command
diff options
context:
space:
mode:
authorRobin Appelman <icewind@owncloud.com>2012-05-11 17:57:55 +0200
committerRobin Appelman <icewind@owncloud.com>2012-05-11 17:57:55 +0200
commit9c2f1051646f1dfb2615065d79d9a76410152b1a (patch)
treeaeb2812f7f37fb58bc6920cd2b3ccdf08d9c1eec /3rdparty/PEAR/Command
parent347ce2aafada161849dad8593100c40e14c641ce (diff)
downloadnextcloud-server-9c2f1051646f1dfb2615065d79d9a76410152b1a.tar.gz
nextcloud-server-9c2f1051646f1dfb2615065d79d9a76410152b1a.zip
update PEAR to 1.9.4
Diffstat (limited to '3rdparty/PEAR/Command')
-rw-r--r--3rdparty/PEAR/Command/Auth.php160
-rw-r--r--3rdparty/PEAR/Command/Auth.xml30
-rw-r--r--3rdparty/PEAR/Command/Build.php72
-rw-r--r--3rdparty/PEAR/Command/Build.xml10
-rw-r--r--3rdparty/PEAR/Command/Channels.php883
-rw-r--r--3rdparty/PEAR/Command/Channels.xml123
-rw-r--r--3rdparty/PEAR/Command/Common.php168
-rw-r--r--3rdparty/PEAR/Command/Config.php345
-rw-r--r--3rdparty/PEAR/Command/Config.xml92
-rw-r--r--3rdparty/PEAR/Command/Install.php1130
-rw-r--r--3rdparty/PEAR/Command/Install.xml276
-rw-r--r--3rdparty/PEAR/Command/Mirror.php136
-rw-r--r--3rdparty/PEAR/Command/Mirror.xml18
-rw-r--r--3rdparty/PEAR/Command/Package.php1133
-rw-r--r--3rdparty/PEAR/Command/Package.xml237
-rw-r--r--3rdparty/PEAR/Command/Pickle.php421
-rw-r--r--3rdparty/PEAR/Command/Pickle.xml36
-rw-r--r--3rdparty/PEAR/Command/Registry.php1026
-rw-r--r--3rdparty/PEAR/Command/Registry.xml58
-rw-r--r--3rdparty/PEAR/Command/Remote.php795
-rw-r--r--3rdparty/PEAR/Command/Remote.xml109
-rw-r--r--3rdparty/PEAR/Command/Test.php337
-rw-r--r--3rdparty/PEAR/Command/Test.xml54
23 files changed, 6389 insertions, 1260 deletions
diff --git a/3rdparty/PEAR/Command/Auth.php b/3rdparty/PEAR/Command/Auth.php
index 0b9d3d3965d..63cd152b900 100644
--- a/3rdparty/PEAR/Command/Auth.php
+++ b/3rdparty/PEAR/Command/Auth.php
@@ -1,43 +1,53 @@
<?php
-//
-// +----------------------------------------------------------------------+
-// | PHP Version 5 |
-// +----------------------------------------------------------------------+
-// | Copyright (c) 1997-2004 The PHP Group |
-// +----------------------------------------------------------------------+
-// | This source file is subject to version 3.0 of the PHP license, |
-// | that is bundled with this package in the file LICENSE, and is |
-// | available through the world-wide-web at the following url: |
-// | http://www.php.net/license/3_0.txt. |
-// | If you did not receive a copy of the PHP license and are unable to |
-// | obtain it through the world-wide-web, please send a note to |
-// | license@php.net so we can mail you a copy immediately. |
-// +----------------------------------------------------------------------+
-// | Author: Stig Bakken <ssb@php.net> |
-// +----------------------------------------------------------------------+
-//
-// $Id: Auth.php,v 1.15 2004/01/08 17:33:13 sniper Exp $
+/**
+ * PEAR_Command_Auth (login, logout commands)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Auth.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ * @deprecated since 1.8.0alpha1
+ */
-require_once "PEAR/Command/Common.php";
-require_once "PEAR/Remote.php";
-require_once "PEAR/Config.php";
+/**
+ * base class
+ */
+require_once 'PEAR/Command/Channels.php';
/**
- * PEAR commands for managing configuration data.
+ * PEAR commands for login/logout
*
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 0.1
+ * @deprecated since 1.8.0alpha1
*/
-class PEAR_Command_Auth extends PEAR_Command_Common
+class PEAR_Command_Auth extends PEAR_Command_Channels
{
- // {{{ properties
-
var $commands = array(
'login' => array(
- 'summary' => 'Connects and authenticates to remote server',
+ 'summary' => 'Connects and authenticates to remote server [Deprecated in favor of channel-login]',
'shortcut' => 'li',
'function' => 'doLogin',
'options' => array(),
- 'doc' => '
-Log in to the remote server. To use remote functions in the installer
+ 'doc' => '<channel name>
+WARNING: This function is deprecated in favor of using channel-login
+
+Log in to a remote channel server. If <channel name> is not supplied,
+the default channel is used. To use remote functions in the installer
that require any kind of privileges, you need to log in first. The
username and password you enter here will be stored in your per-user
PEAR configuration (~/.pearrc on Unix-like systems). After logging
@@ -45,11 +55,13 @@ in, your username and password will be sent along in subsequent
operations on the remote server.',
),
'logout' => array(
- 'summary' => 'Logs out from the remote server',
+ 'summary' => 'Logs out from the remote server [Deprecated in favor of channel-logout]',
'shortcut' => 'lo',
'function' => 'doLogout',
'options' => array(),
'doc' => '
+WARNING: This function is deprecated in favor of using channel-logout
+
Logs out from the remote server. This command does not actually
connect to the remote server, it only deletes the stored username and
password from your user configuration.',
@@ -57,10 +69,6 @@ password from your user configuration.',
);
- // }}}
-
- // {{{ constructor
-
/**
* PEAR_Command_Auth constructor.
*
@@ -68,88 +76,6 @@ password from your user configuration.',
*/
function PEAR_Command_Auth(&$ui, &$config)
{
- parent::PEAR_Command_Common($ui, $config);
- }
-
- // }}}
-
- // {{{ doLogin()
-
- /**
- * Execute the 'login' command.
- *
- * @param string $command command name
- *
- * @param array $options option_name => value
- *
- * @param array $params list of additional parameters
- *
- * @return bool TRUE on success, FALSE for unknown commands, or
- * a PEAR error on failure
- *
- * @access public
- */
- function doLogin($command, $options, $params)
- {
- $server = $this->config->get('master_server');
- $remote = new PEAR_Remote($this->config);
- $username = $this->config->get('username');
- if (empty($username)) {
- $username = @$_ENV['USER'];
- }
- $this->ui->outputData("Logging in to $server.", $command);
-
- list($username, $password) = $this->ui->userDialog(
- $command,
- array('Username', 'Password'),
- array('text', 'password'),
- array($username, '')
- );
- $username = trim($username);
- $password = trim($password);
-
- $this->config->set('username', $username);
- $this->config->set('password', $password);
-
- $remote->expectError(401);
- $ok = $remote->call('logintest');
- $remote->popExpect();
- if ($ok === true) {
- $this->ui->outputData("Logged in.", $command);
- $this->config->store();
- } else {
- return $this->raiseError("Login failed!");
- }
-
- }
-
- // }}}
- // {{{ doLogout()
-
- /**
- * Execute the 'logout' command.
- *
- * @param string $command command name
- *
- * @param array $options option_name => value
- *
- * @param array $params list of additional parameters
- *
- * @return bool TRUE on success, FALSE for unknown commands, or
- * a PEAR error on failure
- *
- * @access public
- */
- function doLogout($command, $options, $params)
- {
- $server = $this->config->get('master_server');
- $this->ui->outputData("Logging out from $server.", $command);
- $this->config->remove('username');
- $this->config->remove('password');
- $this->config->store();
+ parent::PEAR_Command_Channels($ui, $config);
}
-
- // }}}
-}
-
-?> \ No newline at end of file
+} \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Auth.xml b/3rdparty/PEAR/Command/Auth.xml
new file mode 100644
index 00000000000..590193d142a
--- /dev/null
+++ b/3rdparty/PEAR/Command/Auth.xml
@@ -0,0 +1,30 @@
+<commands version="1.0">
+ <login>
+ <summary>Connects and authenticates to remote server [Deprecated in favor of channel-login]</summary>
+ <function>doLogin</function>
+ <shortcut>li</shortcut>
+ <options />
+ <doc>&lt;channel name&gt;
+WARNING: This function is deprecated in favor of using channel-login
+
+Log in to a remote channel server. If &lt;channel name&gt; is not supplied,
+the default channel is used. To use remote functions in the installer
+that require any kind of privileges, you need to log in first. The
+username and password you enter here will be stored in your per-user
+PEAR configuration (~/.pearrc on Unix-like systems). After logging
+in, your username and password will be sent along in subsequent
+operations on the remote server.</doc>
+ </login>
+ <logout>
+ <summary>Logs out from the remote server [Deprecated in favor of channel-logout]</summary>
+ <function>doLogout</function>
+ <shortcut>lo</shortcut>
+ <options />
+ <doc>
+WARNING: This function is deprecated in favor of using channel-logout
+
+Logs out from the remote server. This command does not actually
+connect to the remote server, it only deletes the stored username and
+password from your user configuration.</doc>
+ </logout>
+</commands> \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Build.php b/3rdparty/PEAR/Command/Build.php
index 2ecbbc92f5f..1de7320246a 100644
--- a/3rdparty/PEAR/Command/Build.php
+++ b/3rdparty/PEAR/Command/Build.php
@@ -1,36 +1,42 @@
<?php
-//
-// +----------------------------------------------------------------------+
-// | PHP Version 5 |
-// +----------------------------------------------------------------------+
-// | Copyright (c) 1997-2004 The PHP Group |
-// +----------------------------------------------------------------------+
-// | This source file is subject to version 3.0 of the PHP license, |
-// | that is bundled with this package in the file LICENSE, and is |
-// | available through the world-wide-web at the following url: |
-// | http://www.php.net/license/3_0.txt. |
-// | If you did not receive a copy of the PHP license and are unable to |
-// | obtain it through the world-wide-web, please send a note to |
-// | license@php.net so we can mail you a copy immediately. |
-// +----------------------------------------------------------------------+
-// | Author: Stig Bakken <ssb@php.net> |
-// | Tomas V.V.Cox <cox@idecnet.com> |
-// | |
-// +----------------------------------------------------------------------+
-//
-// $Id: Build.php,v 1.9 2004/01/08 17:33:13 sniper Exp $
+/**
+ * PEAR_Command_Auth (build command)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Tomas V.V.Cox <cox@idecnet.com>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Build.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ */
-require_once "PEAR/Command/Common.php";
-require_once "PEAR/Builder.php";
+/**
+ * base class
+ */
+require_once 'PEAR/Command/Common.php';
/**
* PEAR commands for building extensions.
*
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Tomas V.V.Cox <cox@idecnet.com>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 0.1
*/
class PEAR_Command_Build extends PEAR_Command_Common
{
- // {{{ properties
-
var $commands = array(
'build' => array(
'summary' => 'Build an Extension From C Source',
@@ -42,10 +48,6 @@ Builds one or more extensions contained in a package.'
),
);
- // }}}
-
- // {{{ constructor
-
/**
* PEAR_Command_Build constructor.
*
@@ -56,27 +58,23 @@ Builds one or more extensions contained in a package.'
parent::PEAR_Command_Common($ui, $config);
}
- // }}}
-
- // {{{ doBuild()
-
function doBuild($command, $options, $params)
{
+ require_once 'PEAR/Builder.php';
if (sizeof($params) < 1) {
$params[0] = 'package.xml';
}
+
$builder = &new PEAR_Builder($this->ui);
$this->debug = $this->config->get('verbose');
$err = $builder->build($params[0], array(&$this, 'buildCallback'));
if (PEAR::isError($err)) {
return $err;
}
+
return true;
}
- // }}}
- // {{{ buildCallback()
-
function buildCallback($what, $data)
{
if (($what == 'cmdoutput' && $this->debug > 1) ||
@@ -84,6 +82,4 @@ Builds one or more extensions contained in a package.'
$this->ui->outputData(rtrim($data), 'build');
}
}
-
- // }}}
-}
+} \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Build.xml b/3rdparty/PEAR/Command/Build.xml
new file mode 100644
index 00000000000..ec4e6f554ca
--- /dev/null
+++ b/3rdparty/PEAR/Command/Build.xml
@@ -0,0 +1,10 @@
+<commands version="1.0">
+ <build>
+ <summary>Build an Extension From C Source</summary>
+ <function>doBuild</function>
+ <shortcut>b</shortcut>
+ <options />
+ <doc>[package.xml]
+Builds one or more extensions contained in a package.</doc>
+ </build>
+</commands> \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Channels.php b/3rdparty/PEAR/Command/Channels.php
new file mode 100644
index 00000000000..fcf01b50391
--- /dev/null
+++ b/3rdparty/PEAR/Command/Channels.php
@@ -0,0 +1,883 @@
+<?php
+// /* vim: set expandtab tabstop=4 shiftwidth=4: */
+/**
+ * PEAR_Command_Channels (list-channels, update-channels, channel-delete, channel-add,
+ * channel-update, channel-info, channel-alias, channel-discover commands)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Channels.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 1.4.0a1
+ */
+
+/**
+ * base class
+ */
+require_once 'PEAR/Command/Common.php';
+
+define('PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS', -500);
+
+/**
+ * PEAR commands for managing channels.
+ *
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 1.4.0a1
+ */
+class PEAR_Command_Channels extends PEAR_Command_Common
+{
+ var $commands = array(
+ 'list-channels' => array(
+ 'summary' => 'List Available Channels',
+ 'function' => 'doList',
+ 'shortcut' => 'lc',
+ 'options' => array(),
+ 'doc' => '
+List all available channels for installation.
+',
+ ),
+ 'update-channels' => array(
+ 'summary' => 'Update the Channel List',
+ 'function' => 'doUpdateAll',
+ 'shortcut' => 'uc',
+ 'options' => array(),
+ 'doc' => '
+List all installed packages in all channels.
+'
+ ),
+ 'channel-delete' => array(
+ 'summary' => 'Remove a Channel From the List',
+ 'function' => 'doDelete',
+ 'shortcut' => 'cde',
+ 'options' => array(),
+ 'doc' => '<channel name>
+Delete a channel from the registry. You may not
+remove any channel that has installed packages.
+'
+ ),
+ 'channel-add' => array(
+ 'summary' => 'Add a Channel',
+ 'function' => 'doAdd',
+ 'shortcut' => 'ca',
+ 'options' => array(),
+ 'doc' => '<channel.xml>
+Add a private channel to the channel list. Note that all
+public channels should be synced using "update-channels".
+Parameter may be either a local file or remote URL to a
+channel.xml.
+'
+ ),
+ 'channel-update' => array(
+ 'summary' => 'Update an Existing Channel',
+ 'function' => 'doUpdate',
+ 'shortcut' => 'cu',
+ 'options' => array(
+ 'force' => array(
+ 'shortopt' => 'f',
+ 'doc' => 'will force download of new channel.xml if an existing channel name is used',
+ ),
+ 'channel' => array(
+ 'shortopt' => 'c',
+ 'arg' => 'CHANNEL',
+ 'doc' => 'will force download of new channel.xml if an existing channel name is used',
+ ),
+),
+ 'doc' => '[<channel.xml>|<channel name>]
+Update a channel in the channel list directly. Note that all
+public channels can be synced using "update-channels".
+Parameter may be a local or remote channel.xml, or the name of
+an existing channel.
+'
+ ),
+ 'channel-info' => array(
+ 'summary' => 'Retrieve Information on a Channel',
+ 'function' => 'doInfo',
+ 'shortcut' => 'ci',
+ 'options' => array(),
+ 'doc' => '<package>
+List the files in an installed package.
+'
+ ),
+ 'channel-alias' => array(
+ 'summary' => 'Specify an alias to a channel name',
+ 'function' => 'doAlias',
+ 'shortcut' => 'cha',
+ 'options' => array(),
+ 'doc' => '<channel> <alias>
+Specify a specific alias to use for a channel name.
+The alias may not be an existing channel name or
+alias.
+'
+ ),
+ 'channel-discover' => array(
+ 'summary' => 'Initialize a Channel from its server',
+ 'function' => 'doDiscover',
+ 'shortcut' => 'di',
+ 'options' => array(),
+ 'doc' => '[<channel.xml>|<channel name>]
+Initialize a channel from its server and create a local channel.xml.
+If <channel name> is in the format "<username>:<password>@<channel>" then
+<username> and <password> will be set as the login username/password for
+<channel>. Use caution when passing the username/password in this way, as
+it may allow other users on your computer to briefly view your username/
+password via the system\'s process list.
+'
+ ),
+ 'channel-login' => array(
+ 'summary' => 'Connects and authenticates to remote channel server',
+ 'shortcut' => 'cli',
+ 'function' => 'doLogin',
+ 'options' => array(),
+ 'doc' => '<channel name>
+Log in to a remote channel server. If <channel name> is not supplied,
+the default channel is used. To use remote functions in the installer
+that require any kind of privileges, you need to log in first. The
+username and password you enter here will be stored in your per-user
+PEAR configuration (~/.pearrc on Unix-like systems). After logging
+in, your username and password will be sent along in subsequent
+operations on the remote server.',
+ ),
+ 'channel-logout' => array(
+ 'summary' => 'Logs out from the remote channel server',
+ 'shortcut' => 'clo',
+ 'function' => 'doLogout',
+ 'options' => array(),
+ 'doc' => '<channel name>
+Logs out from a remote channel server. If <channel name> is not supplied,
+the default channel is used. This command does not actually connect to the
+remote server, it only deletes the stored username and password from your user
+configuration.',
+ ),
+ );
+
+ /**
+ * PEAR_Command_Registry constructor.
+ *
+ * @access public
+ */
+ function PEAR_Command_Channels(&$ui, &$config)
+ {
+ parent::PEAR_Command_Common($ui, $config);
+ }
+
+ function _sortChannels($a, $b)
+ {
+ return strnatcasecmp($a->getName(), $b->getName());
+ }
+
+ function doList($command, $options, $params)
+ {
+ $reg = &$this->config->getRegistry();
+ $registered = $reg->getChannels();
+ usort($registered, array(&$this, '_sortchannels'));
+ $i = $j = 0;
+ $data = array(
+ 'caption' => 'Registered Channels:',
+ 'border' => true,
+ 'headline' => array('Channel', 'Alias', 'Summary')
+ );
+ foreach ($registered as $channel) {
+ $data['data'][] = array($channel->getName(),
+ $channel->getAlias(),
+ $channel->getSummary());
+ }
+
+ if (count($registered) === 0) {
+ $data = '(no registered channels)';
+ }
+ $this->ui->outputData($data, $command);
+ return true;
+ }
+
+ function doUpdateAll($command, $options, $params)
+ {
+ $reg = &$this->config->getRegistry();
+ $channels = $reg->getChannels();
+
+ $success = true;
+ foreach ($channels as $channel) {
+ if ($channel->getName() != '__uri') {
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $err = $this->doUpdate('channel-update',
+ $options,
+ array($channel->getName()));
+ if (PEAR::isError($err)) {
+ $this->ui->outputData($err->getMessage(), $command);
+ $success = false;
+ } else {
+ $success &= $err;
+ }
+ }
+ }
+ return $success;
+ }
+
+ function doInfo($command, $options, $params)
+ {
+ if (count($params) !== 1) {
+ return $this->raiseError("No channel specified");
+ }
+
+ $reg = &$this->config->getRegistry();
+ $channel = strtolower($params[0]);
+ if ($reg->channelExists($channel)) {
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($chan)) {
+ return $this->raiseError($chan);
+ }
+ } else {
+ if (strpos($channel, '://')) {
+ $downloader = &$this->getDownloader();
+ $tmpdir = $this->config->get('temp_dir');
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $loc = $downloader->downloadHttp($channel, $this->ui, $tmpdir);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($loc)) {
+ return $this->raiseError('Cannot open "' . $channel .
+ '" (' . $loc->getMessage() . ')');
+ } else {
+ $contents = implode('', file($loc));
+ }
+ } else {
+ if (!file_exists($params[0])) {
+ return $this->raiseError('Unknown channel "' . $channel . '"');
+ }
+
+ $fp = fopen($params[0], 'r');
+ if (!$fp) {
+ return $this->raiseError('Cannot open "' . $params[0] . '"');
+ }
+
+ $contents = '';
+ while (!feof($fp)) {
+ $contents .= fread($fp, 1024);
+ }
+ fclose($fp);
+ }
+
+ if (!class_exists('PEAR_ChannelFile')) {
+ require_once 'PEAR/ChannelFile.php';
+ }
+
+ $chan = new PEAR_ChannelFile;
+ $chan->fromXmlString($contents);
+ $chan->validate();
+ if ($errs = $chan->getErrors(true)) {
+ foreach ($errs as $err) {
+ $this->ui->outputData($err['level'] . ': ' . $err['message']);
+ }
+ return $this->raiseError('Channel file "' . $params[0] . '" is not valid');
+ }
+ }
+
+ if (!$chan) {
+ return $this->raiseError('Serious error: Channel "' . $params[0] .
+ '" has a corrupted registry entry');
+ }
+
+ $channel = $chan->getName();
+ $caption = 'Channel ' . $channel . ' Information:';
+ $data1 = array(
+ 'caption' => $caption,
+ 'border' => true);
+ $data1['data']['server'] = array('Name and Server', $chan->getName());
+ if ($chan->getAlias() != $chan->getName()) {
+ $data1['data']['alias'] = array('Alias', $chan->getAlias());
+ }
+
+ $data1['data']['summary'] = array('Summary', $chan->getSummary());
+ $validate = $chan->getValidationPackage();
+ $data1['data']['vpackage'] = array('Validation Package Name', $validate['_content']);
+ $data1['data']['vpackageversion'] =
+ array('Validation Package Version', $validate['attribs']['version']);
+ $d = array();
+ $d['main'] = $data1;
+
+ $data['data'] = array();
+ $data['caption'] = 'Server Capabilities';
+ $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
+ if ($chan->supportsREST()) {
+ if ($chan->supportsREST()) {
+ $funcs = $chan->getFunctions('rest');
+ if (!isset($funcs[0])) {
+ $funcs = array($funcs);
+ }
+ foreach ($funcs as $protocol) {
+ $data['data'][] = array('rest', $protocol['attribs']['type'],
+ $protocol['_content']);
+ }
+ }
+ } else {
+ $data['data'][] = array('No supported protocols');
+ }
+
+ $d['protocols'] = $data;
+ $data['data'] = array();
+ $mirrors = $chan->getMirrors();
+ if ($mirrors) {
+ $data['caption'] = 'Channel ' . $channel . ' Mirrors:';
+ unset($data['headline']);
+ foreach ($mirrors as $mirror) {
+ $data['data'][] = array($mirror['attribs']['host']);
+ $d['mirrors'] = $data;
+ }
+
+ foreach ($mirrors as $i => $mirror) {
+ $data['data'] = array();
+ $data['caption'] = 'Mirror ' . $mirror['attribs']['host'] . ' Capabilities';
+ $data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
+ if ($chan->supportsREST($mirror['attribs']['host'])) {
+ if ($chan->supportsREST($mirror['attribs']['host'])) {
+ $funcs = $chan->getFunctions('rest', $mirror['attribs']['host']);
+ if (!isset($funcs[0])) {
+ $funcs = array($funcs);
+ }
+
+ foreach ($funcs as $protocol) {
+ $data['data'][] = array('rest', $protocol['attribs']['type'],
+ $protocol['_content']);
+ }
+ }
+ } else {
+ $data['data'][] = array('No supported protocols');
+ }
+ $d['mirrorprotocols' . $i] = $data;
+ }
+ }
+ $this->ui->outputData($d, 'channel-info');
+ }
+
+ // }}}
+
+ function doDelete($command, $options, $params)
+ {
+ if (count($params) !== 1) {
+ return $this->raiseError('channel-delete: no channel specified');
+ }
+
+ $reg = &$this->config->getRegistry();
+ if (!$reg->channelExists($params[0])) {
+ return $this->raiseError('channel-delete: channel "' . $params[0] . '" does not exist');
+ }
+
+ $channel = $reg->channelName($params[0]);
+ if ($channel == 'pear.php.net') {
+ return $this->raiseError('Cannot delete the pear.php.net channel');
+ }
+
+ if ($channel == 'pecl.php.net') {
+ return $this->raiseError('Cannot delete the pecl.php.net channel');
+ }
+
+ if ($channel == 'doc.php.net') {
+ return $this->raiseError('Cannot delete the doc.php.net channel');
+ }
+
+ if ($channel == '__uri') {
+ return $this->raiseError('Cannot delete the __uri pseudo-channel');
+ }
+
+ if (PEAR::isError($err = $reg->listPackages($channel))) {
+ return $err;
+ }
+
+ if (count($err)) {
+ return $this->raiseError('Channel "' . $channel .
+ '" has installed packages, cannot delete');
+ }
+
+ if (!$reg->deleteChannel($channel)) {
+ return $this->raiseError('Channel "' . $channel . '" deletion failed');
+ } else {
+ $this->config->deleteChannel($channel);
+ $this->ui->outputData('Channel "' . $channel . '" deleted', $command);
+ }
+ }
+
+ function doAdd($command, $options, $params)
+ {
+ if (count($params) !== 1) {
+ return $this->raiseError('channel-add: no channel file specified');
+ }
+
+ if (strpos($params[0], '://')) {
+ $downloader = &$this->getDownloader();
+ $tmpdir = $this->config->get('temp_dir');
+ if (!file_exists($tmpdir)) {
+ require_once 'System.php';
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $err = System::mkdir(array('-p', $tmpdir));
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($err)) {
+ return $this->raiseError('channel-add: temp_dir does not exist: "' .
+ $tmpdir .
+ '" - You can change this location with "pear config-set temp_dir"');
+ }
+ }
+
+ if (!is_writable($tmpdir)) {
+ return $this->raiseError('channel-add: temp_dir is not writable: "' .
+ $tmpdir .
+ '" - You can change this location with "pear config-set temp_dir"');
+ }
+
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $loc = $downloader->downloadHttp($params[0], $this->ui, $tmpdir, null, false);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($loc)) {
+ return $this->raiseError('channel-add: Cannot open "' . $params[0] .
+ '" (' . $loc->getMessage() . ')');
+ }
+
+ list($loc, $lastmodified) = $loc;
+ $contents = implode('', file($loc));
+ } else {
+ $lastmodified = $fp = false;
+ if (file_exists($params[0])) {
+ $fp = fopen($params[0], 'r');
+ }
+
+ if (!$fp) {
+ return $this->raiseError('channel-add: cannot open "' . $params[0] . '"');
+ }
+
+ $contents = '';
+ while (!feof($fp)) {
+ $contents .= fread($fp, 1024);
+ }
+ fclose($fp);
+ }
+
+ if (!class_exists('PEAR_ChannelFile')) {
+ require_once 'PEAR/ChannelFile.php';
+ }
+
+ $channel = new PEAR_ChannelFile;
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $result = $channel->fromXmlString($contents);
+ PEAR::staticPopErrorHandling();
+ if (!$result) {
+ $exit = false;
+ if (count($errors = $channel->getErrors(true))) {
+ foreach ($errors as $error) {
+ $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
+ if (!$exit) {
+ $exit = $error['level'] == 'error' ? true : false;
+ }
+ }
+ if ($exit) {
+ return $this->raiseError('channel-add: invalid channel.xml file');
+ }
+ }
+ }
+
+ $reg = &$this->config->getRegistry();
+ if ($reg->channelExists($channel->getName())) {
+ return $this->raiseError('channel-add: Channel "' . $channel->getName() .
+ '" exists, use channel-update to update entry', PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
+ }
+
+ $ret = $reg->addChannel($channel, $lastmodified);
+ if (PEAR::isError($ret)) {
+ return $ret;
+ }
+
+ if (!$ret) {
+ return $this->raiseError('channel-add: adding Channel "' . $channel->getName() .
+ '" to registry failed');
+ }
+
+ $this->config->setChannels($reg->listChannels());
+ $this->config->writeConfigFile();
+ $this->ui->outputData('Adding Channel "' . $channel->getName() . '" succeeded', $command);
+ }
+
+ function doUpdate($command, $options, $params)
+ {
+ if (count($params) !== 1) {
+ return $this->raiseError("No channel file specified");
+ }
+
+ $tmpdir = $this->config->get('temp_dir');
+ if (!file_exists($tmpdir)) {
+ require_once 'System.php';
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $err = System::mkdir(array('-p', $tmpdir));
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($err)) {
+ return $this->raiseError('channel-add: temp_dir does not exist: "' .
+ $tmpdir .
+ '" - You can change this location with "pear config-set temp_dir"');
+ }
+ }
+
+ if (!is_writable($tmpdir)) {
+ return $this->raiseError('channel-add: temp_dir is not writable: "' .
+ $tmpdir .
+ '" - You can change this location with "pear config-set temp_dir"');
+ }
+
+ $reg = &$this->config->getRegistry();
+ $lastmodified = false;
+ if ((!file_exists($params[0]) || is_dir($params[0]))
+ && $reg->channelExists(strtolower($params[0]))) {
+ $c = $reg->getChannel(strtolower($params[0]));
+ if (PEAR::isError($c)) {
+ return $this->raiseError($c);
+ }
+
+ $this->ui->outputData("Updating channel \"$params[0]\"", $command);
+ $dl = &$this->getDownloader(array());
+ // if force is specified, use a timestamp of "1" to force retrieval
+ $lastmodified = isset($options['force']) ? false : $c->lastModified();
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $contents = $dl->downloadHttp('http://' . $c->getName() . '/channel.xml',
+ $this->ui, $tmpdir, null, $lastmodified);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($contents)) {
+ // Attempt to fall back to https
+ $this->ui->outputData("Channel \"$params[0]\" is not responding over http://, failed with message: " . $contents->getMessage());
+ $this->ui->outputData("Trying channel \"$params[0]\" over https:// instead");
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $contents = $dl->downloadHttp('https://' . $c->getName() . '/channel.xml',
+ $this->ui, $tmpdir, null, $lastmodified);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($contents)) {
+ return $this->raiseError('Cannot retrieve channel.xml for channel "' .
+ $c->getName() . '" (' . $contents->getMessage() . ')');
+ }
+ }
+
+ list($contents, $lastmodified) = $contents;
+ if (!$contents) {
+ $this->ui->outputData("Channel \"$params[0]\" is up to date");
+ return;
+ }
+
+ $contents = implode('', file($contents));
+ if (!class_exists('PEAR_ChannelFile')) {
+ require_once 'PEAR/ChannelFile.php';
+ }
+
+ $channel = new PEAR_ChannelFile;
+ $channel->fromXmlString($contents);
+ if (!$channel->getErrors()) {
+ // security check: is the downloaded file for the channel we got it from?
+ if (strtolower($channel->getName()) != strtolower($c->getName())) {
+ if (!isset($options['force'])) {
+ return $this->raiseError('ERROR: downloaded channel definition file' .
+ ' for channel "' . $channel->getName() . '" from channel "' .
+ strtolower($c->getName()) . '"');
+ }
+
+ $this->ui->log(0, 'WARNING: downloaded channel definition file' .
+ ' for channel "' . $channel->getName() . '" from channel "' .
+ strtolower($c->getName()) . '"');
+ }
+ }
+ } else {
+ if (strpos($params[0], '://')) {
+ $dl = &$this->getDownloader();
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $loc = $dl->downloadHttp($params[0],
+ $this->ui, $tmpdir, null, $lastmodified);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($loc)) {
+ return $this->raiseError("Cannot open " . $params[0] .
+ ' (' . $loc->getMessage() . ')');
+ }
+
+ list($loc, $lastmodified) = $loc;
+ $contents = implode('', file($loc));
+ } else {
+ $fp = false;
+ if (file_exists($params[0])) {
+ $fp = fopen($params[0], 'r');
+ }
+
+ if (!$fp) {
+ return $this->raiseError("Cannot open " . $params[0]);
+ }
+
+ $contents = '';
+ while (!feof($fp)) {
+ $contents .= fread($fp, 1024);
+ }
+ fclose($fp);
+ }
+
+ if (!class_exists('PEAR_ChannelFile')) {
+ require_once 'PEAR/ChannelFile.php';
+ }
+
+ $channel = new PEAR_ChannelFile;
+ $channel->fromXmlString($contents);
+ }
+
+ $exit = false;
+ if (count($errors = $channel->getErrors(true))) {
+ foreach ($errors as $error) {
+ $this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
+ if (!$exit) {
+ $exit = $error['level'] == 'error' ? true : false;
+ }
+ }
+ if ($exit) {
+ return $this->raiseError('Invalid channel.xml file');
+ }
+ }
+
+ if (!$reg->channelExists($channel->getName())) {
+ return $this->raiseError('Error: Channel "' . $channel->getName() .
+ '" does not exist, use channel-add to add an entry');
+ }
+
+ $ret = $reg->updateChannel($channel, $lastmodified);
+ if (PEAR::isError($ret)) {
+ return $ret;
+ }
+
+ if (!$ret) {
+ return $this->raiseError('Updating Channel "' . $channel->getName() .
+ '" in registry failed');
+ }
+
+ $this->config->setChannels($reg->listChannels());
+ $this->config->writeConfigFile();
+ $this->ui->outputData('Update of Channel "' . $channel->getName() . '" succeeded');
+ }
+
+ function &getDownloader()
+ {
+ if (!class_exists('PEAR_Downloader')) {
+ require_once 'PEAR/Downloader.php';
+ }
+ $a = new PEAR_Downloader($this->ui, array(), $this->config);
+ return $a;
+ }
+
+ function doAlias($command, $options, $params)
+ {
+ if (count($params) === 1) {
+ return $this->raiseError('No channel alias specified');
+ }
+
+ if (count($params) !== 2 || (!empty($params[1]) && $params[1]{0} == '-')) {
+ return $this->raiseError(
+ 'Invalid format, correct is: channel-alias channel alias');
+ }
+
+ $reg = &$this->config->getRegistry();
+ if (!$reg->channelExists($params[0], true)) {
+ $extra = '';
+ if ($reg->isAlias($params[0])) {
+ $extra = ' (use "channel-alias ' . $reg->channelName($params[0]) . ' ' .
+ strtolower($params[1]) . '")';
+ }
+
+ return $this->raiseError('"' . $params[0] . '" is not a valid channel' . $extra);
+ }
+
+ if ($reg->isAlias($params[1])) {
+ return $this->raiseError('Channel "' . $reg->channelName($params[1]) . '" is ' .
+ 'already aliased to "' . strtolower($params[1]) . '", cannot re-alias');
+ }
+
+ $chan = &$reg->getChannel($params[0]);
+ if (PEAR::isError($chan)) {
+ return $this->raiseError('Corrupt registry? Error retrieving channel "' . $params[0] .
+ '" information (' . $chan->getMessage() . ')');
+ }
+
+ // make it a local alias
+ if (!$chan->setAlias(strtolower($params[1]), true)) {
+ return $this->raiseError('Alias "' . strtolower($params[1]) .
+ '" is not a valid channel alias');
+ }
+
+ $reg->updateChannel($chan);
+ $this->ui->outputData('Channel "' . $chan->getName() . '" aliased successfully to "' .
+ strtolower($params[1]) . '"');
+ }
+
+ /**
+ * The channel-discover command
+ *
+ * @param string $command command name
+ * @param array $options option_name => value
+ * @param array $params list of additional parameters.
+ * $params[0] should contain a string with either:
+ * - <channel name> or
+ * - <username>:<password>@<channel name>
+ * @return null|PEAR_Error
+ */
+ function doDiscover($command, $options, $params)
+ {
+ if (count($params) !== 1) {
+ return $this->raiseError("No channel server specified");
+ }
+
+ // Look for the possible input format "<username>:<password>@<channel>"
+ if (preg_match('/^(.+):(.+)@(.+)\\z/', $params[0], $matches)) {
+ $username = $matches[1];
+ $password = $matches[2];
+ $channel = $matches[3];
+ } else {
+ $channel = $params[0];
+ }
+
+ $reg = &$this->config->getRegistry();
+ if ($reg->channelExists($channel)) {
+ if (!$reg->isAlias($channel)) {
+ return $this->raiseError("Channel \"$channel\" is already initialized", PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS);
+ }
+
+ return $this->raiseError("A channel alias named \"$channel\" " .
+ 'already exists, aliasing channel "' . $reg->channelName($channel)
+ . '"');
+ }
+
+ $this->pushErrorHandling(PEAR_ERROR_RETURN);
+ $err = $this->doAdd($command, $options, array('http://' . $channel . '/channel.xml'));
+ $this->popErrorHandling();
+ if (PEAR::isError($err)) {
+ if ($err->getCode() === PEAR_COMMAND_CHANNELS_CHANNEL_EXISTS) {
+ return $this->raiseError("Discovery of channel \"$channel\" failed (" .
+ $err->getMessage() . ')');
+ }
+ // Attempt fetch via https
+ $this->ui->outputData("Discovering channel $channel over http:// failed with message: " . $err->getMessage());
+ $this->ui->outputData("Trying to discover channel $channel over https:// instead");
+ $this->pushErrorHandling(PEAR_ERROR_RETURN);
+ $err = $this->doAdd($command, $options, array('https://' . $channel . '/channel.xml'));
+ $this->popErrorHandling();
+ if (PEAR::isError($err)) {
+ return $this->raiseError("Discovery of channel \"$channel\" failed (" .
+ $err->getMessage() . ')');
+ }
+ }
+
+ // Store username/password if they were given
+ // Arguably we should do a logintest on the channel here, but since
+ // that's awkward on a REST-based channel (even "pear login" doesn't
+ // do it for those), and XML-RPC is deprecated, it's fairly pointless.
+ if (isset($username)) {
+ $this->config->set('username', $username, 'user', $channel);
+ $this->config->set('password', $password, 'user', $channel);
+ $this->config->store();
+ $this->ui->outputData("Stored login for channel \"$channel\" using username \"$username\"", $command);
+ }
+
+ $this->ui->outputData("Discovery of channel \"$channel\" succeeded", $command);
+ }
+
+ /**
+ * Execute the 'login' command.
+ *
+ * @param string $command command name
+ * @param array $options option_name => value
+ * @param array $params list of additional parameters
+ *
+ * @return bool TRUE on success or
+ * a PEAR error on failure
+ *
+ * @access public
+ */
+ function doLogin($command, $options, $params)
+ {
+ $reg = &$this->config->getRegistry();
+
+ // If a parameter is supplied, use that as the channel to log in to
+ $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');
+
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($chan)) {
+ return $this->raiseError($chan);
+ }
+
+ $server = $this->config->get('preferred_mirror', null, $channel);
+ $username = $this->config->get('username', null, $channel);
+ if (empty($username)) {
+ $username = isset($_ENV['USER']) ? $_ENV['USER'] : null;
+ }
+ $this->ui->outputData("Logging in to $server.", $command);
+
+ list($username, $password) = $this->ui->userDialog(
+ $command,
+ array('Username', 'Password'),
+ array('text', 'password'),
+ array($username, '')
+ );
+ $username = trim($username);
+ $password = trim($password);
+
+ $ourfile = $this->config->getConfFile('user');
+ if (!$ourfile) {
+ $ourfile = $this->config->getConfFile('system');
+ }
+
+ $this->config->set('username', $username, 'user', $channel);
+ $this->config->set('password', $password, 'user', $channel);
+
+ if ($chan->supportsREST()) {
+ $ok = true;
+ }
+
+ if ($ok !== true) {
+ return $this->raiseError('Login failed!');
+ }
+
+ $this->ui->outputData("Logged in.", $command);
+ // avoid changing any temporary settings changed with -d
+ $ourconfig = new PEAR_Config($ourfile, $ourfile);
+ $ourconfig->set('username', $username, 'user', $channel);
+ $ourconfig->set('password', $password, 'user', $channel);
+ $ourconfig->store();
+
+ return true;
+ }
+
+ /**
+ * Execute the 'logout' command.
+ *
+ * @param string $command command name
+ * @param array $options option_name => value
+ * @param array $params list of additional parameters
+ *
+ * @return bool TRUE on success or
+ * a PEAR error on failure
+ *
+ * @access public
+ */
+ function doLogout($command, $options, $params)
+ {
+ $reg = &$this->config->getRegistry();
+
+ // If a parameter is supplied, use that as the channel to log in to
+ $channel = isset($params[0]) ? $params[0] : $this->config->get('default_channel');
+
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($chan)) {
+ return $this->raiseError($chan);
+ }
+
+ $server = $this->config->get('preferred_mirror', null, $channel);
+ $this->ui->outputData("Logging out from $server.", $command);
+ $this->config->remove('username', 'user', $channel);
+ $this->config->remove('password', 'user', $channel);
+ $this->config->store();
+ return true;
+ }
+} \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Channels.xml b/3rdparty/PEAR/Command/Channels.xml
new file mode 100644
index 00000000000..47b72066abf
--- /dev/null
+++ b/3rdparty/PEAR/Command/Channels.xml
@@ -0,0 +1,123 @@
+<commands version="1.0">
+ <list-channels>
+ <summary>List Available Channels</summary>
+ <function>doList</function>
+ <shortcut>lc</shortcut>
+ <options />
+ <doc>
+List all available channels for installation.
+</doc>
+ </list-channels>
+ <update-channels>
+ <summary>Update the Channel List</summary>
+ <function>doUpdateAll</function>
+ <shortcut>uc</shortcut>
+ <options />
+ <doc>
+List all installed packages in all channels.
+</doc>
+ </update-channels>
+ <channel-delete>
+ <summary>Remove a Channel From the List</summary>
+ <function>doDelete</function>
+ <shortcut>cde</shortcut>
+ <options />
+ <doc>&lt;channel name&gt;
+Delete a channel from the registry. You may not
+remove any channel that has installed packages.
+</doc>
+ </channel-delete>
+ <channel-add>
+ <summary>Add a Channel</summary>
+ <function>doAdd</function>
+ <shortcut>ca</shortcut>
+ <options />
+ <doc>&lt;channel.xml&gt;
+Add a private channel to the channel list. Note that all
+public channels should be synced using &quot;update-channels&quot;.
+Parameter may be either a local file or remote URL to a
+channel.xml.
+</doc>
+ </channel-add>
+ <channel-update>
+ <summary>Update an Existing Channel</summary>
+ <function>doUpdate</function>
+ <shortcut>cu</shortcut>
+ <options>
+ <force>
+ <shortopt>f</shortopt>
+ <doc>will force download of new channel.xml if an existing channel name is used</doc>
+ </force>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>will force download of new channel.xml if an existing channel name is used</doc>
+ <arg>CHANNEL</arg>
+ </channel>
+ </options>
+ <doc>[&lt;channel.xml&gt;|&lt;channel name&gt;]
+Update a channel in the channel list directly. Note that all
+public channels can be synced using &quot;update-channels&quot;.
+Parameter may be a local or remote channel.xml, or the name of
+an existing channel.
+</doc>
+ </channel-update>
+ <channel-info>
+ <summary>Retrieve Information on a Channel</summary>
+ <function>doInfo</function>
+ <shortcut>ci</shortcut>
+ <options />
+ <doc>&lt;package&gt;
+List the files in an installed package.
+</doc>
+ </channel-info>
+ <channel-alias>
+ <summary>Specify an alias to a channel name</summary>
+ <function>doAlias</function>
+ <shortcut>cha</shortcut>
+ <options />
+ <doc>&lt;channel&gt; &lt;alias&gt;
+Specify a specific alias to use for a channel name.
+The alias may not be an existing channel name or
+alias.
+</doc>
+ </channel-alias>
+ <channel-discover>
+ <summary>Initialize a Channel from its server</summary>
+ <function>doDiscover</function>
+ <shortcut>di</shortcut>
+ <options />
+ <doc>[&lt;channel.xml&gt;|&lt;channel name&gt;]
+Initialize a channel from its server and create a local channel.xml.
+If &lt;channel name&gt; is in the format &quot;&lt;username&gt;:&lt;password&gt;@&lt;channel&gt;&quot; then
+&lt;username&gt; and &lt;password&gt; will be set as the login username/password for
+&lt;channel&gt;. Use caution when passing the username/password in this way, as
+it may allow other users on your computer to briefly view your username/
+password via the system&#039;s process list.
+</doc>
+ </channel-discover>
+ <channel-login>
+ <summary>Connects and authenticates to remote channel server</summary>
+ <function>doLogin</function>
+ <shortcut>cli</shortcut>
+ <options />
+ <doc>&lt;channel name&gt;
+Log in to a remote channel server. If &lt;channel name&gt; is not supplied,
+the default channel is used. To use remote functions in the installer
+that require any kind of privileges, you need to log in first. The
+username and password you enter here will be stored in your per-user
+PEAR configuration (~/.pearrc on Unix-like systems). After logging
+in, your username and password will be sent along in subsequent
+operations on the remote server.</doc>
+ </channel-login>
+ <channel-logout>
+ <summary>Logs out from the remote channel server</summary>
+ <function>doLogout</function>
+ <shortcut>clo</shortcut>
+ <options />
+ <doc>&lt;channel name&gt;
+Logs out from a remote channel server. If &lt;channel name&gt; is not supplied,
+the default channel is used. This command does not actually connect to the
+remote server, it only deletes the stored username and password from your user
+configuration.</doc>
+ </channel-logout>
+</commands> \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Common.php b/3rdparty/PEAR/Command/Common.php
index c6ace694caf..279a716623d 100644
--- a/3rdparty/PEAR/Command/Common.php
+++ b/3rdparty/PEAR/Command/Common.php
@@ -1,36 +1,52 @@
<?php
-//
-// +----------------------------------------------------------------------+
-// | PHP Version 5 |
-// +----------------------------------------------------------------------+
-// | Copyright (c) 1997-2004 The PHP Group |
-// +----------------------------------------------------------------------+
-// | This source file is subject to version 3.0 of the PHP license, |
-// | that is bundled with this package in the file LICENSE, and is |
-// | available through the world-wide-web at the following url: |
-// | http://www.php.net/license/3_0.txt. |
-// | If you did not receive a copy of the PHP license and are unable to |
-// | obtain it through the world-wide-web, please send a note to |
-// | license@php.net so we can mail you a copy immediately. |
-// +----------------------------------------------------------------------+
-// | Author: Stig Sæther Bakken <ssb@php.net> |
-// +----------------------------------------------------------------------+
-//
-// $Id: Common.php,v 1.24 2004/01/08 17:33:13 sniper Exp $
-
-require_once "PEAR.php";
+/**
+ * PEAR_Command_Common base class
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ */
+/**
+ * base class
+ */
+require_once 'PEAR.php';
+
+/**
+ * PEAR commands base class
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 0.1
+ */
class PEAR_Command_Common extends PEAR
{
- // {{{ properties
-
/**
* PEAR_Config object used to pass user system and configuration
* on when executing commands
*
- * @var object
+ * @var PEAR_Config
*/
var $config;
+ /**
+ * @var PEAR_Registry
+ * @access protected
+ */
+ var $_registry;
/**
* User Interface object, for all interaction with the user.
@@ -50,7 +66,7 @@ class PEAR_Command_Common extends PEAR
var $_deps_type_trans = array(
'pkg' => 'package',
- 'extension' => 'extension',
+ 'ext' => 'extension',
'php' => 'PHP',
'prog' => 'external program',
'ldlib' => 'external library for linking',
@@ -60,9 +76,6 @@ class PEAR_Command_Common extends PEAR
'sapi' => 'SAPI backend'
);
- // }}}
- // {{{ constructor
-
/**
* PEAR_Command_Common constructor.
*
@@ -75,10 +88,6 @@ class PEAR_Command_Common extends PEAR
$this->ui = &$ui;
}
- // }}}
-
- // {{{ getCommands()
-
/**
* Return a list of all the commands defined by this class.
* @return array list of commands
@@ -90,12 +99,10 @@ class PEAR_Command_Common extends PEAR
foreach (array_keys($this->commands) as $command) {
$ret[$command] = $this->commands[$command]['summary'];
}
+
return $ret;
}
- // }}}
- // {{{ getShortcuts()
-
/**
* Return a list of all the command shortcuts defined by this class.
* @return array shortcut => command
@@ -109,28 +116,34 @@ class PEAR_Command_Common extends PEAR
$ret[$this->commands[$command]['shortcut']] = $command;
}
}
+
return $ret;
}
- // }}}
- // {{{ getOptions()
-
function getOptions($command)
{
- return @$this->commands[$command]['options'];
- }
+ $shortcuts = $this->getShortcuts();
+ if (isset($shortcuts[$command])) {
+ $command = $shortcuts[$command];
+ }
- // }}}
- // {{{ getGetoptArgs()
+ if (isset($this->commands[$command]) &&
+ isset($this->commands[$command]['options'])) {
+ return $this->commands[$command]['options'];
+ }
+
+ return null;
+ }
function getGetoptArgs($command, &$short_args, &$long_args)
{
- $short_args = "";
+ $short_args = '';
$long_args = array();
- if (empty($this->commands[$command])) {
+ if (empty($this->commands[$command]) || empty($this->commands[$command]['options'])) {
return;
}
- reset($this->commands[$command]);
+
+ reset($this->commands[$command]['options']);
while (list($option, $info) = each($this->commands[$command]['options'])) {
$larg = $sarg = '';
if (isset($info['arg'])) {
@@ -144,15 +157,15 @@ class PEAR_Command_Common extends PEAR
$arg = $info['arg'];
}
}
+
if (isset($info['shortopt'])) {
$short_args .= $info['shortopt'] . $sarg;
}
+
$long_args[] = $option . $larg;
}
}
- // }}}
- // {{{ getHelp()
/**
* Returns the help message for the given command
*
@@ -164,29 +177,38 @@ class PEAR_Command_Common extends PEAR
function getHelp($command)
{
$config = &PEAR_Config::singleton();
- $help = @$this->commands[$command]['doc'];
+ if (!isset($this->commands[$command])) {
+ return "No such command \"$command\"";
+ }
+
+ $help = null;
+ if (isset($this->commands[$command]['doc'])) {
+ $help = $this->commands[$command]['doc'];
+ }
+
if (empty($help)) {
// XXX (cox) Fallback to summary if there is no doc (show both?)
- if (!$help = @$this->commands[$command]['summary']) {
+ if (!isset($this->commands[$command]['summary'])) {
return "No help for command \"$command\"";
}
+ $help = $this->commands[$command]['summary'];
}
+
if (preg_match_all('/{config\s+([^\}]+)}/e', $help, $matches)) {
foreach($matches[0] as $k => $v) {
$help = preg_replace("/$v/", $config->get($matches[1][$k]), $help);
}
}
+
return array($help, $this->getHelpArgs($command));
}
- // }}}
- // {{{ getHelpArgs()
/**
- * Returns the help for the accepted arguments of a command
- *
- * @param string $command
- * @return string The help string
- */
+ * Returns the help for the accepted arguments of a command
+ *
+ * @param string $command
+ * @return string The help string
+ */
function getHelpArgs($command)
{
if (isset($this->commands[$command]['options']) &&
@@ -195,7 +217,7 @@ class PEAR_Command_Common extends PEAR
$help = "Options:\n";
foreach ($this->commands[$command]['options'] as $k => $v) {
if (isset($v['arg'])) {
- if ($v['arg']{0} == '(') {
+ if ($v['arg'][0] == '(') {
$arg = substr($v['arg'], 1, -1);
$sapp = " [$arg]";
$lapp = "[=$arg]";
@@ -206,44 +228,46 @@ class PEAR_Command_Common extends PEAR
} else {
$sapp = $lapp = "";
}
+
if (isset($v['shortopt'])) {
$s = $v['shortopt'];
- @$help .= " -$s$sapp, --$k$lapp\n";
+ $help .= " -$s$sapp, --$k$lapp\n";
} else {
- @$help .= " --$k$lapp\n";
+ $help .= " --$k$lapp\n";
}
+
$p = " ";
$doc = rtrim(str_replace("\n", "\n$p", $v['doc']));
$help .= " $doc\n";
}
+
return $help;
}
+
return null;
}
- // }}}
- // {{{ run()
-
function run($command, $options, $params)
{
- $func = @$this->commands[$command]['function'];
- if (empty($func)) {
+ if (empty($this->commands[$command]['function'])) {
// look for shortcuts
foreach (array_keys($this->commands) as $cmd) {
- if (@$this->commands[$cmd]['shortcut'] == $command) {
- $command = $cmd;
- $func = @$this->commands[$command]['function'];
- if (empty($func)) {
+ if (isset($this->commands[$cmd]['shortcut']) && $this->commands[$cmd]['shortcut'] == $command) {
+ if (empty($this->commands[$cmd]['function'])) {
return $this->raiseError("unknown command `$command'");
+ } else {
+ $func = $this->commands[$cmd]['function'];
}
+ $command = $cmd;
+
+ //$command = $this->commands[$cmd]['function'];
break;
}
}
+ } else {
+ $func = $this->commands[$command]['function'];
}
+
return $this->$func($command, $options, $params);
}
-
- // }}}
-}
-
-?> \ No newline at end of file
+} \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Config.php b/3rdparty/PEAR/Command/Config.php
index 474a2345170..a761b277f5f 100644
--- a/3rdparty/PEAR/Command/Config.php
+++ b/3rdparty/PEAR/Command/Config.php
@@ -1,74 +1,101 @@
<?php
-//
-// +----------------------------------------------------------------------+
-// | PHP Version 5 |
-// +----------------------------------------------------------------------+
-// | Copyright (c) 1997-2004 The PHP Group |
-// +----------------------------------------------------------------------+
-// | This source file is subject to version 3.0 of the PHP license, |
-// | that is bundled with this package in the file LICENSE, and is |
-// | available through the world-wide-web at the following url: |
-// | http://www.php.net/license/3_0.txt. |
-// | If you did not receive a copy of the PHP license and are unable to |
-// | obtain it through the world-wide-web, please send a note to |
-// | license@php.net so we can mail you a copy immediately. |
-// +----------------------------------------------------------------------+
-// | Author: Stig Bakken <ssb@php.net> |
-// | Tomas V.V.Cox <cox@idecnet.com> |
-// | |
-// +----------------------------------------------------------------------+
-//
-// $Id: Config.php,v 1.27 2004/06/15 16:48:49 pajoye Exp $
-
-require_once "PEAR/Command/Common.php";
-require_once "PEAR/Config.php";
+/**
+ * PEAR_Command_Config (config-show, config-get, config-set, config-help, config-create commands)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Config.php 313024 2011-07-06 19:51:24Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ */
+
+/**
+ * base class
+ */
+require_once 'PEAR/Command/Common.php';
/**
* PEAR commands for managing configuration data.
*
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 0.1
*/
class PEAR_Command_Config extends PEAR_Command_Common
{
- // {{{ properties
-
var $commands = array(
'config-show' => array(
'summary' => 'Show All Settings',
'function' => 'doConfigShow',
'shortcut' => 'csh',
- 'options' => array(),
- 'doc' => '
+ 'options' => array(
+ 'channel' => array(
+ 'shortopt' => 'c',
+ 'doc' => 'show configuration variables for another channel',
+ 'arg' => 'CHAN',
+ ),
+),
+ 'doc' => '[layer]
Displays all configuration values. An optional argument
may be used to tell which configuration layer to display. Valid
-configuration layers are "user", "system" and "default".
+configuration layers are "user", "system" and "default". To display
+configurations for different channels, set the default_channel
+configuration variable and run config-show again.
',
),
'config-get' => array(
'summary' => 'Show One Setting',
'function' => 'doConfigGet',
'shortcut' => 'cg',
- 'options' => array(),
+ 'options' => array(
+ 'channel' => array(
+ 'shortopt' => 'c',
+ 'doc' => 'show configuration variables for another channel',
+ 'arg' => 'CHAN',
+ ),
+),
'doc' => '<parameter> [layer]
Displays the value of one configuration parameter. The
first argument is the name of the parameter, an optional second argument
may be used to tell which configuration layer to look in. Valid configuration
layers are "user", "system" and "default". If no layer is specified, a value
will be picked from the first layer that defines the parameter, in the order
-just specified.
+just specified. The configuration value will be retrieved for the channel
+specified by the default_channel configuration variable.
',
),
'config-set' => array(
'summary' => 'Change Setting',
'function' => 'doConfigSet',
'shortcut' => 'cs',
- 'options' => array(),
+ 'options' => array(
+ 'channel' => array(
+ 'shortopt' => 'c',
+ 'doc' => 'show configuration variables for another channel',
+ 'arg' => 'CHAN',
+ ),
+),
'doc' => '<parameter> <value> [layer]
Sets the value of one configuration parameter. The first argument is
the name of the parameter, the second argument is the new value. Some
parameters are subject to validation, and the command will fail with
an error message if the new value does not make sense. An optional
third argument may be used to specify in which layer to set the
-configuration parameter. The default layer is "user".
+configuration parameter. The default layer is "user". The
+configuration value will be set for the current channel, which
+is controlled by the default_channel configuration variable.
',
),
'config-help' => array(
@@ -81,11 +108,26 @@ Displays help for a configuration parameter. Without arguments it
displays help for all configuration parameters.
',
),
+ 'config-create' => array(
+ 'summary' => 'Create a Default configuration file',
+ 'function' => 'doConfigCreate',
+ 'shortcut' => 'coc',
+ 'options' => array(
+ 'windows' => array(
+ 'shortopt' => 'w',
+ 'doc' => 'create a config file for a windows install',
+ ),
+ ),
+ 'doc' => '<root path> <filename>
+Create a default configuration file with all directory configuration
+variables set to subdirectories of <root path>, and save it as <filename>.
+This is useful especially for creating a configuration file for a remote
+PEAR installation (using the --remoteconfig option of install, upgrade,
+and uninstall).
+',
+ ),
);
- // }}}
- // {{{ constructor
-
/**
* PEAR_Command_Config constructor.
*
@@ -96,94 +138,154 @@ displays help for all configuration parameters.
parent::PEAR_Command_Common($ui, $config);
}
- // }}}
-
- // {{{ doConfigShow()
-
function doConfigShow($command, $options, $params)
{
+ $layer = null;
+ if (is_array($params)) {
+ $layer = isset($params[0]) ? $params[0] : null;
+ }
+
// $params[0] -> the layer
- if ($error = $this->_checkLayer(@$params[0])) {
- return $this->raiseError($error);
+ if ($error = $this->_checkLayer($layer)) {
+ return $this->raiseError("config-show:$error");
}
+
$keys = $this->config->getKeys();
sort($keys);
- $data = array('caption' => 'Configuration:');
+ $channel = isset($options['channel']) ? $options['channel'] :
+ $this->config->get('default_channel');
+ $reg = &$this->config->getRegistry();
+ if (!$reg->channelExists($channel)) {
+ return $this->raiseError('Channel "' . $channel . '" does not exist');
+ }
+
+ $channel = $reg->channelName($channel);
+ $data = array('caption' => 'Configuration (channel ' . $channel . '):');
foreach ($keys as $key) {
$type = $this->config->getType($key);
- $value = $this->config->get($key, @$params[0]);
+ $value = $this->config->get($key, $layer, $channel);
if ($type == 'password' && $value) {
$value = '********';
}
+
if ($value === false) {
$value = 'false';
} elseif ($value === true) {
$value = 'true';
}
+
$data['data'][$this->config->getGroup($key)][] = array($this->config->getPrompt($key) , $key, $value);
}
+
+ foreach ($this->config->getLayers() as $layer) {
+ $data['data']['Config Files'][] = array(ucfirst($layer) . ' Configuration File', 'Filename' , $this->config->getConfFile($layer));
+ }
+
$this->ui->outputData($data, $command);
return true;
}
- // }}}
- // {{{ doConfigGet()
-
function doConfigGet($command, $options, $params)
{
- // $params[0] -> the parameter
- // $params[1] -> the layer
- if ($error = $this->_checkLayer(@$params[1])) {
- return $this->raiseError($error);
- }
- if (sizeof($params) < 1 || sizeof($params) > 2) {
- return $this->raiseError("config-get expects 1 or 2 parameters");
- } elseif (sizeof($params) == 1) {
- $this->ui->outputData($this->config->get($params[0]), $command);
- } else {
- $data = $this->config->get($params[0], $params[1]);
- $this->ui->outputData($data, $command);
+ $args_cnt = is_array($params) ? count($params) : 0;
+ switch ($args_cnt) {
+ case 1:
+ $config_key = $params[0];
+ $layer = null;
+ break;
+ case 2:
+ $config_key = $params[0];
+ $layer = $params[1];
+ if ($error = $this->_checkLayer($layer)) {
+ return $this->raiseError("config-get:$error");
+ }
+ break;
+ case 0:
+ default:
+ return $this->raiseError("config-get expects 1 or 2 parameters");
+ }
+
+ $reg = &$this->config->getRegistry();
+ $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
+ if (!$reg->channelExists($channel)) {
+ return $this->raiseError('Channel "' . $channel . '" does not exist');
}
+
+ $channel = $reg->channelName($channel);
+ $this->ui->outputData($this->config->get($config_key, $layer, $channel), $command);
return true;
}
- // }}}
- // {{{ doConfigSet()
-
function doConfigSet($command, $options, $params)
{
// $param[0] -> a parameter to set
// $param[1] -> the value for the parameter
// $param[2] -> the layer
$failmsg = '';
- if (sizeof($params) < 2 || sizeof($params) > 3) {
+ if (count($params) < 2 || count($params) > 3) {
$failmsg .= "config-set expects 2 or 3 parameters";
return PEAR::raiseError($failmsg);
}
- if ($error = $this->_checkLayer(@$params[2])) {
+
+ if (isset($params[2]) && ($error = $this->_checkLayer($params[2]))) {
$failmsg .= $error;
- return PEAR::raiseError($failmsg);
+ return PEAR::raiseError("config-set:$failmsg");
+ }
+
+ $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
+ $reg = &$this->config->getRegistry();
+ if (!$reg->channelExists($channel)) {
+ return $this->raiseError('Channel "' . $channel . '" does not exist');
+ }
+
+ $channel = $reg->channelName($channel);
+ if ($params[0] == 'default_channel' && !$reg->channelExists($params[1])) {
+ return $this->raiseError('Channel "' . $params[1] . '" does not exist');
+ }
+
+ if ($params[0] == 'preferred_mirror'
+ && (
+ !$reg->mirrorExists($channel, $params[1]) &&
+ (!$reg->channelExists($params[1]) || $channel != $params[1])
+ )
+ ) {
+ $msg = 'Channel Mirror "' . $params[1] . '" does not exist';
+ $msg .= ' in your registry for channel "' . $channel . '".';
+ $msg .= "\n" . 'Attempt to run "pear channel-update ' . $channel .'"';
+ $msg .= ' if you believe this mirror should exist as you may';
+ $msg .= ' have outdated channel information.';
+ return $this->raiseError($msg);
+ }
+
+ if (count($params) == 2) {
+ array_push($params, 'user');
+ $layer = 'user';
+ } else {
+ $layer = $params[2];
}
- if (!call_user_func_array(array(&$this->config, 'set'), $params))
- {
- $failmsg = "config-set (" . implode(", ", $params) . ") failed";
+
+ array_push($params, $channel);
+ if (!call_user_func_array(array(&$this->config, 'set'), $params)) {
+ array_pop($params);
+ $failmsg = "config-set (" . implode(", ", $params) . ") failed, channel $channel";
} else {
- $this->config->store();
+ $this->config->store($layer);
}
+
if ($failmsg) {
return $this->raiseError($failmsg);
}
+
+ $this->ui->outputData('config-set succeeded', $command);
return true;
}
- // }}}
- // {{{ doConfigHelp()
-
function doConfigHelp($command, $options, $params)
{
if (empty($params)) {
$params = $this->config->getKeys();
}
+
$data['caption'] = "Config help" . ((count($params) == 1) ? " for $params[0]" : '');
$data['headline'] = array('Name', 'Type', 'Description');
$data['border'] = true;
@@ -194,13 +296,103 @@ displays help for all configuration parameters.
$docs = rtrim($docs) . "\nValid set: " .
implode(' ', $this->config->getSetValues($name));
}
+
$data['data'][] = array($name, $type, $docs);
}
+
$this->ui->outputData($data, $command);
}
- // }}}
- // {{{ _checkLayer()
+ function doConfigCreate($command, $options, $params)
+ {
+ if (count($params) != 2) {
+ return PEAR::raiseError('config-create: must have 2 parameters, root path and ' .
+ 'filename to save as');
+ }
+
+ $root = $params[0];
+ // Clean up the DIRECTORY_SEPARATOR mess
+ $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
+ $root = preg_replace(array('!\\\\+!', '!/+!', "!$ds2+!"),
+ array('/', '/', '/'),
+ $root);
+ if ($root{0} != '/') {
+ if (!isset($options['windows'])) {
+ return PEAR::raiseError('Root directory must be an absolute path beginning ' .
+ 'with "/", was: "' . $root . '"');
+ }
+
+ if (!preg_match('/^[A-Za-z]:/', $root)) {
+ return PEAR::raiseError('Root directory must be an absolute path beginning ' .
+ 'with "\\" or "C:\\", was: "' . $root . '"');
+ }
+ }
+
+ $windows = isset($options['windows']);
+ if ($windows) {
+ $root = str_replace('/', '\\', $root);
+ }
+
+ if (!file_exists($params[1]) && !@touch($params[1])) {
+ return PEAR::raiseError('Could not create "' . $params[1] . '"');
+ }
+
+ $params[1] = realpath($params[1]);
+ $config = &new PEAR_Config($params[1], '#no#system#config#', false, false);
+ if ($root{strlen($root) - 1} == '/') {
+ $root = substr($root, 0, strlen($root) - 1);
+ }
+
+ $config->noRegistry();
+ $config->set('php_dir', $windows ? "$root\\pear\\php" : "$root/pear/php", 'user');
+ $config->set('data_dir', $windows ? "$root\\pear\\data" : "$root/pear/data");
+ $config->set('www_dir', $windows ? "$root\\pear\\www" : "$root/pear/www");
+ $config->set('cfg_dir', $windows ? "$root\\pear\\cfg" : "$root/pear/cfg");
+ $config->set('ext_dir', $windows ? "$root\\pear\\ext" : "$root/pear/ext");
+ $config->set('doc_dir', $windows ? "$root\\pear\\docs" : "$root/pear/docs");
+ $config->set('test_dir', $windows ? "$root\\pear\\tests" : "$root/pear/tests");
+ $config->set('cache_dir', $windows ? "$root\\pear\\cache" : "$root/pear/cache");
+ $config->set('download_dir', $windows ? "$root\\pear\\download" : "$root/pear/download");
+ $config->set('temp_dir', $windows ? "$root\\pear\\temp" : "$root/pear/temp");
+ $config->set('bin_dir', $windows ? "$root\\pear" : "$root/pear");
+ $config->writeConfigFile();
+ $this->_showConfig($config);
+ $this->ui->outputData('Successfully created default configuration file "' . $params[1] . '"',
+ $command);
+ }
+
+ function _showConfig(&$config)
+ {
+ $params = array('user');
+ $keys = $config->getKeys();
+ sort($keys);
+ $channel = 'pear.php.net';
+ $data = array('caption' => 'Configuration (channel ' . $channel . '):');
+ foreach ($keys as $key) {
+ $type = $config->getType($key);
+ $value = $config->get($key, 'user', $channel);
+ if ($type == 'password' && $value) {
+ $value = '********';
+ }
+
+ if ($value === false) {
+ $value = 'false';
+ } elseif ($value === true) {
+ $value = 'true';
+ }
+ $data['data'][$config->getGroup($key)][] =
+ array($config->getPrompt($key) , $key, $value);
+ }
+
+ foreach ($config->getLayers() as $layer) {
+ $data['data']['Config Files'][] =
+ array(ucfirst($layer) . ' Configuration File', 'Filename' ,
+ $config->getConfFile($layer));
+ }
+
+ $this->ui->outputData($data, 'config-show');
+ return true;
+ }
/**
* Checks if a layer is defined or not
@@ -216,10 +408,7 @@ displays help for all configuration parameters.
return " only the layers: \"" . implode('" or "', $layers) . "\" are supported";
}
}
+
return false;
}
-
- // }}}
-}
-
-?>
+} \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Config.xml b/3rdparty/PEAR/Command/Config.xml
new file mode 100644
index 00000000000..f64a925f52c
--- /dev/null
+++ b/3rdparty/PEAR/Command/Config.xml
@@ -0,0 +1,92 @@
+<commands version="1.0">
+ <config-show>
+ <summary>Show All Settings</summary>
+ <function>doConfigShow</function>
+ <shortcut>csh</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>show configuration variables for another channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ </options>
+ <doc>[layer]
+Displays all configuration values. An optional argument
+may be used to tell which configuration layer to display. Valid
+configuration layers are &quot;user&quot;, &quot;system&quot; and &quot;default&quot;. To display
+configurations for different channels, set the default_channel
+configuration variable and run config-show again.
+</doc>
+ </config-show>
+ <config-get>
+ <summary>Show One Setting</summary>
+ <function>doConfigGet</function>
+ <shortcut>cg</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>show configuration variables for another channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ </options>
+ <doc>&lt;parameter&gt; [layer]
+Displays the value of one configuration parameter. The
+first argument is the name of the parameter, an optional second argument
+may be used to tell which configuration layer to look in. Valid configuration
+layers are &quot;user&quot;, &quot;system&quot; and &quot;default&quot;. If no layer is specified, a value
+will be picked from the first layer that defines the parameter, in the order
+just specified. The configuration value will be retrieved for the channel
+specified by the default_channel configuration variable.
+</doc>
+ </config-get>
+ <config-set>
+ <summary>Change Setting</summary>
+ <function>doConfigSet</function>
+ <shortcut>cs</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>show configuration variables for another channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ </options>
+ <doc>&lt;parameter&gt; &lt;value&gt; [layer]
+Sets the value of one configuration parameter. The first argument is
+the name of the parameter, the second argument is the new value. Some
+parameters are subject to validation, and the command will fail with
+an error message if the new value does not make sense. An optional
+third argument may be used to specify in which layer to set the
+configuration parameter. The default layer is &quot;user&quot;. The
+configuration value will be set for the current channel, which
+is controlled by the default_channel configuration variable.
+</doc>
+ </config-set>
+ <config-help>
+ <summary>Show Information About Setting</summary>
+ <function>doConfigHelp</function>
+ <shortcut>ch</shortcut>
+ <options />
+ <doc>[parameter]
+Displays help for a configuration parameter. Without arguments it
+displays help for all configuration parameters.
+</doc>
+ </config-help>
+ <config-create>
+ <summary>Create a Default configuration file</summary>
+ <function>doConfigCreate</function>
+ <shortcut>coc</shortcut>
+ <options>
+ <windows>
+ <shortopt>w</shortopt>
+ <doc>create a config file for a windows install</doc>
+ </windows>
+ </options>
+ <doc>&lt;root path&gt; &lt;filename&gt;
+Create a default configuration file with all directory configuration
+variables set to subdirectories of &lt;root path&gt;, and save it as &lt;filename&gt;.
+This is useful especially for creating a configuration file for a remote
+PEAR installation (using the --remoteconfig option of install, upgrade,
+and uninstall).
+</doc>
+ </config-create>
+</commands> \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Install.php b/3rdparty/PEAR/Command/Install.php
index dce52f017e2..c035f6d20de 100644
--- a/3rdparty/PEAR/Command/Install.php
+++ b/3rdparty/PEAR/Command/Install.php
@@ -1,30 +1,38 @@
<?php
-//
-// +----------------------------------------------------------------------+
-// | PHP Version 5 |
-// +----------------------------------------------------------------------+
-// | Copyright (c) 1997-2004 The PHP Group |
-// +----------------------------------------------------------------------+
-// | This source file is subject to version 3.0 of the PHP license, |
-// | that is bundled with this package in the file LICENSE, and is |
-// | available through the world-wide-web at the following url: |
-// | http://www.php.net/license/3_0.txt. |
-// | If you did not receive a copy of the PHP license and are unable to |
-// | obtain it through the world-wide-web, please send a note to |
-// | license@php.net so we can mail you a copy immediately. |
-// +----------------------------------------------------------------------+
-// | Author: Stig Sæther Bakken <ssb@php.net> |
-// +----------------------------------------------------------------------+
-//
-// $Id: Install.php,v 1.53.2.1 2004/10/19 04:08:42 cellog Exp $
-
-require_once "PEAR/Command/Common.php";
-require_once "PEAR/Installer.php";
+/**
+ * PEAR_Command_Install (install, upgrade, upgrade-all, uninstall, bundle, run-scripts commands)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Install.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ */
+
+/**
+ * base class
+ */
+require_once 'PEAR/Command/Common.php';
/**
* PEAR commands for installation or deinstallation/upgrading of
* packages.
*
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 0.1
*/
class PEAR_Command_Install extends PEAR_Command_Common
{
@@ -40,6 +48,10 @@ class PEAR_Command_Install extends PEAR_Command_Common
'shortopt' => 'f',
'doc' => 'will overwrite newer installed packages',
),
+ 'loose' => array(
+ 'shortopt' => 'l',
+ 'doc' => 'do not check for recommended dependency version',
+ ),
'nodeps' => array(
'shortopt' => 'n',
'doc' => 'ignore dependencies, install anyway',
@@ -63,7 +75,12 @@ class PEAR_Command_Install extends PEAR_Command_Common
'installroot' => array(
'shortopt' => 'R',
'arg' => 'DIR',
- 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
+ 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
+ ),
+ 'packagingroot' => array(
+ 'shortopt' => 'P',
+ 'arg' => 'DIR',
+ 'doc' => 'root directory used when packaging files, like RPM packaging',
),
'ignore-errors' => array(
'doc' => 'force install even if there were errors',
@@ -76,8 +93,16 @@ class PEAR_Command_Install extends PEAR_Command_Common
'shortopt' => 'o',
'doc' => 'install all required dependencies',
),
+ 'offline' => array(
+ 'shortopt' => 'O',
+ 'doc' => 'do not attempt to download any urls or contact channels',
+ ),
+ 'pretend' => array(
+ 'shortopt' => 'p',
+ 'doc' => 'Only list the packages that would be downloaded',
+ ),
),
- 'doc' => '<package> ...
+ 'doc' => '[channel/]<package> ...
Installs one or more PEAR packages. You can specify a package to
install in four ways:
@@ -90,10 +115,17 @@ anywhere on the net.
package.xml. Useful for testing, or for wrapping a PEAR package in
another package manager such as RPM.
-"Package" : queries your configured server
+"Package[-version/state][.tar]" : queries your default channel\'s server
({config master_server}) and downloads the newest package with
the preferred quality/state ({config preferred_state}).
+To retrieve Package version 1.1, use "Package-1.1," to retrieve
+Package state beta, use "Package-beta." To retrieve an uncompressed
+file, append .tar (make sure there is no file by the same name first)
+
+To download a package from another channel, prefix with the channel name like
+"channel/Package"
+
More than one package may be specified at once. It is ok to mix these
four ways of specifying packages.
'),
@@ -102,10 +134,19 @@ four ways of specifying packages.
'function' => 'doInstall',
'shortcut' => 'up',
'options' => array(
+ 'channel' => array(
+ 'shortopt' => 'c',
+ 'doc' => 'upgrade packages from a specific channel',
+ 'arg' => 'CHAN',
+ ),
'force' => array(
'shortopt' => 'f',
'doc' => 'overwrite newer installed packages',
),
+ 'loose' => array(
+ 'shortopt' => 'l',
+ 'doc' => 'do not check for recommended dependency version',
+ ),
'nodeps' => array(
'shortopt' => 'n',
'doc' => 'ignore dependencies, upgrade anyway',
@@ -138,6 +179,14 @@ four ways of specifying packages.
'shortopt' => 'o',
'doc' => 'install all required dependencies',
),
+ 'offline' => array(
+ 'shortopt' => 'O',
+ 'doc' => 'do not attempt to download any urls or contact channels',
+ ),
+ 'pretend' => array(
+ 'shortopt' => 'p',
+ 'doc' => 'Only list the packages that would be downloaded',
+ ),
),
'doc' => '<package> ...
Upgrades one or more PEAR packages. See documentation for the
@@ -150,10 +199,15 @@ upgrade anyway).
More than one package may be specified at once.
'),
'upgrade-all' => array(
- 'summary' => 'Upgrade All Packages',
- 'function' => 'doInstall',
+ 'summary' => 'Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]',
+ 'function' => 'doUpgradeAll',
'shortcut' => 'ua',
'options' => array(
+ 'channel' => array(
+ 'shortopt' => 'c',
+ 'doc' => 'upgrade packages from a specific channel',
+ 'arg' => 'CHAN',
+ ),
'nodeps' => array(
'shortopt' => 'n',
'doc' => 'ignore dependencies, upgrade anyway',
@@ -173,13 +227,18 @@ More than one package may be specified at once.
'installroot' => array(
'shortopt' => 'R',
'arg' => 'DIR',
- 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
+ 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
),
'ignore-errors' => array(
'doc' => 'force install even if there were errors',
),
+ 'loose' => array(
+ 'doc' => 'do not check for recommended dependency version',
+ ),
),
'doc' => '
+WARNING: This function is deprecated in favor of using the upgrade command with no params
+
Upgrades all packages that have a newer release available. Upgrades are
done only if there is a release available of the state specified in
"preferred_state" (currently {config preferred_state}), or a state considered
@@ -206,10 +265,15 @@ more stable.
'ignore-errors' => array(
'doc' => 'force install even if there were errors',
),
+ 'offline' => array(
+ 'shortopt' => 'O',
+ 'doc' => 'do not attempt to uninstall remotely',
+ ),
),
- 'doc' => '<package> ...
+ 'doc' => '[channel/]<package> ...
Uninstalls one or more PEAR packages. More than one package may be
-specified at once.
+specified at once. Prefix with channel name to uninstall from a
+channel not in your default channel ({config default_channel})
'),
'bundle' => array(
'summary' => 'Unpacks a Pecl Package',
@@ -230,6 +294,15 @@ specified at once.
Unpacks a Pecl Package into the selected location. It will download the
package if needed.
'),
+ 'run-scripts' => array(
+ 'summary' => 'Run Post-Install Scripts bundled with a package',
+ 'function' => 'doRunScripts',
+ 'shortcut' => 'rs',
+ 'options' => array(
+ ),
+ 'doc' => '<package>
+Run post-installation scripts in package <package>, if any exist.
+'),
);
// }}}
@@ -247,123 +320,763 @@ package if needed.
// }}}
+ /**
+ * For unit testing purposes
+ */
+ function &getDownloader(&$ui, $options, &$config)
+ {
+ if (!class_exists('PEAR_Downloader')) {
+ require_once 'PEAR/Downloader.php';
+ }
+ $a = &new PEAR_Downloader($ui, $options, $config);
+ return $a;
+ }
+
+ /**
+ * For unit testing purposes
+ */
+ function &getInstaller(&$ui)
+ {
+ if (!class_exists('PEAR_Installer')) {
+ require_once 'PEAR/Installer.php';
+ }
+ $a = &new PEAR_Installer($ui);
+ return $a;
+ }
+
+ function enableExtension($binaries, $type)
+ {
+ if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
+ return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
+ }
+ $ini = $this->_parseIni($phpini);
+ if (PEAR::isError($ini)) {
+ return $ini;
+ }
+ $line = 0;
+ if ($type == 'extsrc' || $type == 'extbin') {
+ $search = 'extensions';
+ $enable = 'extension';
+ } else {
+ $search = 'zend_extensions';
+ ob_start();
+ phpinfo(INFO_GENERAL);
+ $info = ob_get_contents();
+ ob_end_clean();
+ $debug = function_exists('leak') ? '_debug' : '';
+ $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
+ $enable = 'zend_extension' . $debug . $ts;
+ }
+ foreach ($ini[$search] as $line => $extension) {
+ if (in_array($extension, $binaries, true) || in_array(
+ $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
+ // already enabled - assume if one is, all are
+ return true;
+ }
+ }
+ if ($line) {
+ $newini = array_slice($ini['all'], 0, $line);
+ } else {
+ $newini = array();
+ }
+ foreach ($binaries as $binary) {
+ if ($ini['extension_dir']) {
+ $binary = basename($binary);
+ }
+ $newini[] = $enable . '="' . $binary . '"' . (OS_UNIX ? "\n" : "\r\n");
+ }
+ $newini = array_merge($newini, array_slice($ini['all'], $line));
+ $fp = @fopen($phpini, 'wb');
+ if (!$fp) {
+ return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
+ }
+ foreach ($newini as $line) {
+ fwrite($fp, $line);
+ }
+ fclose($fp);
+ return true;
+ }
+
+ function disableExtension($binaries, $type)
+ {
+ if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
+ return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
+ }
+ $ini = $this->_parseIni($phpini);
+ if (PEAR::isError($ini)) {
+ return $ini;
+ }
+ $line = 0;
+ if ($type == 'extsrc' || $type == 'extbin') {
+ $search = 'extensions';
+ $enable = 'extension';
+ } else {
+ $search = 'zend_extensions';
+ ob_start();
+ phpinfo(INFO_GENERAL);
+ $info = ob_get_contents();
+ ob_end_clean();
+ $debug = function_exists('leak') ? '_debug' : '';
+ $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
+ $enable = 'zend_extension' . $debug . $ts;
+ }
+ $found = false;
+ foreach ($ini[$search] as $line => $extension) {
+ if (in_array($extension, $binaries, true) || in_array(
+ $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
+ $found = true;
+ break;
+ }
+ }
+ if (!$found) {
+ // not enabled
+ return true;
+ }
+ $fp = @fopen($phpini, 'wb');
+ if (!$fp) {
+ return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
+ }
+ if ($line) {
+ $newini = array_slice($ini['all'], 0, $line);
+ // delete the enable line
+ $newini = array_merge($newini, array_slice($ini['all'], $line + 1));
+ } else {
+ $newini = array_slice($ini['all'], 1);
+ }
+ foreach ($newini as $line) {
+ fwrite($fp, $line);
+ }
+ fclose($fp);
+ return true;
+ }
+
+ function _parseIni($filename)
+ {
+ if (!file_exists($filename)) {
+ return PEAR::raiseError('php.ini "' . $filename . '" does not exist');
+ }
+
+ if (filesize($filename) > 300000) {
+ return PEAR::raiseError('php.ini "' . $filename . '" is too large, aborting');
+ }
+
+ ob_start();
+ phpinfo(INFO_GENERAL);
+ $info = ob_get_contents();
+ ob_end_clean();
+ $debug = function_exists('leak') ? '_debug' : '';
+ $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
+ $zend_extension_line = 'zend_extension' . $debug . $ts;
+ $all = @file($filename);
+ if (!$all) {
+ return PEAR::raiseError('php.ini "' . $filename .'" could not be read');
+ }
+ $zend_extensions = $extensions = array();
+ // assume this is right, but pull from the php.ini if it is found
+ $extension_dir = ini_get('extension_dir');
+ foreach ($all as $linenum => $line) {
+ $line = trim($line);
+ if (!$line) {
+ continue;
+ }
+ if ($line[0] == ';') {
+ continue;
+ }
+ if (strtolower(substr($line, 0, 13)) == 'extension_dir') {
+ $line = trim(substr($line, 13));
+ if ($line[0] == '=') {
+ $x = trim(substr($line, 1));
+ $x = explode(';', $x);
+ $extension_dir = str_replace('"', '', array_shift($x));
+ continue;
+ }
+ }
+ if (strtolower(substr($line, 0, 9)) == 'extension') {
+ $line = trim(substr($line, 9));
+ if ($line[0] == '=') {
+ $x = trim(substr($line, 1));
+ $x = explode(';', $x);
+ $extensions[$linenum] = str_replace('"', '', array_shift($x));
+ continue;
+ }
+ }
+ if (strtolower(substr($line, 0, strlen($zend_extension_line))) ==
+ $zend_extension_line) {
+ $line = trim(substr($line, strlen($zend_extension_line)));
+ if ($line[0] == '=') {
+ $x = trim(substr($line, 1));
+ $x = explode(';', $x);
+ $zend_extensions[$linenum] = str_replace('"', '', array_shift($x));
+ continue;
+ }
+ }
+ }
+ return array(
+ 'extensions' => $extensions,
+ 'zend_extensions' => $zend_extensions,
+ 'extension_dir' => $extension_dir,
+ 'all' => $all,
+ );
+ }
+
// {{{ doInstall()
function doInstall($command, $options, $params)
{
- require_once 'PEAR/Downloader.php';
+ if (!class_exists('PEAR_PackageFile')) {
+ require_once 'PEAR/PackageFile.php';
+ }
+
+ if (isset($options['installroot']) && isset($options['packagingroot'])) {
+ return $this->raiseError('ERROR: cannot use both --installroot and --packagingroot');
+ }
+
+ $reg = &$this->config->getRegistry();
+ $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
+ if (!$reg->channelExists($channel)) {
+ return $this->raiseError('Channel "' . $channel . '" does not exist');
+ }
+
if (empty($this->installer)) {
- $this->installer = &new PEAR_Installer($this->ui);
+ $this->installer = &$this->getInstaller($this->ui);
}
- if ($command == 'upgrade') {
+
+ if ($command == 'upgrade' || $command == 'upgrade-all') {
+ // If people run the upgrade command but pass nothing, emulate a upgrade-all
+ if ($command == 'upgrade' && empty($params)) {
+ return $this->doUpgradeAll($command, $options, $params);
+ }
$options['upgrade'] = true;
+ } else {
+ $packages = $params;
}
- if ($command == 'upgrade-all') {
- include_once "PEAR/Remote.php";
- $options['upgrade'] = true;
- $remote = &new PEAR_Remote($this->config);
- $state = $this->config->get('preferred_state');
- if (empty($state) || $state == 'any') {
- $latest = $remote->call("package.listLatestReleases");
- } else {
- $latest = $remote->call("package.listLatestReleases", $state);
- }
- if (PEAR::isError($latest)) {
- return $latest;
- }
- $reg = new PEAR_Registry($this->config->get('php_dir'));
- $installed = array_flip($reg->listPackages());
- $params = array();
- foreach ($latest as $package => $info) {
- $package = strtolower($package);
- if (!isset($installed[$package])) {
- // skip packages we don't have installed
+
+ $instreg = &$reg; // instreg used to check if package is installed
+ if (isset($options['packagingroot']) && !isset($options['upgrade'])) {
+ $packrootphp_dir = $this->installer->_prependPath(
+ $this->config->get('php_dir', null, 'pear.php.net'),
+ $options['packagingroot']);
+ $instreg = new PEAR_Registry($packrootphp_dir); // other instreg!
+
+ if ($this->config->get('verbose') > 2) {
+ $this->ui->outputData('using package root: ' . $options['packagingroot']);
+ }
+ }
+
+ $abstractpackages = $otherpackages = array();
+ // parse params
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+
+ foreach ($params as $param) {
+ if (strpos($param, 'http://') === 0) {
+ $otherpackages[] = $param;
+ continue;
+ }
+
+ if (strpos($param, 'channel://') === false && @file_exists($param)) {
+ if (isset($options['force'])) {
+ $otherpackages[] = $param;
continue;
}
- $inst_version = $reg->packageInfo($package, 'version');
- if (version_compare("$info[version]", "$inst_version", "le")) {
- // installed version is up-to-date
+
+ $pkg = new PEAR_PackageFile($this->config);
+ $pf = $pkg->fromAnyFile($param, PEAR_VALIDATE_DOWNLOADING);
+ if (PEAR::isError($pf)) {
+ $otherpackages[] = $param;
+ continue;
+ }
+
+ $exists = $reg->packageExists($pf->getPackage(), $pf->getChannel());
+ $pversion = $reg->packageInfo($pf->getPackage(), 'version', $pf->getChannel());
+ $version_compare = version_compare($pf->getVersion(), $pversion, '<=');
+ if ($exists && $version_compare) {
+ if ($this->config->get('verbose')) {
+ $this->ui->outputData('Ignoring installed package ' .
+ $reg->parsedPackageNameToString(
+ array('package' => $pf->getPackage(),
+ 'channel' => $pf->getChannel()), true));
+ }
continue;
}
- $params[] = $package;
- $this->ui->outputData(array('data' => "Will upgrade $package"), $command);
+ $otherpackages[] = $param;
+ continue;
+ }
+
+ $e = $reg->parsePackageName($param, $channel);
+ if (PEAR::isError($e)) {
+ $otherpackages[] = $param;
+ } else {
+ $abstractpackages[] = $e;
+ }
+ }
+ PEAR::staticPopErrorHandling();
+
+ // if there are any local package .tgz or remote static url, we can't
+ // filter. The filter only works for abstract packages
+ if (count($abstractpackages) && !isset($options['force'])) {
+ // when not being forced, only do necessary upgrades/installs
+ if (isset($options['upgrade'])) {
+ $abstractpackages = $this->_filterUptodatePackages($abstractpackages, $command);
+ } else {
+ $count = count($abstractpackages);
+ foreach ($abstractpackages as $i => $package) {
+ if (isset($package['group'])) {
+ // do not filter out install groups
+ continue;
+ }
+
+ if ($instreg->packageExists($package['package'], $package['channel'])) {
+ if ($count > 1) {
+ if ($this->config->get('verbose')) {
+ $this->ui->outputData('Ignoring installed package ' .
+ $reg->parsedPackageNameToString($package, true));
+ }
+ unset($abstractpackages[$i]);
+ } elseif ($count === 1) {
+ // Lets try to upgrade it since it's already installed
+ $options['upgrade'] = true;
+ }
+ }
+ }
+ }
+ $abstractpackages =
+ array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
+ } elseif (count($abstractpackages)) {
+ $abstractpackages =
+ array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
+ }
+
+ $packages = array_merge($abstractpackages, $otherpackages);
+ if (!count($packages)) {
+ $c = '';
+ if (isset($options['channel'])){
+ $c .= ' in channel "' . $options['channel'] . '"';
}
+ $this->ui->outputData('Nothing to ' . $command . $c);
+ return true;
+ }
+
+ $this->downloader = &$this->getDownloader($this->ui, $options, $this->config);
+ $errors = $downloaded = $binaries = array();
+ $downloaded = &$this->downloader->download($packages);
+ if (PEAR::isError($downloaded)) {
+ return $this->raiseError($downloaded);
}
- $this->downloader = &new PEAR_Downloader($this->ui, $options, $this->config);
- $errors = array();
- $downloaded = array();
- $this->downloader->download($params);
+
$errors = $this->downloader->getErrorMsgs();
if (count($errors)) {
- $err['data'] = array($errors);
- $err['headline'] = 'Install Errors';
- $this->ui->outputData($err);
- return $this->raiseError("$command failed");
- }
- $downloaded = $this->downloader->getDownloadedPackages();
- $this->installer->sortPkgDeps($downloaded);
- foreach ($downloaded as $pkg) {
- PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
- $info = $this->installer->install($pkg['file'], $options, $this->config);
- PEAR::popErrorHandling();
- if (PEAR::isError($info)) {
- $this->ui->outputData('ERROR: ' .$info->getMessage());
- continue;
+ $err = array();
+ $err['data'] = array();
+ foreach ($errors as $error) {
+ if ($error !== null) {
+ $err['data'][] = array($error);
+ }
}
- if (is_array($info)) {
- if ($this->config->get('verbose') > 0) {
- $label = "$info[package] $info[version]";
- $out = array('data' => "$command ok: $label");
- if (isset($info['release_warnings'])) {
- $out['release_warnings'] = $info['release_warnings'];
+
+ if (!empty($err['data'])) {
+ $err['headline'] = 'Install Errors';
+ $this->ui->outputData($err);
+ }
+
+ if (!count($downloaded)) {
+ return $this->raiseError("$command failed");
+ }
+ }
+
+ $data = array(
+ 'headline' => 'Packages that would be Installed'
+ );
+
+ if (isset($options['pretend'])) {
+ foreach ($downloaded as $package) {
+ $data['data'][] = array($reg->parsedPackageNameToString($package->getParsedPackage()));
+ }
+ $this->ui->outputData($data, 'pretend');
+ return true;
+ }
+
+ $this->installer->setOptions($options);
+ $this->installer->sortPackagesForInstall($downloaded);
+ if (PEAR::isError($err = $this->installer->setDownloadedPackages($downloaded))) {
+ $this->raiseError($err->getMessage());
+ return true;
+ }
+
+ $binaries = $extrainfo = array();
+ foreach ($downloaded as $param) {
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $info = $this->installer->install($param, $options);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($info)) {
+ $oldinfo = $info;
+ $pkg = &$param->getPackageFile();
+ if ($info->getCode() != PEAR_INSTALLER_NOBINARY) {
+ if (!($info = $pkg->installBinary($this->installer))) {
+ $this->ui->outputData('ERROR: ' .$oldinfo->getMessage());
+ continue;
}
- $this->ui->outputData($out, $command);
+
+ // we just installed a different package than requested,
+ // let's change the param and info so that the rest of this works
+ $param = $info[0];
+ $info = $info[1];
}
- } else {
+ }
+
+ if (!is_array($info)) {
return $this->raiseError("$command failed");
}
+
+ if ($param->getPackageType() == 'extsrc' ||
+ $param->getPackageType() == 'extbin' ||
+ $param->getPackageType() == 'zendextsrc' ||
+ $param->getPackageType() == 'zendextbin'
+ ) {
+ $pkg = &$param->getPackageFile();
+ if ($instbin = $pkg->getInstalledBinary()) {
+ $instpkg = &$instreg->getPackage($instbin, $pkg->getChannel());
+ } else {
+ $instpkg = &$instreg->getPackage($pkg->getPackage(), $pkg->getChannel());
+ }
+
+ foreach ($instpkg->getFilelist() as $name => $atts) {
+ $pinfo = pathinfo($atts['installed_as']);
+ if (!isset($pinfo['extension']) ||
+ in_array($pinfo['extension'], array('c', 'h'))
+ ) {
+ continue; // make sure we don't match php_blah.h
+ }
+
+ if ((strpos($pinfo['basename'], 'php_') === 0 &&
+ $pinfo['extension'] == 'dll') ||
+ // most unices
+ $pinfo['extension'] == 'so' ||
+ // hp-ux
+ $pinfo['extension'] == 'sl') {
+ $binaries[] = array($atts['installed_as'], $pinfo);
+ break;
+ }
+ }
+
+ if (count($binaries)) {
+ foreach ($binaries as $pinfo) {
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $ret = $this->enableExtension(array($pinfo[0]), $param->getPackageType());
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($ret)) {
+ $extrainfo[] = $ret->getMessage();
+ if ($param->getPackageType() == 'extsrc' ||
+ $param->getPackageType() == 'extbin') {
+ $exttype = 'extension';
+ } else {
+ ob_start();
+ phpinfo(INFO_GENERAL);
+ $info = ob_get_contents();
+ ob_end_clean();
+ $debug = function_exists('leak') ? '_debug' : '';
+ $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
+ $exttype = 'zend_extension' . $debug . $ts;
+ }
+ $extrainfo[] = 'You should add "' . $exttype . '=' .
+ $pinfo[1]['basename'] . '" to php.ini';
+ } else {
+ $extrainfo[] = 'Extension ' . $instpkg->getProvidesExtension() .
+ ' enabled in php.ini';
+ }
+ }
+ }
+ }
+
+ if ($this->config->get('verbose') > 0) {
+ $chan = $param->getChannel();
+ $label = $reg->parsedPackageNameToString(
+ array(
+ 'channel' => $chan,
+ 'package' => $param->getPackage(),
+ 'version' => $param->getVersion(),
+ ));
+ $out = array('data' => "$command ok: $label");
+ if (isset($info['release_warnings'])) {
+ $out['release_warnings'] = $info['release_warnings'];
+ }
+ $this->ui->outputData($out, $command);
+
+ if (!isset($options['register-only']) && !isset($options['offline'])) {
+ if ($this->config->isDefinedLayer('ftp')) {
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $info = $this->installer->ftpInstall($param);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($info)) {
+ $this->ui->outputData($info->getMessage());
+ $this->ui->outputData("remote install failed: $label");
+ } else {
+ $this->ui->outputData("remote install ok: $label");
+ }
+ }
+ }
+ }
+
+ $deps = $param->getDeps();
+ if ($deps) {
+ if (isset($deps['group'])) {
+ $groups = $deps['group'];
+ if (!isset($groups[0])) {
+ $groups = array($groups);
+ }
+
+ foreach ($groups as $group) {
+ if ($group['attribs']['name'] == 'default') {
+ // default group is always installed, unless the user
+ // explicitly chooses to install another group
+ continue;
+ }
+ $extrainfo[] = $param->getPackage() . ': Optional feature ' .
+ $group['attribs']['name'] . ' available (' .
+ $group['attribs']['hint'] . ')';
+ }
+
+ $extrainfo[] = $param->getPackage() .
+ ': To install optional features use "pear install ' .
+ $reg->parsedPackageNameToString(
+ array('package' => $param->getPackage(),
+ 'channel' => $param->getChannel()), true) .
+ '#featurename"';
+ }
+ }
+
+ $pkg = &$instreg->getPackage($param->getPackage(), $param->getChannel());
+ // $pkg may be NULL if install is a 'fake' install via --packagingroot
+ if (is_object($pkg)) {
+ $pkg->setConfig($this->config);
+ if ($list = $pkg->listPostinstallScripts()) {
+ $pn = $reg->parsedPackageNameToString(array('channel' =>
+ $param->getChannel(), 'package' => $param->getPackage()), true);
+ $extrainfo[] = $pn . ' has post-install scripts:';
+ foreach ($list as $file) {
+ $extrainfo[] = $file;
+ }
+ $extrainfo[] = $param->getPackage() .
+ ': Use "pear run-scripts ' . $pn . '" to finish setup.';
+ $extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES';
+ }
+ }
+ }
+
+ if (count($extrainfo)) {
+ foreach ($extrainfo as $info) {
+ $this->ui->outputData($info);
+ }
}
+
return true;
}
// }}}
+ // {{{ doUpgradeAll()
+
+ function doUpgradeAll($command, $options, $params)
+ {
+ $reg = &$this->config->getRegistry();
+ $upgrade = array();
+
+ if (isset($options['channel'])) {
+ $channels = array($options['channel']);
+ } else {
+ $channels = $reg->listChannels();
+ }
+
+ foreach ($channels as $channel) {
+ if ($channel == '__uri') {
+ continue;
+ }
+
+ // parse name with channel
+ foreach ($reg->listPackages($channel) as $name) {
+ $upgrade[] = $reg->parsedPackageNameToString(array(
+ 'channel' => $channel,
+ 'package' => $name
+ ));
+ }
+ }
+
+ $err = $this->doInstall($command, $options, $upgrade);
+ if (PEAR::isError($err)) {
+ $this->ui->outputData($err->getMessage(), $command);
+ }
+ }
+
+ // }}}
// {{{ doUninstall()
function doUninstall($command, $options, $params)
{
+ if (count($params) < 1) {
+ return $this->raiseError("Please supply the package(s) you want to uninstall");
+ }
+
if (empty($this->installer)) {
- $this->installer = &new PEAR_Installer($this->ui);
+ $this->installer = &$this->getInstaller($this->ui);
}
- if (sizeof($params) < 1) {
- return $this->raiseError("Please supply the package(s) you want to uninstall");
+
+ if (isset($options['remoteconfig'])) {
+ $e = $this->config->readFTPConfigFile($options['remoteconfig']);
+ if (!PEAR::isError($e)) {
+ $this->installer->setConfig($this->config);
+ }
}
- include_once 'PEAR/Registry.php';
- $reg = new PEAR_Registry($this->config->get('php_dir'));
+
+ $reg = &$this->config->getRegistry();
$newparams = array();
+ $binaries = array();
$badparams = array();
foreach ($params as $pkg) {
- $info = $reg->packageInfo($pkg);
+ $channel = $this->config->get('default_channel');
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $parsed = $reg->parsePackageName($pkg, $channel);
+ PEAR::staticPopErrorHandling();
+ if (!$parsed || PEAR::isError($parsed)) {
+ $badparams[] = $pkg;
+ continue;
+ }
+ $package = $parsed['package'];
+ $channel = $parsed['channel'];
+ $info = &$reg->getPackage($package, $channel);
+ if ($info === null &&
+ ($channel == 'pear.php.net' || $channel == 'pecl.php.net')) {
+ // make sure this isn't a package that has flipped from pear to pecl but
+ // used a package.xml 1.0
+ $testc = ($channel == 'pear.php.net') ? 'pecl.php.net' : 'pear.php.net';
+ $info = &$reg->getPackage($package, $testc);
+ if ($info !== null) {
+ $channel = $testc;
+ }
+ }
if ($info === null) {
$badparams[] = $pkg;
} else {
- $newparams[] = $info;
+ $newparams[] = &$info;
+ // check for binary packages (this is an alias for those packages if so)
+ if ($installedbinary = $info->getInstalledBinary()) {
+ $this->ui->log('adding binary package ' .
+ $reg->parsedPackageNameToString(array('channel' => $channel,
+ 'package' => $installedbinary), true));
+ $newparams[] = &$reg->getPackage($installedbinary, $channel);
+ }
+ // add the contents of a dependency group to the list of installed packages
+ if (isset($parsed['group'])) {
+ $group = $info->getDependencyGroup($parsed['group']);
+ if ($group) {
+ $installed = $reg->getInstalledGroup($group);
+ if ($installed) {
+ foreach ($installed as $i => $p) {
+ $newparams[] = &$installed[$i];
+ }
+ }
+ }
+ }
}
}
- $this->installer->sortPkgDeps($newparams, true);
- $params = array();
- foreach($newparams as $info) {
- $params[] = $info['info']['package'];
+ $err = $this->installer->sortPackagesForUninstall($newparams);
+ if (PEAR::isError($err)) {
+ $this->ui->outputData($err->getMessage(), $command);
+ return true;
}
+ $params = $newparams;
+ // twist this to use it to check on whether dependent packages are also being uninstalled
+ // for circular dependencies like subpackages
+ $this->installer->setUninstallPackages($newparams);
$params = array_merge($params, $badparams);
+ $binaries = array();
foreach ($params as $pkg) {
- if ($this->installer->uninstall($pkg, $options)) {
+ $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
+ if ($err = $this->installer->uninstall($pkg, $options)) {
+ $this->installer->popErrorHandling();
+ if (PEAR::isError($err)) {
+ $this->ui->outputData($err->getMessage(), $command);
+ continue;
+ }
+ if ($pkg->getPackageType() == 'extsrc' ||
+ $pkg->getPackageType() == 'extbin' ||
+ $pkg->getPackageType() == 'zendextsrc' ||
+ $pkg->getPackageType() == 'zendextbin') {
+ if ($instbin = $pkg->getInstalledBinary()) {
+ continue; // this will be uninstalled later
+ }
+
+ foreach ($pkg->getFilelist() as $name => $atts) {
+ $pinfo = pathinfo($atts['installed_as']);
+ if (!isset($pinfo['extension']) ||
+ in_array($pinfo['extension'], array('c', 'h'))) {
+ continue; // make sure we don't match php_blah.h
+ }
+ if ((strpos($pinfo['basename'], 'php_') === 0 &&
+ $pinfo['extension'] == 'dll') ||
+ // most unices
+ $pinfo['extension'] == 'so' ||
+ // hp-ux
+ $pinfo['extension'] == 'sl') {
+ $binaries[] = array($atts['installed_as'], $pinfo);
+ break;
+ }
+ }
+ if (count($binaries)) {
+ foreach ($binaries as $pinfo) {
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $ret = $this->disableExtension(array($pinfo[0]), $pkg->getPackageType());
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($ret)) {
+ $extrainfo[] = $ret->getMessage();
+ if ($pkg->getPackageType() == 'extsrc' ||
+ $pkg->getPackageType() == 'extbin') {
+ $exttype = 'extension';
+ } else {
+ ob_start();
+ phpinfo(INFO_GENERAL);
+ $info = ob_get_contents();
+ ob_end_clean();
+ $debug = function_exists('leak') ? '_debug' : '';
+ $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
+ $exttype = 'zend_extension' . $debug . $ts;
+ }
+ $this->ui->outputData('Unable to remove "' . $exttype . '=' .
+ $pinfo[1]['basename'] . '" from php.ini', $command);
+ } else {
+ $this->ui->outputData('Extension ' . $pkg->getProvidesExtension() .
+ ' disabled in php.ini', $command);
+ }
+ }
+ }
+ }
+ $savepkg = $pkg;
if ($this->config->get('verbose') > 0) {
+ if (is_object($pkg)) {
+ $pkg = $reg->parsedPackageNameToString($pkg);
+ }
$this->ui->outputData("uninstall ok: $pkg", $command);
}
+ if (!isset($options['offline']) && is_object($savepkg) &&
+ defined('PEAR_REMOTEINSTALL_OK')) {
+ if ($this->config->isDefinedLayer('ftp')) {
+ $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
+ $info = $this->installer->ftpUninstall($savepkg);
+ $this->installer->popErrorHandling();
+ if (PEAR::isError($info)) {
+ $this->ui->outputData($info->getMessage());
+ $this->ui->outputData("remote uninstall failed: $pkg");
+ } else {
+ $this->ui->outputData("remote uninstall ok: $pkg");
+ }
+ }
+ }
} else {
- return $this->raiseError("uninstall failed: $pkg");
+ $this->installer->popErrorHandling();
+ if (!is_object($pkg)) {
+ return $this->raiseError("uninstall failed: $pkg");
+ }
+ $pkg = $reg->parsedPackageNameToString($pkg);
}
}
+
return true;
}
@@ -379,66 +1092,17 @@ package if needed.
function doBundle($command, $options, $params)
{
- if (empty($this->installer)) {
- $this->installer = &new PEAR_Downloader($this->ui);
- }
- $installer = &$this->installer;
- if (sizeof($params) < 1) {
+ $opts = array(
+ 'force' => true,
+ 'nodeps' => true,
+ 'soft' => true,
+ 'downloadonly' => true
+ );
+ $downloader = &$this->getDownloader($this->ui, $opts, $this->config);
+ $reg = &$this->config->getRegistry();
+ if (count($params) < 1) {
return $this->raiseError("Please supply the package you want to bundle");
}
- $pkgfile = $params[0];
- $need_download = false;
- if (preg_match('#^(http|ftp)://#', $pkgfile)) {
- $need_download = true;
- } elseif (!@is_file($pkgfile)) {
- if ($installer->validPackageName($pkgfile)) {
- $pkgfile = $installer->getPackageDownloadUrl($pkgfile);
- $need_download = true;
- } else {
- if (strlen($pkgfile)) {
- return $this->raiseError("Could not open the package file: $pkgfile");
- } else {
- return $this->raiseError("No package file given");
- }
- }
- }
-
- // Download package -----------------------------------------------
- if ($need_download) {
- $downloaddir = $installer->config->get('download_dir');
- if (empty($downloaddir)) {
- if (PEAR::isError($downloaddir = System::mktemp('-d'))) {
- return $downloaddir;
- }
- $installer->log(2, '+ tmp dir created at ' . $downloaddir);
- }
- $callback = $this->ui ? array(&$installer, '_downloadCallback') : null;
- $file = $installer->downloadHttp($pkgfile, $this->ui, $downloaddir, $callback);
- if (PEAR::isError($file)) {
- return $this->raiseError($file);
- }
- $pkgfile = $file;
- }
-
- // Parse xml file -----------------------------------------------
- $pkginfo = $installer->infoFromTgzFile($pkgfile);
- if (PEAR::isError($pkginfo)) {
- return $this->raiseError($pkginfo);
- }
- $installer->validatePackageInfo($pkginfo, $errors, $warnings);
- // XXX We allow warnings, do we have to do it?
- if (count($errors)) {
- if (empty($options['force'])) {
- return $this->raiseError("The following errors where found:\n".
- implode("\n", $errors));
- } else {
- $this->log(0, "warning : the following errors were found:\n".
- implode("\n", $errors));
- }
- }
- $pkgname = $pkginfo['package'];
-
- // Unpacking -------------------------------------------------
if (isset($options['destination'])) {
if (!is_dir($options['destination'])) {
@@ -446,19 +1110,35 @@ package if needed.
}
$dest = realpath($options['destination']);
} else {
- $pwd = getcwd();
- if (is_dir($pwd . DIRECTORY_SEPARATOR . 'ext')) {
- $dest = $pwd . DIRECTORY_SEPARATOR . 'ext';
- } else {
- $dest = $pwd;
- }
+ $pwd = getcwd();
+ $dir = $pwd . DIRECTORY_SEPARATOR . 'ext';
+ $dest = is_dir($dir) ? $dir : $pwd;
+ }
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $err = $downloader->setDownloadDir($dest);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($err)) {
+ return PEAR::raiseError('download directory "' . $dest .
+ '" is not writeable.');
+ }
+ $result = &$downloader->download(array($params[0]));
+ if (PEAR::isError($result)) {
+ return $result;
}
+ if (!isset($result[0])) {
+ return $this->raiseError('unable to unpack ' . $params[0]);
+ }
+ $pkgfile = &$result[0]->getPackageFile();
+ $pkgname = $pkgfile->getName();
+ $pkgversion = $pkgfile->getVersion();
+
+ // Unpacking -------------------------------------------------
$dest .= DIRECTORY_SEPARATOR . $pkgname;
- $orig = $pkgname . '-' . $pkginfo['version'];
+ $orig = $pkgname . '-' . $pkgversion;
- $tar = new Archive_Tar($pkgfile);
- if (!@$tar->extractModify($dest, $orig)) {
- return $this->raiseError("unable to unpack $pkgfile");
+ $tar = &new Archive_Tar($pkgfile->getArchiveFile());
+ if (!$tar->extractModify($dest, $orig)) {
+ return $this->raiseError('unable to unpack ' . $pkgfile->getArchiveFile());
}
$this->ui->outputData("Package ready at '$dest'");
// }}}
@@ -466,5 +1146,123 @@ package if needed.
// }}}
-}
-?>
+ function doRunScripts($command, $options, $params)
+ {
+ if (!isset($params[0])) {
+ return $this->raiseError('run-scripts expects 1 parameter: a package name');
+ }
+
+ $reg = &$this->config->getRegistry();
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($parsed)) {
+ return $this->raiseError($parsed);
+ }
+
+ $package = &$reg->getPackage($parsed['package'], $parsed['channel']);
+ if (!is_object($package)) {
+ return $this->raiseError('Could not retrieve package "' . $params[0] . '" from registry');
+ }
+
+ $package->setConfig($this->config);
+ $package->runPostinstallScripts();
+ $this->ui->outputData('Install scripts complete', $command);
+ return true;
+ }
+
+ /**
+ * Given a list of packages, filter out those ones that are already up to date
+ *
+ * @param $packages: packages, in parsed array format !
+ * @return list of packages that can be upgraded
+ */
+ function _filterUptodatePackages($packages, $command)
+ {
+ $reg = &$this->config->getRegistry();
+ $latestReleases = array();
+
+ $ret = array();
+ foreach ($packages as $package) {
+ if (isset($package['group'])) {
+ $ret[] = $package;
+ continue;
+ }
+
+ $channel = $package['channel'];
+ $name = $package['package'];
+ if (!$reg->packageExists($name, $channel)) {
+ $ret[] = $package;
+ continue;
+ }
+
+ if (!isset($latestReleases[$channel])) {
+ // fill in cache for this channel
+ $chan = &$reg->getChannel($channel);
+ if (PEAR::isError($chan)) {
+ return $this->raiseError($chan);
+ }
+
+ $base2 = false;
+ $preferred_mirror = $this->config->get('preferred_mirror', null, $channel);
+ if ($chan->supportsREST($preferred_mirror) &&
+ (
+ //($base2 = $chan->getBaseURL('REST1.4', $preferred_mirror)) ||
+ ($base = $chan->getBaseURL('REST1.0', $preferred_mirror))
+ )
+ ) {
+ $dorest = true;
+ }
+
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ if (!isset($package['state'])) {
+ $state = $this->config->get('preferred_state', null, $channel);
+ } else {
+ $state = $package['state'];
+ }
+
+ if ($dorest) {
+ if ($base2) {
+ $rest = &$this->config->getREST('1.4', array());
+ $base = $base2;
+ } else {
+ $rest = &$this->config->getREST('1.0', array());
+ }
+
+ $installed = array_flip($reg->listPackages($channel));
+ $latest = $rest->listLatestUpgrades($base, $state, $installed, $channel, $reg);
+ }
+
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($latest)) {
+ $this->ui->outputData('Error getting channel info from ' . $channel .
+ ': ' . $latest->getMessage());
+ continue;
+ }
+
+ $latestReleases[$channel] = array_change_key_case($latest);
+ }
+
+ // check package for latest release
+ $name_lower = strtolower($name);
+ if (isset($latestReleases[$channel][$name_lower])) {
+ // if not set, up to date
+ $inst_version = $reg->packageInfo($name, 'version', $channel);
+ $channel_version = $latestReleases[$channel][$name_lower]['version'];
+ if (version_compare($channel_version, $inst_version, 'le')) {
+ // installed version is up-to-date
+ continue;
+ }
+
+ // maintain BC
+ if ($command == 'upgrade-all') {
+ $this->ui->outputData(array('data' => 'Will upgrade ' .
+ $reg->parsedPackageNameToString($package)), $command);
+ }
+ $ret[] = $package;
+ }
+ }
+
+ return $ret;
+ }
+} \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Install.xml b/3rdparty/PEAR/Command/Install.xml
new file mode 100644
index 00000000000..1b1e933c22d
--- /dev/null
+++ b/3rdparty/PEAR/Command/Install.xml
@@ -0,0 +1,276 @@
+<commands version="1.0">
+ <install>
+ <summary>Install Package</summary>
+ <function>doInstall</function>
+ <shortcut>i</shortcut>
+ <options>
+ <force>
+ <shortopt>f</shortopt>
+ <doc>will overwrite newer installed packages</doc>
+ </force>
+ <loose>
+ <shortopt>l</shortopt>
+ <doc>do not check for recommended dependency version</doc>
+ </loose>
+ <nodeps>
+ <shortopt>n</shortopt>
+ <doc>ignore dependencies, install anyway</doc>
+ </nodeps>
+ <register-only>
+ <shortopt>r</shortopt>
+ <doc>do not install files, only register the package as installed</doc>
+ </register-only>
+ <soft>
+ <shortopt>s</shortopt>
+ <doc>soft install, fail silently, or upgrade if already installed</doc>
+ </soft>
+ <nobuild>
+ <shortopt>B</shortopt>
+ <doc>don&#039;t build C extensions</doc>
+ </nobuild>
+ <nocompress>
+ <shortopt>Z</shortopt>
+ <doc>request uncompressed files when downloading</doc>
+ </nocompress>
+ <installroot>
+ <shortopt>R</shortopt>
+ <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT), use packagingroot for RPM</doc>
+ <arg>DIR</arg>
+ </installroot>
+ <packagingroot>
+ <shortopt>P</shortopt>
+ <doc>root directory used when packaging files, like RPM packaging</doc>
+ <arg>DIR</arg>
+ </packagingroot>
+ <ignore-errors>
+ <shortopt></shortopt>
+ <doc>force install even if there were errors</doc>
+ </ignore-errors>
+ <alldeps>
+ <shortopt>a</shortopt>
+ <doc>install all required and optional dependencies</doc>
+ </alldeps>
+ <onlyreqdeps>
+ <shortopt>o</shortopt>
+ <doc>install all required dependencies</doc>
+ </onlyreqdeps>
+ <offline>
+ <shortopt>O</shortopt>
+ <doc>do not attempt to download any urls or contact channels</doc>
+ </offline>
+ <pretend>
+ <shortopt>p</shortopt>
+ <doc>Only list the packages that would be downloaded</doc>
+ </pretend>
+ </options>
+ <doc>[channel/]&lt;package&gt; ...
+Installs one or more PEAR packages. You can specify a package to
+install in four ways:
+
+&quot;Package-1.0.tgz&quot; : installs from a local file
+
+&quot;http://example.com/Package-1.0.tgz&quot; : installs from
+anywhere on the net.
+
+&quot;package.xml&quot; : installs the package described in
+package.xml. Useful for testing, or for wrapping a PEAR package in
+another package manager such as RPM.
+
+&quot;Package[-version/state][.tar]&quot; : queries your default channel&#039;s server
+({config master_server}) and downloads the newest package with
+the preferred quality/state ({config preferred_state}).
+
+To retrieve Package version 1.1, use &quot;Package-1.1,&quot; to retrieve
+Package state beta, use &quot;Package-beta.&quot; To retrieve an uncompressed
+file, append .tar (make sure there is no file by the same name first)
+
+To download a package from another channel, prefix with the channel name like
+&quot;channel/Package&quot;
+
+More than one package may be specified at once. It is ok to mix these
+four ways of specifying packages.
+</doc>
+ </install>
+ <upgrade>
+ <summary>Upgrade Package</summary>
+ <function>doInstall</function>
+ <shortcut>up</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>upgrade packages from a specific channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ <force>
+ <shortopt>f</shortopt>
+ <doc>overwrite newer installed packages</doc>
+ </force>
+ <loose>
+ <shortopt>l</shortopt>
+ <doc>do not check for recommended dependency version</doc>
+ </loose>
+ <nodeps>
+ <shortopt>n</shortopt>
+ <doc>ignore dependencies, upgrade anyway</doc>
+ </nodeps>
+ <register-only>
+ <shortopt>r</shortopt>
+ <doc>do not install files, only register the package as upgraded</doc>
+ </register-only>
+ <nobuild>
+ <shortopt>B</shortopt>
+ <doc>don&#039;t build C extensions</doc>
+ </nobuild>
+ <nocompress>
+ <shortopt>Z</shortopt>
+ <doc>request uncompressed files when downloading</doc>
+ </nocompress>
+ <installroot>
+ <shortopt>R</shortopt>
+ <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT)</doc>
+ <arg>DIR</arg>
+ </installroot>
+ <ignore-errors>
+ <shortopt></shortopt>
+ <doc>force install even if there were errors</doc>
+ </ignore-errors>
+ <alldeps>
+ <shortopt>a</shortopt>
+ <doc>install all required and optional dependencies</doc>
+ </alldeps>
+ <onlyreqdeps>
+ <shortopt>o</shortopt>
+ <doc>install all required dependencies</doc>
+ </onlyreqdeps>
+ <offline>
+ <shortopt>O</shortopt>
+ <doc>do not attempt to download any urls or contact channels</doc>
+ </offline>
+ <pretend>
+ <shortopt>p</shortopt>
+ <doc>Only list the packages that would be downloaded</doc>
+ </pretend>
+ </options>
+ <doc>&lt;package&gt; ...
+Upgrades one or more PEAR packages. See documentation for the
+&quot;install&quot; command for ways to specify a package.
+
+When upgrading, your package will be updated if the provided new
+package has a higher version number (use the -f option if you need to
+upgrade anyway).
+
+More than one package may be specified at once.
+</doc>
+ </upgrade>
+ <upgrade-all>
+ <summary>Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]</summary>
+ <function>doUpgradeAll</function>
+ <shortcut>ua</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>upgrade packages from a specific channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ <nodeps>
+ <shortopt>n</shortopt>
+ <doc>ignore dependencies, upgrade anyway</doc>
+ </nodeps>
+ <register-only>
+ <shortopt>r</shortopt>
+ <doc>do not install files, only register the package as upgraded</doc>
+ </register-only>
+ <nobuild>
+ <shortopt>B</shortopt>
+ <doc>don&#039;t build C extensions</doc>
+ </nobuild>
+ <nocompress>
+ <shortopt>Z</shortopt>
+ <doc>request uncompressed files when downloading</doc>
+ </nocompress>
+ <installroot>
+ <shortopt>R</shortopt>
+ <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT), use packagingroot for RPM</doc>
+ <arg>DIR</arg>
+ </installroot>
+ <ignore-errors>
+ <shortopt></shortopt>
+ <doc>force install even if there were errors</doc>
+ </ignore-errors>
+ <loose>
+ <shortopt></shortopt>
+ <doc>do not check for recommended dependency version</doc>
+ </loose>
+ </options>
+ <doc>
+WARNING: This function is deprecated in favor of using the upgrade command with no params
+
+Upgrades all packages that have a newer release available. Upgrades are
+done only if there is a release available of the state specified in
+&quot;preferred_state&quot; (currently {config preferred_state}), or a state considered
+more stable.
+</doc>
+ </upgrade-all>
+ <uninstall>
+ <summary>Un-install Package</summary>
+ <function>doUninstall</function>
+ <shortcut>un</shortcut>
+ <options>
+ <nodeps>
+ <shortopt>n</shortopt>
+ <doc>ignore dependencies, uninstall anyway</doc>
+ </nodeps>
+ <register-only>
+ <shortopt>r</shortopt>
+ <doc>do not remove files, only register the packages as not installed</doc>
+ </register-only>
+ <installroot>
+ <shortopt>R</shortopt>
+ <doc>root directory used when installing files (ala PHP&#039;s INSTALL_ROOT)</doc>
+ <arg>DIR</arg>
+ </installroot>
+ <ignore-errors>
+ <shortopt></shortopt>
+ <doc>force install even if there were errors</doc>
+ </ignore-errors>
+ <offline>
+ <shortopt>O</shortopt>
+ <doc>do not attempt to uninstall remotely</doc>
+ </offline>
+ </options>
+ <doc>[channel/]&lt;package&gt; ...
+Uninstalls one or more PEAR packages. More than one package may be
+specified at once. Prefix with channel name to uninstall from a
+channel not in your default channel ({config default_channel})
+</doc>
+ </uninstall>
+ <bundle>
+ <summary>Unpacks a Pecl Package</summary>
+ <function>doBundle</function>
+ <shortcut>bun</shortcut>
+ <options>
+ <destination>
+ <shortopt>d</shortopt>
+ <doc>Optional destination directory for unpacking (defaults to current path or &quot;ext&quot; if exists)</doc>
+ <arg>DIR</arg>
+ </destination>
+ <force>
+ <shortopt>f</shortopt>
+ <doc>Force the unpacking even if there were errors in the package</doc>
+ </force>
+ </options>
+ <doc>&lt;package&gt;
+Unpacks a Pecl Package into the selected location. It will download the
+package if needed.
+</doc>
+ </bundle>
+ <run-scripts>
+ <summary>Run Post-Install Scripts bundled with a package</summary>
+ <function>doRunScripts</function>
+ <shortcut>rs</shortcut>
+ <options />
+ <doc>&lt;package&gt;
+Run post-installation scripts in package &lt;package&gt;, if any exist.
+</doc>
+ </run-scripts>
+</commands> \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Mirror.php b/3rdparty/PEAR/Command/Mirror.php
index bf56c3db640..4d157c6b888 100644
--- a/3rdparty/PEAR/Command/Mirror.php
+++ b/3rdparty/PEAR/Command/Mirror.php
@@ -1,53 +1,58 @@
<?php
-//
-// +----------------------------------------------------------------------+
-// | PHP Version 5 |
-// +----------------------------------------------------------------------+
-// | Copyright (c) 1997-2004 The PHP Group |
-// +----------------------------------------------------------------------+
-// | This source file is subject to version 3.0 of the PHP license, |
-// | that is bundled with this package in the file LICENSE, and is |
-// | available through the world-wide-web at the following url: |
-// | http://www.php.net/license/3_0.txt. |
-// | If you did not receive a copy of the PHP license and are unable to |
-// | obtain it through the world-wide-web, please send a note to |
-// | license@php.net so we can mail you a copy immediately. |
-// +----------------------------------------------------------------------+
-// | Author: Alexander Merz <alexmerz@php.net> |
-// | |
-// +----------------------------------------------------------------------+
-//
-// $Id: Mirror.php,v 1.5 2004/03/18 12:23:57 mj Exp $
+/**
+ * PEAR_Command_Mirror (download-all command)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Alexander Merz <alexmerz@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Mirror.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 1.2.0
+ */
-require_once "PEAR/Command/Common.php";
-require_once "PEAR/Command.php";
-require_once "PEAR/Remote.php";
-require_once "PEAR.php";
+/**
+ * base class
+ */
+require_once 'PEAR/Command/Common.php';
/**
* PEAR commands for providing file mirrors
*
+ * @category pear
+ * @package PEAR
+ * @author Alexander Merz <alexmerz@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 1.2.0
*/
class PEAR_Command_Mirror extends PEAR_Command_Common
{
- // {{{ properties
-
var $commands = array(
'download-all' => array(
- 'summary' => 'Downloads each available package from master_server',
+ 'summary' => 'Downloads each available package from the default channel',
'function' => 'doDownloadAll',
'shortcut' => 'da',
- 'options' => array(),
+ 'options' => array(
+ 'channel' =>
+ array(
+ 'shortopt' => 'c',
+ 'doc' => 'specify a channel other than the default channel',
+ 'arg' => 'CHAN',
+ ),
+ ),
'doc' => '
- Requests a list of available packages from the package server
- (master_server) and downloads them to current working directory'
+Requests a list of available packages from the default channel ({config default_channel})
+and downloads them to current working directory. Note: only
+packages within preferred_state ({config preferred_state}) will be downloaded'
),
);
- // }}}
-
- // {{{ constructor
-
/**
* PEAR_Command_Mirror constructor.
*
@@ -60,9 +65,15 @@ class PEAR_Command_Mirror extends PEAR_Command_Common
parent::PEAR_Command_Common($ui, $config);
}
- // }}}
+ /**
+ * For unit-testing
+ */
+ function &factory($a)
+ {
+ $a = &PEAR_Command::factory($a, $this->config);
+ return $a;
+ }
- // {{{ doDownloadAll()
/**
* retrieves a list of avaible Packages from master server
* and downloads them
@@ -72,30 +83,57 @@ class PEAR_Command_Mirror extends PEAR_Command_Common
* @param array $options the command options before the command
* @param array $params the stuff after the command name
* @return bool true if succesful
- * @throw PEAR_Error
+ * @throw PEAR_Error
*/
function doDownloadAll($command, $options, $params)
{
- $this->config->set("php_dir", ".");
- $remote = &new PEAR_Remote($this->config);
- $remoteInfo = $remote->call("package.listAll");
+ $savechannel = $this->config->get('default_channel');
+ $reg = &$this->config->getRegistry();
+ $channel = isset($options['channel']) ? $options['channel'] :
+ $this->config->get('default_channel');
+ if (!$reg->channelExists($channel)) {
+ $this->config->set('default_channel', $savechannel);
+ return $this->raiseError('Channel "' . $channel . '" does not exist');
+ }
+ $this->config->set('default_channel', $channel);
+
+ $this->ui->outputData('Using Channel ' . $this->config->get('default_channel'));
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($chan)) {
+ return $this->raiseError($chan);
+ }
+
+ if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
+ $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
+ $rest = &$this->config->getREST('1.0', array());
+ $remoteInfo = array_flip($rest->listPackages($base, $channel));
+ }
+
if (PEAR::isError($remoteInfo)) {
return $remoteInfo;
}
- $cmd = &PEAR_Command::factory("download", $this->config);
+
+ $cmd = &$this->factory("download");
if (PEAR::isError($cmd)) {
return $cmd;
}
- foreach ($remoteInfo as $pkgn => $pkg) {
- /**
- * Error handling not neccesary, because already done by
- * the download command
- */
- $cmd->run("download", array(), array($pkgn));
+
+ $this->ui->outputData('Using Preferred State of ' .
+ $this->config->get('preferred_state'));
+ $this->ui->outputData('Gathering release information, please wait...');
+
+ /**
+ * Error handling not necessary, because already done by
+ * the download command
+ */
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $err = $cmd->run('download', array('downloadonly' => true), array_keys($remoteInfo));
+ PEAR::staticPopErrorHandling();
+ $this->config->set('default_channel', $savechannel);
+ if (PEAR::isError($err)) {
+ $this->ui->outputData($err->getMessage());
}
return true;
}
-
- // }}}
-}
+} \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Mirror.xml b/3rdparty/PEAR/Command/Mirror.xml
new file mode 100644
index 00000000000..fe8be9d03bf
--- /dev/null
+++ b/3rdparty/PEAR/Command/Mirror.xml
@@ -0,0 +1,18 @@
+<commands version="1.0">
+ <download-all>
+ <summary>Downloads each available package from the default channel</summary>
+ <function>doDownloadAll</function>
+ <shortcut>da</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>specify a channel other than the default channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ </options>
+ <doc>
+Requests a list of available packages from the default channel ({config default_channel})
+and downloads them to current working directory. Note: only
+packages within preferred_state ({config preferred_state}) will be downloaded</doc>
+ </download-all>
+</commands> \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Package.php b/3rdparty/PEAR/Command/Package.php
index aca87111118..81df7bf6945 100644
--- a/3rdparty/PEAR/Command/Package.php
+++ b/3rdparty/PEAR/Command/Package.php
@@ -1,32 +1,44 @@
<?php
-//
-// +----------------------------------------------------------------------+
-// | PHP Version 5 |
-// +----------------------------------------------------------------------+
-// | Copyright (c) 1997-2004 The PHP Group |
-// +----------------------------------------------------------------------+
-// | This source file is subject to version 3.0 of the PHP license, |
-// | that is bundled with this package in the file LICENSE, and is |
-// | available through the world-wide-web at the following url: |
-// | http://www.php.net/license/3_0.txt. |
-// | If you did not receive a copy of the PHP license and are unable to |
-// | obtain it through the world-wide-web, please send a note to |
-// | license@php.net so we can mail you a copy immediately. |
-// +----------------------------------------------------------------------+
-// | Authors: Stig Bakken <ssb@php.net> |
-// | Martin Jansen <mj@php.net> |
-// | Greg Beaver <cellog@php.net> |
-// +----------------------------------------------------------------------+
-//
-// $Id: Package.php,v 1.61.2.7 2005/02/17 17:47:55 cellog Exp $
-
-require_once 'PEAR/Common.php';
+/**
+ * PEAR_Command_Package (package, package-validate, cvsdiff, cvstag, package-dependencies,
+ * sign, makerpm, convert commands)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Martin Jansen <mj@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Package.php 313024 2011-07-06 19:51:24Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ */
+
+/**
+ * base class
+ */
require_once 'PEAR/Command/Common.php';
+/**
+ * PEAR commands for login/logout
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Martin Jansen <mj@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 0.1
+ */
+
class PEAR_Command_Package extends PEAR_Command_Common
{
- // {{{ properties
-
var $commands = array(
'package' => array(
'summary' => 'Build Package',
@@ -42,9 +54,13 @@ class PEAR_Command_Package extends PEAR_Command_Common
'doc' => 'Print the name of the packaged file.',
),
),
- 'doc' => '[descfile]
+ 'doc' => '[descfile] [descfile2]
Creates a PEAR package from its description file (usually called
-package.xml).
+package.xml). If a second packagefile is passed in, then
+the packager will check to make sure that one is a package.xml
+version 1.0, and the other is a package.xml version 2.0. The
+package.xml version 1.0 will be saved as "package.xml" in the archive,
+and the other as "package2.xml" in the archive"
'
),
'package-validate' => array(
@@ -118,6 +134,39 @@ Using the -r or -R option you may compare the current code with that
of a specific release.
',
),
+ 'svntag' => array(
+ 'summary' => 'Set SVN Release Tag',
+ 'function' => 'doSvnTag',
+ 'shortcut' => 'sv',
+ 'options' => array(
+ 'quiet' => array(
+ 'shortopt' => 'q',
+ 'doc' => 'Be quiet',
+ ),
+ 'slide' => array(
+ 'shortopt' => 'F',
+ 'doc' => 'Move (slide) tag if it exists',
+ ),
+ 'delete' => array(
+ 'shortopt' => 'd',
+ 'doc' => 'Remove tag',
+ ),
+ 'dry-run' => array(
+ 'shortopt' => 'n',
+ 'doc' => 'Don\'t do anything, just pretend',
+ ),
+ ),
+ 'doc' => '<package.xml> [files...]
+ Sets a SVN tag on all files in a package. Use this command after you have
+ packaged a distribution tarball with the "package" command to tag what
+ revisions of what files were in that release. If need to fix something
+ after running svntag once, but before the tarball is released to the public,
+ use the "slide" option to move the release tag.
+
+ to include files (such as a second package.xml, or tests not included in the
+ release), pass them as additional parameters.
+ ',
+ ),
'cvstag' => array(
'summary' => 'Set CVS Release Tag',
'function' => 'doCvsTag',
@@ -144,49 +193,36 @@ of a specific release.
'doc' => 'Don\'t do anything, just pretend',
),
),
- 'doc' => '<package.xml>
+ 'doc' => '<package.xml> [files...]
Sets a CVS tag on all files in a package. Use this command after you have
packaged a distribution tarball with the "package" command to tag what
revisions of what files were in that release. If need to fix something
after running cvstag once, but before the tarball is released to the public,
use the "slide" option to move the release tag.
+
+to include files (such as a second package.xml, or tests not included in the
+release), pass them as additional parameters.
',
),
- 'run-tests' => array(
- 'summary' => 'Run Regression Tests',
- 'function' => 'doRunTests',
- 'shortcut' => 'rt',
- 'options' => array(
- 'recur' => array(
- 'shortopt' => 'r',
- 'doc' => 'Run tests in child directories, recursively. 4 dirs deep maximum',
- ),
- 'ini' => array(
- 'shortopt' => 'i',
- 'doc' => 'actual string of settings to pass to php in format " -d setting=blah"',
- 'arg' => 'SETTINGS'
- ),
- 'realtimelog' => array(
- 'shortopt' => 'l',
- 'doc' => 'Log test runs/results as they are run',
- ),
- ),
- 'doc' => '[testfile|dir ...]
-Run regression tests with PHP\'s regression testing script (run-tests.php).',
- ),
'package-dependencies' => array(
'summary' => 'Show package dependencies',
'function' => 'doPackageDependencies',
'shortcut' => 'pd',
'options' => array(),
- 'doc' => '
-List all depencies the package has.'
+ 'doc' => '<package-file> or <package.xml> or <install-package-name>
+List all dependencies the package has.
+Can take a tgz / tar file, package.xml or a package name of an installed package.'
),
'sign' => array(
'summary' => 'Sign a package distribution file',
'function' => 'doSign',
'shortcut' => 'si',
- 'options' => array(),
+ 'options' => array(
+ 'verbose' => array(
+ 'shortopt' => 'v',
+ 'doc' => 'Display GnuPG output',
+ ),
+ ),
'doc' => '<package-file>
Signs a package distribution (.tar or .tgz) file with GnuPG.',
),
@@ -220,13 +256,28 @@ $ rpm -bb PEAR::Net_Socket-1.0.spec
Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
',
),
+ 'convert' => array(
+ 'summary' => 'Convert a package.xml 1.0 to package.xml 2.0 format',
+ 'function' => 'doConvert',
+ 'shortcut' => 'c2',
+ 'options' => array(
+ 'flat' => array(
+ 'shortopt' => 'f',
+ 'doc' => 'do not beautify the filelist.',
+ ),
+ ),
+ 'doc' => '[descfile] [descfile2]
+Converts a package.xml in 1.0 format into a package.xml
+in 2.0 format. The new file will be named package2.xml by default,
+and package.xml will be used as the old file by default.
+This is not the most intelligent conversion, and should only be
+used for automated conversion or learning the format.
+'
+ ),
);
var $output;
- // }}}
- // {{{ constructor
-
/**
* PEAR_Command_Package constructor.
*
@@ -237,10 +288,6 @@ Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
parent::PEAR_Command_Common($ui, $config);
}
- // }}}
-
- // {{{ _displayValidationResults()
-
function _displayValidationResults($err, $warn, $strict = false)
{
foreach ($err as $e) {
@@ -251,121 +298,407 @@ Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
}
$this->output .= sprintf('Validation: %d error(s), %d warning(s)'."\n",
sizeof($err), sizeof($warn));
- if ($strict && sizeof($err) > 0) {
+ if ($strict && count($err) > 0) {
$this->output .= "Fix these errors and try again.";
return false;
}
return true;
}
- // }}}
- // {{{ doPackage()
+ function &getPackager()
+ {
+ if (!class_exists('PEAR_Packager')) {
+ require_once 'PEAR/Packager.php';
+ }
+ $a = &new PEAR_Packager;
+ return $a;
+ }
+
+ function &getPackageFile($config, $debug = false)
+ {
+ if (!class_exists('PEAR_Common')) {
+ require_once 'PEAR/Common.php';
+ }
+ if (!class_exists('PEAR_PackageFile')) {
+ require_once 'PEAR/PackageFile.php';
+ }
+ $a = &new PEAR_PackageFile($config, $debug);
+ $common = new PEAR_Common;
+ $common->ui = $this->ui;
+ $a->setLogger($common);
+ return $a;
+ }
function doPackage($command, $options, $params)
{
$this->output = '';
- include_once 'PEAR/Packager.php';
- if (sizeof($params) < 1) {
- $params[0] = "package.xml";
- }
$pkginfofile = isset($params[0]) ? $params[0] : 'package.xml';
- $packager =& new PEAR_Packager();
- $err = $warn = array();
- $dir = dirname($pkginfofile);
+ $pkg2 = isset($params[1]) ? $params[1] : null;
+ if (!$pkg2 && !isset($params[0]) && file_exists('package2.xml')) {
+ $pkg2 = 'package2.xml';
+ }
+
+ $packager = &$this->getPackager();
$compress = empty($options['nocompress']) ? true : false;
- $result = $packager->package($pkginfofile, $compress);
+ $result = $packager->package($pkginfofile, $compress, $pkg2);
if (PEAR::isError($result)) {
- $this->ui->outputData($this->output, $command);
return $this->raiseError($result);
}
+
// Don't want output, only the package file name just created
if (isset($options['showname'])) {
$this->output = $result;
}
- if (PEAR::isError($result)) {
- $this->output .= "Package failed: ".$result->getMessage();
+
+ if ($this->output) {
+ $this->ui->outputData($this->output, $command);
}
- $this->ui->outputData($this->output, $command);
+
return true;
}
- // }}}
- // {{{ doPackageValidate()
-
function doPackageValidate($command, $options, $params)
{
$this->output = '';
- if (sizeof($params) < 1) {
- $params[0] = "package.xml";
- }
- $obj = new PEAR_Common;
- $info = null;
- if ($fp = @fopen($params[0], "r")) {
- $test = fread($fp, 5);
- fclose($fp);
- if ($test == "<?xml") {
- $info = $obj->infoFromDescriptionFile($params[0]);
- }
+ if (count($params) < 1) {
+ $params[0] = 'package.xml';
}
- if (empty($info)) {
- $info = $obj->infoFromTgzFile($params[0]);
+
+ $obj = &$this->getPackageFile($this->config, $this->_debug);
+ $obj->rawReturn();
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL);
+ if (PEAR::isError($info)) {
+ $info = $obj->fromPackageFile($params[0], PEAR_VALIDATE_NORMAL);
+ } else {
+ $archive = $info->getArchiveFile();
+ $tar = &new Archive_Tar($archive);
+ $tar->extract(dirname($info->getPackageFile()));
+ $info->setPackageFile(dirname($info->getPackageFile()) . DIRECTORY_SEPARATOR .
+ $info->getPackage() . '-' . $info->getVersion() . DIRECTORY_SEPARATOR .
+ basename($info->getPackageFile()));
}
+
+ PEAR::staticPopErrorHandling();
if (PEAR::isError($info)) {
return $this->raiseError($info);
}
- $obj->validatePackageInfo($info, $err, $warn);
+
+ $valid = false;
+ if ($info->getPackagexmlVersion() == '2.0') {
+ if ($valid = $info->validate(PEAR_VALIDATE_NORMAL)) {
+ $info->flattenFileList();
+ $valid = $info->validate(PEAR_VALIDATE_PACKAGING);
+ }
+ } else {
+ $valid = $info->validate(PEAR_VALIDATE_PACKAGING);
+ }
+
+ $err = $warn = array();
+ if ($errors = $info->getValidationWarnings()) {
+ foreach ($errors as $error) {
+ if ($error['level'] == 'warning') {
+ $warn[] = $error['message'];
+ } else {
+ $err[] = $error['message'];
+ }
+ }
+ }
+
$this->_displayValidationResults($err, $warn);
$this->ui->outputData($this->output, $command);
return true;
}
- // }}}
- // {{{ doCvsTag()
+ function doSvnTag($command, $options, $params)
+ {
+ $this->output = '';
+ $_cmd = $command;
+ if (count($params) < 1) {
+ $help = $this->getHelp($command);
+ return $this->raiseError("$command: missing parameter: $help[0]");
+ }
+
+ $packageFile = realpath($params[0]);
+ $dir = dirname($packageFile);
+ $dir = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1);
+ $obj = &$this->getPackageFile($this->config, $this->_debug);
+ $info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL);
+ if (PEAR::isError($info)) {
+ return $this->raiseError($info);
+ }
+
+ $err = $warn = array();
+ if (!$info->validate()) {
+ foreach ($info->getValidationWarnings() as $error) {
+ if ($error['level'] == 'warning') {
+ $warn[] = $error['message'];
+ } else {
+ $err[] = $error['message'];
+ }
+ }
+ }
+
+ if (!$this->_displayValidationResults($err, $warn, true)) {
+ $this->ui->outputData($this->output, $command);
+ return $this->raiseError('SVN tag failed');
+ }
+
+ $version = $info->getVersion();
+ $package = $info->getName();
+ $svntag = "$package-$version";
+
+ if (isset($options['delete'])) {
+ return $this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options);
+ }
+
+ $path = $this->_svnFindPath($packageFile);
+
+ // Check if there are any modified files
+ $fp = popen('svn st --xml ' . dirname($packageFile), "r");
+ $out = '';
+ while ($line = fgets($fp, 1024)) {
+ $out .= rtrim($line)."\n";
+ }
+ pclose($fp);
+
+ if (!isset($options['quiet']) && strpos($out, 'item="modified"')) {
+ $params = array(array(
+ 'name' => 'modified',
+ 'type' => 'yesno',
+ 'default' => 'no',
+ 'prompt' => 'You have files in your SVN checkout (' . $path['from'] . ') that have been modified but not commited, do you still want to tag ' . $version . '?',
+ ));
+ $answers = $this->ui->confirmDialog($params);
+
+ if (!in_array($answers['modified'], array('y', 'yes', 'on', '1'))) {
+ return true;
+ }
+ }
+
+ if (isset($options['slide'])) {
+ $this->_svnRemoveTag($version, $package, $svntag, $packageFile, $options);
+ }
+
+ // Check if tag already exists
+ $releaseTag = $path['local']['base'] . 'tags' . DIRECTORY_SEPARATOR . $svntag;
+ $existsCommand = 'svn ls ' . $path['base'] . 'tags/';
+
+ $fp = popen($existsCommand, "r");
+ $out = '';
+ while ($line = fgets($fp, 1024)) {
+ $out .= rtrim($line)."\n";
+ }
+ pclose($fp);
+
+ if (in_array($svntag . DIRECTORY_SEPARATOR, explode("\n", $out))) {
+ $this->ui->outputData($this->output, $command);
+ return $this->raiseError('SVN tag ' . $svntag . ' for ' . $package . ' already exists.');
+ } elseif (file_exists($path['local']['base'] . 'tags') === false) {
+ return $this->raiseError('Can not locate the tags directory at ' . $path['local']['base'] . 'tags');
+ } elseif (is_writeable($path['local']['base'] . 'tags') === false) {
+ return $this->raiseError('Can not write to the tag directory at ' . $path['local']['base'] . 'tags');
+ } else {
+ $makeCommand = 'svn mkdir ' . $releaseTag;
+ $this->output .= "+ $makeCommand\n";
+ if (empty($options['dry-run'])) {
+ // We need to create the tag dir.
+ $fp = popen($makeCommand, "r");
+ $out = '';
+ while ($line = fgets($fp, 1024)) {
+ $out .= rtrim($line)."\n";
+ }
+ pclose($fp);
+ $this->output .= "$out\n";
+ }
+ }
+
+ $command = 'svn';
+ if (isset($options['quiet'])) {
+ $command .= ' -q';
+ }
+
+ $command .= ' copy --parents ';
+
+ $dir = dirname($packageFile);
+ $dir = substr($dir, strrpos($dir, DIRECTORY_SEPARATOR) + 1);
+ $files = array_keys($info->getFilelist());
+ if (!in_array(basename($packageFile), $files)) {
+ $files[] = basename($packageFile);
+ }
+
+ array_shift($params);
+ if (count($params)) {
+ // add in additional files to be tagged (package files and such)
+ $files = array_merge($files, $params);
+ }
+
+ $commands = array();
+ foreach ($files as $file) {
+ if (!file_exists($file)) {
+ $file = $dir . DIRECTORY_SEPARATOR . $file;
+ }
+ $commands[] = $command . ' ' . escapeshellarg($file) . ' ' .
+ escapeshellarg($releaseTag . DIRECTORY_SEPARATOR . $file);
+ }
+
+ $this->output .= implode("\n", $commands) . "\n";
+ if (empty($options['dry-run'])) {
+ foreach ($commands as $command) {
+ $fp = popen($command, "r");
+ while ($line = fgets($fp, 1024)) {
+ $this->output .= rtrim($line)."\n";
+ }
+ pclose($fp);
+ }
+ }
+
+ $command = 'svn ci -m "Tagging the ' . $version . ' release" ' . $releaseTag . "\n";
+ $this->output .= "+ $command\n";
+ if (empty($options['dry-run'])) {
+ $fp = popen($command, "r");
+ while ($line = fgets($fp, 1024)) {
+ $this->output .= rtrim($line)."\n";
+ }
+ pclose($fp);
+ }
+
+ $this->ui->outputData($this->output, $_cmd);
+ return true;
+ }
+
+ function _svnFindPath($file)
+ {
+ $xml = '';
+ $command = "svn info --xml $file";
+ $fp = popen($command, "r");
+ while ($line = fgets($fp, 1024)) {
+ $xml .= rtrim($line)."\n";
+ }
+ pclose($fp);
+ $url_tag = strpos($xml, '<url>');
+ $url = substr($xml, $url_tag + 5, strpos($xml, '</url>', $url_tag + 5) - ($url_tag + 5));
+
+ $path = array();
+ $path['from'] = substr($url, 0, strrpos($url, '/'));
+ $path['base'] = substr($path['from'], 0, strrpos($path['from'], '/') + 1);
+
+ // Figure out the local paths - see http://pear.php.net/bugs/17463
+ $pos = strpos($file, DIRECTORY_SEPARATOR . 'trunk' . DIRECTORY_SEPARATOR);
+ if ($pos === false) {
+ $pos = strpos($file, DIRECTORY_SEPARATOR . 'branches' . DIRECTORY_SEPARATOR);
+ }
+ $path['local']['base'] = substr($file, 0, $pos + 1);
+
+ return $path;
+ }
+
+ function _svnRemoveTag($version, $package, $tag, $packageFile, $options)
+ {
+ $command = 'svn';
+
+ if (isset($options['quiet'])) {
+ $command .= ' -q';
+ }
+
+ $command .= ' remove';
+ $command .= ' -m "Removing tag for the ' . $version . ' release."';
+
+ $path = $this->_svnFindPath($packageFile);
+ $command .= ' ' . $path['base'] . 'tags/' . $tag;
+
+
+ if ($this->config->get('verbose') > 1) {
+ $this->output .= "+ $command\n";
+ }
+
+ $this->output .= "+ $command\n";
+ if (empty($options['dry-run'])) {
+ $fp = popen($command, "r");
+ while ($line = fgets($fp, 1024)) {
+ $this->output .= rtrim($line)."\n";
+ }
+ pclose($fp);
+ }
+
+ $this->ui->outputData($this->output, $command);
+ return true;
+ }
function doCvsTag($command, $options, $params)
{
$this->output = '';
$_cmd = $command;
- if (sizeof($params) < 1) {
+ if (count($params) < 1) {
$help = $this->getHelp($command);
return $this->raiseError("$command: missing parameter: $help[0]");
}
- $obj = new PEAR_Common;
- $info = $obj->infoFromDescriptionFile($params[0]);
+
+ $packageFile = realpath($params[0]);
+ $obj = &$this->getPackageFile($this->config, $this->_debug);
+ $info = $obj->fromAnyFile($packageFile, PEAR_VALIDATE_NORMAL);
if (PEAR::isError($info)) {
return $this->raiseError($info);
}
+
$err = $warn = array();
- $obj->validatePackageInfo($info, $err, $warn);
+ if (!$info->validate()) {
+ foreach ($info->getValidationWarnings() as $error) {
+ if ($error['level'] == 'warning') {
+ $warn[] = $error['message'];
+ } else {
+ $err[] = $error['message'];
+ }
+ }
+ }
+
if (!$this->_displayValidationResults($err, $warn, true)) {
$this->ui->outputData($this->output, $command);
- break;
+ return $this->raiseError('CVS tag failed');
}
- $version = $info['version'];
+
+ $version = $info->getVersion();
$cvsversion = preg_replace('/[^a-z0-9]/i', '_', $version);
- $cvstag = "RELEASE_$cvsversion";
- $files = array_keys($info['filelist']);
- $command = "cvs";
+ $cvstag = "RELEASE_$cvsversion";
+ $files = array_keys($info->getFilelist());
+ $command = 'cvs';
if (isset($options['quiet'])) {
$command .= ' -q';
}
+
if (isset($options['reallyquiet'])) {
$command .= ' -Q';
}
+
$command .= ' tag';
if (isset($options['slide'])) {
$command .= ' -F';
}
+
if (isset($options['delete'])) {
$command .= ' -d';
}
+
$command .= ' ' . $cvstag . ' ' . escapeshellarg($params[0]);
+ array_shift($params);
+ if (count($params)) {
+ // add in additional files to be tagged
+ $files = array_merge($files, $params);
+ }
+
+ $dir = dirname($packageFile);
+ $dir = substr($dir, strrpos($dir, '/') + 1);
foreach ($files as $file) {
+ if (!file_exists($file)) {
+ $file = $dir . DIRECTORY_SEPARATOR . $file;
+ }
$command .= ' ' . escapeshellarg($file);
}
+
if ($this->config->get('verbose') > 1) {
$this->output .= "+ $command\n";
}
+
$this->output .= "+ $command\n";
if (empty($options['dry-run'])) {
$fp = popen($command, "r");
@@ -374,13 +707,11 @@ Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
}
pclose($fp);
}
+
$this->ui->outputData($this->output, $_cmd);
return true;
}
- // }}}
- // {{{ doCvsDiff()
-
function doCvsDiff($command, $options, $params)
{
$this->output = '';
@@ -388,48 +719,78 @@ Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
$help = $this->getHelp($command);
return $this->raiseError("$command: missing parameter: $help[0]");
}
- $obj = new PEAR_Common;
- $info = $obj->infoFromDescriptionFile($params[0]);
+
+ $file = realpath($params[0]);
+ $obj = &$this->getPackageFile($this->config, $this->_debug);
+ $info = $obj->fromAnyFile($file, PEAR_VALIDATE_NORMAL);
if (PEAR::isError($info)) {
return $this->raiseError($info);
}
- $files = array_keys($info['filelist']);
+
+ $err = $warn = array();
+ if (!$info->validate()) {
+ foreach ($info->getValidationWarnings() as $error) {
+ if ($error['level'] == 'warning') {
+ $warn[] = $error['message'];
+ } else {
+ $err[] = $error['message'];
+ }
+ }
+ }
+
+ if (!$this->_displayValidationResults($err, $warn, true)) {
+ $this->ui->outputData($this->output, $command);
+ return $this->raiseError('CVS diff failed');
+ }
+
+ $info1 = $info->getFilelist();
+ $files = $info1;
$cmd = "cvs";
if (isset($options['quiet'])) {
$cmd .= ' -q';
unset($options['quiet']);
}
+
if (isset($options['reallyquiet'])) {
$cmd .= ' -Q';
unset($options['reallyquiet']);
}
+
if (isset($options['release'])) {
$cvsversion = preg_replace('/[^a-z0-9]/i', '_', $options['release']);
$cvstag = "RELEASE_$cvsversion";
$options['revision'] = $cvstag;
unset($options['release']);
}
+
$execute = true;
if (isset($options['dry-run'])) {
$execute = false;
unset($options['dry-run']);
}
+
$cmd .= ' diff';
// the rest of the options are passed right on to "cvs diff"
foreach ($options as $option => $optarg) {
- $arg = @$this->commands[$command]['options'][$option]['arg'];
- $short = @$this->commands[$command]['options'][$option]['shortopt'];
+ $arg = $short = false;
+ if (isset($this->commands[$command]['options'][$option])) {
+ $arg = $this->commands[$command]['options'][$option]['arg'];
+ $short = $this->commands[$command]['options'][$option]['shortopt'];
+ }
$cmd .= $short ? " -$short" : " --$option";
if ($arg && $optarg) {
$cmd .= ($short ? '' : '=') . escapeshellarg($optarg);
}
}
+
foreach ($files as $file) {
- $cmd .= ' ' . escapeshellarg($file);
+ $cmd .= ' ' . escapeshellarg($file['name']);
}
+
if ($this->config->get('verbose') > 1) {
$this->output .= "+ $cmd\n";
}
+
if ($execute) {
$fp = popen($cmd, "r");
while ($line = fgets($fp, 1024)) {
@@ -437,179 +798,148 @@ Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
}
pclose($fp);
}
- $this->ui->outputData($this->output, $command);
- return true;
- }
-
- // }}}
- // {{{ doRunTests()
-
- function doRunTests($command, $options, $params)
- {
- include_once 'PEAR/RunTest.php';
- $log = new PEAR_Common;
- $log->ui = &$this->ui; // slightly hacky, but it will work
- $run = new PEAR_RunTest($log);
- $tests = array();
- if (isset($options['recur'])) {
- $depth = 4;
- } else {
- $depth = 1;
- }
- if (!count($params)) {
- $params[] = '.';
- }
- foreach ($params as $p) {
- if (is_dir($p)) {
- $dir = System::find(array($p, '-type', 'f',
- '-maxdepth', $depth,
- '-name', '*.phpt'));
- $tests = array_merge($tests, $dir);
- } else {
- if (!@file_exists($p)) {
- if (!preg_match('/\.phpt$/', $p)) {
- $p .= '.phpt';
- }
- $dir = System::find(array(dirname($p), '-type', 'f',
- '-maxdepth', $depth,
- '-name', $p));
- $tests = array_merge($tests, $dir);
- } else {
- $tests[] = $p;
- }
- }
- }
- $ini_settings = '';
- if (isset($options['ini'])) {
- $ini_settings .= $options['ini'];
- }
- if (isset($_ENV['TEST_PHP_INCLUDE_PATH'])) {
- $ini_settings .= " -d include_path={$_ENV['TEST_PHP_INCLUDE_PATH']}";
- }
- if ($ini_settings) {
- $this->ui->outputData('Using INI settings: "' . $ini_settings . '"');
- }
- $skipped = $passed = $failed = array();
- $this->ui->outputData('Running ' . count($tests) . ' tests', $command);
- $start = time();
- if (isset($options['realtimelog'])) {
- @unlink('run-tests.log');
- }
- foreach ($tests as $t) {
- if (isset($options['realtimelog'])) {
- $fp = @fopen('run-tests.log', 'a');
- if ($fp) {
- fwrite($fp, "Running test $t...");
- fclose($fp);
- }
- }
- $result = $run->run($t, $ini_settings);
- if (OS_WINDOWS) {
- for($i=0;$i<2000;$i++) {
- $i = $i; // delay - race conditions on windows
- }
- }
- if (isset($options['realtimelog'])) {
- $fp = @fopen('run-tests.log', 'a');
- if ($fp) {
- fwrite($fp, "$result\n");
- fclose($fp);
- }
- }
- if ($result == 'FAILED') {
- $failed[] = $t;
- }
- if ($result == 'PASSED') {
- $passed[] = $t;
- }
- if ($result == 'SKIPPED') {
- $skipped[] = $t;
- }
- }
- $total = date('i:s', time() - $start);
- if (count($failed)) {
- $output = "TOTAL TIME: $total\n";
- $output .= count($passed) . " PASSED TESTS\n";
- $output .= count($skipped) . " SKIPPED TESTS\n";
- $output .= count($failed) . " FAILED TESTS:\n";
- foreach ($failed as $failure) {
- $output .= $failure . "\n";
- }
- if (isset($options['realtimelog'])) {
- $fp = @fopen('run-tests.log', 'a');
- } else {
- $fp = @fopen('run-tests.log', 'w');
- }
- if ($fp) {
- fwrite($fp, $output, strlen($output));
- fclose($fp);
- $this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command);
- }
- } elseif (@file_exists('run-tests.log') && !@is_dir('run-tests.log')) {
- @unlink('run-tests.log');
- }
- $this->ui->outputData('TOTAL TIME: ' . $total);
- $this->ui->outputData(count($passed) . ' PASSED TESTS', $command);
- $this->ui->outputData(count($skipped) . ' SKIPPED TESTS', $command);
- if (count($failed)) {
- $this->ui->outputData(count($failed) . ' FAILED TESTS:', $command);
- foreach ($failed as $failure) {
- $this->ui->outputData($failure, $command);
- }
- }
+ $this->ui->outputData($this->output, $command);
return true;
}
- // }}}
- // {{{ doPackageDependencies()
-
function doPackageDependencies($command, $options, $params)
{
// $params[0] -> the PEAR package to list its information
- if (sizeof($params) != 1) {
+ if (count($params) !== 1) {
return $this->raiseError("bad parameter(s), try \"help $command\"");
}
- $obj = new PEAR_Common();
- if (PEAR::isError($info = $obj->infoFromAny($params[0]))) {
+ $obj = &$this->getPackageFile($this->config, $this->_debug);
+ if (is_file($params[0]) || strpos($params[0], '.xml') > 0) {
+ $info = $obj->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
+ } else {
+ $reg = $this->config->getRegistry();
+ $info = $obj->fromArray($reg->packageInfo($params[0]));
+ }
+
+ if (PEAR::isError($info)) {
return $this->raiseError($info);
}
- if (is_array($info['release_deps'])) {
- $data = array(
- 'caption' => 'Dependencies for ' . $info['package'],
- 'border' => true,
- 'headline' => array("Type", "Name", "Relation", "Version"),
- );
+ $deps = $info->getDeps();
+ if (is_array($deps)) {
+ if ($info->getPackagexmlVersion() == '1.0') {
+ $data = array(
+ 'caption' => 'Dependencies for pear/' . $info->getPackage(),
+ 'border' => true,
+ 'headline' => array("Required?", "Type", "Name", "Relation", "Version"),
+ );
+
+ foreach ($deps as $d) {
+ if (isset($d['optional'])) {
+ if ($d['optional'] == 'yes') {
+ $req = 'No';
+ } else {
+ $req = 'Yes';
+ }
+ } else {
+ $req = 'Yes';
+ }
- foreach ($info['release_deps'] as $d) {
+ if (isset($this->_deps_rel_trans[$d['rel']])) {
+ $rel = $this->_deps_rel_trans[$d['rel']];
+ } else {
+ $rel = $d['rel'];
+ }
- if (isset($this->_deps_rel_trans[$d['rel']])) {
- $rel = $this->_deps_rel_trans[$d['rel']];
- } else {
- $rel = $d['rel'];
- }
+ if (isset($this->_deps_type_trans[$d['type']])) {
+ $type = ucfirst($this->_deps_type_trans[$d['type']]);
+ } else {
+ $type = $d['type'];
+ }
- if (isset($this->_deps_type_trans[$d['type']])) {
- $type = ucfirst($this->_deps_type_trans[$d['type']]);
- } else {
- $type = $d['type'];
- }
+ if (isset($d['name'])) {
+ $name = $d['name'];
+ } else {
+ $name = '';
+ }
- if (isset($d['name'])) {
- $name = $d['name'];
- } else {
- $name = '';
- }
+ if (isset($d['version'])) {
+ $version = $d['version'];
+ } else {
+ $version = '';
+ }
- if (isset($d['version'])) {
- $version = $d['version'];
- } else {
- $version = '';
+ $data['data'][] = array($req, $type, $name, $rel, $version);
+ }
+ } else { // package.xml 2.0 dependencies display
+ require_once 'PEAR/Dependency2.php';
+ $deps = $info->getDependencies();
+ $reg = &$this->config->getRegistry();
+ if (is_array($deps)) {
+ $d = new PEAR_Dependency2($this->config, array(), '');
+ $data = array(
+ 'caption' => 'Dependencies for ' . $info->getPackage(),
+ 'border' => true,
+ 'headline' => array("Required?", "Type", "Name", 'Versioning', 'Group'),
+ );
+ foreach ($deps as $type => $subd) {
+ $req = ($type == 'required') ? 'Yes' : 'No';
+ if ($type == 'group') {
+ $group = $subd['attribs']['name'];
+ } else {
+ $group = '';
+ }
+
+ if (!isset($subd[0])) {
+ $subd = array($subd);
+ }
+
+ foreach ($subd as $groupa) {
+ foreach ($groupa as $deptype => $depinfo) {
+ if ($deptype == 'attribs') {
+ continue;
+ }
+
+ if ($deptype == 'pearinstaller') {
+ $deptype = 'pear Installer';
+ }
+
+ if (!isset($depinfo[0])) {
+ $depinfo = array($depinfo);
+ }
+
+ foreach ($depinfo as $inf) {
+ $name = '';
+ if (isset($inf['channel'])) {
+ $alias = $reg->channelAlias($inf['channel']);
+ if (!$alias) {
+ $alias = '(channel?) ' .$inf['channel'];
+ }
+ $name = $alias . '/';
+
+ }
+ if (isset($inf['name'])) {
+ $name .= $inf['name'];
+ } elseif (isset($inf['pattern'])) {
+ $name .= $inf['pattern'];
+ } else {
+ $name .= '';
+ }
+
+ if (isset($inf['uri'])) {
+ $name .= ' [' . $inf['uri'] . ']';
+ }
+
+ if (isset($inf['conflicts'])) {
+ $ver = 'conflicts';
+ } else {
+ $ver = $d->_getExtraString($inf);
+ }
+
+ $data['data'][] = array($req, ucfirst($deptype), $name,
+ $ver, $group);
+ }
+ }
+ }
+ }
}
-
- $data['data'][] = array($type, $name, $rel, $version);
}
$this->ui->outputData($data, $command);
@@ -620,200 +950,175 @@ Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
$this->ui->outputData("This package does not have any dependencies.", $command);
}
- // }}}
- // {{{ doSign()
-
function doSign($command, $options, $params)
{
// should move most of this code into PEAR_Packager
// so it'll be easy to implement "pear package --sign"
- if (sizeof($params) != 1) {
+ if (count($params) !== 1) {
return $this->raiseError("bad parameter(s), try \"help $command\"");
}
+
+ require_once 'System.php';
+ require_once 'Archive/Tar.php';
+
if (!file_exists($params[0])) {
return $this->raiseError("file does not exist: $params[0]");
}
- $obj = new PEAR_Common;
- $info = $obj->infoFromTgzFile($params[0]);
+
+ $obj = $this->getPackageFile($this->config, $this->_debug);
+ $info = $obj->fromTgzFile($params[0], PEAR_VALIDATE_NORMAL);
if (PEAR::isError($info)) {
return $this->raiseError($info);
}
- include_once "Archive/Tar.php";
- include_once "System.php";
+
$tar = new Archive_Tar($params[0]);
- $tmpdir = System::mktemp('-d pearsign');
- if (!$tar->extractList('package.xml package.sig', $tmpdir)) {
+
+ $tmpdir = $this->config->get('temp_dir');
+ $tmpdir = System::mktemp(' -t "' . $tmpdir . '" -d pearsign');
+ if (!$tar->extractList('package2.xml package.xml package.sig', $tmpdir)) {
return $this->raiseError("failed to extract tar file");
}
+
if (file_exists("$tmpdir/package.sig")) {
return $this->raiseError("package already signed");
}
- @unlink("$tmpdir/package.sig");
+
+ $packagexml = 'package.xml';
+ if (file_exists("$tmpdir/package2.xml")) {
+ $packagexml = 'package2.xml';
+ }
+
+ if (file_exists("$tmpdir/package.sig")) {
+ unlink("$tmpdir/package.sig");
+ }
+
+ if (!file_exists("$tmpdir/$packagexml")) {
+ return $this->raiseError("Extracted file $tmpdir/$packagexml not found.");
+ }
+
$input = $this->ui->userDialog($command,
array('GnuPG Passphrase'),
array('password'));
- $gpg = popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/package.xml 2>/dev/null", "w");
+ if (!isset($input[0])) {
+ //use empty passphrase
+ $input[0] = '';
+ }
+
+ $devnull = (isset($options['verbose'])) ? '' : ' 2>/dev/null';
+ $gpg = popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/$packagexml" . $devnull, "w");
if (!$gpg) {
return $this->raiseError("gpg command failed");
}
- fwrite($gpg, "$input[0]\r");
+
+ fwrite($gpg, "$input[0]\n");
if (pclose($gpg) || !file_exists("$tmpdir/package.sig")) {
return $this->raiseError("gpg sign failed");
}
- $tar->addModify("$tmpdir/package.sig", '', $tmpdir);
- return true;
- }
-
- // }}}
- // {{{ doMakeRPM()
- /*
-
- (cox)
-
- TODO:
-
- - Fill the rpm dependencies in the template file.
-
- IDEAS:
-
- - Instead of mapping the role to rpm vars, perhaps it's better
-
- to use directly the pear cmd to install the files by itself
-
- in %postrun so:
-
- pear -d php_dir=%{_libdir}/php/pear -d test_dir=.. <package>
+ if (!$tar->addModify("$tmpdir/package.sig", '', $tmpdir)) {
+ return $this->raiseError('failed adding signature to file');
+ }
- */
+ $this->ui->outputData("Package signed.", $command);
+ return true;
+ }
- function doMakeRPM($command, $options, $params)
+ /**
+ * For unit testing purposes
+ */
+ function &getInstaller(&$ui)
{
- if (sizeof($params) != 1) {
- return $this->raiseError("bad parameter(s), try \"help $command\"");
- }
- if (!file_exists($params[0])) {
- return $this->raiseError("file does not exist: $params[0]");
- }
- include_once "Archive/Tar.php";
- include_once "PEAR/Installer.php";
- include_once "System.php";
- $tar = new Archive_Tar($params[0]);
- $tmpdir = System::mktemp('-d pear2rpm');
- $instroot = System::mktemp('-d pear2rpm');
- $tmp = $this->config->get('verbose');
- $this->config->set('verbose', 0);
- $installer = new PEAR_Installer($this->ui);
- $info = $installer->install($params[0],
- array('installroot' => $instroot,
- 'nodeps' => true));
- $pkgdir = "$info[package]-$info[version]";
- $info['rpm_xml_dir'] = '/var/lib/pear';
- $this->config->set('verbose', $tmp);
- if (!$tar->extractList("package.xml", $tmpdir, $pkgdir)) {
- return $this->raiseError("failed to extract $params[0]");
- }
- if (!file_exists("$tmpdir/package.xml")) {
- return $this->raiseError("no package.xml found in $params[0]");
- }
- if (isset($options['spec-template'])) {
- $spec_template = $options['spec-template'];
- } else {
- $spec_template = $this->config->get('data_dir') .
- '/PEAR/template.spec';
+ if (!class_exists('PEAR_Installer')) {
+ require_once 'PEAR/Installer.php';
}
- if (isset($options['rpm-pkgname'])) {
- $rpm_pkgname_format = $options['rpm-pkgname'];
- } else {
- $rpm_pkgname_format = "PEAR::%s";
- }
-
- $info['extra_headers'] = '';
- $info['doc_files'] = '';
- $info['files'] = '';
- $info['rpm_package'] = sprintf($rpm_pkgname_format, $info['package']);
- $srcfiles = 0;
- foreach ($info['filelist'] as $name => $attr) {
+ $a = &new PEAR_Installer($ui);
+ return $a;
+ }
- if (!isset($attr['role'])) {
- continue;
+ /**
+ * For unit testing purposes
+ */
+ function &getCommandPackaging(&$ui, &$config)
+ {
+ if (!class_exists('PEAR_Command_Packaging')) {
+ if ($fp = @fopen('PEAR/Command/Packaging.php', 'r', true)) {
+ fclose($fp);
+ include_once 'PEAR/Command/Packaging.php';
}
- $name = preg_replace('![/:\\\\]!', '/', $name);
- if ($attr['role'] == 'doc') {
- $info['doc_files'] .= " $name";
-
- // Map role to the rpm vars
- } else {
-
- $c_prefix = '%{_libdir}/php/pear';
-
- switch ($attr['role']) {
-
- case 'php':
-
- $prefix = $c_prefix; break;
-
- case 'ext':
-
- $prefix = '%{_libdir}/php'; break; // XXX good place?
-
- case 'src':
-
- $srcfiles++;
-
- $prefix = '%{_includedir}/php'; break; // XXX good place?
-
- case 'test':
+ }
- $prefix = "$c_prefix/tests/" . $info['package']; break;
+ if (class_exists('PEAR_Command_Packaging')) {
+ $a = &new PEAR_Command_Packaging($ui, $config);
+ } else {
+ $a = null;
+ }
- case 'data':
+ return $a;
+ }
- $prefix = "$c_prefix/data/" . $info['package']; break;
+ function doMakeRPM($command, $options, $params)
+ {
- case 'script':
+ // Check to see if PEAR_Command_Packaging is installed, and
+ // transparently switch to use the "make-rpm-spec" command from it
+ // instead, if it does. Otherwise, continue to use the old version
+ // of "makerpm" supplied with this package (PEAR).
+ $packaging_cmd = $this->getCommandPackaging($this->ui, $this->config);
+ if ($packaging_cmd !== null) {
+ $this->ui->outputData('PEAR_Command_Packaging is installed; using '.
+ 'newer "make-rpm-spec" command instead');
+ return $packaging_cmd->run('make-rpm-spec', $options, $params);
+ }
- $prefix = '%{_bindir}'; break;
+ $this->ui->outputData('WARNING: "pear makerpm" is no longer available; an '.
+ 'improved version is available via "pear make-rpm-spec", which '.
+ 'is available by installing PEAR_Command_Packaging');
+ return true;
+ }
+ function doConvert($command, $options, $params)
+ {
+ $packagexml = isset($params[0]) ? $params[0] : 'package.xml';
+ $newpackagexml = isset($params[1]) ? $params[1] : dirname($packagexml) .
+ DIRECTORY_SEPARATOR . 'package2.xml';
+ $pkg = &$this->getPackageFile($this->config, $this->_debug);
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $pf = $pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($pf)) {
+ if (is_array($pf->getUserInfo())) {
+ foreach ($pf->getUserInfo() as $warning) {
+ $this->ui->outputData($warning['message']);
}
-
- $name = str_replace('\\', '/', $name);
- $info['files'] .= "$prefix/$name\n";
-
}
+ return $this->raiseError($pf);
}
- if ($srcfiles > 0) {
- include_once "OS/Guess.php";
- $os = new OS_Guess;
- $arch = $os->getCpu();
- } else {
- $arch = 'noarch';
- }
- $cfg = array('master_server', 'php_dir', 'ext_dir', 'doc_dir',
- 'bin_dir', 'data_dir', 'test_dir');
- foreach ($cfg as $k) {
- $info[$k] = $this->config->get($k);
- }
- $info['arch'] = $arch;
- $fp = @fopen($spec_template, "r");
- if (!$fp) {
- return $this->raiseError("could not open RPM spec file template $spec_template: $php_errormsg");
+
+ if (is_a($pf, 'PEAR_PackageFile_v2')) {
+ $this->ui->outputData($packagexml . ' is already a package.xml version 2.0');
+ return true;
}
- $spec_contents = preg_replace('/@([a-z0-9_-]+)@/e', '$info["\1"]', fread($fp, filesize($spec_template)));
- fclose($fp);
- $spec_file = "$info[rpm_package]-$info[version].spec";
- $wp = fopen($spec_file, "wb");
- if (!$wp) {
- return $this->raiseError("could not write RPM spec file $spec_file: $php_errormsg");
+
+ $gen = &$pf->getDefaultGenerator();
+ $newpf = &$gen->toV2();
+ $newpf->setPackagefile($newpackagexml);
+ $gen = &$newpf->getDefaultGenerator();
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $state = (isset($options['flat']) ? PEAR_VALIDATE_PACKAGING : PEAR_VALIDATE_NORMAL);
+ $saved = $gen->toPackageFile(dirname($newpackagexml), $state, basename($newpackagexml));
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($saved)) {
+ if (is_array($saved->getUserInfo())) {
+ foreach ($saved->getUserInfo() as $warning) {
+ $this->ui->outputData($warning['message']);
+ }
+ }
+
+ $this->ui->outputData($saved->getMessage());
+ return true;
}
- fwrite($wp, $spec_contents);
- fclose($wp);
- $this->ui->outputData("Wrote RPM spec file $spec_file", $command);
+ $this->ui->outputData('Wrote new version 2.0 package.xml to "' . $saved . '"');
return true;
}
-
- // }}}
-}
-
-?>
+} \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Package.xml b/3rdparty/PEAR/Command/Package.xml
new file mode 100644
index 00000000000..d1aff9d48de
--- /dev/null
+++ b/3rdparty/PEAR/Command/Package.xml
@@ -0,0 +1,237 @@
+<commands version="1.0">
+ <package>
+ <summary>Build Package</summary>
+ <function>doPackage</function>
+ <shortcut>p</shortcut>
+ <options>
+ <nocompress>
+ <shortopt>Z</shortopt>
+ <doc>Do not gzip the package file</doc>
+ </nocompress>
+ <showname>
+ <shortopt>n</shortopt>
+ <doc>Print the name of the packaged file.</doc>
+ </showname>
+ </options>
+ <doc>[descfile] [descfile2]
+Creates a PEAR package from its description file (usually called
+package.xml). If a second packagefile is passed in, then
+the packager will check to make sure that one is a package.xml
+version 1.0, and the other is a package.xml version 2.0. The
+package.xml version 1.0 will be saved as &quot;package.xml&quot; in the archive,
+and the other as &quot;package2.xml&quot; in the archive&quot;
+</doc>
+ </package>
+ <package-validate>
+ <summary>Validate Package Consistency</summary>
+ <function>doPackageValidate</function>
+ <shortcut>pv</shortcut>
+ <options />
+ <doc>
+</doc>
+ </package-validate>
+ <cvsdiff>
+ <summary>Run a &quot;cvs diff&quot; for all files in a package</summary>
+ <function>doCvsDiff</function>
+ <shortcut>cd</shortcut>
+ <options>
+ <quiet>
+ <shortopt>q</shortopt>
+ <doc>Be quiet</doc>
+ </quiet>
+ <reallyquiet>
+ <shortopt>Q</shortopt>
+ <doc>Be really quiet</doc>
+ </reallyquiet>
+ <date>
+ <shortopt>D</shortopt>
+ <doc>Diff against revision of DATE</doc>
+ <arg>DATE</arg>
+ </date>
+ <release>
+ <shortopt>R</shortopt>
+ <doc>Diff against tag for package release REL</doc>
+ <arg>REL</arg>
+ </release>
+ <revision>
+ <shortopt>r</shortopt>
+ <doc>Diff against revision REV</doc>
+ <arg>REV</arg>
+ </revision>
+ <context>
+ <shortopt>c</shortopt>
+ <doc>Generate context diff</doc>
+ </context>
+ <unified>
+ <shortopt>u</shortopt>
+ <doc>Generate unified diff</doc>
+ </unified>
+ <ignore-case>
+ <shortopt>i</shortopt>
+ <doc>Ignore case, consider upper- and lower-case letters equivalent</doc>
+ </ignore-case>
+ <ignore-whitespace>
+ <shortopt>b</shortopt>
+ <doc>Ignore changes in amount of white space</doc>
+ </ignore-whitespace>
+ <ignore-blank-lines>
+ <shortopt>B</shortopt>
+ <doc>Ignore changes that insert or delete blank lines</doc>
+ </ignore-blank-lines>
+ <brief>
+ <shortopt></shortopt>
+ <doc>Report only whether the files differ, no details</doc>
+ </brief>
+ <dry-run>
+ <shortopt>n</shortopt>
+ <doc>Don&#039;t do anything, just pretend</doc>
+ </dry-run>
+ </options>
+ <doc>&lt;package.xml&gt;
+Compares all the files in a package. Without any options, this
+command will compare the current code with the last checked-in code.
+Using the -r or -R option you may compare the current code with that
+of a specific release.
+</doc>
+ </cvsdiff>
+ <svntag>
+ <summary>Set SVN Release Tag</summary>
+ <function>doSvnTag</function>
+ <shortcut>sv</shortcut>
+ <options>
+ <quiet>
+ <shortopt>q</shortopt>
+ <doc>Be quiet</doc>
+ </quiet>
+ <slide>
+ <shortopt>F</shortopt>
+ <doc>Move (slide) tag if it exists</doc>
+ </slide>
+ <delete>
+ <shortopt>d</shortopt>
+ <doc>Remove tag</doc>
+ </delete>
+ <dry-run>
+ <shortopt>n</shortopt>
+ <doc>Don&#039;t do anything, just pretend</doc>
+ </dry-run>
+ </options>
+ <doc>&lt;package.xml&gt; [files...]
+ Sets a SVN tag on all files in a package. Use this command after you have
+ packaged a distribution tarball with the &quot;package&quot; command to tag what
+ revisions of what files were in that release. If need to fix something
+ after running svntag once, but before the tarball is released to the public,
+ use the &quot;slide&quot; option to move the release tag.
+
+ to include files (such as a second package.xml, or tests not included in the
+ release), pass them as additional parameters.
+ </doc>
+ </svntag>
+ <cvstag>
+ <summary>Set CVS Release Tag</summary>
+ <function>doCvsTag</function>
+ <shortcut>ct</shortcut>
+ <options>
+ <quiet>
+ <shortopt>q</shortopt>
+ <doc>Be quiet</doc>
+ </quiet>
+ <reallyquiet>
+ <shortopt>Q</shortopt>
+ <doc>Be really quiet</doc>
+ </reallyquiet>
+ <slide>
+ <shortopt>F</shortopt>
+ <doc>Move (slide) tag if it exists</doc>
+ </slide>
+ <delete>
+ <shortopt>d</shortopt>
+ <doc>Remove tag</doc>
+ </delete>
+ <dry-run>
+ <shortopt>n</shortopt>
+ <doc>Don&#039;t do anything, just pretend</doc>
+ </dry-run>
+ </options>
+ <doc>&lt;package.xml&gt; [files...]
+Sets a CVS tag on all files in a package. Use this command after you have
+packaged a distribution tarball with the &quot;package&quot; command to tag what
+revisions of what files were in that release. If need to fix something
+after running cvstag once, but before the tarball is released to the public,
+use the &quot;slide&quot; option to move the release tag.
+
+to include files (such as a second package.xml, or tests not included in the
+release), pass them as additional parameters.
+</doc>
+ </cvstag>
+ <package-dependencies>
+ <summary>Show package dependencies</summary>
+ <function>doPackageDependencies</function>
+ <shortcut>pd</shortcut>
+ <options />
+ <doc>&lt;package-file&gt; or &lt;package.xml&gt; or &lt;install-package-name&gt;
+List all dependencies the package has.
+Can take a tgz / tar file, package.xml or a package name of an installed package.</doc>
+ </package-dependencies>
+ <sign>
+ <summary>Sign a package distribution file</summary>
+ <function>doSign</function>
+ <shortcut>si</shortcut>
+ <options>
+ <verbose>
+ <shortopt>v</shortopt>
+ <doc>Display GnuPG output</doc>
+ </verbose>
+ </options>
+ <doc>&lt;package-file&gt;
+Signs a package distribution (.tar or .tgz) file with GnuPG.</doc>
+ </sign>
+ <makerpm>
+ <summary>Builds an RPM spec file from a PEAR package</summary>
+ <function>doMakeRPM</function>
+ <shortcut>rpm</shortcut>
+ <options>
+ <spec-template>
+ <shortopt>t</shortopt>
+ <doc>Use FILE as RPM spec file template</doc>
+ <arg>FILE</arg>
+ </spec-template>
+ <rpm-pkgname>
+ <shortopt>p</shortopt>
+ <doc>Use FORMAT as format string for RPM package name, %s is replaced
+by the PEAR package name, defaults to &quot;PEAR::%s&quot;.</doc>
+ <arg>FORMAT</arg>
+ </rpm-pkgname>
+ </options>
+ <doc>&lt;package-file&gt;
+
+Creates an RPM .spec file for wrapping a PEAR package inside an RPM
+package. Intended to be used from the SPECS directory, with the PEAR
+package tarball in the SOURCES directory:
+
+$ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
+Wrote RPM spec file PEAR::Net_Geo-1.0.spec
+$ rpm -bb PEAR::Net_Socket-1.0.spec
+...
+Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
+</doc>
+ </makerpm>
+ <convert>
+ <summary>Convert a package.xml 1.0 to package.xml 2.0 format</summary>
+ <function>doConvert</function>
+ <shortcut>c2</shortcut>
+ <options>
+ <flat>
+ <shortopt>f</shortopt>
+ <doc>do not beautify the filelist.</doc>
+ </flat>
+ </options>
+ <doc>[descfile] [descfile2]
+Converts a package.xml in 1.0 format into a package.xml
+in 2.0 format. The new file will be named package2.xml by default,
+and package.xml will be used as the old file by default.
+This is not the most intelligent conversion, and should only be
+used for automated conversion or learning the format.
+</doc>
+ </convert>
+</commands> \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Pickle.php b/3rdparty/PEAR/Command/Pickle.php
new file mode 100644
index 00000000000..87aa25ea30c
--- /dev/null
+++ b/3rdparty/PEAR/Command/Pickle.php
@@ -0,0 +1,421 @@
+<?php
+/**
+ * PEAR_Command_Pickle (pickle command)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 2005-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Pickle.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 1.4.1
+ */
+
+/**
+ * base class
+ */
+require_once 'PEAR/Command/Common.php';
+
+/**
+ * PEAR commands for login/logout
+ *
+ * @category pear
+ * @package PEAR
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 2005-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 1.4.1
+ */
+
+class PEAR_Command_Pickle extends PEAR_Command_Common
+{
+ var $commands = array(
+ 'pickle' => array(
+ 'summary' => 'Build PECL Package',
+ 'function' => 'doPackage',
+ 'shortcut' => 'pi',
+ 'options' => array(
+ 'nocompress' => array(
+ 'shortopt' => 'Z',
+ 'doc' => 'Do not gzip the package file'
+ ),
+ 'showname' => array(
+ 'shortopt' => 'n',
+ 'doc' => 'Print the name of the packaged file.',
+ ),
+ ),
+ 'doc' => '[descfile]
+Creates a PECL package from its package2.xml file.
+
+An automatic conversion will be made to a package.xml 1.0 and written out to
+disk in the current directory as "package.xml". Note that
+only simple package.xml 2.0 will be converted. package.xml 2.0 with:
+
+ - dependency types other than required/optional PECL package/ext/php/pearinstaller
+ - more than one extsrcrelease or zendextsrcrelease
+ - zendextbinrelease, extbinrelease, phprelease, or bundle release type
+ - dependency groups
+ - ignore tags in release filelist
+ - tasks other than replace
+ - custom roles
+
+will cause pickle to fail, and output an error message. If your package2.xml
+uses any of these features, you are best off using PEAR_PackageFileManager to
+generate both package.xml.
+'
+ ),
+ );
+
+ /**
+ * PEAR_Command_Package constructor.
+ *
+ * @access public
+ */
+ function PEAR_Command_Pickle(&$ui, &$config)
+ {
+ parent::PEAR_Command_Common($ui, $config);
+ }
+
+ /**
+ * For unit-testing ease
+ *
+ * @return PEAR_Packager
+ */
+ function &getPackager()
+ {
+ if (!class_exists('PEAR_Packager')) {
+ require_once 'PEAR/Packager.php';
+ }
+
+ $a = &new PEAR_Packager;
+ return $a;
+ }
+
+ /**
+ * For unit-testing ease
+ *
+ * @param PEAR_Config $config
+ * @param bool $debug
+ * @param string|null $tmpdir
+ * @return PEAR_PackageFile
+ */
+ function &getPackageFile($config, $debug = false)
+ {
+ if (!class_exists('PEAR_Common')) {
+ require_once 'PEAR/Common.php';
+ }
+
+ if (!class_exists('PEAR_PackageFile')) {
+ require_once 'PEAR/PackageFile.php';
+ }
+
+ $a = &new PEAR_PackageFile($config, $debug);
+ $common = new PEAR_Common;
+ $common->ui = $this->ui;
+ $a->setLogger($common);
+ return $a;
+ }
+
+ function doPackage($command, $options, $params)
+ {
+ $this->output = '';
+ $pkginfofile = isset($params[0]) ? $params[0] : 'package2.xml';
+ $packager = &$this->getPackager();
+ if (PEAR::isError($err = $this->_convertPackage($pkginfofile))) {
+ return $err;
+ }
+
+ $compress = empty($options['nocompress']) ? true : false;
+ $result = $packager->package($pkginfofile, $compress, 'package.xml');
+ if (PEAR::isError($result)) {
+ return $this->raiseError($result);
+ }
+
+ // Don't want output, only the package file name just created
+ if (isset($options['showname'])) {
+ $this->ui->outputData($result, $command);
+ }
+
+ return true;
+ }
+
+ function _convertPackage($packagexml)
+ {
+ $pkg = &$this->getPackageFile($this->config);
+ $pf2 = &$pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
+ if (!is_a($pf2, 'PEAR_PackageFile_v2')) {
+ return $this->raiseError('Cannot process "' .
+ $packagexml . '", is not a package.xml 2.0');
+ }
+
+ require_once 'PEAR/PackageFile/v1.php';
+ $pf = new PEAR_PackageFile_v1;
+ $pf->setConfig($this->config);
+ if ($pf2->getPackageType() != 'extsrc' && $pf2->getPackageType() != 'zendextsrc') {
+ return $this->raiseError('Cannot safely convert "' . $packagexml .
+ '", is not an extension source package. Using a PEAR_PackageFileManager-based ' .
+ 'script is an option');
+ }
+
+ if (is_array($pf2->getUsesRole())) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml .
+ '", contains custom roles. Using a PEAR_PackageFileManager-based script or ' .
+ 'the convert command is an option');
+ }
+
+ if (is_array($pf2->getUsesTask())) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml .
+ '", contains custom tasks. Using a PEAR_PackageFileManager-based script or ' .
+ 'the convert command is an option');
+ }
+
+ $deps = $pf2->getDependencies();
+ if (isset($deps['group'])) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml .
+ '", contains dependency groups. Using a PEAR_PackageFileManager-based script ' .
+ 'or the convert command is an option');
+ }
+
+ if (isset($deps['required']['subpackage']) ||
+ isset($deps['optional']['subpackage'])) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml .
+ '", contains subpackage dependencies. Using a PEAR_PackageFileManager-based '.
+ 'script is an option');
+ }
+
+ if (isset($deps['required']['os'])) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml .
+ '", contains os dependencies. Using a PEAR_PackageFileManager-based '.
+ 'script is an option');
+ }
+
+ if (isset($deps['required']['arch'])) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml .
+ '", contains arch dependencies. Using a PEAR_PackageFileManager-based '.
+ 'script is an option');
+ }
+
+ $pf->setPackage($pf2->getPackage());
+ $pf->setSummary($pf2->getSummary());
+ $pf->setDescription($pf2->getDescription());
+ foreach ($pf2->getMaintainers() as $maintainer) {
+ $pf->addMaintainer($maintainer['role'], $maintainer['handle'],
+ $maintainer['name'], $maintainer['email']);
+ }
+
+ $pf->setVersion($pf2->getVersion());
+ $pf->setDate($pf2->getDate());
+ $pf->setLicense($pf2->getLicense());
+ $pf->setState($pf2->getState());
+ $pf->setNotes($pf2->getNotes());
+ $pf->addPhpDep($deps['required']['php']['min'], 'ge');
+ if (isset($deps['required']['php']['max'])) {
+ $pf->addPhpDep($deps['required']['php']['max'], 'le');
+ }
+
+ if (isset($deps['required']['package'])) {
+ if (!isset($deps['required']['package'][0])) {
+ $deps['required']['package'] = array($deps['required']['package']);
+ }
+
+ foreach ($deps['required']['package'] as $dep) {
+ if (!isset($dep['channel'])) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
+ ' contains uri-based dependency on a package. Using a ' .
+ 'PEAR_PackageFileManager-based script is an option');
+ }
+
+ if ($dep['channel'] != 'pear.php.net'
+ && $dep['channel'] != 'pecl.php.net'
+ && $dep['channel'] != 'doc.php.net') {
+ return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
+ ' contains dependency on a non-standard channel package. Using a ' .
+ 'PEAR_PackageFileManager-based script is an option');
+ }
+
+ if (isset($dep['conflicts'])) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
+ ' contains conflicts dependency. Using a ' .
+ 'PEAR_PackageFileManager-based script is an option');
+ }
+
+ if (isset($dep['exclude'])) {
+ $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
+ }
+
+ if (isset($dep['min'])) {
+ $pf->addPackageDep($dep['name'], $dep['min'], 'ge');
+ }
+
+ if (isset($dep['max'])) {
+ $pf->addPackageDep($dep['name'], $dep['max'], 'le');
+ }
+ }
+ }
+
+ if (isset($deps['required']['extension'])) {
+ if (!isset($deps['required']['extension'][0])) {
+ $deps['required']['extension'] = array($deps['required']['extension']);
+ }
+
+ foreach ($deps['required']['extension'] as $dep) {
+ if (isset($dep['conflicts'])) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
+ ' contains conflicts dependency. Using a ' .
+ 'PEAR_PackageFileManager-based script is an option');
+ }
+
+ if (isset($dep['exclude'])) {
+ $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
+ }
+
+ if (isset($dep['min'])) {
+ $pf->addExtensionDep($dep['name'], $dep['min'], 'ge');
+ }
+
+ if (isset($dep['max'])) {
+ $pf->addExtensionDep($dep['name'], $dep['max'], 'le');
+ }
+ }
+ }
+
+ if (isset($deps['optional']['package'])) {
+ if (!isset($deps['optional']['package'][0])) {
+ $deps['optional']['package'] = array($deps['optional']['package']);
+ }
+
+ foreach ($deps['optional']['package'] as $dep) {
+ if (!isset($dep['channel'])) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
+ ' contains uri-based dependency on a package. Using a ' .
+ 'PEAR_PackageFileManager-based script is an option');
+ }
+
+ if ($dep['channel'] != 'pear.php.net'
+ && $dep['channel'] != 'pecl.php.net'
+ && $dep['channel'] != 'doc.php.net') {
+ return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
+ ' contains dependency on a non-standard channel package. Using a ' .
+ 'PEAR_PackageFileManager-based script is an option');
+ }
+
+ if (isset($dep['exclude'])) {
+ $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
+ }
+
+ if (isset($dep['min'])) {
+ $pf->addPackageDep($dep['name'], $dep['min'], 'ge', 'yes');
+ }
+
+ if (isset($dep['max'])) {
+ $pf->addPackageDep($dep['name'], $dep['max'], 'le', 'yes');
+ }
+ }
+ }
+
+ if (isset($deps['optional']['extension'])) {
+ if (!isset($deps['optional']['extension'][0])) {
+ $deps['optional']['extension'] = array($deps['optional']['extension']);
+ }
+
+ foreach ($deps['optional']['extension'] as $dep) {
+ if (isset($dep['exclude'])) {
+ $this->ui->outputData('WARNING: exclude tags are ignored in conversion');
+ }
+
+ if (isset($dep['min'])) {
+ $pf->addExtensionDep($dep['name'], $dep['min'], 'ge', 'yes');
+ }
+
+ if (isset($dep['max'])) {
+ $pf->addExtensionDep($dep['name'], $dep['max'], 'le', 'yes');
+ }
+ }
+ }
+
+ $contents = $pf2->getContents();
+ $release = $pf2->getReleases();
+ if (isset($releases[0])) {
+ return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
+ . 'multiple extsrcrelease/zendextsrcrelease tags. Using a PEAR_PackageFileManager-based script ' .
+ 'or the convert command is an option');
+ }
+
+ if ($configoptions = $pf2->getConfigureOptions()) {
+ foreach ($configoptions as $option) {
+ $default = isset($option['default']) ? $option['default'] : false;
+ $pf->addConfigureOption($option['name'], $option['prompt'], $default);
+ }
+ }
+
+ if (isset($release['filelist']['ignore'])) {
+ return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
+ . 'ignore tags. Using a PEAR_PackageFileManager-based script or the convert' .
+ ' command is an option');
+ }
+
+ if (isset($release['filelist']['install']) &&
+ !isset($release['filelist']['install'][0])) {
+ $release['filelist']['install'] = array($release['filelist']['install']);
+ }
+
+ if (isset($contents['dir']['attribs']['baseinstalldir'])) {
+ $baseinstalldir = $contents['dir']['attribs']['baseinstalldir'];
+ } else {
+ $baseinstalldir = false;
+ }
+
+ if (!isset($contents['dir']['file'][0])) {
+ $contents['dir']['file'] = array($contents['dir']['file']);
+ }
+
+ foreach ($contents['dir']['file'] as $file) {
+ if ($baseinstalldir && !isset($file['attribs']['baseinstalldir'])) {
+ $file['attribs']['baseinstalldir'] = $baseinstalldir;
+ }
+
+ $processFile = $file;
+ unset($processFile['attribs']);
+ if (count($processFile)) {
+ foreach ($processFile as $name => $task) {
+ if ($name != $pf2->getTasksNs() . ':replace') {
+ return $this->raiseError('Cannot safely process "' . $packagexml .
+ '" contains tasks other than replace. Using a ' .
+ 'PEAR_PackageFileManager-based script is an option.');
+ }
+ $file['attribs']['replace'][] = $task;
+ }
+ }
+
+ if (!in_array($file['attribs']['role'], PEAR_Common::getFileRoles())) {
+ return $this->raiseError('Cannot safely convert "' . $packagexml .
+ '", contains custom roles. Using a PEAR_PackageFileManager-based script ' .
+ 'or the convert command is an option');
+ }
+
+ if (isset($release['filelist']['install'])) {
+ foreach ($release['filelist']['install'] as $installas) {
+ if ($installas['attribs']['name'] == $file['attribs']['name']) {
+ $file['attribs']['install-as'] = $installas['attribs']['as'];
+ }
+ }
+ }
+
+ $pf->addFile('/', $file['attribs']['name'], $file['attribs']);
+ }
+
+ if ($pf2->getChangeLog()) {
+ $this->ui->outputData('WARNING: changelog is not translated to package.xml ' .
+ '1.0, use PEAR_PackageFileManager-based script if you need changelog-' .
+ 'translation for package.xml 1.0');
+ }
+
+ $gen = &$pf->getDefaultGenerator();
+ $gen->toPackageFile('.');
+ }
+} \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Pickle.xml b/3rdparty/PEAR/Command/Pickle.xml
new file mode 100644
index 00000000000..721ecea995e
--- /dev/null
+++ b/3rdparty/PEAR/Command/Pickle.xml
@@ -0,0 +1,36 @@
+<commands version="1.0">
+ <pickle>
+ <summary>Build PECL Package</summary>
+ <function>doPackage</function>
+ <shortcut>pi</shortcut>
+ <options>
+ <nocompress>
+ <shortopt>Z</shortopt>
+ <doc>Do not gzip the package file</doc>
+ </nocompress>
+ <showname>
+ <shortopt>n</shortopt>
+ <doc>Print the name of the packaged file.</doc>
+ </showname>
+ </options>
+ <doc>[descfile]
+Creates a PECL package from its package2.xml file.
+
+An automatic conversion will be made to a package.xml 1.0 and written out to
+disk in the current directory as &quot;package.xml&quot;. Note that
+only simple package.xml 2.0 will be converted. package.xml 2.0 with:
+
+ - dependency types other than required/optional PECL package/ext/php/pearinstaller
+ - more than one extsrcrelease or zendextsrcrelease
+ - zendextbinrelease, extbinrelease, phprelease, or bundle release type
+ - dependency groups
+ - ignore tags in release filelist
+ - tasks other than replace
+ - custom roles
+
+will cause pickle to fail, and output an error message. If your package2.xml
+uses any of these features, you are best off using PEAR_PackageFileManager to
+generate both package.xml.
+</doc>
+ </pickle>
+</commands> \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Registry.php b/3rdparty/PEAR/Command/Registry.php
index 62cb4b00e28..4304db5ddf5 100644
--- a/3rdparty/PEAR/Command/Registry.php
+++ b/3rdparty/PEAR/Command/Registry.php
@@ -1,44 +1,75 @@
<?php
-// /* vim: set expandtab tabstop=4 shiftwidth=4: */
-// +----------------------------------------------------------------------+
-// | PHP Version 5 |
-// +----------------------------------------------------------------------+
-// | Copyright (c) 1997-2004 The PHP Group |
-// +----------------------------------------------------------------------+
-// | This source file is subject to version 3.0 of the PHP license, |
-// | that is bundled with this package in the file LICENSE, and is |
-// | available through the world-wide-web at the following url: |
-// | http://www.php.net/license/3_0.txt. |
-// | If you did not receive a copy of the PHP license and are unable to |
-// | obtain it through the world-wide-web, please send a note to |
-// | license@php.net so we can mail you a copy immediately. |
-// +----------------------------------------------------------------------+
-// | Author: Stig Bakken <ssb@php.net> |
-// | |
-// +----------------------------------------------------------------------+
-//
-// $Id: Registry.php,v 1.36 2004/01/08 17:33:13 sniper Exp $
+/**
+ * PEAR_Command_Registry (list, list-files, shell-test, info commands)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Registry.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ */
+/**
+ * base class
+ */
require_once 'PEAR/Command/Common.php';
-require_once 'PEAR/Registry.php';
-require_once 'PEAR/Config.php';
+/**
+ * PEAR commands for registry manipulation
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 0.1
+ */
class PEAR_Command_Registry extends PEAR_Command_Common
{
- // {{{ properties
-
var $commands = array(
'list' => array(
- 'summary' => 'List Installed Packages',
+ 'summary' => 'List Installed Packages In The Default Channel',
'function' => 'doList',
'shortcut' => 'l',
- 'options' => array(),
- 'doc' => '[package]
+ 'options' => array(
+ 'channel' => array(
+ 'shortopt' => 'c',
+ 'doc' => 'list installed packages from this channel',
+ 'arg' => 'CHAN',
+ ),
+ 'allchannels' => array(
+ 'shortopt' => 'a',
+ 'doc' => 'list installed packages from all channels',
+ ),
+ 'channelinfo' => array(
+ 'shortopt' => 'i',
+ 'doc' => 'output fully channel-aware data, even on failure',
+ ),
+ ),
+ 'doc' => '<package>
If invoked without parameters, this command lists the PEAR packages
-installed in your php_dir ({config php_dir)). With a parameter, it
-lists the files in that package.
+installed in your php_dir ({config php_dir}). With a parameter, it
+lists the files in a package.
',
),
+ 'list-files' => array(
+ 'summary' => 'List Files In Installed Package',
+ 'function' => 'doFileList',
+ 'shortcut' => 'fl',
+ 'options' => array(),
+ 'doc' => '<package>
+List the files in an installed package.
+'
+ ),
'shell-test' => array(
'summary' => 'Shell Script Test',
'function' => 'doShellTest',
@@ -62,9 +93,6 @@ installed package.'
)
);
- // }}}
- // {{{ constructor
-
/**
* PEAR_Command_Registry constructor.
*
@@ -75,64 +103,204 @@ installed package.'
parent::PEAR_Command_Common($ui, $config);
}
- // }}}
-
- // {{{ doList()
-
function _sortinfo($a, $b)
{
- return strcmp($a['package'], $b['package']);
+ $apackage = isset($a['package']) ? $a['package'] : $a['name'];
+ $bpackage = isset($b['package']) ? $b['package'] : $b['name'];
+ return strcmp($apackage, $bpackage);
}
function doList($command, $options, $params)
{
- $reg = new PEAR_Registry($this->config->get('php_dir'));
- if (sizeof($params) == 0) {
- $installed = $reg->packageInfo();
- usort($installed, array(&$this, '_sortinfo'));
- $i = $j = 0;
- $data = array(
- 'caption' => 'Installed packages:',
- 'border' => true,
- 'headline' => array('Package', 'Version', 'State')
- );
- foreach ($installed as $package) {
- $data['data'][] = array($package['package'],
- $package['version'],
- @$package['release_state']);
+ $reg = &$this->config->getRegistry();
+ $channelinfo = isset($options['channelinfo']);
+ if (isset($options['allchannels']) && !$channelinfo) {
+ return $this->doListAll($command, array(), $params);
+ }
+
+ if (isset($options['allchannels']) && $channelinfo) {
+ // allchannels with $channelinfo
+ unset($options['allchannels']);
+ $channels = $reg->getChannels();
+ $errors = array();
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ foreach ($channels as $channel) {
+ $options['channel'] = $channel->getName();
+ $ret = $this->doList($command, $options, $params);
+
+ if (PEAR::isError($ret)) {
+ $errors[] = $ret;
+ }
}
- if (count($installed)==0) {
- $data = '(no packages installed)';
+
+ PEAR::staticPopErrorHandling();
+ if (count($errors)) {
+ // for now, only give first error
+ return PEAR::raiseError($errors[0]);
}
- $this->ui->outputData($data, $command);
+
+ return true;
+ }
+
+ if (count($params) === 1) {
+ return $this->doFileList($command, $options, $params);
+ }
+
+ if (isset($options['channel'])) {
+ if (!$reg->channelExists($options['channel'])) {
+ return $this->raiseError('Channel "' . $options['channel'] .'" does not exist');
+ }
+
+ $channel = $reg->channelName($options['channel']);
} else {
- if (file_exists($params[0]) && !is_dir($params[0])) {
- include_once "PEAR/Common.php";
- $obj = &new PEAR_Common;
- $info = $obj->infoFromAny($params[0]);
- $headings = array('Package File', 'Install Path');
- $installed = false;
+ $channel = $this->config->get('default_channel');
+ }
+
+ $installed = $reg->packageInfo(null, null, $channel);
+ usort($installed, array(&$this, '_sortinfo'));
+
+ $data = array(
+ 'caption' => 'Installed packages, channel ' .
+ $channel . ':',
+ 'border' => true,
+ 'headline' => array('Package', 'Version', 'State'),
+ 'channel' => $channel,
+ );
+ if ($channelinfo) {
+ $data['headline'] = array('Channel', 'Package', 'Version', 'State');
+ }
+
+ if (count($installed) && !isset($data['data'])) {
+ $data['data'] = array();
+ }
+
+ foreach ($installed as $package) {
+ $pobj = $reg->getPackage(isset($package['package']) ?
+ $package['package'] : $package['name'], $channel);
+ if ($channelinfo) {
+ $packageinfo = array($pobj->getChannel(), $pobj->getPackage(), $pobj->getVersion(),
+ $pobj->getState() ? $pobj->getState() : null);
} else {
- $info = $reg->packageInfo($params[0]);
- $headings = array('Type', 'Install Path');
- $installed = true;
- }
- if (PEAR::isError($info)) {
- return $this->raiseError($info);
- }
- if ($info === null) {
- return $this->raiseError("`$params[0]' not installed");
+ $packageinfo = array($pobj->getPackage(), $pobj->getVersion(),
+ $pobj->getState() ? $pobj->getState() : null);
}
- $list = $info['filelist'];
- if ($installed) {
- $caption = 'Installed Files For ' . $params[0];
+ $data['data'][] = $packageinfo;
+ }
+
+ if (count($installed) === 0) {
+ if (!$channelinfo) {
+ $data = '(no packages installed from channel ' . $channel . ')';
} else {
- $caption = 'Contents of ' . basename($params[0]);
+ $data = array(
+ 'caption' => 'Installed packages, channel ' .
+ $channel . ':',
+ 'border' => true,
+ 'channel' => $channel,
+ 'data' => array(array('(no packages installed)')),
+ );
}
+ }
+
+ $this->ui->outputData($data, $command);
+ return true;
+ }
+
+ function doListAll($command, $options, $params)
+ {
+ // This duplicate code is deprecated over
+ // list --channelinfo, which gives identical
+ // output for list and list --allchannels.
+ $reg = &$this->config->getRegistry();
+ $installed = $reg->packageInfo(null, null, null);
+ foreach ($installed as $channel => $packages) {
+ usort($packages, array($this, '_sortinfo'));
$data = array(
- 'caption' => $caption,
- 'border' => true,
- 'headline' => $headings);
+ 'caption' => 'Installed packages, channel ' . $channel . ':',
+ 'border' => true,
+ 'headline' => array('Package', 'Version', 'State'),
+ 'channel' => $channel
+ );
+
+ foreach ($packages as $package) {
+ $p = isset($package['package']) ? $package['package'] : $package['name'];
+ $pobj = $reg->getPackage($p, $channel);
+ $data['data'][] = array($pobj->getPackage(), $pobj->getVersion(),
+ $pobj->getState() ? $pobj->getState() : null);
+ }
+
+ // Adds a blank line after each section
+ $data['data'][] = array();
+
+ if (count($packages) === 0) {
+ $data = array(
+ 'caption' => 'Installed packages, channel ' . $channel . ':',
+ 'border' => true,
+ 'data' => array(array('(no packages installed)'), array()),
+ 'channel' => $channel
+ );
+ }
+ $this->ui->outputData($data, $command);
+ }
+ return true;
+ }
+
+ function doFileList($command, $options, $params)
+ {
+ if (count($params) !== 1) {
+ return $this->raiseError('list-files expects 1 parameter');
+ }
+
+ $reg = &$this->config->getRegistry();
+ $fp = false;
+ if (!is_dir($params[0]) && (file_exists($params[0]) || $fp = @fopen($params[0], 'r'))) {
+ if ($fp) {
+ fclose($fp);
+ }
+
+ if (!class_exists('PEAR_PackageFile')) {
+ require_once 'PEAR/PackageFile.php';
+ }
+
+ $pkg = &new PEAR_PackageFile($this->config, $this->_debug);
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $info = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
+ PEAR::staticPopErrorHandling();
+ $headings = array('Package File', 'Install Path');
+ $installed = false;
+ } else {
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($parsed)) {
+ return $this->raiseError($parsed);
+ }
+
+ $info = &$reg->getPackage($parsed['package'], $parsed['channel']);
+ $headings = array('Type', 'Install Path');
+ $installed = true;
+ }
+
+ if (PEAR::isError($info)) {
+ return $this->raiseError($info);
+ }
+
+ if ($info === null) {
+ return $this->raiseError("`$params[0]' not installed");
+ }
+
+ $list = ($info->getPackagexmlVersion() == '1.0' || $installed) ?
+ $info->getFilelist() : $info->getContents();
+ if ($installed) {
+ $caption = 'Installed Files For ' . $params[0];
+ } else {
+ $caption = 'Contents of ' . basename($params[0]);
+ }
+
+ $data = array(
+ 'caption' => $caption,
+ 'border' => true,
+ 'headline' => $headings);
+ if ($info->getPackagexmlVersion() == '1.0' || $installed) {
foreach ($list as $file => $att) {
if ($installed) {
if (empty($att['installed_as'])) {
@@ -140,7 +308,8 @@ installed package.'
}
$data['data'][] = array($att['role'], $att['installed_as']);
} else {
- if (isset($att['baseinstalldir'])) {
+ if (isset($att['baseinstalldir']) && !in_array($att['role'],
+ array('test', 'data', 'doc'))) {
$dest = $att['baseinstalldir'] . DIRECTORY_SEPARATOR .
$file;
} else {
@@ -149,89 +318,183 @@ installed package.'
switch ($att['role']) {
case 'test':
case 'data':
- if ($installed) {
- break 2;
- }
- $dest = '-- will not be installed --';
- break;
case 'doc':
- $dest = $this->config->get('doc_dir') . DIRECTORY_SEPARATOR .
- $dest;
+ $role = $att['role'];
+ if ($role == 'test') {
+ $role .= 's';
+ }
+ $dest = $this->config->get($role . '_dir') . DIRECTORY_SEPARATOR .
+ $info->getPackage() . DIRECTORY_SEPARATOR . $dest;
break;
case 'php':
default:
$dest = $this->config->get('php_dir') . DIRECTORY_SEPARATOR .
$dest;
}
- $dest = preg_replace('!/+!', '/', $dest);
+ $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
+ $dest = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
+ array(DIRECTORY_SEPARATOR,
+ DIRECTORY_SEPARATOR,
+ DIRECTORY_SEPARATOR),
+ $dest);
$file = preg_replace('!/+!', '/', $file);
$data['data'][] = array($file, $dest);
}
}
- $this->ui->outputData($data, $command);
-
+ } else { // package.xml 2.0, not installed
+ if (!isset($list['dir']['file'][0])) {
+ $list['dir']['file'] = array($list['dir']['file']);
+ }
+ foreach ($list['dir']['file'] as $att) {
+ $att = $att['attribs'];
+ $file = $att['name'];
+ $role = &PEAR_Installer_Role::factory($info, $att['role'], $this->config);
+ $role->setup($this, $info, $att, $file);
+ if (!$role->isInstallable()) {
+ $dest = '(not installable)';
+ } else {
+ $dest = $role->processInstallation($info, $att, $file, '');
+ if (PEAR::isError($dest)) {
+ $dest = '(Unknown role "' . $att['role'] . ')';
+ } else {
+ list(,, $dest) = $dest;
+ }
+ }
+ $data['data'][] = array($file, $dest);
+ }
}
+
+ $this->ui->outputData($data, $command);
return true;
}
- // }}}
- // {{{ doShellTest()
-
function doShellTest($command, $options, $params)
{
- $this->pushErrorHandling(PEAR_ERROR_RETURN);
- $reg = &new PEAR_Registry($this->config->get('php_dir'));
+ if (count($params) < 1) {
+ return PEAR::raiseError('ERROR, usage: pear shell-test packagename [[relation] version]');
+ }
+
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $reg = &$this->config->getRegistry();
+ $info = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
+ if (PEAR::isError($info)) {
+ exit(1); // invalid package name
+ }
+
+ $package = $info['package'];
+ $channel = $info['channel'];
// "pear shell-test Foo"
- if (sizeof($params) == 1) {
- if (!$reg->packageExists($params[0])) {
+ if (!$reg->packageExists($package, $channel)) {
+ if ($channel == 'pecl.php.net') {
+ if ($reg->packageExists($package, 'pear.php.net')) {
+ $channel = 'pear.php.net'; // magically change channels for extensions
+ }
+ }
+ }
+
+ if (count($params) === 1) {
+ if (!$reg->packageExists($package, $channel)) {
exit(1);
}
// "pear shell-test Foo 1.0"
- } elseif (sizeof($params) == 2) {
- $v = $reg->packageInfo($params[0], 'version');
+ } elseif (count($params) === 2) {
+ $v = $reg->packageInfo($package, 'version', $channel);
if (!$v || !version_compare("$v", "{$params[1]}", "ge")) {
exit(1);
}
// "pear shell-test Foo ge 1.0"
- } elseif (sizeof($params) == 3) {
- $v = $reg->packageInfo($params[0], 'version');
+ } elseif (count($params) === 3) {
+ $v = $reg->packageInfo($package, 'version', $channel);
if (!$v || !version_compare("$v", "{$params[2]}", $params[1])) {
exit(1);
}
} else {
- $this->popErrorHandling();
+ PEAR::staticPopErrorHandling();
$this->raiseError("$command: expects 1 to 3 parameters");
exit(1);
}
}
- // }}}
- // {{{ doInfo
-
function doInfo($command, $options, $params)
{
- // $params[0] The package for showing info
- if (sizeof($params) != 1) {
- return $this->raiseError("This command only accepts one param: ".
- "the package you want information");
- }
- if (@is_file($params[0])) {
- $obj = &new PEAR_Common();
- $info = $obj->infoFromAny($params[0]);
+ if (count($params) !== 1) {
+ return $this->raiseError('pear info expects 1 parameter');
+ }
+
+ $info = $fp = false;
+ $reg = &$this->config->getRegistry();
+ if (is_file($params[0]) && !is_dir($params[0]) &&
+ (file_exists($params[0]) || $fp = @fopen($params[0], 'r'))
+ ) {
+ if ($fp) {
+ fclose($fp);
+ }
+
+ if (!class_exists('PEAR_PackageFile')) {
+ require_once 'PEAR/PackageFile.php';
+ }
+
+ $pkg = &new PEAR_PackageFile($this->config, $this->_debug);
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $obj = &$pkg->fromAnyFile($params[0], PEAR_VALIDATE_NORMAL);
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($obj)) {
+ $uinfo = $obj->getUserInfo();
+ if (is_array($uinfo)) {
+ foreach ($uinfo as $message) {
+ if (is_array($message)) {
+ $message = $message['message'];
+ }
+ $this->ui->outputData($message);
+ }
+ }
+
+ return $this->raiseError($obj);
+ }
+
+ if ($obj->getPackagexmlVersion() != '1.0') {
+ return $this->_doInfo2($command, $options, $params, $obj, false);
+ }
+
+ $info = $obj->toArray();
} else {
- $reg = &new PEAR_Registry($this->config->get('php_dir'));
- $info = $reg->packageInfo($params[0]);
+ $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
+ if (PEAR::isError($parsed)) {
+ return $this->raiseError($parsed);
+ }
+
+ $package = $parsed['package'];
+ $channel = $parsed['channel'];
+ $info = $reg->packageInfo($package, null, $channel);
+ if (isset($info['old'])) {
+ $obj = $reg->getPackage($package, $channel);
+ return $this->_doInfo2($command, $options, $params, $obj, true);
+ }
}
+
if (PEAR::isError($info)) {
return $info;
}
+
if (empty($info)) {
- $this->raiseError("Nothing found for `$params[0]'");
+ $this->raiseError("No information found for `$params[0]'");
return;
}
+
unset($info['filelist']);
+ unset($info['dirtree']);
unset($info['changelog']);
+ if (isset($info['xsdversion'])) {
+ $info['package.xml version'] = $info['xsdversion'];
+ unset($info['xsdversion']);
+ }
+
+ if (isset($info['packagerversion'])) {
+ $info['packaged with PEAR version'] = $info['packagerversion'];
+ unset($info['packagerversion']);
+ }
+
$keys = array_keys($info);
$longtext = array('description', 'summary');
foreach ($keys as $key) {
@@ -279,7 +542,12 @@ installed package.'
} else {
$version = '';
}
- $dstr .= "$type $name$rel $version\n";
+ if (isset($d['optional']) && $d['optional'] == 'yes') {
+ $optional = ' (optional)';
+ } else {
+ $optional = '';
+ }
+ $dstr .= "$type $name$rel $version$optional\n";
}
$info[$key] = $dstr;
break;
@@ -315,16 +583,30 @@ installed package.'
$info[$key] = $pstr;
break;
}
+ case 'configure_options' : {
+ foreach ($info[$key] as $i => $p) {
+ $info[$key][$i] = array_map(null, array_keys($p), array_values($p));
+ $info[$key][$i] = array_map(create_function('$a',
+ 'return join(" = ",$a);'), $info[$key][$i]);
+ $info[$key][$i] = implode(', ', $info[$key][$i]);
+ }
+ $info[$key] = implode("\n", $info[$key]);
+ break;
+ }
default: {
$info[$key] = implode(", ", $info[$key]);
break;
}
}
}
+
if ($key == '_lastmodified') {
$hdate = date('Y-m-d', $info[$key]);
unset($info[$key]);
$info['Last Modified'] = $hdate;
+ } elseif ($key == '_lastversion') {
+ $info['Previous Installed Version'] = $info[$key] ? $info[$key] : '- None -';
+ unset($info[$key]);
} else {
$info[$key] = trim($info[$key]);
if (in_array($key, $longtext)) {
@@ -332,6 +614,7 @@ installed package.'
}
}
}
+
$caption = 'About ' . $info['package'] . '-' . $info['version'];
$data = array(
'caption' => $caption,
@@ -345,7 +628,518 @@ installed package.'
$this->ui->outputData($data, 'package-info');
}
- // }}}
-}
+ /**
+ * @access private
+ */
+ function _doInfo2($command, $options, $params, &$obj, $installed)
+ {
+ $reg = &$this->config->getRegistry();
+ $caption = 'About ' . $obj->getChannel() . '/' .$obj->getPackage() . '-' .
+ $obj->getVersion();
+ $data = array(
+ 'caption' => $caption,
+ 'border' => true);
+ switch ($obj->getPackageType()) {
+ case 'php' :
+ $release = 'PEAR-style PHP-based Package';
+ break;
+ case 'extsrc' :
+ $release = 'PECL-style PHP extension (source code)';
+ break;
+ case 'zendextsrc' :
+ $release = 'PECL-style Zend extension (source code)';
+ break;
+ case 'extbin' :
+ $release = 'PECL-style PHP extension (binary)';
+ break;
+ case 'zendextbin' :
+ $release = 'PECL-style Zend extension (binary)';
+ break;
+ case 'bundle' :
+ $release = 'Package bundle (collection of packages)';
+ break;
+ }
+ $extends = $obj->getExtends();
+ $extends = $extends ?
+ $obj->getPackage() . ' (extends ' . $extends . ')' : $obj->getPackage();
+ if ($src = $obj->getSourcePackage()) {
+ $extends .= ' (source package ' . $src['channel'] . '/' . $src['package'] . ')';
+ }
+
+ $info = array(
+ 'Release Type' => $release,
+ 'Name' => $extends,
+ 'Channel' => $obj->getChannel(),
+ 'Summary' => preg_replace('/ +/', ' ', $obj->getSummary()),
+ 'Description' => preg_replace('/ +/', ' ', $obj->getDescription()),
+ );
+ $info['Maintainers'] = '';
+ foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
+ $leads = $obj->{"get{$role}s"}();
+ if (!$leads) {
+ continue;
+ }
+
+ if (isset($leads['active'])) {
+ $leads = array($leads);
+ }
+
+ foreach ($leads as $lead) {
+ if (!empty($info['Maintainers'])) {
+ $info['Maintainers'] .= "\n";
+ }
+
+ $active = $lead['active'] == 'no' ? ', inactive' : '';
+ $info['Maintainers'] .= $lead['name'] . ' <';
+ $info['Maintainers'] .= $lead['email'] . "> ($role$active)";
+ }
+ }
-?>
+ $info['Release Date'] = $obj->getDate();
+ if ($time = $obj->getTime()) {
+ $info['Release Date'] .= ' ' . $time;
+ }
+
+ $info['Release Version'] = $obj->getVersion() . ' (' . $obj->getState() . ')';
+ $info['API Version'] = $obj->getVersion('api') . ' (' . $obj->getState('api') . ')';
+ $info['License'] = $obj->getLicense();
+ $uri = $obj->getLicenseLocation();
+ if ($uri) {
+ if (isset($uri['uri'])) {
+ $info['License'] .= ' (' . $uri['uri'] . ')';
+ } else {
+ $extra = $obj->getInstalledLocation($info['filesource']);
+ if ($extra) {
+ $info['License'] .= ' (' . $uri['filesource'] . ')';
+ }
+ }
+ }
+
+ $info['Release Notes'] = $obj->getNotes();
+ if ($compat = $obj->getCompatible()) {
+ if (!isset($compat[0])) {
+ $compat = array($compat);
+ }
+
+ $info['Compatible with'] = '';
+ foreach ($compat as $package) {
+ $info['Compatible with'] .= $package['channel'] . '/' . $package['name'] .
+ "\nVersions >= " . $package['min'] . ', <= ' . $package['max'];
+ if (isset($package['exclude'])) {
+ if (is_array($package['exclude'])) {
+ $package['exclude'] = implode(', ', $package['exclude']);
+ }
+
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+ $info['Not Compatible with'] .= $package['channel'] . '/' .
+ $package['name'] . "\nVersions " . $package['exclude'];
+ }
+ }
+ }
+
+ $usesrole = $obj->getUsesrole();
+ if ($usesrole) {
+ if (!isset($usesrole[0])) {
+ $usesrole = array($usesrole);
+ }
+
+ foreach ($usesrole as $roledata) {
+ if (isset($info['Uses Custom Roles'])) {
+ $info['Uses Custom Roles'] .= "\n";
+ } else {
+ $info['Uses Custom Roles'] = '';
+ }
+
+ if (isset($roledata['package'])) {
+ $rolepackage = $reg->parsedPackageNameToString($roledata, true);
+ } else {
+ $rolepackage = $roledata['uri'];
+ }
+ $info['Uses Custom Roles'] .= $roledata['role'] . ' (' . $rolepackage . ')';
+ }
+ }
+
+ $usestask = $obj->getUsestask();
+ if ($usestask) {
+ if (!isset($usestask[0])) {
+ $usestask = array($usestask);
+ }
+
+ foreach ($usestask as $taskdata) {
+ if (isset($info['Uses Custom Tasks'])) {
+ $info['Uses Custom Tasks'] .= "\n";
+ } else {
+ $info['Uses Custom Tasks'] = '';
+ }
+
+ if (isset($taskdata['package'])) {
+ $taskpackage = $reg->parsedPackageNameToString($taskdata, true);
+ } else {
+ $taskpackage = $taskdata['uri'];
+ }
+ $info['Uses Custom Tasks'] .= $taskdata['task'] . ' (' . $taskpackage . ')';
+ }
+ }
+
+ $deps = $obj->getDependencies();
+ $info['Required Dependencies'] = 'PHP version ' . $deps['required']['php']['min'];
+ if (isset($deps['required']['php']['max'])) {
+ $info['Required Dependencies'] .= '-' . $deps['required']['php']['max'] . "\n";
+ } else {
+ $info['Required Dependencies'] .= "\n";
+ }
+
+ if (isset($deps['required']['php']['exclude'])) {
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+
+ if (is_array($deps['required']['php']['exclude'])) {
+ $deps['required']['php']['exclude'] =
+ implode(', ', $deps['required']['php']['exclude']);
+ }
+ $info['Not Compatible with'] .= "PHP versions\n " .
+ $deps['required']['php']['exclude'];
+ }
+
+ $info['Required Dependencies'] .= 'PEAR installer version';
+ if (isset($deps['required']['pearinstaller']['max'])) {
+ $info['Required Dependencies'] .= 's ' .
+ $deps['required']['pearinstaller']['min'] . '-' .
+ $deps['required']['pearinstaller']['max'];
+ } else {
+ $info['Required Dependencies'] .= ' ' .
+ $deps['required']['pearinstaller']['min'] . ' or newer';
+ }
+
+ if (isset($deps['required']['pearinstaller']['exclude'])) {
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+
+ if (is_array($deps['required']['pearinstaller']['exclude'])) {
+ $deps['required']['pearinstaller']['exclude'] =
+ implode(', ', $deps['required']['pearinstaller']['exclude']);
+ }
+ $info['Not Compatible with'] .= "PEAR installer\n Versions " .
+ $deps['required']['pearinstaller']['exclude'];
+ }
+
+ foreach (array('Package', 'Extension') as $type) {
+ $index = strtolower($type);
+ if (isset($deps['required'][$index])) {
+ if (isset($deps['required'][$index]['name'])) {
+ $deps['required'][$index] = array($deps['required'][$index]);
+ }
+
+ foreach ($deps['required'][$index] as $package) {
+ if (isset($package['conflicts'])) {
+ $infoindex = 'Not Compatible with';
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+ } else {
+ $infoindex = 'Required Dependencies';
+ $info[$infoindex] .= "\n";
+ }
+
+ if ($index == 'extension') {
+ $name = $package['name'];
+ } else {
+ if (isset($package['channel'])) {
+ $name = $package['channel'] . '/' . $package['name'];
+ } else {
+ $name = '__uri/' . $package['name'] . ' (static URI)';
+ }
+ }
+
+ $info[$infoindex] .= "$type $name";
+ if (isset($package['uri'])) {
+ $info[$infoindex] .= "\n Download URI: $package[uri]";
+ continue;
+ }
+
+ if (isset($package['max']) && isset($package['min'])) {
+ $info[$infoindex] .= " \n Versions " .
+ $package['min'] . '-' . $package['max'];
+ } elseif (isset($package['min'])) {
+ $info[$infoindex] .= " \n Version " .
+ $package['min'] . ' or newer';
+ } elseif (isset($package['max'])) {
+ $info[$infoindex] .= " \n Version " .
+ $package['max'] . ' or older';
+ }
+
+ if (isset($package['recommended'])) {
+ $info[$infoindex] .= "\n Recommended version: $package[recommended]";
+ }
+
+ if (isset($package['exclude'])) {
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+
+ if (is_array($package['exclude'])) {
+ $package['exclude'] = implode(', ', $package['exclude']);
+ }
+
+ $package['package'] = $package['name']; // for parsedPackageNameToString
+ if (isset($package['conflicts'])) {
+ $info['Not Compatible with'] .= '=> except ';
+ }
+ $info['Not Compatible with'] .= 'Package ' .
+ $reg->parsedPackageNameToString($package, true);
+ $info['Not Compatible with'] .= "\n Versions " . $package['exclude'];
+ }
+ }
+ }
+ }
+
+ if (isset($deps['required']['os'])) {
+ if (isset($deps['required']['os']['name'])) {
+ $dep['required']['os']['name'] = array($dep['required']['os']['name']);
+ }
+
+ foreach ($dep['required']['os'] as $os) {
+ if (isset($os['conflicts']) && $os['conflicts'] == 'yes') {
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+ $info['Not Compatible with'] .= "$os[name] Operating System";
+ } else {
+ $info['Required Dependencies'] .= "\n";
+ $info['Required Dependencies'] .= "$os[name] Operating System";
+ }
+ }
+ }
+
+ if (isset($deps['required']['arch'])) {
+ if (isset($deps['required']['arch']['pattern'])) {
+ $dep['required']['arch']['pattern'] = array($dep['required']['os']['pattern']);
+ }
+
+ foreach ($dep['required']['arch'] as $os) {
+ if (isset($os['conflicts']) && $os['conflicts'] == 'yes') {
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+ $info['Not Compatible with'] .= "OS/Arch matching pattern '/$os[pattern]/'";
+ } else {
+ $info['Required Dependencies'] .= "\n";
+ $info['Required Dependencies'] .= "OS/Arch matching pattern '/$os[pattern]/'";
+ }
+ }
+ }
+
+ if (isset($deps['optional'])) {
+ foreach (array('Package', 'Extension') as $type) {
+ $index = strtolower($type);
+ if (isset($deps['optional'][$index])) {
+ if (isset($deps['optional'][$index]['name'])) {
+ $deps['optional'][$index] = array($deps['optional'][$index]);
+ }
+
+ foreach ($deps['optional'][$index] as $package) {
+ if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
+ $infoindex = 'Not Compatible with';
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+ } else {
+ $infoindex = 'Optional Dependencies';
+ if (!isset($info['Optional Dependencies'])) {
+ $info['Optional Dependencies'] = '';
+ } else {
+ $info['Optional Dependencies'] .= "\n";
+ }
+ }
+
+ if ($index == 'extension') {
+ $name = $package['name'];
+ } else {
+ if (isset($package['channel'])) {
+ $name = $package['channel'] . '/' . $package['name'];
+ } else {
+ $name = '__uri/' . $package['name'] . ' (static URI)';
+ }
+ }
+
+ $info[$infoindex] .= "$type $name";
+ if (isset($package['uri'])) {
+ $info[$infoindex] .= "\n Download URI: $package[uri]";
+ continue;
+ }
+
+ if ($infoindex == 'Not Compatible with') {
+ // conflicts is only used to say that all versions conflict
+ continue;
+ }
+
+ if (isset($package['max']) && isset($package['min'])) {
+ $info[$infoindex] .= " \n Versions " .
+ $package['min'] . '-' . $package['max'];
+ } elseif (isset($package['min'])) {
+ $info[$infoindex] .= " \n Version " .
+ $package['min'] . ' or newer';
+ } elseif (isset($package['max'])) {
+ $info[$infoindex] .= " \n Version " .
+ $package['min'] . ' or older';
+ }
+
+ if (isset($package['recommended'])) {
+ $info[$infoindex] .= "\n Recommended version: $package[recommended]";
+ }
+
+ if (isset($package['exclude'])) {
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info['Not Compatible with'] .= "\n";
+ }
+
+ if (is_array($package['exclude'])) {
+ $package['exclude'] = implode(', ', $package['exclude']);
+ }
+
+ $info['Not Compatible with'] .= "Package $package\n Versions " .
+ $package['exclude'];
+ }
+ }
+ }
+ }
+ }
+
+ if (isset($deps['group'])) {
+ if (!isset($deps['group'][0])) {
+ $deps['group'] = array($deps['group']);
+ }
+
+ foreach ($deps['group'] as $group) {
+ $info['Dependency Group ' . $group['attribs']['name']] = $group['attribs']['hint'];
+ $groupindex = $group['attribs']['name'] . ' Contents';
+ $info[$groupindex] = '';
+ foreach (array('Package', 'Extension') as $type) {
+ $index = strtolower($type);
+ if (isset($group[$index])) {
+ if (isset($group[$index]['name'])) {
+ $group[$index] = array($group[$index]);
+ }
+
+ foreach ($group[$index] as $package) {
+ if (!empty($info[$groupindex])) {
+ $info[$groupindex] .= "\n";
+ }
+
+ if ($index == 'extension') {
+ $name = $package['name'];
+ } else {
+ if (isset($package['channel'])) {
+ $name = $package['channel'] . '/' . $package['name'];
+ } else {
+ $name = '__uri/' . $package['name'] . ' (static URI)';
+ }
+ }
+
+ if (isset($package['uri'])) {
+ if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
+ $info[$groupindex] .= "Not Compatible with $type $name";
+ } else {
+ $info[$groupindex] .= "$type $name";
+ }
+
+ $info[$groupindex] .= "\n Download URI: $package[uri]";
+ continue;
+ }
+
+ if (isset($package['conflicts']) && $package['conflicts'] == 'yes') {
+ $info[$groupindex] .= "Not Compatible with $type $name";
+ continue;
+ }
+
+ $info[$groupindex] .= "$type $name";
+ if (isset($package['max']) && isset($package['min'])) {
+ $info[$groupindex] .= " \n Versions " .
+ $package['min'] . '-' . $package['max'];
+ } elseif (isset($package['min'])) {
+ $info[$groupindex] .= " \n Version " .
+ $package['min'] . ' or newer';
+ } elseif (isset($package['max'])) {
+ $info[$groupindex] .= " \n Version " .
+ $package['min'] . ' or older';
+ }
+
+ if (isset($package['recommended'])) {
+ $info[$groupindex] .= "\n Recommended version: $package[recommended]";
+ }
+
+ if (isset($package['exclude'])) {
+ if (!isset($info['Not Compatible with'])) {
+ $info['Not Compatible with'] = '';
+ } else {
+ $info[$groupindex] .= "Not Compatible with\n";
+ }
+
+ if (is_array($package['exclude'])) {
+ $package['exclude'] = implode(', ', $package['exclude']);
+ }
+ $info[$groupindex] .= " Package $package\n Versions " .
+ $package['exclude'];
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ($obj->getPackageType() == 'bundle') {
+ $info['Bundled Packages'] = '';
+ foreach ($obj->getBundledPackages() as $package) {
+ if (!empty($info['Bundled Packages'])) {
+ $info['Bundled Packages'] .= "\n";
+ }
+
+ if (isset($package['uri'])) {
+ $info['Bundled Packages'] .= '__uri/' . $package['name'];
+ $info['Bundled Packages'] .= "\n (URI: $package[uri]";
+ } else {
+ $info['Bundled Packages'] .= $package['channel'] . '/' . $package['name'];
+ }
+ }
+ }
+
+ $info['package.xml version'] = '2.0';
+ if ($installed) {
+ if ($obj->getLastModified()) {
+ $info['Last Modified'] = date('Y-m-d H:i', $obj->getLastModified());
+ }
+
+ $v = $obj->getLastInstalledVersion();
+ $info['Previous Installed Version'] = $v ? $v : '- None -';
+ }
+
+ foreach ($info as $key => $value) {
+ $data['data'][] = array($key, $value);
+ }
+
+ $data['raw'] = $obj->getArray(); // no validation needed
+ $this->ui->outputData($data, 'package-info');
+ }
+} \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Registry.xml b/3rdparty/PEAR/Command/Registry.xml
new file mode 100644
index 00000000000..9f4e2149672
--- /dev/null
+++ b/3rdparty/PEAR/Command/Registry.xml
@@ -0,0 +1,58 @@
+<commands version="1.0">
+ <list>
+ <summary>List Installed Packages In The Default Channel</summary>
+ <function>doList</function>
+ <shortcut>l</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>list installed packages from this channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ <allchannels>
+ <shortopt>a</shortopt>
+ <doc>list installed packages from all channels</doc>
+ </allchannels>
+ <channelinfo>
+ <shortopt>i</shortopt>
+ <doc>output fully channel-aware data, even on failure</doc>
+ </channelinfo>
+ </options>
+ <doc>&lt;package&gt;
+If invoked without parameters, this command lists the PEAR packages
+installed in your php_dir ({config php_dir}). With a parameter, it
+lists the files in a package.
+</doc>
+ </list>
+ <list-files>
+ <summary>List Files In Installed Package</summary>
+ <function>doFileList</function>
+ <shortcut>fl</shortcut>
+ <options />
+ <doc>&lt;package&gt;
+List the files in an installed package.
+</doc>
+ </list-files>
+ <shell-test>
+ <summary>Shell Script Test</summary>
+ <function>doShellTest</function>
+ <shortcut>st</shortcut>
+ <options />
+ <doc>&lt;package&gt; [[relation] version]
+Tests if a package is installed in the system. Will exit(1) if it is not.
+ &lt;relation&gt; The version comparison operator. One of:
+ &lt;, lt, &lt;=, le, &gt;, gt, &gt;=, ge, ==, =, eq, !=, &lt;&gt;, ne
+ &lt;version&gt; The version to compare with
+</doc>
+ </shell-test>
+ <info>
+ <summary>Display information about a package</summary>
+ <function>doInfo</function>
+ <shortcut>in</shortcut>
+ <options />
+ <doc>&lt;package&gt;
+Displays information about a package. The package argument may be a
+local package file, an URL to a package file, or the name of an
+installed package.</doc>
+ </info>
+</commands> \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Remote.php b/3rdparty/PEAR/Command/Remote.php
index bbd16093f5d..74478d83c7a 100644
--- a/3rdparty/PEAR/Command/Remote.php
+++ b/3rdparty/PEAR/Command/Remote.php
@@ -1,33 +1,42 @@
<?php
-// /* vim: set expandtab tabstop=4 shiftwidth=4: */
-// +----------------------------------------------------------------------+
-// | PHP Version 5 |
-// +----------------------------------------------------------------------+
-// | Copyright (c) 1997-2004 The PHP Group |
-// +----------------------------------------------------------------------+
-// | This source file is subject to version 3.0 of the PHP license, |
-// | that is bundled with this package in the file LICENSE, and is |
-// | available through the world-wide-web at the following url: |
-// | http://www.php.net/license/3_0.txt. |
-// | If you did not receive a copy of the PHP license and are unable to |
-// | obtain it through the world-wide-web, please send a note to |
-// | license@php.net so we can mail you a copy immediately. |
-// +----------------------------------------------------------------------+
-// | Author: Stig Bakken <ssb@php.net> |
-// | |
-// +----------------------------------------------------------------------+
-//
-// $Id: Remote.php,v 1.39 2004/04/03 15:56:00 cellog Exp $
-
+/**
+ * PEAR_Command_Remote (remote-info, list-upgrades, remote-list, search, list-all, download,
+ * clear-cache commands)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Remote.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ */
+
+/**
+ * base class
+ */
require_once 'PEAR/Command/Common.php';
-require_once 'PEAR/Common.php';
-require_once 'PEAR/Remote.php';
-require_once 'PEAR/Registry.php';
-
+require_once 'PEAR/REST.php';
+
+/**
+ * PEAR commands for remote server querying
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 0.1
+ */
class PEAR_Command_Remote extends PEAR_Command_Common
{
- // {{{ command definitions
-
var $commands = array(
'remote-info' => array(
'summary' => 'Information About Remote Packages',
@@ -41,16 +50,29 @@ Get details on a package from the server.',
'summary' => 'List Available Upgrades',
'function' => 'doListUpgrades',
'shortcut' => 'lu',
- 'options' => array(),
- 'doc' => '
+ 'options' => array(
+ 'channelinfo' => array(
+ 'shortopt' => 'i',
+ 'doc' => 'output fully channel-aware data, even on failure',
+ ),
+ ),
+ 'doc' => '[preferred_state]
List releases on the server of packages you have installed where
-a newer version is available with the same release state (stable etc.).'
+a newer version is available with the same release state (stable etc.)
+or the state passed as the second parameter.'
),
'remote-list' => array(
'summary' => 'List Remote Packages',
'function' => 'doRemoteList',
'shortcut' => 'rl',
- 'options' => array(),
+ 'options' => array(
+ 'channel' =>
+ array(
+ 'shortopt' => 'c',
+ 'doc' => 'specify a channel other than the default channel',
+ 'arg' => 'CHAN',
+ )
+ ),
'doc' => '
Lists the packages available on the configured server along with the
latest stable release of each package.',
@@ -59,16 +81,44 @@ latest stable release of each package.',
'summary' => 'Search remote package database',
'function' => 'doSearch',
'shortcut' => 'sp',
- 'options' => array(),
- 'doc' => '
-Lists all packages which match the search parameters (first param
-is package name, second package info)',
+ 'options' => array(
+ 'channel' =>
+ array(
+ 'shortopt' => 'c',
+ 'doc' => 'specify a channel other than the default channel',
+ 'arg' => 'CHAN',
+ ),
+ 'allchannels' => array(
+ 'shortopt' => 'a',
+ 'doc' => 'search packages from all known channels',
+ ),
+ 'channelinfo' => array(
+ 'shortopt' => 'i',
+ 'doc' => 'output fully channel-aware data, even on failure',
+ ),
+ ),
+ 'doc' => '[packagename] [packageinfo]
+Lists all packages which match the search parameters. The first
+parameter is a fragment of a packagename. The default channel
+will be used unless explicitly overridden. The second parameter
+will be used to match any portion of the summary/description',
),
'list-all' => array(
'summary' => 'List All Packages',
'function' => 'doListAll',
'shortcut' => 'la',
- 'options' => array(),
+ 'options' => array(
+ 'channel' =>
+ array(
+ 'shortopt' => 'c',
+ 'doc' => 'specify a channel other than the default channel',
+ 'arg' => 'CHAN',
+ ),
+ 'channelinfo' => array(
+ 'shortopt' => 'i',
+ 'doc' => 'output fully channel-aware data, even on failure',
+ ),
+ ),
'doc' => '
Lists the packages available on the configured server along with the
latest stable release of each package.',
@@ -83,26 +133,23 @@ latest stable release of each package.',
'doc' => 'download an uncompressed (.tar) file',
),
),
- 'doc' => '{package|package-version}
-Download a package tarball. The file will be named as suggested by the
+ 'doc' => '<package>...
+Download package tarballs. The files will be named as suggested by the
server, for example if you download the DB package and the latest stable
-version of DB is 1.2, the downloaded file will be DB-1.2.tgz.',
+version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.',
),
'clear-cache' => array(
- 'summary' => 'Clear XML-RPC Cache',
+ 'summary' => 'Clear Web Services Cache',
'function' => 'doClearCache',
'shortcut' => 'cc',
'options' => array(),
'doc' => '
-Clear the XML-RPC cache. See also the cache_ttl configuration
+Clear the REST cache. See also the cache_ttl configuration
parameter.
',
),
);
- // }}}
- // {{{ constructor
-
/**
* PEAR_Command_Remote constructor.
*
@@ -113,98 +160,216 @@ parameter.
parent::PEAR_Command_Common($ui, $config);
}
- // }}}
-
- // {{{ doRemoteInfo()
+ function _checkChannelForStatus($channel, $chan)
+ {
+ if (PEAR::isError($chan)) {
+ $this->raiseError($chan);
+ }
+ if (!is_a($chan, 'PEAR_ChannelFile')) {
+ return $this->raiseError('Internal corruption error: invalid channel "' .
+ $channel . '"');
+ }
+ $rest = new PEAR_REST($this->config);
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $mirror = $this->config->get('preferred_mirror', null,
+ $channel);
+ $a = $rest->downloadHttp('http://' . $channel .
+ '/channel.xml', $chan->lastModified());
+ PEAR::staticPopErrorHandling();
+ if (!PEAR::isError($a) && $a) {
+ $this->ui->outputData('WARNING: channel "' . $channel . '" has ' .
+ 'updated its protocols, use "' . PEAR_RUNTYPE . ' channel-update ' . $channel .
+ '" to update');
+ }
+ }
function doRemoteInfo($command, $options, $params)
{
if (sizeof($params) != 1) {
return $this->raiseError("$command expects one param: the remote package name");
}
- $r = new PEAR_Remote($this->config);
- $info = $r->call('package.info', $params[0]);
+ $savechannel = $channel = $this->config->get('default_channel');
+ $reg = &$this->config->getRegistry();
+ $package = $params[0];
+ $parsed = $reg->parsePackageName($package, $channel);
+ if (PEAR::isError($parsed)) {
+ return $this->raiseError('Invalid package name "' . $package . '"');
+ }
+
+ $channel = $parsed['channel'];
+ $this->config->set('default_channel', $channel);
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
+ return $e;
+ }
+
+ $mirror = $this->config->get('preferred_mirror');
+ if ($chan->supportsREST($mirror) && $base = $chan->getBaseURL('REST1.0', $mirror)) {
+ $rest = &$this->config->getREST('1.0', array());
+ $info = $rest->packageInfo($base, $parsed['package'], $channel);
+ }
+
+ if (!isset($info)) {
+ return $this->raiseError('No supported protocol was found');
+ }
+
if (PEAR::isError($info)) {
+ $this->config->set('default_channel', $savechannel);
return $this->raiseError($info);
}
- $reg = new PEAR_Registry($this->config->get('php_dir'));
- $installed = $reg->packageInfo($info['name']);
+ if (!isset($info['name'])) {
+ return $this->raiseError('No remote package "' . $package . '" was found');
+ }
+
+ $installed = $reg->packageInfo($info['name'], null, $channel);
$info['installed'] = $installed['version'] ? $installed['version'] : '- no -';
+ if (is_array($info['installed'])) {
+ $info['installed'] = $info['installed']['release'];
+ }
$this->ui->outputData($info, $command);
+ $this->config->set('default_channel', $savechannel);
return true;
}
- // }}}
- // {{{ doRemoteList()
-
function doRemoteList($command, $options, $params)
{
- $r = new PEAR_Remote($this->config);
+ $savechannel = $channel = $this->config->get('default_channel');
+ $reg = &$this->config->getRegistry();
+ if (isset($options['channel'])) {
+ $channel = $options['channel'];
+ if (!$reg->channelExists($channel)) {
+ return $this->raiseError('Channel "' . $channel . '" does not exist');
+ }
+
+ $this->config->set('default_channel', $channel);
+ }
+
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
+ return $e;
+ }
+
$list_options = false;
- if ($this->config->get('preferred_state') == 'stable')
+ if ($this->config->get('preferred_state') == 'stable') {
$list_options = true;
- $available = $r->call('package.listAll', $list_options);
+ }
+
+ $available = array();
+ if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
+ $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))
+ ) {
+ // use faster list-all if available
+ $rest = &$this->config->getREST('1.1', array());
+ $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
+ } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
+ $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
+ $rest = &$this->config->getREST('1.0', array());
+ $available = $rest->listAll($base, $list_options, true, false, false, $chan->getName());
+ }
+
if (PEAR::isError($available)) {
+ $this->config->set('default_channel', $savechannel);
return $this->raiseError($available);
}
+
$i = $j = 0;
$data = array(
- 'caption' => 'Available packages:',
+ 'caption' => 'Channel ' . $channel . ' Available packages:',
'border' => true,
'headline' => array('Package', 'Version'),
+ 'channel' => $channel
);
- foreach ($available as $name => $info) {
- $data['data'][] = array($name, isset($info['stable']) ? $info['stable'] : '-n/a-');
- }
- if (count($available)==0) {
- $data = '(no packages installed yet)';
+
+ if (count($available) == 0) {
+ $data = '(no packages available yet)';
+ } else {
+ foreach ($available as $name => $info) {
+ $version = (isset($info['stable']) && $info['stable']) ? $info['stable'] : '-n/a-';
+ $data['data'][] = array($name, $version);
+ }
}
$this->ui->outputData($data, $command);
+ $this->config->set('default_channel', $savechannel);
return true;
}
- // }}}
- // {{{ doListAll()
-
function doListAll($command, $options, $params)
{
- $r = new PEAR_Remote($this->config);
- $reg = new PEAR_Registry($this->config->get('php_dir'));
+ $savechannel = $channel = $this->config->get('default_channel');
+ $reg = &$this->config->getRegistry();
+ if (isset($options['channel'])) {
+ $channel = $options['channel'];
+ if (!$reg->channelExists($channel)) {
+ return $this->raiseError("Channel \"$channel\" does not exist");
+ }
+
+ $this->config->set('default_channel', $channel);
+ }
+
$list_options = false;
- if ($this->config->get('preferred_state') == 'stable')
+ if ($this->config->get('preferred_state') == 'stable') {
$list_options = true;
- $available = $r->call('package.listAll', $list_options);
- if (PEAR::isError($available)) {
- return $this->raiseError($available);
}
- if (!is_array($available)) {
- return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "'.$available.'")');
+
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
+ return $e;
+ }
+
+ if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
+ $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) {
+ // use faster list-all if available
+ $rest = &$this->config->getREST('1.1', array());
+ $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
+ } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) &&
+ $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
+ $rest = &$this->config->getREST('1.0', array());
+ $available = $rest->listAll($base, $list_options, false, false, false, $chan->getName());
+ }
+
+ if (PEAR::isError($available)) {
+ $this->config->set('default_channel', $savechannel);
+ return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "' . $available->getMessage() . '")');
}
+
$data = array(
- 'caption' => 'All packages:',
+ 'caption' => 'All packages [Channel ' . $channel . ']:',
'border' => true,
'headline' => array('Package', 'Latest', 'Local'),
+ 'channel' => $channel,
);
- $local_pkgs = $reg->listPackages();
-
+
+ if (isset($options['channelinfo'])) {
+ // add full channelinfo
+ $data['caption'] = 'Channel ' . $channel . ' All packages:';
+ $data['headline'] = array('Channel', 'Package', 'Latest', 'Local',
+ 'Description', 'Dependencies');
+ }
+ $local_pkgs = $reg->listPackages($channel);
+
foreach ($available as $name => $info) {
- $installed = $reg->packageInfo($name);
+ $installed = $reg->packageInfo($name, null, $channel);
+ if (is_array($installed['version'])) {
+ $installed['version'] = $installed['version']['release'];
+ }
$desc = $info['summary'];
- if (isset($params[$name]))
+ if (isset($params[$name])) {
$desc .= "\n\n".$info['description'];
-
+ }
if (isset($options['mode']))
{
- if ($options['mode'] == 'installed' && !isset($installed['version']))
+ if ($options['mode'] == 'installed' && !isset($installed['version'])) {
continue;
- if ($options['mode'] == 'notinstalled' && isset($installed['version']))
+ }
+ if ($options['mode'] == 'notinstalled' && isset($installed['version'])) {
continue;
+ }
if ($options['mode'] == 'upgrades'
- && (!isset($installed['version']) || $installed['version'] == $info['stable']))
- {
+ && (!isset($installed['version']) || version_compare($installed['version'],
+ $info['stable'], '>='))) {
continue;
}
}
@@ -213,112 +378,253 @@ parameter.
unset($local_pkgs[$pos]);
}
- $data['data'][$info['category']][] = array(
- $name,
- @$info['stable'],
- @$installed['version'],
- @$desc,
- @$info['deps'],
+ if (isset($info['stable']) && !$info['stable']) {
+ $info['stable'] = null;
+ }
+
+ if (isset($options['channelinfo'])) {
+ // add full channelinfo
+ if ($info['stable'] === $info['unstable']) {
+ $state = $info['state'];
+ } else {
+ $state = 'stable';
+ }
+ $latest = $info['stable'].' ('.$state.')';
+ $local = '';
+ if (isset($installed['version'])) {
+ $inst_state = $reg->packageInfo($name, 'release_state', $channel);
+ $local = $installed['version'].' ('.$inst_state.')';
+ }
+
+ $packageinfo = array(
+ $channel,
+ $name,
+ $latest,
+ $local,
+ isset($desc) ? $desc : null,
+ isset($info['deps']) ? $info['deps'] : null,
);
+ } else {
+ $packageinfo = array(
+ $reg->channelAlias($channel) . '/' . $name,
+ isset($info['stable']) ? $info['stable'] : null,
+ isset($installed['version']) ? $installed['version'] : null,
+ isset($desc) ? $desc : null,
+ isset($info['deps']) ? $info['deps'] : null,
+ );
+ }
+ $data['data'][$info['category']][] = $packageinfo;
}
-
+
+ if (isset($options['mode']) && in_array($options['mode'], array('notinstalled', 'upgrades'))) {
+ $this->config->set('default_channel', $savechannel);
+ $this->ui->outputData($data, $command);
+ return true;
+ }
+
foreach ($local_pkgs as $name) {
- $info = $reg->packageInfo($name);
+ $info = &$reg->getPackage($name, $channel);
$data['data']['Local'][] = array(
- $info['package'],
+ $reg->channelAlias($channel) . '/' . $info->getPackage(),
'',
- $info['version'],
- $info['summary'],
- @$info['release_deps']
+ $info->getVersion(),
+ $info->getSummary(),
+ $info->getDeps()
);
}
+ $this->config->set('default_channel', $savechannel);
$this->ui->outputData($data, $command);
return true;
}
- // }}}
- // {{{ doSearch()
-
function doSearch($command, $options, $params)
{
if ((!isset($params[0]) || empty($params[0]))
&& (!isset($params[1]) || empty($params[1])))
{
return $this->raiseError('no valid search string supplied');
- };
+ }
+
+ $channelinfo = isset($options['channelinfo']);
+ $reg = &$this->config->getRegistry();
+ if (isset($options['allchannels'])) {
+ // search all channels
+ unset($options['allchannels']);
+ $channels = $reg->getChannels();
+ $errors = array();
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ foreach ($channels as $channel) {
+ if ($channel->getName() != '__uri') {
+ $options['channel'] = $channel->getName();
+ $ret = $this->doSearch($command, $options, $params);
+ if (PEAR::isError($ret)) {
+ $errors[] = $ret;
+ }
+ }
+ }
+
+ PEAR::staticPopErrorHandling();
+ if (count($errors) !== 0) {
+ // for now, only give first error
+ return PEAR::raiseError($errors[0]);
+ }
+
+ return true;
+ }
+
+ $savechannel = $channel = $this->config->get('default_channel');
+ $package = strtolower($params[0]);
+ $summary = isset($params[1]) ? $params[1] : false;
+ if (isset($options['channel'])) {
+ $reg = &$this->config->getRegistry();
+ $channel = $options['channel'];
+ if (!$reg->channelExists($channel)) {
+ return $this->raiseError('Channel "' . $channel . '" does not exist');
+ }
+
+ $this->config->set('default_channel', $channel);
+ }
+
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
+ return $e;
+ }
+
+ if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
+ $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
+ $rest = &$this->config->getREST('1.0', array());
+ $available = $rest->listAll($base, false, false, $package, $summary, $chan->getName());
+ }
- $r = new PEAR_Remote($this->config);
- $reg = new PEAR_Registry($this->config->get('php_dir'));
- $available = $r->call('package.listAll', true, false);
if (PEAR::isError($available)) {
+ $this->config->set('default_channel', $savechannel);
return $this->raiseError($available);
}
- $data = array(
- 'caption' => 'Matched packages:',
- 'border' => true,
- 'headline' => array('Package', 'Stable/(Latest)', 'Local'),
- );
- foreach ($available as $name => $info) {
- $found = (!empty($params[0]) && stristr($name, $params[0]) !== false);
- if (!$found && !(isset($params[1]) && !empty($params[1])
- && (stristr($info['summary'], $params[1]) !== false
- || stristr($info['description'], $params[1]) !== false)))
- {
- continue;
- };
+ if (!$available && !$channelinfo) {
+ // clean exit when not found, no error !
+ $data = 'no packages found that match pattern "' . $package . '", for channel '.$channel.'.';
+ $this->ui->outputData($data);
+ $this->config->set('default_channel', $channel);
+ return true;
+ }
+
+ if ($channelinfo) {
+ $data = array(
+ 'caption' => 'Matched packages, channel ' . $channel . ':',
+ 'border' => true,
+ 'headline' => array('Channel', 'Package', 'Stable/(Latest)', 'Local'),
+ 'channel' => $channel
+ );
+ } else {
+ $data = array(
+ 'caption' => 'Matched packages, channel ' . $channel . ':',
+ 'border' => true,
+ 'headline' => array('Package', 'Stable/(Latest)', 'Local'),
+ 'channel' => $channel
+ );
+ }
- $installed = $reg->packageInfo($name);
+ if (!$available && $channelinfo) {
+ unset($data['headline']);
+ $data['data'] = 'No packages found that match pattern "' . $package . '".';
+ $available = array();
+ }
+
+ foreach ($available as $name => $info) {
+ $installed = $reg->packageInfo($name, null, $channel);
$desc = $info['summary'];
if (isset($params[$name]))
$desc .= "\n\n".$info['description'];
- $unstable = '';
- if ($info['unstable']) {
- $unstable = '/(' . $info['unstable'] . $info['state'] . ')';
- }
if (!isset($info['stable']) || !$info['stable']) {
- $info['stable'] = 'none';
+ $version_remote = 'none';
+ } else {
+ if ($info['unstable']) {
+ $version_remote = $info['unstable'];
+ } else {
+ $version_remote = $info['stable'];
+ }
+ $version_remote .= ' ('.$info['state'].')';
}
- $data['data'][$info['category']][] = array(
- $name,
- $info['stable'] . $unstable,
- $installed['version'],
- $desc,
+ $version = is_array($installed['version']) ? $installed['version']['release'] :
+ $installed['version'];
+ if ($channelinfo) {
+ $packageinfo = array(
+ $channel,
+ $name,
+ $version_remote,
+ $version,
+ $desc,
);
+ } else {
+ $packageinfo = array(
+ $name,
+ $version_remote,
+ $version,
+ $desc,
+ );
+ }
+ $data['data'][$info['category']][] = $packageinfo;
}
- if (!isset($data['data'])) {
- return $this->raiseError('no packages found');
- }
+
$this->ui->outputData($data, $command);
+ $this->config->set('default_channel', $channel);
return true;
}
- // }}}
- // {{{ doDownload()
+ function &getDownloader($options)
+ {
+ if (!class_exists('PEAR_Downloader')) {
+ require_once 'PEAR/Downloader.php';
+ }
+ $a = &new PEAR_Downloader($this->ui, $options, $this->config);
+ return $a;
+ }
function doDownload($command, $options, $params)
{
- //$params[0] -> The package to download
- if (count($params) != 1) {
- return PEAR::raiseError("download expects one argument: the package to download");
- }
- $server = $this->config->get('master_server');
- if (!ereg('^http://', $params[0])) {
- $getoption = isset($options['nocompress'])&&$options['nocompress']==1?'?uncompress=on':'';
- $pkgfile = "http://$server/get/$params[0]".$getoption;
- } else {
- $pkgfile = $params[0];
+ // make certain that dependencies are ignored
+ $options['downloadonly'] = 1;
+
+ // eliminate error messages for preferred_state-related errors
+ /* TODO: Should be an option, but until now download does respect
+ prefered state */
+ /* $options['ignorepreferred_state'] = 1; */
+ // eliminate error messages for preferred_state-related errors
+
+ $downloader = &$this->getDownloader($options);
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $e = $downloader->setDownloadDir(getcwd());
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($e)) {
+ return $this->raiseError('Current directory is not writeable, cannot download');
}
- $this->bytes_downloaded = 0;
- $saved = PEAR_Common::downloadHttp($pkgfile, $this->ui, '.',
- array(&$this, 'downloadCallback'));
- if (PEAR::isError($saved)) {
- return $this->raiseError($saved);
+
+ $errors = array();
+ $downloaded = array();
+ $err = $downloader->download($params);
+ if (PEAR::isError($err)) {
+ return $err;
}
- $fname = basename($saved);
- $this->ui->outputData("File $fname downloaded ($this->bytes_downloaded bytes)", $command);
+
+ $errors = $downloader->getErrorMsgs();
+ if (count($errors)) {
+ foreach ($errors as $error) {
+ if ($error !== null) {
+ $this->ui->outputData($error);
+ }
+ }
+
+ return $this->raiseError("$command failed");
+ }
+
+ $downloaded = $downloader->getDownloadedPackages();
+ foreach ($downloaded as $pkg) {
+ $this->ui->outputData("File $pkg[file] downloaded", $command);
+ }
+
return true;
}
@@ -329,107 +635,176 @@ parameter.
}
}
- // }}}
- // {{{ doListUpgrades()
-
function doListUpgrades($command, $options, $params)
{
- include_once "PEAR/Registry.php";
- $remote = new PEAR_Remote($this->config);
- if (empty($params[0])) {
- $state = $this->config->get('preferred_state');
- } else {
- $state = $params[0];
- }
- $caption = 'Available Upgrades';
- if (empty($state) || $state == 'any') {
- $latest = $remote->call("package.listLatestReleases");
- } else {
- $latest = $remote->call("package.listLatestReleases", $state);
- $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')';
+ require_once 'PEAR/Common.php';
+ if (isset($params[0]) && !is_array(PEAR_Common::betterStates($params[0]))) {
+ return $this->raiseError($params[0] . ' is not a valid state (stable/beta/alpha/devel/etc.) try "pear help list-upgrades"');
}
- $caption .= ':';
- if (PEAR::isError($latest)) {
- return $latest;
- }
- $reg = new PEAR_Registry($this->config->get('php_dir'));
- $inst = array_flip($reg->listPackages());
- $data = array(
- 'caption' => $caption,
- 'border' => 1,
- 'headline' => array('Package', 'Local', 'Remote', 'Size'),
- );
- foreach ((array)$latest as $pkg => $info) {
- $package = strtolower($pkg);
- if (!isset($inst[$package])) {
- // skip packages we don't have installed
+
+ $savechannel = $channel = $this->config->get('default_channel');
+ $reg = &$this->config->getRegistry();
+ foreach ($reg->listChannels() as $channel) {
+ $inst = array_flip($reg->listPackages($channel));
+ if (!count($inst)) {
continue;
}
- extract($info);
- $pkginfo = $reg->packageInfo($package);
- $inst_version = $pkginfo['version'];
- $inst_state = $pkginfo['release_state'];
- if (version_compare("$version", "$inst_version", "le")) {
- // installed version is up-to-date
+
+ if ($channel == '__uri') {
continue;
}
- if ($filesize >= 20480) {
- $filesize += 1024 - ($filesize % 1024);
- $fs = sprintf("%dkB", $filesize / 1024);
- } elseif ($filesize > 0) {
- $filesize += 103 - ($filesize % 103);
- $fs = sprintf("%.1fkB", $filesize / 1024.0);
+
+ $this->config->set('default_channel', $channel);
+ $state = empty($params[0]) ? $this->config->get('preferred_state') : $params[0];
+
+ $caption = $channel . ' Available Upgrades';
+ $chan = $reg->getChannel($channel);
+ if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) {
+ return $e;
+ }
+
+ $latest = array();
+ $base2 = false;
+ $preferred_mirror = $this->config->get('preferred_mirror');
+ if ($chan->supportsREST($preferred_mirror) &&
+ (
+ //($base2 = $chan->getBaseURL('REST1.4', $preferred_mirror)) ||
+ ($base = $chan->getBaseURL('REST1.0', $preferred_mirror))
+ )
+
+ ) {
+ if ($base2) {
+ $rest = &$this->config->getREST('1.4', array());
+ $base = $base2;
+ } else {
+ $rest = &$this->config->getREST('1.0', array());
+ }
+
+ if (empty($state) || $state == 'any') {
+ $state = false;
+ } else {
+ $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')';
+ }
+
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ $latest = $rest->listLatestUpgrades($base, $state, $inst, $channel, $reg);
+ PEAR::staticPopErrorHandling();
+ }
+
+ if (PEAR::isError($latest)) {
+ $this->ui->outputData($latest->getMessage());
+ continue;
+ }
+
+ $caption .= ':';
+ if (PEAR::isError($latest)) {
+ $this->config->set('default_channel', $savechannel);
+ return $latest;
+ }
+
+ $data = array(
+ 'caption' => $caption,
+ 'border' => 1,
+ 'headline' => array('Channel', 'Package', 'Local', 'Remote', 'Size'),
+ 'channel' => $channel
+ );
+
+ foreach ((array)$latest as $pkg => $info) {
+ $package = strtolower($pkg);
+ if (!isset($inst[$package])) {
+ // skip packages we don't have installed
+ continue;
+ }
+
+ extract($info);
+ $inst_version = $reg->packageInfo($package, 'version', $channel);
+ $inst_state = $reg->packageInfo($package, 'release_state', $channel);
+ if (version_compare("$version", "$inst_version", "le")) {
+ // installed version is up-to-date
+ continue;
+ }
+
+ if ($filesize >= 20480) {
+ $filesize += 1024 - ($filesize % 1024);
+ $fs = sprintf("%dkB", $filesize / 1024);
+ } elseif ($filesize > 0) {
+ $filesize += 103 - ($filesize % 103);
+ $fs = sprintf("%.1fkB", $filesize / 1024.0);
+ } else {
+ $fs = " -"; // XXX center instead
+ }
+
+ $data['data'][] = array($channel, $pkg, "$inst_version ($inst_state)", "$version ($state)", $fs);
+ }
+
+ if (isset($options['channelinfo'])) {
+ if (empty($data['data'])) {
+ unset($data['headline']);
+ if (count($inst) == 0) {
+ $data['data'] = '(no packages installed)';
+ } else {
+ $data['data'] = '(no upgrades available)';
+ }
+ }
+ $this->ui->outputData($data, $command);
} else {
- $fs = " -"; // XXX center instead
+ if (empty($data['data'])) {
+ $this->ui->outputData('Channel ' . $channel . ': No upgrades available');
+ } else {
+ $this->ui->outputData($data, $command);
+ }
}
- $data['data'][] = array($pkg, "$inst_version ($inst_state)", "$version ($state)", $fs);
- }
- if (empty($data['data'])) {
- $this->ui->outputData('No upgrades available');
- } else {
- $this->ui->outputData($data, $command);
}
+
+ $this->config->set('default_channel', $savechannel);
return true;
}
- // }}}
- // {{{ doClearCache()
-
function doClearCache($command, $options, $params)
{
$cache_dir = $this->config->get('cache_dir');
- $verbose = $this->config->get('verbose');
+ $verbose = $this->config->get('verbose');
$output = '';
+ if (!file_exists($cache_dir) || !is_dir($cache_dir)) {
+ return $this->raiseError("$cache_dir does not exist or is not a directory");
+ }
+
if (!($dp = @opendir($cache_dir))) {
return $this->raiseError("opendir($cache_dir) failed: $php_errormsg");
}
+
if ($verbose >= 1) {
$output .= "reading directory $cache_dir\n";
}
+
$num = 0;
while ($ent = readdir($dp)) {
- if (preg_match('/^xmlrpc_cache_[a-z0-9]{32}$/', $ent)) {
+ if (preg_match('/rest.cache(file|id)\\z/', $ent)) {
$path = $cache_dir . DIRECTORY_SEPARATOR . $ent;
- $ok = @unlink($path);
+ if (file_exists($path)) {
+ $ok = @unlink($path);
+ } else {
+ $ok = false;
+ $php_errormsg = '';
+ }
+
if ($ok) {
if ($verbose >= 2) {
$output .= "deleted $path\n";
}
$num++;
} elseif ($verbose >= 1) {
- $output .= "failed to delete $path\n";
+ $output .= "failed to delete $path $php_errormsg\n";
}
}
}
+
closedir($dp);
if ($verbose >= 1) {
$output .= "$num cache entries cleared\n";
}
+
$this->ui->outputData(rtrim($output), $command);
return $num;
}
-
- // }}}
-}
-
-?>
+} \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Remote.xml b/3rdparty/PEAR/Command/Remote.xml
new file mode 100644
index 00000000000..b4f6100c793
--- /dev/null
+++ b/3rdparty/PEAR/Command/Remote.xml
@@ -0,0 +1,109 @@
+<commands version="1.0">
+ <remote-info>
+ <summary>Information About Remote Packages</summary>
+ <function>doRemoteInfo</function>
+ <shortcut>ri</shortcut>
+ <options />
+ <doc>&lt;package&gt;
+Get details on a package from the server.</doc>
+ </remote-info>
+ <list-upgrades>
+ <summary>List Available Upgrades</summary>
+ <function>doListUpgrades</function>
+ <shortcut>lu</shortcut>
+ <options>
+ <channelinfo>
+ <shortopt>i</shortopt>
+ <doc>output fully channel-aware data, even on failure</doc>
+ </channelinfo>
+ </options>
+ <doc>[preferred_state]
+List releases on the server of packages you have installed where
+a newer version is available with the same release state (stable etc.)
+or the state passed as the second parameter.</doc>
+ </list-upgrades>
+ <remote-list>
+ <summary>List Remote Packages</summary>
+ <function>doRemoteList</function>
+ <shortcut>rl</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>specify a channel other than the default channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ </options>
+ <doc>
+Lists the packages available on the configured server along with the
+latest stable release of each package.</doc>
+ </remote-list>
+ <search>
+ <summary>Search remote package database</summary>
+ <function>doSearch</function>
+ <shortcut>sp</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>specify a channel other than the default channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ <allchannels>
+ <shortopt>a</shortopt>
+ <doc>search packages from all known channels</doc>
+ </allchannels>
+ <channelinfo>
+ <shortopt>i</shortopt>
+ <doc>output fully channel-aware data, even on failure</doc>
+ </channelinfo>
+ </options>
+ <doc>[packagename] [packageinfo]
+Lists all packages which match the search parameters. The first
+parameter is a fragment of a packagename. The default channel
+will be used unless explicitly overridden. The second parameter
+will be used to match any portion of the summary/description</doc>
+ </search>
+ <list-all>
+ <summary>List All Packages</summary>
+ <function>doListAll</function>
+ <shortcut>la</shortcut>
+ <options>
+ <channel>
+ <shortopt>c</shortopt>
+ <doc>specify a channel other than the default channel</doc>
+ <arg>CHAN</arg>
+ </channel>
+ <channelinfo>
+ <shortopt>i</shortopt>
+ <doc>output fully channel-aware data, even on failure</doc>
+ </channelinfo>
+ </options>
+ <doc>
+Lists the packages available on the configured server along with the
+latest stable release of each package.</doc>
+ </list-all>
+ <download>
+ <summary>Download Package</summary>
+ <function>doDownload</function>
+ <shortcut>d</shortcut>
+ <options>
+ <nocompress>
+ <shortopt>Z</shortopt>
+ <doc>download an uncompressed (.tar) file</doc>
+ </nocompress>
+ </options>
+ <doc>&lt;package&gt;...
+Download package tarballs. The files will be named as suggested by the
+server, for example if you download the DB package and the latest stable
+version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.</doc>
+ </download>
+ <clear-cache>
+ <summary>Clear Web Services Cache</summary>
+ <function>doClearCache</function>
+ <shortcut>cc</shortcut>
+ <options />
+ <doc>
+Clear the XML-RPC/REST cache. See also the cache_ttl configuration
+parameter.
+</doc>
+ </clear-cache>
+</commands> \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Test.php b/3rdparty/PEAR/Command/Test.php
new file mode 100644
index 00000000000..a757d9e5790
--- /dev/null
+++ b/3rdparty/PEAR/Command/Test.php
@@ -0,0 +1,337 @@
+<?php
+/**
+ * PEAR_Command_Test (run-tests)
+ *
+ * PHP versions 4 and 5
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Martin Jansen <mj@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Test.php 313023 2011-07-06 19:17:11Z dufuz $
+ * @link http://pear.php.net/package/PEAR
+ * @since File available since Release 0.1
+ */
+
+/**
+ * base class
+ */
+require_once 'PEAR/Command/Common.php';
+
+/**
+ * PEAR commands for login/logout
+ *
+ * @category pear
+ * @package PEAR
+ * @author Stig Bakken <ssb@php.net>
+ * @author Martin Jansen <mj@php.net>
+ * @author Greg Beaver <cellog@php.net>
+ * @copyright 1997-2009 The Authors
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.9.4
+ * @link http://pear.php.net/package/PEAR
+ * @since Class available since Release 0.1
+ */
+
+class PEAR_Command_Test extends PEAR_Command_Common
+{
+ var $commands = array(
+ 'run-tests' => array(
+ 'summary' => 'Run Regression Tests',
+ 'function' => 'doRunTests',
+ 'shortcut' => 'rt',
+ 'options' => array(
+ 'recur' => array(
+ 'shortopt' => 'r',
+ 'doc' => 'Run tests in child directories, recursively. 4 dirs deep maximum',
+ ),
+ 'ini' => array(
+ 'shortopt' => 'i',
+ 'doc' => 'actual string of settings to pass to php in format " -d setting=blah"',
+ 'arg' => 'SETTINGS'
+ ),
+ 'realtimelog' => array(
+ 'shortopt' => 'l',
+ 'doc' => 'Log test runs/results as they are run',
+ ),
+ 'quiet' => array(
+ 'shortopt' => 'q',
+ 'doc' => 'Only display detail for failed tests',
+ ),
+ 'simple' => array(
+ 'shortopt' => 's',
+ 'doc' => 'Display simple output for all tests',
+ ),
+ 'package' => array(
+ 'shortopt' => 'p',
+ 'doc' => 'Treat parameters as installed packages from which to run tests',
+ ),
+ 'phpunit' => array(
+ 'shortopt' => 'u',
+ 'doc' => 'Search parameters for AllTests.php, and use that to run phpunit-based tests
+If none is found, all .phpt tests will be tried instead.',
+ ),
+ 'tapoutput' => array(
+ 'shortopt' => 't',
+ 'doc' => 'Output run-tests.log in TAP-compliant format',
+ ),
+ 'cgi' => array(
+ 'shortopt' => 'c',
+ 'doc' => 'CGI php executable (needed for tests with POST/GET section)',
+ 'arg' => 'PHPCGI',
+ ),
+ 'coverage' => array(
+ 'shortopt' => 'x',
+ 'doc' => 'Generate a code coverage report (requires Xdebug 2.0.0+)',
+ ),
+ ),
+ 'doc' => '[testfile|dir ...]
+Run regression tests with PHP\'s regression testing script (run-tests.php).',
+ ),
+ );
+
+ var $output;
+
+ /**
+ * PEAR_Command_Test constructor.
+ *
+ * @access public
+ */
+ function PEAR_Command_Test(&$ui, &$config)
+ {
+ parent::PEAR_Command_Common($ui, $config);
+ }
+
+ function doRunTests($command, $options, $params)
+ {
+ if (isset($options['phpunit']) && isset($options['tapoutput'])) {
+ return $this->raiseError('ERROR: cannot use both --phpunit and --tapoutput at the same time');
+ }
+
+ require_once 'PEAR/Common.php';
+ require_once 'System.php';
+ $log = new PEAR_Common;
+ $log->ui = &$this->ui; // slightly hacky, but it will work
+ $tests = array();
+ $depth = isset($options['recur']) ? 14 : 1;
+
+ if (!count($params)) {
+ $params[] = '.';
+ }
+
+ if (isset($options['package'])) {
+ $oldparams = $params;
+ $params = array();
+ $reg = &$this->config->getRegistry();
+ foreach ($oldparams as $param) {
+ $pname = $reg->parsePackageName($param, $this->config->get('default_channel'));
+ if (PEAR::isError($pname)) {
+ return $this->raiseError($pname);
+ }
+
+ $package = &$reg->getPackage($pname['package'], $pname['channel']);
+ if (!$package) {
+ return PEAR::raiseError('Unknown package "' .
+ $reg->parsedPackageNameToString($pname) . '"');
+ }
+
+ $filelist = $package->getFilelist();
+ foreach ($filelist as $name => $atts) {
+ if (isset($atts['role']) && $atts['role'] != 'test') {
+ continue;
+ }
+
+ if (isset($options['phpunit']) && preg_match('/AllTests\.php\\z/i', $name)) {
+ $params[] = $atts['installed_as'];
+ continue;
+ } elseif (!preg_match('/\.phpt\\z/', $name)) {
+ continue;
+ }
+ $params[] = $atts['installed_as'];
+ }
+ }
+ }
+
+ foreach ($params as $p) {
+ if (is_dir($p)) {
+ if (isset($options['phpunit'])) {
+ $dir = System::find(array($p, '-type', 'f',
+ '-maxdepth', $depth,
+ '-name', 'AllTests.php'));
+ if (count($dir)) {
+ foreach ($dir as $p) {
+ $p = realpath($p);
+ if (!count($tests) ||
+ (count($tests) && strlen($p) < strlen($tests[0]))) {
+ // this is in a higher-level directory, use this one instead.
+ $tests = array($p);
+ }
+ }
+ }
+ continue;
+ }
+
+ $args = array($p, '-type', 'f', '-name', '*.phpt');
+ } else {
+ if (isset($options['phpunit'])) {
+ if (preg_match('/AllTests\.php\\z/i', $p)) {
+ $p = realpath($p);
+ if (!count($tests) ||
+ (count($tests) && strlen($p) < strlen($tests[0]))) {
+ // this is in a higher-level directory, use this one instead.
+ $tests = array($p);
+ }
+ }
+ continue;
+ }
+
+ if (file_exists($p) && preg_match('/\.phpt$/', $p)) {
+ $tests[] = $p;
+ continue;
+ }
+
+ if (!preg_match('/\.phpt\\z/', $p)) {
+ $p .= '.phpt';
+ }
+
+ $args = array(dirname($p), '-type', 'f', '-name', $p);
+ }
+
+ if (!isset($options['recur'])) {
+ $args[] = '-maxdepth';
+ $args[] = 1;
+ }
+
+ $dir = System::find($args);
+ $tests = array_merge($tests, $dir);
+ }
+
+ $ini_settings = '';
+ if (isset($options['ini'])) {
+ $ini_settings .= $options['ini'];
+ }
+
+ if (isset($_ENV['TEST_PHP_INCLUDE_PATH'])) {
+ $ini_settings .= " -d include_path={$_ENV['TEST_PHP_INCLUDE_PATH']}";
+ }
+
+ if ($ini_settings) {
+ $this->ui->outputData('Using INI settings: "' . $ini_settings . '"');
+ }
+
+ $skipped = $passed = $failed = array();
+ $tests_count = count($tests);
+ $this->ui->outputData('Running ' . $tests_count . ' tests', $command);
+ $start = time();
+ if (isset($options['realtimelog']) && file_exists('run-tests.log')) {
+ unlink('run-tests.log');
+ }
+
+ if (isset($options['tapoutput'])) {
+ $tap = '1..' . $tests_count . "\n";
+ }
+
+ require_once 'PEAR/RunTest.php';
+ $run = new PEAR_RunTest($log, $options);
+ $run->tests_count = $tests_count;
+
+ if (isset($options['coverage']) && extension_loaded('xdebug')){
+ $run->xdebug_loaded = true;
+ } else {
+ $run->xdebug_loaded = false;
+ }
+
+ $j = $i = 1;
+ foreach ($tests as $t) {
+ if (isset($options['realtimelog'])) {
+ $fp = @fopen('run-tests.log', 'a');
+ if ($fp) {
+ fwrite($fp, "Running test [$i / $tests_count] $t...");
+ fclose($fp);
+ }
+ }
+ PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
+ if (isset($options['phpunit'])) {
+ $result = $run->runPHPUnit($t, $ini_settings);
+ } else {
+ $result = $run->run($t, $ini_settings, $j);
+ }
+ PEAR::staticPopErrorHandling();
+ if (PEAR::isError($result)) {
+ $this->ui->log($result->getMessage());
+ continue;
+ }
+
+ if (isset($options['tapoutput'])) {
+ $tap .= $result[0] . ' ' . $i . $result[1] . "\n";
+ continue;
+ }
+
+ if (isset($options['realtimelog'])) {
+ $fp = @fopen('run-tests.log', 'a');
+ if ($fp) {
+ fwrite($fp, "$result\n");
+ fclose($fp);
+ }
+ }
+
+ if ($result == 'FAILED') {
+ $failed[] = $t;
+ }
+ if ($result == 'PASSED') {
+ $passed[] = $t;
+ }
+ if ($result == 'SKIPPED') {
+ $skipped[] = $t;
+ }
+
+ $j++;
+ }
+
+ $total = date('i:s', time() - $start);
+ if (isset($options['tapoutput'])) {
+ $fp = @fopen('run-tests.log', 'w');
+ if ($fp) {
+ fwrite($fp, $tap, strlen($tap));
+ fclose($fp);
+ $this->ui->outputData('wrote TAP-format log to "' .realpath('run-tests.log') .
+ '"', $command);
+ }
+ } else {
+ if (count($failed)) {
+ $output = "TOTAL TIME: $total\n";
+ $output .= count($passed) . " PASSED TESTS\n";
+ $output .= count($skipped) . " SKIPPED TESTS\n";
+ $output .= count($failed) . " FAILED TESTS:\n";
+ foreach ($failed as $failure) {
+ $output .= $failure . "\n";
+ }
+
+ $mode = isset($options['realtimelog']) ? 'a' : 'w';
+ $fp = @fopen('run-tests.log', $mode);
+
+ if ($fp) {
+ fwrite($fp, $output, strlen($output));
+ fclose($fp);
+ $this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command);
+ }
+ } elseif (file_exists('run-tests.log') && !is_dir('run-tests.log')) {
+ @unlink('run-tests.log');
+ }
+ }
+ $this->ui->outputData('TOTAL TIME: ' . $total);
+ $this->ui->outputData(count($passed) . ' PASSED TESTS', $command);
+ $this->ui->outputData(count($skipped) . ' SKIPPED TESTS', $command);
+ if (count($failed)) {
+ $this->ui->outputData(count($failed) . ' FAILED TESTS:', $command);
+ foreach ($failed as $failure) {
+ $this->ui->outputData($failure, $command);
+ }
+ }
+
+ return true;
+ }
+} \ No newline at end of file
diff --git a/3rdparty/PEAR/Command/Test.xml b/3rdparty/PEAR/Command/Test.xml
new file mode 100644
index 00000000000..bbe9fcccc51
--- /dev/null
+++ b/3rdparty/PEAR/Command/Test.xml
@@ -0,0 +1,54 @@
+<commands version="1.0">
+ <run-tests>
+ <summary>Run Regression Tests</summary>
+ <function>doRunTests</function>
+ <shortcut>rt</shortcut>
+ <options>
+ <recur>
+ <shortopt>r</shortopt>
+ <doc>Run tests in child directories, recursively. 4 dirs deep maximum</doc>
+ </recur>
+ <ini>
+ <shortopt>i</shortopt>
+ <doc>actual string of settings to pass to php in format &quot; -d setting=blah&quot;</doc>
+ <arg>SETTINGS</arg>
+ </ini>
+ <realtimelog>
+ <shortopt>l</shortopt>
+ <doc>Log test runs/results as they are run</doc>
+ </realtimelog>
+ <quiet>
+ <shortopt>q</shortopt>
+ <doc>Only display detail for failed tests</doc>
+ </quiet>
+ <simple>
+ <shortopt>s</shortopt>
+ <doc>Display simple output for all tests</doc>
+ </simple>
+ <package>
+ <shortopt>p</shortopt>
+ <doc>Treat parameters as installed packages from which to run tests</doc>
+ </package>
+ <phpunit>
+ <shortopt>u</shortopt>
+ <doc>Search parameters for AllTests.php, and use that to run phpunit-based tests
+If none is found, all .phpt tests will be tried instead.</doc>
+ </phpunit>
+ <tapoutput>
+ <shortopt>t</shortopt>
+ <doc>Output run-tests.log in TAP-compliant format</doc>
+ </tapoutput>
+ <cgi>
+ <shortopt>c</shortopt>
+ <doc>CGI php executable (needed for tests with POST/GET section)</doc>
+ <arg>PHPCGI</arg>
+ </cgi>
+ <coverage>
+ <shortopt>x</shortopt>
+ <doc>Generate a code coverage report (requires Xdebug 2.0.0+)</doc>
+ </coverage>
+ </options>
+ <doc>[testfile|dir ...]
+Run regression tests with PHP&#039;s regression testing script (run-tests.php).</doc>
+ </run-tests>
+</commands> \ No newline at end of file